"use client"; import { cancelReveal, finishReveal, revealNext, setVisibility, startReveal } from "@/app/admin/live-actions"; import { Button, buttonClass } from "@/components/ui/button"; import { formatScore } from "@/lib/criteria"; import type { LiveView } from "@/lib/live-view"; import type { Visibility } from "@/lib/scoreboard"; import { ErrorText } from "./error-text"; import { useAction } from "./use-action"; export const VISIBILITY_ORDER: Visibility[] = ["visible", "frozen", "hidden"]; const options: Record = { visible: { action: "Show scores", state: "Visible", explain: "The room sees live scores." }, frozen: { action: "Freeze scores", state: "Frozen", explain: "The room sees the scores from the moment you froze them.", }, hidden: { action: "Hide scores", state: "Hidden", explain: "The room sees team names only, no scores." }, }; const ordinal = (rank: number) => { const suffix = rank % 100 >= 11 && rank % 100 <= 13 ? "th" : (["th", "st", "nd", "rd"][rank % 10] ?? "th"); return `${rank}${suffix}`; }; export function ScoreboardPanel({ view }: { view: LiveView }) { const { event, reveal, teams } = view; const { pending, error, run } = useAction(); const nextTeam = reveal.next ? teams.find((team) => team.id === reveal.next?.teamId) : undefined; return (
{reveal.active ? (

Reveal mode · {reveal.revealedCount} of {teams.length} revealed. {" "} {reveal.next ? ( // Only the host sees who is next, so they can build it up out loud. <> Next: {ordinal(reveal.next.rank)} place — {nextTeam?.name} ( {formatScore(reveal.next.total)}) ) : ( "Every team is revealed." )}

{reveal.next && ( )}
) : ( <>
{VISIBILITY_ORDER.map((visibility) => { const selected = event.visibility === visibility; return ( ); })}

{options[event.visibility].explain}

)}
Open scoreboard {!reveal.active && ( )}
{error && (
{error}
)}
); }