57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import { useState, useEffect } from "react";
|
|
import { Link, useParams } from "react-router-dom";
|
|
import { Person } from "../items";
|
|
import { apiFetch } from "./api";
|
|
import { GameImage } from "./GameImage";
|
|
|
|
export const PersonDetails = () => {
|
|
const { name } = useParams<{ name: string }>();
|
|
const [person, setPerson] = useState<Person | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (name) {
|
|
apiFetch(`/api/${name}`)
|
|
.then((res) => res.arrayBuffer())
|
|
.then((buffer) => {
|
|
try {
|
|
setPerson(Person.decode(new Uint8Array(buffer)));
|
|
} catch (e) {
|
|
console.error("Failed to decode person:", e);
|
|
}
|
|
})
|
|
.catch(console.error);
|
|
}
|
|
}, [name]);
|
|
|
|
if (!person) return <div>Loading...</div>;
|
|
|
|
return (
|
|
<div>
|
|
<div style={{ marginBottom: "2rem" }}>
|
|
<h2>{person.name}</h2>
|
|
<ul className="grid-container">
|
|
{person.opinion.map((op, i) => (
|
|
<Link
|
|
to={`/game/${encodeURIComponent(op.title)}`}
|
|
key={i}
|
|
className="list-item"
|
|
style={{
|
|
textDecoration: "none",
|
|
color: "inherit",
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
borderColor: op.wouldPlay ? "#4caf50" : "#f44336",
|
|
}}
|
|
>
|
|
<strong>{op.title}</strong>
|
|
|
|
<GameImage game={op.title} />
|
|
</Link>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|