game_list/frontend/src/GameDetails.tsx

70 lines
2.0 KiB
TypeScript

import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { Game, Source } from "../items";
import { apiFetch } from "./api";
export function GameDetails() {
const { title } = useParams<{ title: string }>();
const [game, setGame] = useState<Game | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!title) return;
apiFetch(`/api/game/${encodeURIComponent(title)}`)
.then(async (res) => {
if (!res.ok) throw new Error("Game not found");
return Game.decode(new Uint8Array(await res.arrayBuffer()));
})
.then((data) => {
setGame(data);
setLoading(false);
})
.catch((err) => {
console.error(err);
setLoading(false);
});
}, [title]);
if (loading) return <div>Loading...</div>;
if (!game) return <div>Game not found</div>;
const getExternalLink = () => {
if (game.source === Source.STEAM) {
return `https://store.steampowered.com/app/${game.remoteId}`;
} else if (game.source === Source.ROBLOX) {
return `https://www.roblox.com/games/${game.remoteId}`;
}
return "#";
};
return (
<div className="card" style={{ maxWidth: "600px", margin: "0 auto" }}>
<h2>{game.title}</h2>
<div style={{ display: "grid", gap: "1rem", marginTop: "1rem" }}>
<div>
<strong>Source:</strong>{" "}
{game.source === Source.STEAM ? "Steam" : "Roblox"}
</div>
<div>
<strong>Players:</strong> {game.minPlayers} - {game.maxPlayers}
</div>
<div>
<strong>Price:</strong> ${game.price}
</div>
</div>
<div style={{ marginTop: "2rem" }}>
<a
href={getExternalLink()}
target="_blank"
rel="noopener noreferrer"
className="btn-primary"
style={{ textDecoration: "none", display: "inline-block" }}
>
View on {game.source === Source.STEAM ? "Steam" : "Roblox"}
</a>
</div>
</div>
);
}