"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { GAME_META, GAMES, GameId } from "@/lib/levels"; import { loadStats, GameStats } from "@/lib/stats"; import { allStats as allLevelStats, GameStats as LevelStats } from "@/lib/progress"; function fmt(s: number): string { if (s === 0) return "--:--"; return `${String(Math.floor(s / 60)).padStart(2, "0")}:${String(s % 60).padStart(2, "0")}`; } function getDaysRange(days: number): string[] { const result: string[] = []; const today = new Date(); for (let i = days - 1; i >= 0; i--) { const d = new Date(today); d.setDate(d.getDate() - i); result.push(`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`); } return result; } // ── Heatmap ─────────────────────────────────────────────────────────────────── function Heatmap({ game, solvedDates, accent }: { game: GameId; solvedDates: string[]; accent: string }) { const days = getDaysRange(91); // 13 weeks const solvedSet = new Set(solvedDates); // Group by weeks (7 days per column) const weeks: string[][] = []; for (let i = 0; i < days.length; i += 7) { weeks.push(days.slice(i, i + 7)); } return (
{weeks.map((week, wi) => (
{week.map(day => { const solved = solvedSet.has(day); return (
); })}
))}
); } // ── Game stat card ──────────────────────────────────────────────────────────── function GameStatCard({ game, dailyStats, levelStats, }: { game: GameId; dailyStats: GameStats; levelStats: LevelStats | undefined; }) { const { name, accent, symbol, subtitle } = GAME_META[game]; return (
{/* Header */}
{symbol}

{name}

{subtitle}

{/* Daily stats */}
Série {dailyStats.streak}j
Total {dailyStats.total}
Record {fmt(dailyStats.bestTime)}
{/* Heatmap (last 13 weeks) */} {dailyStats.solvedDates && dailyStats.solvedDates.length > 0 ? (

13 dernières semaines

) : (

Joue ta première partie pour voir l'historique

)} {/* Level progress */} {levelStats && levelStats.completed > 0 && (
{levelStats.completed}/100 niv. Continuer →
)}
); } // ── Main page ───────────────────────────────────────────────────────────────── export default function StatsPage() { const [dailyStats, setDailyStats] = useState | null>(null); const [levelStatsAll, setLevelStatsAll] = useState | null>(null); useEffect(() => { const ds = {} as Record; for (const g of GAMES) ds[g] = loadStats(g); setDailyStats(ds); setLevelStatsAll(allLevelStats()); }, []); const totalDaily = dailyStats ? GAMES.reduce((sum, g) => sum + (dailyStats[g]?.total ?? 0), 0) : 0; const bestStreak = dailyStats ? Math.max(...GAMES.map(g => dailyStats[g]?.streak ?? 0)) : 0; return (
{/* Header */}

Mes statistiques

Puzzles quotidiens & entraînement

{/* Summary strip */} {dailyStats && (

{totalDaily}

puzzles résolus

🔥

{bestStreak}

meilleure série

)} {/* Per-game cards */} {dailyStats ? (
{GAMES.map(game => ( ))}
) : (
{[...Array(5)].map((_, i) => (
))}
)} ← Retour aux puzzles du jour
); }