feat: implement game listing API and integrate into frontend for display and selection.
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { Game, Source } from "../items";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Game, Source, GameList as GameListProto } from "../items";
|
||||
import { apiFetch } from "./api";
|
||||
|
||||
export function GameList() {
|
||||
const [games, setGames] = useState<Game[]>([]);
|
||||
const [title, setTitle] = useState("");
|
||||
const [source, setSource] = useState<Source>(Source.STEAM);
|
||||
const [multiplayer, setMultiplayer] = useState(false);
|
||||
@@ -12,6 +13,24 @@ export function GameList() {
|
||||
const [remoteId, setRemoteId] = useState(0);
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const fetchGames = () => {
|
||||
apiFetch("/api/games")
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((buffer) => {
|
||||
try {
|
||||
const list = GameListProto.decode(new Uint8Array(buffer));
|
||||
setGames(list.games);
|
||||
} catch (e) {
|
||||
console.error("Failed to decode games:", e);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchGames();
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const game = {
|
||||
@@ -37,6 +56,7 @@ export function GameList() {
|
||||
if (res.ok) {
|
||||
setMessage("Game added successfully!");
|
||||
setTitle("");
|
||||
fetchGames();
|
||||
// Reset other fields if needed
|
||||
} else {
|
||||
setMessage("Failed to add game.");
|
||||
@@ -121,6 +141,17 @@ export function GameList() {
|
||||
</label>
|
||||
<button type="submit">Add Game</button>
|
||||
</form>
|
||||
|
||||
<div style={{ marginTop: "2rem" }}>
|
||||
<h3>Existing Games</h3>
|
||||
<ul>
|
||||
{games.map((game) => (
|
||||
<li key={game.title}>
|
||||
{game.title} ({game.source === Source.STEAM ? "Steam" : "Roblox"})
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,32 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Person, AddOpinionRequest } from "../items";
|
||||
import { Person, AddOpinionRequest, Game, GameList } from "../items";
|
||||
import { apiFetch } from "./api";
|
||||
|
||||
export const PersonDetails = () => {
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const [person, setPerson] = useState<Person | null>(null);
|
||||
const [games, setGames] = useState<Game[]>([]);
|
||||
const [gameTitle, setGameTitle] = useState("");
|
||||
const [wouldPlay, setWouldPlay] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
apiFetch("/api/games")
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((buffer) => {
|
||||
try {
|
||||
const list = GameList.decode(new Uint8Array(buffer));
|
||||
setGames(list.games);
|
||||
if (list.games.length > 0) {
|
||||
setGameTitle(list.games[0].title);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to decode games:", e);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (name) {
|
||||
apiFetch(`/api/${name}`)
|
||||
@@ -76,12 +94,16 @@ export const PersonDetails = () => {
|
||||
>
|
||||
<h3>Add Opinion</h3>
|
||||
<div style={{ display: "flex", gap: "1rem", alignItems: "center" }}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Game Title"
|
||||
<select
|
||||
value={gameTitle}
|
||||
onChange={(e) => setGameTitle(e.target.value)}
|
||||
/>
|
||||
>
|
||||
{games.map((g) => (
|
||||
<option key={g.title} value={g.title}>
|
||||
{g.title}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
|
||||
Reference in New Issue
Block a user