"use client"; import { useState } from "react"; import Link from "next/link"; import { Crown, Trophy, EyeOff, Info } from "lucide-react"; import type { LeaderboardView, LeaderboardEntry } from "@spinza/shared"; import { formatMultiplier, formatSC } from "@spinza/shared"; import { useSession } from "@/lib/store"; import { useApi } from "@/lib/use-api"; import { cn, timeAgo } from "@/lib/utils"; import { Card, Empty, Skeleton, Tabs } from "@/components/ui"; import { AppShell } from "@/components/shell/app-shell"; import { ApiErrorState } from "@/components/shell/api-error"; const CATEGORIES = [ { value: "biggest_win_today", label: "Biggest Win Today", short: "Today" }, { value: "biggest_win_week", label: "Biggest Win This Week", short: "This Week" }, { value: "biggest_multiplier", label: "Biggest Multiplier", short: "Multiplier" }, { value: "most_spins", label: "Most Spins", short: "Spins" }, { value: "highest_level", label: "Highest Level", short: "Level" }, ] as const; type Category = (typeof CATEGORIES)[number]["value"]; function formatValue(cat: Category, v: number): string { switch (cat) { case "biggest_multiplier": return formatMultiplier(v); case "most_spins": return `${Math.round(v).toLocaleString("en-US")} spins`; case "highest_level": return `Level ${Math.round(v)}`; default: return formatSC(v); } } function Avatar({ name, rank, size = "md" }: { name: string; rank: number; size?: "md" | "lg" }) { const ring = rank === 1 ? "ring-2 ring-accent shadow-glow" : rank === 2 ? "ring-2 ring-[#c7ccd8]" : rank === 3 ? "ring-2 ring-[#b87b4b]" : "ring-1 ring-line-2"; return ( {name.slice(0, 1)} ); } function Podium({ entries, cat }: { entries: LeaderboardEntry[]; cat: Category }) { const order = [entries[1], entries[0], entries[2]].filter(Boolean) as LeaderboardEntry[]; if (!entries.length) return null; return (
{order.map((e) => { const first = e.rank === 1; return (
{first ? : null} {e.rank}
{e.isYou ? "You" : e.username}
Level {e.level}
{formatValue(cat, e.value)}
{e.game ?
{e.game}
: null}
); })}
); } export default function LeaderboardPage() { const [cat, setCat] = useState("biggest_win_today"); const { data, error, loading, reload } = useApi(`/api/leaderboards?category=${cat}`); const status = useSession((s) => s.status); const optIn = useSession((s) => s.settings?.leaderboardOptIn ?? true); const entries = data?.entries ?? []; const rest = entries.slice(3); return (
Leaderboard

{data?.label || CATEGORIES.find((c) => c.value === cat)?.label}

Bragging rights only. All values are in fictional Spinza Credits or gameplay stats — nothing is ever paid out.

value={cat} onChange={setCat} items={CATEGORIES.map((c) => ({ value: c.value, label: c.short }))} />
{status === "authenticated" && !optIn ? (

You have opted out of leaderboards, so your results are hidden from other players.{" "} Change in settings

) : null} {error && !data ? ( ) : loading && !data ? (
{Array.from({ length: 6 }).map((_, i) => ( ))}
) : !entries.length ? ( } /> ) : (
{rest.length ? ( {rest.map((e) => (
  • {e.rank}
    {e.isYou ? `${e.username} (you)` : e.username}
    Level {e.level} {e.game ? ` · ${e.game}` : ""}
    {formatValue(cat, e.value)}
  • ))}
    ) : null} {status === "authenticated" ? ( data?.you && !entries.some((e) => e.isYou) ? ( {data.you.rank}
    {data.you.username} (you)
    Level {data.you.level}
    {formatValue(cat, data.you.value)}
    ) : !data?.you ? (

    {optIn ? "You are not on this board yet. Play a few rounds to enter." : "Opt back in to appear on leaderboards."}

    ) : null ) : (

    Sign in {" "} to see where you rank.

    )} {data?.updatedAt ?

    Updated {timeAgo(data.updatedAt)}

    : null}
    )}

    Privacy: leaderboards show your username, level and result only. You can leave all leaderboards at any time from{" "} Settings → Leaderboard participation . Spinza never shares data with third parties.

    ); }