teecup/frontend/components/tournament-status-badge.tsx
Erol Haagenrud 2e9c97c943 Update Todos
Legge til status i TournamentUpdate + enum-cast i update_tournament

Scratch-verifisere status-oppdatering (enum-cast, PATCH-semantikk, validering)

Bygge frontend-UI for å sette turnering-status

Ekte typesjekket frontend-build

Oppdatere .md-filer + deploy etter bekreftelse
2026-07-19 21:51:05 +02:00

93 lines
2.8 KiB
TypeScript

import { ChevronDown } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { cn } from "@/lib/utils"
export type TournamentStatus = "draft" | "active" | "completed" | "archived"
const STATUS_CONFIG: Record<
TournamentStatus,
{ label: string; dot: string; badge: string }
> = {
draft: {
label: "Utkast",
dot: "bg-muted-foreground",
badge: "bg-muted text-foreground",
},
active: {
label: "Aktiv",
dot: "bg-primary",
badge: "bg-primary/15 text-foreground",
},
completed: {
label: "Fullført",
dot: "bg-brand-orange",
badge: "bg-brand-orange/12 text-foreground",
},
archived: {
label: "Arkivert",
dot: "bg-muted-foreground/50",
badge: "border border-border bg-transparent text-muted-foreground",
},
}
export function TournamentStatusBadge({ status }: { status: TournamentStatus }) {
const config = STATUS_CONFIG[status]
return (
<span
className={cn(
"inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold",
config.badge,
)}
>
<span className={cn("size-1.5 rounded-full", config.dot)} aria-hidden="true" />
{config.label}
</span>
)
}
// Redigerbar variant -- lar organisator sette status via PATCH
// /orgs/{id}/tournaments/{id} (ingen egen tilstandsmaskin/overgangsregler,
// samme tillitsnivå som resten av appen). Brukt i tournament-detail.tsx sin
// header; den skrivebeskyttede TournamentStatusBadge over brukes fortsatt i
// dashbordets read-only kortliste.
export function TournamentStatusPicker({
status,
onChange,
}: {
status: TournamentStatus
onChange: (status: TournamentStatus) => void
}) {
const config = STATUS_CONFIG[status]
return (
<DropdownMenu>
<DropdownMenuTrigger
aria-label="Endre turnering-status"
className={cn(
"inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold transition-opacity hover:opacity-80",
config.badge,
)}
>
<span className={cn("size-1.5 rounded-full", config.dot)} aria-hidden="true" />
{config.label}
<ChevronDown aria-hidden="true" className="size-3" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-40 rounded-2xl p-1.5">
{(Object.keys(STATUS_CONFIG) as TournamentStatus[]).map((s) => (
<DropdownMenuItem
key={s}
onClick={() => onChange(s)}
className="flex cursor-pointer items-center gap-2 rounded-xl px-3 py-2.5 text-sm font-semibold"
>
<span className={cn("size-1.5 rounded-full", STATUS_CONFIG[s].dot)} aria-hidden="true" />
{STATUS_CONFIG[s].label}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)
}