diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fcfd49e..70b2656 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,7 @@ import { Login } from "./Login"; import { PersonList } from "./PersonList"; import { PersonDetails } from "./PersonDetails"; import { GameList } from "./GameList"; +import { GameFilter } from "./GameFilter"; import { BrowserRouter, Routes, Route, Link } from "react-router-dom"; import "./App.css"; import { apiFetch } from "./api"; @@ -52,6 +53,9 @@ function App() { Games + + Filter + Logout @@ -60,6 +64,7 @@ function App() { } /> } /> + } /> } /> diff --git a/frontend/src/GameFilter.tsx b/frontend/src/GameFilter.tsx new file mode 100644 index 0000000..e12665a --- /dev/null +++ b/frontend/src/GameFilter.tsx @@ -0,0 +1,142 @@ +import { useState, useEffect } from "react"; +import { Person, PersonList as PersonListProto } from "../items"; +import { apiFetch } from "./api"; + +export function GameFilter() { + const [people, setPeople] = useState([]); + const [selectedPeople, setSelectedPeople] = useState>(new Set()); + const [filteredGames, setFilteredGames] = useState([]); + + useEffect(() => { + apiFetch("/api") + .then((res) => res.arrayBuffer()) + .then((buffer) => { + const list = PersonListProto.decode(new Uint8Array(buffer)); + setPeople(list.person); + }) + .catch((err) => console.error("Failed to fetch people:", err)); + }, []); + + useEffect(() => { + if (selectedPeople.size === 0) { + setFilteredGames([]); + return; + } + + // Get all games where ALL selected people have "Would Play" + const selectedPersons = people.filter((p) => selectedPeople.has(p.name)); + + if (selectedPersons.length === 0) { + setFilteredGames([]); + return; + } + + // Create a map of game -> set of people who would play it + const gameToPlayers = new Map>(); + + selectedPersons.forEach((person) => { + person.opinion.forEach((op) => { + if (op.wouldPlay) { + if (!gameToPlayers.has(op.title)) { + gameToPlayers.set(op.title, new Set()); + } + gameToPlayers.get(op.title)!.add(person.name); + } + }); + }); + + // Filter games where ALL selected people would play + const games = Array.from(gameToPlayers.entries()) + .filter(([, players]) => players.size === selectedPeople.size) + .map(([game]) => game); + + setFilteredGames(games); + }, [selectedPeople, people]); + + const togglePerson = (name: string) => { + const newSelected = new Set(selectedPeople); + if (newSelected.has(name)) { + newSelected.delete(name); + } else { + newSelected.add(name); + } + setSelectedPeople(newSelected); + }; + + return ( + + Game Filter + + Select multiple people to find games that everyone would play + + + + Select People + + {people.map((person) => ( + togglePerson(person.name)} + > + + togglePerson(person.name)} + style={{ cursor: "pointer" }} + /> + {person.name} + + + {person.opinion.length} opinion(s) + + + ))} + + + + {selectedPeople.size > 0 && ( + + Games Everyone Would Play ({filteredGames.length}) + {filteredGames.length > 0 ? ( + + {filteredGames.map((game) => ( + + {game} + + ✓ All {selectedPeople.size} selected would play + + + ))} + + ) : ( + + No games found where all selected people would play + + )} + + )} + + ); +} diff --git a/state.json b/state.json index 286047b..49e289a 100644 --- a/state.json +++ b/state.json @@ -8,12 +8,53 @@ "max_players": 90, "price": 0, "remote_id": 0 + }, + { + "title": "Test2", + "source": 1, + "multiplayer": true, + "min_players": 1, + "max_players": 1, + "price": 0, + "remote_id": 0 } ], "users": [ { "person": { "name": "John", + "opinion": [ + { + "title": "Naramo Nuclear Plant V2", + "would_play": true + }, + { + "title": "Test2", + "would_play": true + } + ] + }, + "password_hash": "$2b$12$DRvTP/ibTWULkuJJr285bumRd7SG3n5bYkDpb09Qpklqf6FeTiHkC" + }, + { + "person": { + "name": "John2", + "opinion": [ + { + "title": "Naramo Nuclear Plant V2", + "would_play": false + }, + { + "title": "Test2", + "would_play": true + } + ] + }, + "password_hash": "$2b$12$DRvTP/ibTWULkuJJr285bumRd7SG3n5bYkDpb09Qpklqf6FeTiHkC" + }, + { + "person": { + "name": "John3", "opinion": [ { "title": "Naramo Nuclear Plant V2",
+ Select multiple people to find games that everyone would play +
+ No games found where all selected people would play +