ux improvements
This commit is contained in:
@@ -3,53 +3,78 @@ import { Link, useParams } from "react-router-dom";
|
||||
import { Person } from "../items";
|
||||
import { apiFetch } from "./api";
|
||||
import { GameImage } from "./GameImage";
|
||||
import { LoadingState, EmptyState } from "./components/EmptyState";
|
||||
|
||||
export const PersonDetails = () => {
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const [person, setPerson] = useState<Person | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (name) {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
apiFetch(`/api/${name}`)
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error("Person not found");
|
||||
}
|
||||
return res.arrayBuffer();
|
||||
})
|
||||
.then((buffer) => {
|
||||
try {
|
||||
setPerson(Person.decode(new Uint8Array(buffer)));
|
||||
} catch (e) {
|
||||
console.error("Failed to decode person:", e);
|
||||
throw new Error("Failed to load person data");
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
setError(err.message || "Failed to load person");
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
}
|
||||
}, [name]);
|
||||
|
||||
if (!person) return <div>Loading...</div>;
|
||||
if (loading) return <LoadingState message="Loading person details..." />;
|
||||
if (error) return <EmptyState icon="⚠️" title="Error" description={error} />;
|
||||
if (!person) return <EmptyState icon="👤" title="Person not found" description="This person doesn't exist" />;
|
||||
|
||||
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>
|
||||
{person.opinion.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="🎮"
|
||||
title="No opinions yet"
|
||||
description={`${person.name} hasn't shared any game opinions`}
|
||||
/>
|
||||
) : (
|
||||
<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>
|
||||
<GameImage game={op.title} />
|
||||
</Link>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user