teecup/frontend/components/round-card.tsx

235 lines
9.1 KiB
TypeScript
Raw Normal View History

V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
import Link from "next/link"
import { CalendarDays, ChevronRight, Flag, Gauge, MapPin, Medal, Trophy, Users } from "lucide-react"
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
import { cn } from "@/lib/utils"
export type RoundStatus = "active" | "completed"
export type Round = {
id: string
name?: string | null
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
courseName: string
status: RoundStatus
teeName: string
holes: 9 | 18
date: string
playerCount: number
// Progress for rounds still in play.
holesPlayed?: number
// Owner's score, present once at least one hole is recorded.
totalScore?: number
toPar?: number
// Handicap differential, only when a completed round counted (one decimal).
differential?: number | null
// Lowest score-to-par among the viewer's own completed rounds (computed
// by the caller across the full rounds list, not by the card itself).
isPersonalBest?: boolean
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
}
const STATUS_CONFIG: Record<RoundStatus, { label: string; dot: string; badge: string }> = {
active: {
label: "Pågår",
dot: "bg-primary",
badge: "bg-primary/15 text-foreground",
},
completed: {
label: "Fullført",
dot: "bg-brand-orange",
badge: "bg-brand-orange/12 text-foreground",
},
}
const dateFormatter = new Intl.DateTimeFormat("no-NO", {
day: "numeric",
month: "short",
year: "numeric",
})
function formatDate(value: string) {
const parsed = new Date(value)
if (Number.isNaN(parsed.getTime())) return value
return dateFormatter.format(parsed)
}
// "+10", "-2" or "E" for level par. The sign carries the meaning (never color alone).
function formatToPar(toPar: number) {
if (toPar === 0) return "E"
return toPar > 0 ? `+${toPar}` : `${toPar}`
}
function toParDescription(toPar: number) {
if (toPar === 0) return "på par"
return toPar > 0 ? `${toPar} over par` : `${Math.abs(toPar)} under par`
}
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
function RoundStatusBadge({ status }: { status: RoundStatus }) {
const config = STATUS_CONFIG[status]
return (
<span
className={cn(
"inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-sm font-semibold",
config.badge,
)}
>
<span className={cn("size-2 rounded-full", config.dot)} aria-hidden="true" />
{config.label}
</span>
)
}
// Prominent right-side tile: final score for completed/scored rounds,
// hole progress for rounds still in play.
function ScoreTile({ round }: { round: Round }) {
const hasScore = typeof round.totalScore === "number" && typeof round.toPar === "number"
if (round.status === "active" || !hasScore) {
const played = round.holesPlayed ?? 0
const pct = round.holes > 0 ? Math.min(100, Math.round((played / round.holes) * 100)) : 0
return (
<div className="flex w-24 shrink-0 flex-col items-center gap-1.5 rounded-2xl bg-secondary px-3 py-3 sm:w-28">
<span className="text-2xl font-extrabold leading-none tabular-nums text-foreground">
{played}
<span className="text-base font-bold text-muted-foreground">/{round.holes}</span>
</span>
<span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
hull spilt
</span>
<div
className="mt-0.5 h-1.5 w-full overflow-hidden rounded-full bg-border"
role="progressbar"
aria-valuenow={played}
aria-valuemin={0}
aria-valuemax={round.holes}
aria-label={`${played} av ${round.holes} hull spilt`}
>
<div className="h-full rounded-full bg-primary" style={{ width: `${pct}%` }} />
</div>
</div>
)
}
const toPar = round.toPar as number
const overPar = toPar > 0
const underPar = toPar < 0
return (
<div className="flex w-24 shrink-0 flex-col items-center gap-1 rounded-2xl bg-secondary px-3 py-3 sm:w-28">
<span className="text-3xl font-extrabold leading-none tabular-nums text-foreground">
{round.totalScore}
</span>
<span
className={cn(
"inline-flex items-center rounded-full px-2.5 py-0.5 text-base font-bold tabular-nums",
underPar && "bg-primary/20 text-foreground",
overPar && "bg-brand-orange/20 text-foreground",
!underPar && !overPar && "bg-muted text-foreground",
)}
>
{formatToPar(toPar)}
</span>
<span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
til par
</span>
</div>
)
}
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
export function RoundCard({ round }: { round: Round }) {
const playerLabel = round.playerCount === 1 ? "spiller" : "spillere"
const hasScore = typeof round.totalScore === "number" && typeof round.toPar === "number"
const showDifferential =
round.status === "completed" &&
typeof round.differential === "number" &&
round.differential !== null
const differentialText =
showDifferential && round.differential != null
? round.differential.toFixed(1).replace(".", ",")
: null
const showPersonalBest = round.status === "completed" && round.isPersonalBest === true
// Concise summary so the compact score tile reads clearly for screen readers.
const scoreSummary =
round.status === "completed" && hasScore
? `Resultat ${round.totalScore} slag, ${toParDescription(round.toPar as number)}.`
: `${round.holesPlayed ?? 0} av ${round.holes} hull spilt.`
const displayTitle = round.name?.trim() || round.courseName
const ariaLabel = `${displayTitle}, ${STATUS_CONFIG[round.status].label}. ${scoreSummary}`
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
return (
// Egen ytre wrapper (2026-07-26) -- kortet var tidligere HELE selve
// lenken til rundesiden; en leaderboard-lenke kan derfor ikke ligge
// NESTET inni den (ugyldig HTML, samme klasse feil som tidligere
// nestede-form-/knapp-feller i prosjektet). Hovedinnholdet er fortsatt
// én stor lenke til rundesiden, leaderboard-lenken en egen, separat
// rad under.
<div className="flex flex-col gap-2">
<Link
href={`/my-rounds/${round.id}`}
aria-label={ariaLabel}
className="group flex min-h-[88px] w-full items-center gap-4 rounded-2xl border border-border bg-card p-4 text-left shadow-sm shadow-black/5 transition-colors hover:border-primary/60 hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:p-5"
>
<div className="flex min-w-0 flex-1 flex-col gap-3">
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
<h3 className="flex min-w-0 items-center gap-2 text-lg font-bold text-foreground">
<MapPin aria-hidden="true" className="size-5 shrink-0 text-primary" />
<span className="truncate">{displayTitle}</span>
</h3>
<RoundStatusBadge status={round.status} />
{showPersonalBest && (
<span className="inline-flex items-center gap-1.5 rounded-full bg-gold/20 px-2.5 py-1 text-xs font-bold text-foreground">
<Medal aria-hidden="true" className="size-3.5 text-gold" />
Personlig rekord
</span>
)}
</div>
<div className="flex flex-wrap items-center gap-x-5 gap-y-1.5 text-base text-muted-foreground">
{round.name?.trim() && <span className="truncate">{round.courseName}</span>}
<span className="flex items-center gap-1.5">
<Flag aria-hidden="true" className="size-4 shrink-0" />
<span>
{round.teeName} · {round.holes} hull
</span>
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
</span>
<span className="flex items-center gap-1.5">
<CalendarDays aria-hidden="true" className="size-4 shrink-0" />
<span className="tabular-nums">{formatDate(round.date)}</span>
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
</span>
<span className="flex items-center gap-1.5">
<Users aria-hidden="true" className="size-4 shrink-0" />
<span>
{round.playerCount} {playerLabel}
</span>
</span>
{differentialText && (
<span className="inline-flex items-center gap-1.5 rounded-full bg-info/15 px-2.5 py-0.5 text-sm font-semibold text-foreground">
<Gauge aria-hidden="true" className="size-4 shrink-0 text-info" />
<span className="tabular-nums">Hcp spilt til {differentialText}</span>
</span>
)}
</div>
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
</div>
<ScoreTile round={round} />
<ChevronRight
aria-hidden="true"
className="size-6 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground"
/>
</Link>
{/* Leaderboard-lenke (2026-07-26) -- kun meningsfullt med flere enn
én deltaker. Vises for BÅDE pågående og fullførte runder (en
fullført rundes sluttstilling er fortsatt nyttig å se). */}
{round.playerCount > 1 && (
<Link
href={`/my-rounds/${round.id}/leaderboard`}
className="flex min-h-11 items-center gap-1.5 self-start rounded-xl px-4 text-sm font-semibold text-primary transition-colors hover:bg-primary/10"
>
<Trophy aria-hidden="true" className="size-4" />
Se leaderboard
</Link>
)}
</div>
V0-integrasjonen er ferdig. Kort om hva som skjedde: Diff mot levende tre (samme rutine som alltid): alle tre eksportene var fulle re-eksporter av hele prosjektet, bare fire filer var faktisk nye/endret for dette formålet: round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx (+ tre app/rounds*/page.tsx-ruter). Alt annet (login-form, dashboard, config osv.) var forventede full-reverts og ble ikke rørt. Ett kjent V0-avvik dukket opp igjen (app/clubs/[id]/page.tsx med feil parameternavn — samme feil som ble rettet i klubbsiderunden) — hoppet bevisst over den, som vanlig. Erstattet mine hånd-bygde skjermer med V0s presentasjon, datalag skrevet om fra mock til ekte fetch, blant annet: Egen-bane-søket er nå et ekte to-stegs oppslag (søk → hent detalj med utslag) siden V0s modell antok baner allerede hadde utslagene ferdig innbakt i søkeresultatet. La til «Annet» som et tredje kjønnsvalg for gjestespillere (V0 hadde kun mann/kvinne) — matcher appens ellers etablerte konvensjon. Beholdt merge-før-PATCH-sikringen fra forrige runde (hull-endepunktet skriver alle felt hver gang). Fjernet V0s dev-only forhåndsvisningsbrytere («Forhåndsvis: Pågår/Fullført» osv.) — samme opprydning som i tidligere runder. Verifisert: ekte typesjekket produksjonsbuild (docker build --target builder) kompilerte rent, alle ruter listet. Ingen backend-endring i denne runden, så API-kontrakten er allerede scratch-bevist fra forrige runde — jeg har ikke kjørt en ny interaktiv nettleser-test (intet slikt verktøy tilgjengelig), kun kodegjennomgang + typesjekk. Zip-filene er slettet fra prosjektroten.
2026-07-23 11:27:37 +02:00
)
}