diff --git a/src/components/pages/costumes.tsx b/src/components/pages/costumes.tsx index 86ef3ba3..8e740fce 100644 --- a/src/components/pages/costumes.tsx +++ b/src/components/pages/costumes.tsx @@ -54,6 +54,7 @@ interface CharactersPageProps { costumes: ICostume[]; abilitiesLookup; charactersLookup; + characters: character[]; } export const weaponTypesLookup = { @@ -93,10 +94,21 @@ function filterCostumesBySkill(costumes: ICostume[], filters) { return filteredCostumes; } +function filterCostumesByCharacter(costumes: ICostume[], filters: character[]) { + if (filters.length === 0) return costumes; + + const charactersIds = filters.map((character) => character.character_id); + + return costumes.filter((costume) => + charactersIds.includes(costume.character_id) + ); +} + export default function CharactersPage({ costumes, abilitiesLookup, charactersLookup, + characters, }: CharactersPageProps): JSX.Element { const showUnreleasedContent = useSettingsStore( (state) => state.showUnreleasedContent @@ -109,6 +121,7 @@ export default function CharactersPage({ return ownedCostumes.includes(cost.costume_id); }); const skills = useCostumesFilters((state) => state.skills); + const filteredCharacters = useCostumesFilters((state) => state.characters); /** * Using a state and useEffect here because Next.js is @@ -144,7 +157,10 @@ export default function CharactersPage({ )} > - +
+ + +
{showInventory && ownedCostumes.length === 0 && ( @@ -164,8 +180,17 @@ export default function CharactersPage({ state.skills); @@ -707,7 +741,12 @@ export function CostumesFilters() { variant={skills.length > 0 ? "contained" : "outlined"} onClick={() => setIsOpen(true)} component="label" - startIcon={} + startIcon={ + + } > {(skills.length > 0 && ( @@ -747,3 +786,80 @@ export function CostumesFilters() { ); } + +export function CostumesCharactersFilters({ + characters, +}: { + characters: character[]; +}) { + const [isOpen, setIsOpen] = useState(false); + + const filteredCharacters = useCostumesFilters((state) => state.characters); + const toggleCharacter = useCostumesFilters((state) => state.toggleCharacter); + + return ( +
+ + setIsOpen(false)} + aria-labelledby="modal-modal-title" + aria-describedby="modal-modal-description" + > +
+
+
+

+ Filter costumes by Character +

+
+ +
+
+ {characters.map((character) => ( +
+ {character.name} + ch.name === character.name + )} + setState={() => toggleCharacter(character)} + /> +
+ ))} +
+
+
+
+ ); +} diff --git a/src/pages/characters/[[...costume]].tsx b/src/pages/characters/[[...costume]].tsx index 3522fe49..cee4be89 100644 --- a/src/pages/characters/[[...costume]].tsx +++ b/src/pages/characters/[[...costume]].tsx @@ -86,6 +86,7 @@ export default function CharactersPage({ costumes={costumes} abilitiesLookup={abilitiesLookup} charactersLookup={charactersLookup} + characters={characters} /> ); } @@ -100,6 +101,12 @@ export async function getStaticProps(context) { }, }); + const characters = await prisma.dump.character.findMany({ + orderBy: { + character_id: "asc", + }, + }); + return { props: JSON.parse( JSON.stringify({ @@ -109,6 +116,7 @@ export async function getStaticProps(context) { costumes, abilitiesLookup, charactersLookup, + characters, }) ), }; diff --git a/src/store/costumes-filters.js b/src/store/costumes-filters.js index ee2d35fc..a86d1f74 100644 --- a/src/store/costumes-filters.js +++ b/src/store/costumes-filters.js @@ -2,6 +2,7 @@ import produce from 'immer'; import create from 'zustand'; export const useCostumesFilters = create((set) => ({ + characters: [], skills: [], toggleSkill: (skill) => set((state) => { @@ -18,4 +19,19 @@ export const useCostumesFilters = create((set) => ({ skills: newSkills }; }), + toggleCharacter: (character) => + set((state) => { + const newCharacters = produce(state.characters, (draft) => { + const index = draft.findIndex((ch) => ch.name === character.name) + if (index > -1) { + draft.splice(index, 1); + } else { + draft.push(character); + } + }); + + return { + characters: newCharacters + }; + }), })); \ No newline at end of file