Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions PTG/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { useEffect, useState } from "react";
import Header from "./Header.tsx"
import ChoosePokemon from "./ChoosePokemon.tsx";
import PokemonGrid from "./PokemonGrid.tsx";
import { loadStoredFilters, saveStoredFilters } from "./pokemonFilters.ts";

export default function App(){

const [selectedGame, setSelectedGame] = useState(() => loadStoredFilters().selectedGame);
const [selectedType, setSelectedType] = useState(() => loadStoredFilters().selectedType);

useEffect(() => {
saveStoredFilters({ selectedGame, selectedType });
}, [selectedGame, selectedType]);

return(
<div>
<Header />
<ChoosePokemon />
<ChoosePokemon
selectedGame={selectedGame}
selectedType={selectedType}
onGameChange={setSelectedGame}
onTypeChange={setSelectedType}
/>
<PokemonGrid selectedGame={selectedGame} selectedType={selectedType} />
</div>

);
}
);
}
5 changes: 5 additions & 0 deletions PTG/src/ChoosePokemon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.chooseType {
field-sizing: content;
width: fit-content;
max-width: 100%;
}
148 changes: 75 additions & 73 deletions PTG/src/ChoosePokemon.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,72 @@
import {useState} from "react"



function ChoosePokemon(){
const [selectedGen, setSelectedGen] = useState('');
const [selectedType, setSelectedType] = useState('');

type Gen = {
label: string,
value: string
}

let gens: Gen[] = [
{label: 'Gen I', value: 'gen_i'},
{label: 'Gen II', value: 'gen_ii'},
{label: 'Gen III', value: 'gen_iii'},
{label: 'Gen IV', value: 'gen_iv'},
{label: 'Gen V', value: 'gen_v'},
{label: 'Gen VI', value: 'gen_vi'},
{label: 'Gen VII', value: 'gen_vii'},
{label: 'Gen VIII', value: 'gen_viii'},
{label: 'Gen IX', value: 'gen_ix'},
]

let types: Gen[] = [
{label: 'Any', value: 'any'},
{label: 'Fire', value: 'fire'},
{label: 'Water', value: 'water'},
{label: 'Grass', value: 'grass'},
{label: 'Electric', value: 'electric'},
{label: 'Rock', value: 'rock'},
{label: 'Ground', value: 'ground'},
{label: 'Flying', value: 'flying'},
{label: 'Dragon', value: 'dragon'},
{label: 'Bug', value: 'bug'},
{label: 'Poison', value: 'poison'},
{label: 'Psychic', value: 'psychic'},
{label: 'Normal', value: 'normal'},
{label: 'Fighting', value: 'fighting'},
{label: 'Ghost', value: 'ghost'},
{label: 'Ice', value: 'ice'},
{label: 'Steel', value: 'steel'},
{label: 'Dark', value: 'dark'},
{label: 'Fairy', value: 'fairy'}
]

function changeTypeArray(){
if (selectedGen === 'gen_i') return types.slice(0, 16);
else if (selectedGen === 'gen_ii' || selectedGen === 'gen_iii' ||
selectedGen === 'gen_iv' || selectedGen === 'gen_v'){
return types.slice(0, 18);
}
return types;
}

function handleGenChange(e: any) { setSelectedGen(e.target.value); }

function handleTypeChange(e: any) { setSelectedType(e.target.value); }

let newTypes : Gen[] = changeTypeArray();
import { useEffect, useState } from "react";
import "./ChoosePokemon.css";
import { fetchGames, type GameOption } from "./games";
import { fetchTypes, type TypeOption } from "./pokemonTypes";

type TypeChoice = {
label: string,
value: string
}

const ANY_TYPE: TypeChoice = { label: 'Any Type', value: 'any' };

type ChoosePokemonProps = {
selectedGame: string;
selectedType: string;
onGameChange: (value: string) => void;
onTypeChange: (value: string) => void;
}

function ChoosePokemon({ selectedGame, selectedType, onGameChange, onTypeChange }: ChoosePokemonProps){
const [games, setGames] = useState<GameOption[]>([]);
const [gamesError, setGamesError] = useState<string | null>(null);
const [types, setTypes] = useState<TypeOption[]>([]);
const [typesError, setTypesError] = useState<string | null>(null);

useEffect(() => {
let cancelled = false;

fetchGames()
.then((data) => {
if (!cancelled) setGames(data);
})
.catch((err: Error) => {
if (!cancelled) setGamesError(err.message);
});

fetchTypes()
.then((data) => {
if (!cancelled) setTypes(data);
})
.catch((err: Error) => {
if (!cancelled) setTypesError(err.message);
});

return () => {
cancelled = true;
};
}, []);

function handleGameChange(e: React.ChangeEvent<HTMLSelectElement>) { onGameChange(e.target.value); }

function handleTypeChange(e: React.ChangeEvent<HTMLSelectElement>) { onTypeChange(e.target.value); }

const newTypes: TypeChoice[] = [ANY_TYPE, ...types];

if (gamesError) return <p className="pokemonGridError">Failed to load games: {gamesError}</p>;
if (typesError) return <p className="pokemonGridError">Failed to load types: {typesError}</p>;

return(
<>
<select
className="chooseType"
value={selectedGen}
onChange={handleGenChange}
value={selectedGame}
onChange={handleGameChange}
>
<option value="">Select</option>
{gens.map((gens) => (
<option key={gens.label} value={gens.value}>
{gens.label}
<option value="">Any Game</option>
{games.map((game) => (
<option key={game.value} value={game.value}>
{game.label}
</option>
))}
</select>
Expand All @@ -86,18 +82,24 @@ function ChoosePokemon(){
</option>
))}
</select>

</>
);
}

export default function generateTeam(){

// Filter controls plus the (not yet wired up) team generation button.
export default function generateTeam({ selectedGame, selectedType, onGameChange, onTypeChange }: ChoosePokemonProps){

return(
<>
<ChoosePokemon />
<ChoosePokemon
selectedGame={selectedGame}
selectedType={selectedType}
onGameChange={onGameChange}
onTypeChange={onTypeChange}
/>
<button>Generate Team</button>
</>

);
}
}
47 changes: 47 additions & 0 deletions PTG/src/PokemonGrid.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.pokemonGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 1rem;
padding: 1rem;
}

.pokemonCard {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid #ddd;
border-radius: 8px;
padding: 0.5rem;
text-align: center;
}

.pokemonCardImage {
position: relative;
width: 100%;
max-width: 120px;
}

.pokemonCardImage > img {
width: 100%;
height: auto;
display: block;
}

.pokemonCardTypes {
position: absolute;
top: 2px;
left: 2px;
display: flex;
gap: 2px;
}

.pokemonCardTypes img {
width: 20px;
height: 20px;
filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.6));
}

.pokemonGridError {
color: red;
text-align: center;
}
Loading