import { useMemo, useState } from "react"; import { Avatar } from "../components/Avatar"; import { PlayerLink } from "../components/PlayerLink"; import { Spinner } from "../components/Spinner"; import type { LeaderboardEntry } from "../domain/types"; import { useLeaderboard } from "../hooks/stats"; type SortKey = "rank" | "games" | "wins" | "win_rate" | "score"; function pct(v: number | null | undefined): string { return v == null ? "—" : `${Math.round(v * 100)}%`; } export function OverallStatsPage() { const { data, isLoading, isError } = useLeaderboard(200); const [q, setQ] = useState(""); const [sortKey, setSortKey] = useState("rank"); const [dir, setDir] = useState<1 | -1>(1); // 1 — по возрастанию const toggleSort = (k: SortKey) => { if (k === sortKey) setDir((d) => (d === 1 ? -1 : 1)); else { setSortKey(k); setDir(k === "rank" ? 1 : -1); // для метрик по умолчанию «лучшие сверху» } }; const filterSort = useMemo(() => { const needle = q.trim().toLowerCase(); const num = (e: LeaderboardEntry) => Number(e[sortKey] ?? 0); return (list: LeaderboardEntry[]) => list .filter((e) => e.nickname.toLowerCase().includes(needle)) .sort((a, b) => (num(a) - num(b)) * dir); }, [q, sortKey, dir]); if (isLoading) return ; if (isError || !data) return
Не удалось загрузить статистику.
; const entries = filterSort(data.entries); const provisional = filterSort(data.provisional); const arrow = (k: SortKey) => (k === sortKey ? (dir === 1 ? " ↑" : " ↓") : ""); const row = (e: LeaderboardEntry, isProvisional = false) => ( {e.rank ?? "—"} {e.nickname} {e.games} {e.wins} {pct(e.win_rate)} {e.score ?? "—"} ); return (
{/* Название страницы уже в верхней панели — в теле сразу поиск. */}
setQ(e.target.value)} />
Игрок
{entries.length === 0 ? (
Никого не найдено.
) : ( entries.map((e) => row(e)) )}
{provisional.length > 0 && (
Новички (меньше {data.min_games} игр)
{provisional.map((e) => row(e, true))}
)}
); }