diff --git a/app/api/pokemons/pokemon/[pokemon_name]/route.ts b/app/api/pokemons/pokemon/[pokemon_name]/route.ts index 88c5847..cd8169e 100644 --- a/app/api/pokemons/pokemon/[pokemon_name]/route.ts +++ b/app/api/pokemons/pokemon/[pokemon_name]/route.ts @@ -28,6 +28,7 @@ export async function GET( buddy_distance, moves, evolution_family, + cp_range, ] = await Promise.all([ findDualTypeDoubleDmgFrom(pokemon_name), findDualTypeDoubleDmgTo(pokemon_name), @@ -40,6 +41,7 @@ export async function GET( findPokemonBuddy(pokemon_name), findAllMoves(pokemon_name), findEvolutionFamily(pokemon_name), + findCPRange(pokemon_name), ]) return NextResponse.json( @@ -57,8 +59,9 @@ export async function GET( buddy_distance: buddy_distance, moves: moves, evolution_family: evolution_family, - sprite: `https://img.pokemondb.net/sprites/go/normal/${pokemon_name}.png`, - sprite_shiny: `https://img.pokemondb.net/sprites/go/shiny/${pokemon_name}.png`, + cp_range: cp_range, + sprite: `https://img.pokemondb.net/sprites/go/normal/${pokemon_details.name}.png`, + sprite_shiny: `https://img.pokemondb.net/sprites/go/shiny/${pokemon_details.name}.png`, }, { status: 200 } ) @@ -69,11 +72,21 @@ export async function GET( } async function getPokemonDetails(pokemonName: string) { + if (pokemonName === "nidoran♀") { + pokemonName = "nidoran-f" + } else if (pokemonName === "nidoran♂") { + pokemonName = "nidoran-m" + } const response = await axios.get(`${POKEAPI}/pokemon/${pokemonName}`) return response.data } async function getFlavorTextEntries(pokemonName: string) { + if (pokemonName === "nidoran♀") { + pokemonName = "nidoran-f" + } else if (pokemonName === "nidoran♂") { + pokemonName = "nidoran-m" + } const response = await axios.get(`${POKEAPI}/pokemon-species/${pokemonName}`) return response.data } @@ -124,6 +137,11 @@ async function getChargedMove(moveName: string) { } async function getEvolutions(pokemonName: string) { + if (pokemonName === "nidoran♀") { + pokemonName = "nidoran-f" + } else if (pokemonName === "nidoran♂") { + pokemonName = "nidoran-m" + } const response = await axios.get(`${POKEAPI}/pokemon-species/${pokemonName}`) const response2 = await axios.get(response.data.evolution_chain.url) function getAllEvolutions(evolutionChain: { chain: any }) { @@ -159,7 +177,6 @@ async function getCurrentMoves(pokemonName: string) { pokemon.pokemon_name.toLowerCase() === pokemonName && pokemon.form === "Normal" ) - console.log(pokemonMoves) if (pokemonMoves.cached) return pokemonMoves // Helper function to handle move details retrieval const fetchMoveDetails = async (moveName: string, isCharged: boolean) => { @@ -277,6 +294,10 @@ async function getPokemonStats(pokemon_name: string) { return stats } +async function getCPMultiplier() { + const response = await axios.get(`${POGOAPI}/cp_multiplier.json`) + return response.data +} async function findPokemonBuddy(pokemon_name: string) { try { const response = await axios.get(`${POGOAPI}/pokemon_buddy_distances.json`) @@ -477,3 +498,48 @@ async function findEvolutionFamily(pokemonName: string) { ) } } + +async function findCPRange(pokemonName: string) { + try { + const pokemonStats = await getPokemonStats(pokemonName) + let CPMultiplier = await getCPMultiplier() + CPMultiplier.push({ level: 45.5, multiplier: 0.81779999 }) + CPMultiplier.push({ level: 46, multiplier: 0.82029999 }) + CPMultiplier.push({ level: 46.5, multiplier: 0.82279999 }) + CPMultiplier.push({ level: 47, multiplier: 0.82529999 }) + CPMultiplier.push({ level: 47.5, multiplier: 0.82779999 }) + CPMultiplier.push({ level: 48, multiplier: 0.83029999 }) + CPMultiplier.push({ level: 48.5, multiplier: 0.83279999 }) + CPMultiplier.push({ level: 49, multiplier: 0.83529999 }) + CPMultiplier.push({ level: 49.5, multiplier: 0.83779999 }) + CPMultiplier.push({ level: 50, multiplier: 0.84029999 }) + CPMultiplier.push({ level: 50.5, multiplier: 0.84279999 }) + let data: any = [] + CPMultiplier.map((cp: { level: number; multiplier: number }) => { + if (Number.isInteger(cp.level)) { + data.push({ + level: cp.level, + range: `${Math.floor( + (pokemonStats.base_attack * + Math.pow(pokemonStats.base_defense, 0.5) * + Math.pow(pokemonStats.base_stamina, 0.5) * + Math.pow(cp.multiplier, 2)) / + 10 + )}-${Math.floor( + ((pokemonStats.base_attack + 15) * + Math.pow(pokemonStats.base_defense + 15, 0.5) * + Math.pow(pokemonStats.base_stamina + 15, 0.5) * + Math.pow(cp.multiplier, 2)) / + 10 + )}`, + }) + } + }) + return data + } catch (error) { + return NextResponse.json( + { msg: "findEvolutionFamily error", error }, + { status: 500 } + ) + } +} diff --git a/app/api/pokemons/route.ts b/app/api/pokemons/route.ts index b823d04..74b46e8 100644 --- a/app/api/pokemons/route.ts +++ b/app/api/pokemons/route.ts @@ -10,9 +10,6 @@ export async function GET(req: Request) { pokemons = pokemons.data.filter((pokemon: { form: string })=> { return pokemon.form === "Normal" }) - - console.log(pokemons) - return NextResponse.json( { msg: "Success", diff --git a/app/page.tsx b/app/page.tsx index 5ecebd5..2257506 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,14 +1,21 @@ import { ColorSchemeToggle } from "@/components/ColorSchemeToggle" -import { Container } from "@mantine/core" +import { Container, Flex, Title } from "@mantine/core" import { SearchBar } from "@/components/SearchBar" -import { PokemonList } from "@/components/PokemonList" +import { NavBar } from "@/components/NavBar" export default function Home() { return ( - - - - + + + + PokeData + + ) } diff --git a/app/pokedex/page.tsx b/app/pokedex/page.tsx new file mode 100644 index 0000000..5773a3d --- /dev/null +++ b/app/pokedex/page.tsx @@ -0,0 +1,13 @@ +"use client" +import { Container } from "@mantine/core" +import { NavBar } from "@/components/NavBar" +import { PokemonList } from "@/components/PokemonList" + +export default function PokemonName() { + return ( + + + + + ) +} diff --git a/app/pokemons/[pokemon_name]/page.tsx b/app/pokemons/[pokemon_name]/page.tsx index 9e09d97..4be7693 100644 --- a/app/pokemons/[pokemon_name]/page.tsx +++ b/app/pokemons/[pokemon_name]/page.tsx @@ -1,10 +1,10 @@ "use client" -import { ColorSchemeToggle } from "@/components/ColorSchemeToggle" import { Container } from "@mantine/core" import { SearchBar } from "@/components/SearchBar" import { useParams } from "next/navigation" import { PokemonCard } from "@/components/PokemonCard" import usePokemon from "@/hooks/usePokemon" +import { NavBar } from "@/components/NavBar" export default function PokemonName() { const { pokemon_name } = useParams() @@ -12,9 +12,8 @@ export default function PokemonName() { return ( - + - {pokemon_name && } ) diff --git a/components/ColorSchemeToggle.tsx b/components/ColorSchemeToggle.tsx index a0d7064..3222553 100644 --- a/components/ColorSchemeToggle.tsx +++ b/components/ColorSchemeToggle.tsx @@ -6,7 +6,7 @@ export function ColorSchemeToggle() { const { setColorScheme } = useMantineColorScheme() return ( - + diff --git a/components/NavBar.tsx b/components/NavBar.tsx new file mode 100644 index 0000000..eea1747 --- /dev/null +++ b/components/NavBar.tsx @@ -0,0 +1,35 @@ +"use client" +import { Badge, NavLink } from "@mantine/core" +import { + IconNotebook, + IconSearch, +} from "@tabler/icons-react" +import { useDisclosure } from "@mantine/hooks" +import { Drawer, Burger, Container } from "@mantine/core" +import { ColorSchemeToggle } from "./ColorSchemeToggle" +import { useRouter } from "next/navigation" + +export const NavBar = () => { + const [opened, { open, close }] = useDisclosure(false) + const router = useRouter() + return ( + <> + + } + onClick={() => router.push("/")} + /> + } + onClick={() => router.push("/pokedex")} + /> + + + + + + + ) +} diff --git a/components/PokemonCPRange.tsx b/components/PokemonCPRange.tsx new file mode 100644 index 0000000..8136fd9 --- /dev/null +++ b/components/PokemonCPRange.tsx @@ -0,0 +1,28 @@ +import { Text, Image, Stack, Title, Group, Table } from "@mantine/core" + +interface PokemonCPRangeProps { + pokemon: Record +} + +export const PokemonCPRange: React.FC = ({ + pokemon: { cp_range }, +}) => { + const renderCP = cp_range?.map((cp: { level: number; range: string }) => ( + + {cp.level} + {cp.range} + + )) + + return ( + + + + Level + CP + + + {renderCP} +
+ ) +} diff --git a/components/PokemonCard.tsx b/components/PokemonCard.tsx index 6180e92..bf4f4b7 100644 --- a/components/PokemonCard.tsx +++ b/components/PokemonCard.tsx @@ -18,6 +18,7 @@ import { PokemonTypes } from "./PokemonTypes" import { PokemonWeatherBoosted } from "./PokemonWeatherBoosted" import { PokemonMoves } from "./PokemonMoves" import { PokemonEvolutions } from "./PokemonEvolutions" +import { PokemonCPRange } from "./PokemonCPRange" interface PokemonCardProps { pokemon: Record @@ -29,12 +30,13 @@ export const PokemonCard: React.FC = ({ isLoading, }) => { return ( - - + + Details Shiny Rates Moves Evolutions + CP Range @@ -129,6 +131,23 @@ export const PokemonCard: React.FC = ({ + + + + + {capitalize(pokemon?.pokemon_name)} + + {`"${pokemon?.pokemon_flavor_text}"`} + + + + + + ) } diff --git a/components/PokemonList.tsx b/components/PokemonList.tsx index 8992e41..f60950c 100644 --- a/components/PokemonList.tsx +++ b/components/PokemonList.tsx @@ -2,16 +2,16 @@ import useAllPokemons from "@/hooks/useAllPokemons" import { Card, - Image, Text, - Badge, - Button, - Group, ScrollArea, - Stack, Flex, + Badge, + Group, + darken } from "@mantine/core" import { useRouter } from "next/navigation" +import { colors } from "@/libs/utils" + export const PokemonList = () => { const { data: allPokemons = [], isLoading: isPokemonsLoading } = @@ -19,7 +19,7 @@ export const PokemonList = () => { const router = useRouter() const renderPokemons = allPokemons?.pokemons?.map((pokemon: any) => ( - router.push( `/pokemons/${pokemon.pokemon_name.replace(/[^a-zA-Z]/g, "")}` @@ -30,22 +30,26 @@ export const PokemonList = () => { withBorder key={pokemon.pokemon_name} > - + {pokemon.pokemon_name} #{pokemon.pokemon_id} - - {pokemon.type.join(",")} - + + {pokemon?.type?.map((type: string) => ( + + {type} + + ))} + )) return ( - + {renderPokemons} ) diff --git a/components/PokemonMoves.tsx b/components/PokemonMoves.tsx index cfb818d..790f224 100644 --- a/components/PokemonMoves.tsx +++ b/components/PokemonMoves.tsx @@ -6,43 +6,8 @@ interface PokemonMoves { } export const PokemonMoves: React.FC = ({ - pokemon: { type_effectiveness, moves }, + pokemon: { moves }, }) => { - const renderTypeEffectiveness = () => { - const list = [] - - for (const key in type_effectiveness) { - if (key) - list.push( - - - {`${capitalize(key)} Moves`}: - - - ) - if (type_effectiveness[key].length === 0) { - list.push( - - - N/A - - - ) - } - for (const key2 in type_effectiveness[key]) { - list.push( - - {`Effective against ${type_effectiveness[key][key2]} types`} - - ) - } - } - return list - } const renderFastMoves = moves?.fast_moves?.map((move: any, index: number) => ( = ({ const list = [] for (const types in pokemon_types) { list.push( - + {pokemon_types[types]} ) @@ -26,7 +23,7 @@ export const PokemonTypes: React.FC = ({ return ( Type - {renderTypes()} + {renderTypes()} ) } diff --git a/components/SearchBar.tsx b/components/SearchBar.tsx index 45dd635..27949a7 100644 --- a/components/SearchBar.tsx +++ b/components/SearchBar.tsx @@ -1,16 +1,20 @@ "use client" import { useState, useRef } from "react" -import { Autocomplete, CloseButton, Container, Stack } from "@mantine/core" +import { + Autocomplete, + CloseButton, + Container, + Flex, + Stack, + Center, +} from "@mantine/core" import useAllPokemons from "@/hooks/useAllPokemons" import { useRouter, usePathname } from "next/navigation" import { CopyURL } from "./CopyURL" export const SearchBar = () => { let currentPage = usePathname() - currentPage = currentPage - .split("/") - .pop() - ?.replace(/[^a-zA-Z]/g, "") as string + currentPage = currentPage.split("/").pop() as string const [value, setValue] = useState(currentPage) const { data: allPokemons = [], isLoading: isPokemonsLoading } = useAllPokemons() @@ -22,39 +26,34 @@ export const SearchBar = () => { if (isPokemonsLoading) { return ( - - - { - setValue(value) - }} - maxDropdownHeight={200} - onOptionSubmit={(value) => { - router.push(`/pokemons/${value}`) - }} - leftSection={ - - } - rightSection={ - value && - } - /> - - + <> + { + setValue(value) + }} + maxDropdownHeight={200} + onOptionSubmit={(value) => { + router.push(`/pokemons/${value}`) + }} + leftSection={} + rightSection={ + value && + } + /> + ) } return ( - - + { onOptionSubmit={(value) => { router.push(`/pokemons/${value}`) }} - leftSection={ - - } + leftSection={} rightSection={ value && ( { ) } /> - - + ) } diff --git a/middleware.ts b/middleware.ts index 8aff64a..d8ccf42 100644 --- a/middleware.ts +++ b/middleware.ts @@ -5,16 +5,16 @@ const PUBLIC_FILE = /\.(.*)$/ // This function can be marked `async` if using `await` inside export function middleware(request: NextRequest) { - const { pathname } = request.nextUrl - if ( - pathname.startsWith("/_next") || // exclude Next.js internals - pathname.startsWith("/api") || // exclude all API routes - pathname.startsWith("/static") || // exclude static files - pathname.startsWith("/pokemons") || - PUBLIC_FILE.test(pathname) // exclude all files in the public folder - ) - return NextResponse.next() - return NextResponse.redirect(new URL("/", request.url)) + // const { pathname } = request.nextUrl + // if ( + // pathname.startsWith("/_next") || // exclude Next.js internals + // pathname.startsWith("/api") || // exclude all API routes + // pathname.startsWith("/static") || // exclude static files + // pathname.startsWith("/pokemons") || + // PUBLIC_FILE.test(pathname) // exclude all files in the public folder + // ) + // return NextResponse.next() + // return NextResponse.redirect(new URL("/", request.url)) } // See "Matching Paths" below to learn more