"use client" // Delt header + fane-rad for Score/Scorekort/Leaderboard (ADR-040 // Beslutning C/D, "det store grepet"). Presentasjon fra V0 (zip 26), // tatt inn UENDRET (rent visuelt/strukturelt, ingen ekte logikk å // bytte ut -- selve rundedataen og handlingene wires inn av // `round-page-shell.tsx`, som eier ekte henting/POST/DELETE). import { useEffect, useRef, useState } from "react" import { createPortal } from "react-dom" import Link from "next/link" import { ArrowLeft, CalendarDays, CheckCircle2, Clock, Flag, MapPin, Settings2, Trash2, Users, X, } from "lucide-react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" // --- Types ----------------------------------------------------------------- export type RoundTab = "score" | "scorecard" | "leaderboard" export type RoundHeaderInfo = { /** Course name — always known. Shown as heading unless a customName exists. */ courseName: string /** Optional custom round name; when set it becomes the heading and the * course name drops to a secondary line. */ customName?: string teeName: string date: string /** Optional tee time, e.g. "09:20". */ teeTime?: string /** Head-to-head match-play round → shows the outlined "Matchspill" badge. */ isMatchPlay?: boolean } type RoundHeaderProps = { activeTab: RoundTab round: RoundHeaderInfo /** Where the back button navigates (out of the round entirely). */ backHref?: string /** Per-tab destinations. When omitted, tabs render as inert buttons * (useful for isolated previews). */ tabHrefs?: Record /** Destination for the round-management screen ("Spillere og runde"). */ manageHref?: string /** Mock admin actions. */ onFinishRound?: () => void onDeleteRound?: () => void className?: string } const TABS: { key: RoundTab; label: string }[] = [ { key: "score", label: "Score" }, { key: "scorecard", label: "Scorekort" }, { key: "leaderboard", label: "Leaderboard" }, ] // --- Shared header --------------------------------------------------------- export function RoundHeader({ activeTab, round, backHref = "/rounds", tabHrefs, manageHref = "#", onFinishRound, onDeleteRound, className, }: RoundHeaderProps) { const [manageOpen, setManageOpen] = useState(false) const heading = round.customName ?? round.courseName // Only show the course name as a secondary line when a custom name replaced it. const showCourseLine = Boolean(round.customName) return (
{/* Row 1: back + identity + manage */}
{/* Row 2: three-tab segmented control */}
{manageOpen && ( setManageOpen(false)} onFinishRound={onFinishRound} onDeleteRound={onDeleteRound} /> )}
) } // --- Management dialog ----------------------------------------------------- function ManageRoundDialog({ manageHref, onClose, onFinishRound, onDeleteRound, }: { manageHref: string onClose: () => void onFinishRound?: () => void onDeleteRound?: () => void }) { const closeRef = useRef(null) const [confirmDelete, setConfirmDelete] = useState(false) const [mounted, setMounted] = useState(false) // Escape to close + focus the close button on open + lock scroll. useEffect(() => { setMounted(true) closeRef.current?.focus() const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose() } document.addEventListener("keydown", onKey) const prevOverflow = document.body.style.overflow document.body.style.overflow = "hidden" return () => { document.removeEventListener("keydown", onKey) document.body.style.overflow = prevOverflow } }, [onClose]) if (!mounted) return null // Portal to so the fixed overlay isn't trapped by the header's // backdrop-filter containing block. return createPortal(
, document.body, ) }