import { useEffect, useState } from "react"; import { Award } from "lucide-react"; import { Link, useSearchParams } from "react-router-dom"; import { getVisitorEventLeaderboard } from "../lib/api"; import { getAttendeeToken } from "../lib/attendeeAuth"; import { HeaderMobile } from "../components/HeaderMobile"; import { MobileShell } from "../components/MobileShell"; import { readStoredVisitorContext } from "../types/visitorContext"; import type { VisitorLeaderboardRow } from "../lib/api"; function Medal({ tier }: { tier: "gold" | "silver" | "bronze" }) { const cls = tier === "gold" ? "text-amber-500" : tier === "silver" ? "text-slate-400" : "text-amber-800"; return ; } function medalForRank(rank: number): "gold" | "silver" | "bronze" | null { if (rank === 1) return "gold"; if (rank === 2) return "silver"; if (rank === 3) return "bronze"; return null; } export function LeaderboardPage() { const [searchParams] = useSearchParams(); const urlEventId = searchParams.get("event_id")?.trim() || ""; const ctx = readStoredVisitorContext(); const eventId = urlEventId || ctx?.eventId || ""; const [rows, setRows] = useState([]); const [yourRank, setYourRank] = useState(null); const [yourTotal, setYourTotal] = useState(null); const [loading, setLoading] = useState(false); const [err, setErr] = useState(null); useEffect(() => { if (!eventId) { setRows([]); setYourRank(null); setYourTotal(null); return; } let cancelled = false; setLoading(true); setErr(null); getVisitorEventLeaderboard(eventId, { limit: 50 }) .then((r) => { if (cancelled) return; setRows(r.leaderboard); if (getAttendeeToken()) { const y = r.your; setYourRank(y?.rank ?? null); setYourTotal(typeof y?.total === "number" ? y.total : null); } else { setYourRank(null); setYourTotal(null); } }) .catch((e) => { if (!cancelled) setErr(e instanceof Error ? e.message : "Could not load leaderboard."); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [eventId]); const top5 = rows.slice(0, 5); const signedIn = Boolean(getAttendeeToken()); return (

Leaderboard

Your rank

{!signedIn ? "—" : loading ? "…" : yourRank != null ? yourRank : "—"} {!signedIn ? "Sign in" : loading ? "…" : yourTotal != null ? `${yourTotal} points` : "0 points"}

Top participants

{err ? (

{err}

) : loading && rows.length === 0 ? (

Loading…

) : top5.length === 0 ? (

No scores yet. Complete activities and earn points when organizers enable rewards.

) : (
    {top5.map((row) => { const medal = medalForRank(row.rank); return (
  • #{row.rank} · {row.total} pts {row.displayName} {medal ? : null}
  • ); })}
)}
Rewards
); }