From 1867c65143c466583c6c7006c157c267069fcdc7 Mon Sep 17 00:00:00 2001
From: Erol Haagenrud
Date: Tue, 18 Aug 2026 20:18:47 +0200
Subject: [PATCH] Turneringsoppsett som steg-wizard (ADR-092)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Oppsett-fanen var én lang stablet side med alle kort etter hverandre.
Omgjort til 6 klikkbare steg med fri navigasjon, strukturelt inspirert
av Golf GameBooks steg-navigasjon (ikke visuelt -- egne clubhouse-
tokens). Grupper og startliste er det eneste genuint nye steget,
løfter Utslagsgrupper ut av å være gjemt inni hver enkelt runde.
Co-Authored-By: Claude Sonnet 5
---
ARCHITECTURE_DECISIONS.md | 83 +++++
CHANGELOG.md | 36 +++
.../individual-tournament-detail.tsx | 297 ++++++++++--------
.../components/round-groups-step-list.tsx | 66 ++++
frontend/components/tournament-setup-nav.tsx | 71 +++++
5 files changed, 425 insertions(+), 128 deletions(-)
create mode 100644 frontend/components/round-groups-step-list.tsx
create mode 100644 frontend/components/tournament-setup-nav.tsx
diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md
index 496ebe2..217804b 100644
--- a/ARCHITECTURE_DECISIONS.md
+++ b/ARCHITECTURE_DECISIONS.md
@@ -9319,6 +9319,89 @@ allerede fungerer andre steder i appen).
ekte `teecup_db`, deretter `docker compose build teecup_api
teecup_frontend && up -d` for begge. Rene logger, 200 OK.
+## ADR-092: Turneringsoppsett som steg-wizard, strukturelt inspirert av Golf GameBook (2026-08-18)
+
+Bruker viste skjermdumper av Golf GameBooks turneringsoppsett (steg-
+navigasjon: Tournament Setup → Round Setup → Tournament Site → Branding
+→ Entries → Players → Groups and Start List → Results and Options) og
+spurte: "Jeg synes denne delen av TeeCup er veldig lite brukervennlig.
+Kan du hjelpe meg å tenke gjennom dette?" -- TeeCups "Oppsett"-fane
+(`SetupTab` i `individual-tournament-detail.tsx`) var én lang stablet
+side med alle kort etter hverandre (`TournamentSettingsCard` →
+Scoringsmetode → `RoundsCard` → `CutCard`/`TiebreakCard` →
+`ClassesCard` → `ParticipantsCard`), i byggerekkefølge, ikke i en
+rekkefølge en arrangør faktisk tenker gjennom oppsettet i. Bruker
+svarte "Full wizard. Bring gjerne V0 inn", med ett eksplisitt forbehold
+underveis: "Yes, men husk at vi ikke skal ende opp med et plagiat av
+Golf GameBook."
+
+**Struktur, ikke visuell kopi.** GameBook-skjermdumpene ble brukt
+UTELUKKENDE som referanse for selve IA-mønsteret (steg i stedet for én
+lang side), ikke som visuell mal -- V0-prompten instruerte eksplisitt
+om å bruke TeeCups egne clubhouse-fargetoken/`rounded-2xl`-kortstil fra
+`DESIGN_SYSTEM.md`, ingen grønnfarge/ikonsett/spacing hentet fra
+GameBook. Dette var et rent IA-/navigasjonsproblem, ikke et manglende-
+funksjonalitet-problem -- praktisk talt alle felt GameBook viser fantes
+allerede og fungerte. Ingen backend-endring, ingen migrasjon.
+
+**6 steg** (ikke GameBooks 8 -- "Tournament Site"/"Branding" dekkes
+allerede av TeeCups egen frittstående Presentasjon-fane, "Entries" er
+allerede en velfungerende inne-i-kortet-seksjon i `TournamentSettings
+Card` som ikke var verdt å splitte ut av et nylig ferdigstilt kort),
+hver drevet av et kort som allerede fantes og fungerte -- ingen av dem
+trengte V0-rework: Turneringsoppsett (`TournamentSettingsCard`), Runder
+og baner (`RoundsCard`), Klasser (`ClassesCard`), Spillere
+(`ParticipantsCard`), Resultat og opsjoner (Scoringsmetode-seksjonen,
+flyttet hit fra å stå løst øverst siden det er et resultatvalg ikke
+identitet, + `CutCard` + `TiebreakCard`, samme betingede visning som
+før).
+
+**Grupper og startliste er det eneste genuint nye steget.**
+`RoundGroupsPanel` var tidligere gjemt bak en "Utslagsgrupper"-knapp
+inni hver enkelt `RoundCard` (måtte åpne runden først) -- direkte i
+ånden til brukerens opprinnelige klage om at rundene har mye å ta tak i
+mens org-oppsettet har lite. Løftet til et eget toppnivå-steg: ny
+`RoundGroupsStepList`-komponent (V0-generert) lister alle runder
+(sammenhengende liste-mønster, `divide-y`, ikke separate kort) med én
+"Rediger grupper"-knapp per runde som åpner samme `RoundGroupsPanel`
+uendret. Den gamle knappen inni `RoundCard` ble FJERNET (ikke bare
+duplisert) -- to veier til samme handling ville vært akkurat den typen
+duplisering wizarden var ment å rydde opp i.
+
+**Fri navigasjon, ingen låsing.** GameBooks egne skjermdumper viser
+faktisk grønne haker på ALLE 8 steg samtidig som "Tournament name"
+sto tomt i opprettelses-flyten -- hakene er altså ikke ekte fullført-
+validering, bare statisk wizard-pynt. Ny `TournamentSetupNav`
+(V0-generert): alle 6 steg alltid klikkbare i vilkårlig rekkefølge,
+ingen fullført-per-steg-logikk bygget (TeeCup er allerede fleksibelt på
+oppsett-rekkefølge, og en slik validering ble aldri etterspurt). Steget
+er ren `useState` inni `SetupTab`, ikke URL-drevet -- samme mønster som
+de ytre fanene (Oppsett/Scorekort/Leaderboard/Presentasjon) allerede
+bruker.
+
+**Bredde-regresjon funnet og rettet under verifisering:** Oppsett-fanen
+delte tidligere en `max-w-4xl` (896px) sidewrapper med Scorekort/
+Presentasjon-fanene. Ved en lokal scratch-visning på 1440px viste det
+seg at 6 steg-piller IKKE fikk plass side ved side i 896px -- akkurat
+den "stor skjerm først"-egenskapen wizarden skulle innfri (jf. samme
+mønster som leaderboardets `max-w-[110rem]`-unntak fra tidligere denne
+dagen). Fikset med en egen `max-w-6xl`-unntaksbredde for `tab ===
+"setup"` i den delte ternæren i `individual-tournament-detail.tsx`
+sin ``.
+
+**Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55. Lokal scratch-
+visning (`next dev` på port 3100, midlertidig `/setupwizardpreviewtmp`-
+side, ALDRI committet, fjernet etter bruk): alle 6 steg klikkbare og
+viser riktig innhold, Grupper-steget bekreftet å sende riktig runde-id
+videre til panelet (tre varianter testet: dato+bane, kun bane, ingen av
+delene), lys+mørk tema, smal skjerm (390px -- steg-raden scroller
+sidelengs i stedet for å wrappe, som spesifisert, i stedet for feilende
+layout).
+
+**Rullet ut 2026-08-18** -- bruker bekreftet. Ingen migrasjon (ren
+frontend). `docker compose build teecup_frontend && up -d
+teecup_frontend`, rene logger, 200 OK.
+
---
## Utviklingsplan (rekkefølge)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index efd5b7c..50c9914 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12878,3 +12878,39 @@ Neste steg:
**Rullet ut 2026-08-18** -- bruker bekreftet. Migrasjon 087 kjørt mot
ekte `teecup_db`, deretter `docker compose build teecup_api
teecup_frontend && up -d` for begge, rene logger, 200 OK.
+
+123. **Turneringsoppsett som steg-wizard -- 2026-08-18 (ADR-092).**
+ Bruker viste GameBook-skjermdumper: "Jeg synes denne delen av
+ TeeCup er veldig lite brukervennlig ... Full wizard. Bring gjerne
+ V0 inn", med presisering underveis: "husk at vi ikke skal ende opp
+ med et plagiat av Golf GameBook." Oppsett-fanen (`SetupTab`) var én
+ lang stablet side -- omgjort til 6 klikkbare steg (Turnerings-
+ oppsett/Runder og baner/Klasser/Spillere/Grupper og startliste/
+ Resultat og opsjoner), fri navigasjon uten låsing eller fullført-
+ haker (GameBooks egne skjermdumper viste haker på alle steg selv
+ med tomt navnefelt -- ikke ekte validering). Kun to nye V0-
+ komponenter, GameBook brukt UTELUKKENDE som strukturelt forbilde
+ (steg-mønsteret), ikke visuelt -- begge bruker TeeCups egne
+ clubhouse-tokens fra `DESIGN_SYSTEM.md`: `tournament-setup-nav.tsx`
+ (steg-raden) og `round-groups-step-list.tsx` (ny topplassering for
+ "Utslagsgrupper", tidligere gjemt bak en knapp inni hver enkelt
+ runde -- den gamle knappen fjernet, ikke duplisert). Alle 6 stegs
+ faktiske innhold er allerede-eksisterende kort (TournamentSettings
+ Card/RoundsCard/ClassesCard/ParticipantsCard/CutCard/TiebreakCard),
+ kun flyttet til riktig steg -- ingen ny logikk, ingen backend-
+ endring, ingen migrasjon. Fant og fikset en bredde-regresjon
+ underveis: Oppsett delte en `max-w-4xl`-wrapper med Scorekort/
+ Presentasjon som gjorde at 6 steg-piller ikke fikk plass ved siden
+ av hverandre selv på en bred skjerm -- egen `max-w-6xl`-unntaksbredde
+ lagt til (samme mønster som leaderboardets `max-w-[110rem]`-unntak).
+
+ **Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55. Lokal
+ scratch-visning (`next dev`, midlertidig previewside, ALDRI
+ committet, fjernet etter bruk): alle 6 steg klikkbare med riktig
+ innhold, Grupper-steget sender riktig runde-id videre (tre
+ varianter: dato+bane/kun bane/ingen av delene), lys+mørk, smal
+ skjerm (steg-raden scroller sidelengs i stedet for å wrappe/feile).
+
+ **Rullet ut 2026-08-18** -- bruker bekreftet. Ingen migrasjon (ren
+ frontend). `docker compose build teecup_frontend && up -d
+ teecup_frontend`, rene logger, 200 OK.
diff --git a/frontend/components/individual-tournament-detail.tsx b/frontend/components/individual-tournament-detail.tsx
index 1ccccc9..72ad10a 100644
--- a/frontend/components/individual-tournament-detail.tsx
+++ b/frontend/components/individual-tournament-detail.tsx
@@ -29,9 +29,11 @@ import {
Crosshair,
Flag,
KeyRound,
+ Layers,
MapPin,
Medal,
Plus,
+ Settings2,
Trash2,
Trophy,
Upload,
@@ -44,7 +46,9 @@ import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { PlayerImportPanel } from "@/components/player-import-panel"
import { RoundGroupsPanel } from "@/components/round-groups-panel"
+import { RoundGroupsStepList, type RoundSummary } from "@/components/round-groups-step-list"
import { TournamentSettingsCard, type TournamentSettingsValues } from "@/components/tournament-settings-card"
+import { TournamentSetupNav, type SetupStep } from "@/components/tournament-setup-nav"
import {
DropdownMenu,
DropdownMenuContent,
@@ -991,11 +995,17 @@ export function IndividualTournamentDetail({
egen kommentar om "storskjerm uten skrolling"), men satt inni denne
delte 4xl-wrapperen (896px, samme wrapper som skjema-tunge Oppsett/
Presentasjon-fanene bruker) fikk den aldri sjansen til det -- felles
- med resten av siden siden komponenten ble bygget/testet isolert. */}
+ med resten av siden siden komponenten ble bygget/testet isolert.
+
+ Oppsett-fanen fikk samme problem 2026-08-18 (ADR-092): 6 steg i
+ TournamentSetupNav får ikke plass side ved side i 896px, selv på en
+ bred skjerm -- akkurat den "stor skjerm først"-regelen wizarden
+ skulle innfri. Egen, litt smalere unntaksbredde enn leaderboardets
+ 110rem (dette er skjemainnhold, ikke en datatabell). */}
{error && (
@@ -1104,6 +1114,21 @@ function fromDatetimeLocalValue(value: string | null): string | null {
return Number.isNaN(date.getTime()) ? null : date.toISOString()
}
+// Wizard-steg (ADR-092) -- GameBook-skjermdumper var strukturelt forbilde
+// (steg i stedet for én lang stablet side), IKKE visuelt forbilde.
+// Fri navigasjon -- ingen låsing/fullført-haker, se ADR-092: GameBooks
+// egne skjermdumper viser haker på alle steg selv med tomt navnefelt,
+// altså ikke ekte validering, og TeeCup er allerede fleksibelt på
+// oppsett-rekkefølge.
+const SETUP_STEPS: SetupStep[] = [
+ { key: "basics", label: "Turneringsoppsett", icon: Settings2 },
+ { key: "rounds", label: "Runder og baner", icon: Flag },
+ { key: "classes", label: "Klasser", icon: Layers },
+ { key: "players", label: "Spillere", icon: Users },
+ { key: "groups", label: "Grupper og startliste", icon: Clock },
+ { key: "results", label: "Resultat og opsjoner", icon: Trophy },
+]
+
function SetupTab({
base,
organizationId,
@@ -1171,6 +1196,8 @@ function SetupTab({
) => Promise
onError: (message: string) => void
}) {
+ const [step, setStep] = useState("basics")
+ const [groupsOpenFor, setGroupsOpenFor] = useState(null)
const [pool, setPool] = useState([])
async function refreshPool() {
@@ -1202,116 +1229,151 @@ function SetupTab({
registrationRequiresApproval: tournament.registration_requires_approval,
}
+ const roundSummaries: RoundSummary[] = rounds.map((r) => ({
+ id: r.id,
+ name: r.name || `Runde ${r.sequence}`,
+ sequence: r.sequence,
+ courseName: r.course_name || null,
+ dateLabel: r.scheduled_at
+ ? new Date(r.scheduled_at).toLocaleDateString("nb-NO", { day: "numeric", month: "short", year: "numeric" })
+ : null,
+ }))
+ const groupsOpenRound = rounds.find((r) => r.id === groupsOpenFor) ?? null
+
return (
-
-
+
+ {step === "basics" && }
-
-
Scoringsmetode
-
- Avgjør hvordan totalen på leaderboardet regnes ut, og om deltakere trenger
- registrert handicap og kjønn.
-