"use client"; import { useEffect, useState } from "react"; import { signOut } from "next-auth/react"; type Game = { id: string; mode: string; startArticle: string; targetArticle: string; path: string[]; clicks: number; timeSeconds: number; won: boolean; playedAt: string; }; type Stats = { total: number; won: number; avgClicks: number; avgTime: number; bestClicks: number; bestTime: number; }; function fmt(s: number): string { const m = Math.floor(s / 60); const sec = Math.floor(s % 60); return `${m}:${String(sec).padStart(2, "0")}`; } function computeStats(games: Game[]): Stats { const won = games.filter((g) => g.won); return { total: games.length, won: won.length, avgClicks: won.length ? Math.round(won.reduce((s, g) => s + g.clicks, 0) / won.length) : 0, avgTime: won.length ? won.reduce((s, g) => s + g.timeSeconds, 0) / won.length : 0, bestClicks: won.length ? Math.min(...won.map((g) => g.clicks)) : 0, bestTime: won.length ? Math.min(...won.map((g) => g.timeSeconds)) : 0, }; } export function ProfileScreen({ userName, onBack }: { userName: string; onBack: () => void }) { const [games, setGames] = useState([]); const [loading, setLoading] = useState(true); const [filter, setFilter] = useState<"all" | "solo" | "multi">("all"); const [confirmDelete, setConfirmDelete] = useState(false); const [deleting, setDeleting] = useState(false); async function handleDeleteAccount() { setDeleting(true); await fetch("/api/account", { method: "DELETE" }); await signOut({ redirect: false }); onBack(); } useEffect(() => { fetch("/api/games") .then((r) => r.json()) .then((data) => setGames(data as Game[])) .finally(() => setLoading(false)); }, []); const filtered = filter === "all" ? games : games.filter((g) => g.mode === filter); const stats = computeStats(filtered); const statCard = "bg-[#1a1a1a] border border-[#2e2e2e] rounded-xl p-3 sm:p-3.5 text-center flex flex-col gap-1"; const btnGhost = "min-h-9 px-3 rounded-lg text-xs sm:text-sm font-semibold bg-[#242424] border border-[#2e2e2e] text-[#f0f0f0] hover:bg-[#1a1a1a] cursor-pointer transition-colors"; return (
{/* Header */}
{userName[0].toUpperCase()}

{userName}

{/* Stats grid */}
{stats.total} Parties
{stats.won} Victoires
{stats.avgClicks > 0 ? stats.avgClicks : "-"} Clics moy.
{stats.avgTime > 0 ? fmt(stats.avgTime) : "-"} Temps moy.
{stats.bestClicks > 0 ? stats.bestClicks : "-"} Meilleur clics
{stats.bestTime > 0 ? fmt(stats.bestTime) : "-"} Meilleur temps
{/* Filters */}
{(["all", "solo", "multi"] as const).map((f) => ( ))}
{/* Game list */}
{loading && (
Chargement...
)} {!loading && filtered.length === 0 && (

Aucune partie enregistrée.

)} {filtered.map((g) => (
{g.mode === "solo" ? "Solo" : "Multi"} {new Date(g.playedAt).toLocaleDateString("fr-FR")} {g.won ? "Victoire" : "Abandon"}
{g.startArticle} {g.targetArticle}
{g.won && (
{g.clicks} clics {fmt(g.timeSeconds)} {g.path.length - 1} articles
)} {g.path.length > 0 && (
{g.path.map((t, i) => ( {i > 0 && } {t} ))}
)}
))}
{/* Mes données */}

Mes données

Télécharge toutes tes données personnelles (RGPD).

Télécharger (.json)
{/* Danger zone */}

Zone dangereuse

{!confirmDelete ? (

Supprime définitivement ton compte et toutes tes parties.

) : (

⚠ Cette action est irréversible. Toutes tes données seront supprimées.

)}
); }