Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
"use client"
// Horisontalt scorekort for en frittstående runde (ADR-033) -- egen,
// dedikert side (ikke en del av round-stats.tsx sin aggregerte statistikk).
// Presentasjon fra V0 (zip 17), datalag skrevet om fra mock til ekte fetch
// mot samme `/rounds/{id}/participants/{id}/holes`-endepunkt som
// round-detail.tsx og round-stats.tsx allerede bruker.
//
// Bevisst forskjell fra V0s eksport: V0s egen `strokesReceived()` var en
// generisk modulo-formel -- byttet ut med backend sin ALLEREDE beregnede
// `strokes_received` per hull (samme `allocate_strokes_by_index()`-
// algoritme som resten av appen), for å unngå to ulike implementasjoner av
// samme HCP-slagfordeling.
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
//
// Format-bevissthet lagt til 2026-07-28: brukeren rapporterte at siden kun
// noensinne viste brutto/netto/stableford, uansett spilleform -- bekreftet
// ved simulering at (a) foursome/greensome/scramble var HELT BLANKE her
// (delt-ball-formater lagrer score PER SIDE, ikke per deltaker -- se
// ADR-039 -- og denne siden spurte kun mot deltaker-endepunktet), og (b)
// match/fourball/skins viste riktige rå tall, men aldri HVORFOR et hull
// ble avgjort som det ble (brutto vs. netto, hvem sitt netto talte for
// siden i fourball, hvem som vant/hvilket hull som rullet videre i skins).
// Fikset ved å: (1) la delt-ball-formater bruke SIDER som "enhet" i stedet
// for deltakere (samme visuelle ScoreBlock-tabell, bare på
// `/rounds/{id}/sides/{id}/holes`, som fikk et nytt `strokes_received`-felt
// samtidig), og (2) legge til en egen "Matchforløp"/"Skins hull for hull"-
// seksjon drevet av `/rounds/{id}/format-result` sitt nye `holes`-felt
// (brutto/netto/slag mottatt PER enhet PER hull, pluss hvem som vant og
// hvorfor).
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
import { useEffect , useState } from "react"
import Link from "next/link"
2026-08-03 17:30:57 +02:00
import { ArrowLeft , ArrowUp , ArrowDown , ArrowRight , ArrowUpLeft , ArrowUpRight , Check , Target } from "lucide-react"
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
import { cn } from "@/lib/utils"
// --- API-typer ---------------------------------------------------------------
type ApiParticipant = {
id : string
2026-07-26 08:22:41 +02:00
user_id : string | null
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
guest_name : string | null
2026-07-26 08:22:41 +02:00
display_name : string
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
is_owner : boolean
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
round_side_id : string | null
2026-07-29 12:44:51 +02:00
playing_handicap : number | null
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
}
type ApiSide = {
id : string
label : string | null
2026-08-05 21:37:32 +02:00
// KUN satt for scramble_solo (migrasjon 056) -- null for alle andre
// formater, som ikke skiller sidene fra hverandre strukturelt.
side_role : "team" | "individual" | null
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
}
type ApiRound = {
2026-07-25 06:29:09 +02:00
name : string | null
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
id : string
course_name_snapshot : string
tee_name_snapshot : string
played_at : string
start_hole : number
holes_planned : number
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
play_format : string
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
participants : ApiParticipant [ ]
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
sides : ApiSide [ ]
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
}
type ApiHole = {
hole_number : number
par : number
stroke_index : number
played : boolean
score : number | null
Stableford is now a real spilleform for frittstående runder, alongside Slagspill/Match: selectable at round creation, editable afterward, shown as a badge everywhere the round appears.
"Plukket opp" — a new button in the scoring wizard's Slag step (only for Slagspill/Stableford, when handicap is known). Tapping it auto-hops forward just like picking a stroke count, and the server writes the exact Net Double Bogey score (par+2+mottatte slag) — so it flows through the existing HCP/AGS pipeline unchanged, always nets to exactly 0 Stableford points. Shown everywhere as a "PU" badge instead of a raw number: scorekortet, leaderboardet, "Så langt i runden".
Along the way, browser testing caught two real bugs (not just theoretical): the new-round form briefly showed a nonsensical "set up sides" notice under Stableford, and — more seriously — the match/skins territory-bar panel was rendering empty "Side A/Side B" bars on a Stableford round. Both traced to the same root cause (=== "stroke" checks that needed to also exclude the new format), and a full grep caught three more of the same pattern in watch-round.tsx before they could reach production.
Everything verified in scratch (hand-calculated math matched exactly) and in the browser (all four display surfaces, plus a regression check on an existing match round). Migration 038 applied to the real database, both containers redeployed, teeoff.no unaffected.
2026-07-29 19:46:17 +02:00
picked_up : boolean
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
strokes_received : number | null
2026-08-03 17:30:57 +02:00
// Detaljfelt (2026-08-03) -- allerede returnert av samme
// RoundHoleOut/`/rounds/.../holes`-endepunkt denne siden lenge har brukt,
// bare ikke tidligere lest her. Presentert som egne, forkortede rader i
// ScoreBlock i stedet for kun å ligge tilgjengelig i round-detail.tsx sin
// "Så langt i runden"-seksjon.
putts : number | null
tee_shot_result : "fairway" | "left" | "right" | null
approach_result : "hit" | "short" | "long" | "left" | "right" | null
chip_count : number | null
bunker_shot_count : number | null
penalty_strokes : number | null
anyway_strokes : number | null
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
}
Update Todos
Chapman: format-valg i new-round.tsx + tournament-program.tsx (session)
Nassau: nytt vindu-resultatvisning i round-detail.tsx + session-scorecard.tsx
Københavner: format-valg + poengtabell-visning i individual-tournament-detail.tsx
Bingo Bango Bongo: format-valg + per-hull picker + poengtabell
Flaggturnering: format-valg + nedtelling/resultatvisning
Shamble: format-valg + best_n + lagvisning (frittstående + org-lag)
Money Ball: format-valg + lineup_order + lagvisning (frittstående + org-lag)
High-low-high: format-valg + løpende poeng-resultatvisning (alle 3 flater)
Ekte produksjonsbuild -- FERDIG, kompilerte rent (27 ruter)
Browserverifisert alle åtte formatene -- fant og fikset ekte backend-bug (side-handicap-recompute)
Rullet ut mot ekte teecup_api/teecup_frontend -- FERDIG, health checks grønne, teeoff.no upåvirket
Rullet ut live 2026-07-30. Frontend for alle åtte nye turneringsformatene (Chapman, Nassau, Københavner, Bingo Bango Bongo, Flaggturnering, Shamble, Money Ball, High-low-high) er nå bygget, browserverifisert og live — dekker alle tre flatene (frittstående runder, org-lagturneringer, org-individuelle turneringer). Fant og fikset én reell backend-bug underveis (side-handicap ble ikke regnet på nytt når en deltakers HCP ble satt/endret etter at de allerede var tildelt en side). Ingen migrasjon i denne runden, teeoff.no upåvirket. ADR-039/åtte-formater-arbeidet er dermed helt ferdig, backend og frontend.
2026-08-01 06:51:53 +02:00
const SHARED_BALL_FORMATS = [ "foursome" , "greensome" , "scramble_2" , "scramble_4" , "chapman" ]
2026-08-05 21:37:32 +02:00
// scramble_solo_match (migrasjon 057) lagt til her -- KUN denne bruken
// (isTwoSided) gater MatchScorecardGrid, som får sin egen dedikerte
// scramble-solo-familie-gren for å unngå dupliserte rader (se der).
// SHARED_BALL_FORMATS/isSharedBall RØRES bevisst ikke -- se
// SCRAMBLE_SOLO_FORMATS under for den egne, riktige klassifiseringen.
const TWO_SIDED_FORMATS = [ "match" , "fourball" , "high_low_high" , "scramble_solo_match" , . . . SHARED_BALL_FORMATS ]
// Begge scramble-mot-enkeltspiller-variantene deler NØYAKTIG samme
// asymmetriske side-/enhetsstruktur (laget = side, individualspilleren =
// participant) -- kun selve resultat-sammenligningen skiller dem. Én
// samlet klassifisering brukt for alt UNNTATT selve resultatvisningen.
const SCRAMBLE_SOLO_FORMATS = new Set ( [ "scramble_solo" , "scramble_solo_match" ] )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const FORMAT_LABELS : Record < string , string > = {
stroke : "Slagspill" ,
Stableford is now a real spilleform for frittstående runder, alongside Slagspill/Match: selectable at round creation, editable afterward, shown as a badge everywhere the round appears.
"Plukket opp" — a new button in the scoring wizard's Slag step (only for Slagspill/Stableford, when handicap is known). Tapping it auto-hops forward just like picking a stroke count, and the server writes the exact Net Double Bogey score (par+2+mottatte slag) — so it flows through the existing HCP/AGS pipeline unchanged, always nets to exactly 0 Stableford points. Shown everywhere as a "PU" badge instead of a raw number: scorekortet, leaderboardet, "Så langt i runden".
Along the way, browser testing caught two real bugs (not just theoretical): the new-round form briefly showed a nonsensical "set up sides" notice under Stableford, and — more seriously — the match/skins territory-bar panel was rendering empty "Side A/Side B" bars on a Stableford round. Both traced to the same root cause (=== "stroke" checks that needed to also exclude the new format), and a full grep caught three more of the same pattern in watch-round.tsx before they could reach production.
Everything verified in scratch (hand-calculated math matched exactly) and in the browser (all four display surfaces, plus a regression check on an existing match round). Migration 038 applied to the real database, both containers redeployed, teeoff.no unaffected.
2026-07-29 19:46:17 +02:00
stableford : "Stableford" ,
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
match : "Match" ,
skins : "Skins" ,
fourball : "Fourball" ,
foursome : "Foursome" ,
greensome : "Greensome" ,
scramble_2 : "Scramble (2)" ,
scramble_4 : "Scramble (4)" ,
Update Todos
Chapman: format-valg i new-round.tsx + tournament-program.tsx (session)
Nassau: nytt vindu-resultatvisning i round-detail.tsx + session-scorecard.tsx
Københavner: format-valg + poengtabell-visning i individual-tournament-detail.tsx
Bingo Bango Bongo: format-valg + per-hull picker + poengtabell
Flaggturnering: format-valg + nedtelling/resultatvisning
Shamble: format-valg + best_n + lagvisning (frittstående + org-lag)
Money Ball: format-valg + lineup_order + lagvisning (frittstående + org-lag)
High-low-high: format-valg + løpende poeng-resultatvisning (alle 3 flater)
Ekte produksjonsbuild -- FERDIG, kompilerte rent (27 ruter)
Browserverifisert alle åtte formatene -- fant og fikset ekte backend-bug (side-handicap-recompute)
Rullet ut mot ekte teecup_api/teecup_frontend -- FERDIG, health checks grønne, teeoff.no upåvirket
Rullet ut live 2026-07-30. Frontend for alle åtte nye turneringsformatene (Chapman, Nassau, Københavner, Bingo Bango Bongo, Flaggturnering, Shamble, Money Ball, High-low-high) er nå bygget, browserverifisert og live — dekker alle tre flatene (frittstående runder, org-lagturneringer, org-individuelle turneringer). Fant og fikset én reell backend-bug underveis (side-handicap ble ikke regnet på nytt når en deltakers HCP ble satt/endret etter at de allerede var tildelt en side). Ingen migrasjon i denne runden, teeoff.no upåvirket. ADR-039/åtte-formater-arbeidet er dermed helt ferdig, backend og frontend.
2026-08-01 06:51:53 +02:00
chapman : "Chapman" ,
copenhagen : "Københavner" ,
bbb : "Bingo Bango Bongo" ,
flag : "Flaggturnering" ,
shamble : "Shamble" ,
money_ball : "Money Ball" ,
high_low_high : "High-low-high" ,
2026-08-05 21:37:32 +02:00
scramble_solo : "Scramble mot enkeltspiller" ,
scramble_solo_match : "Scramble mot enkeltspiller (matchspill)" ,
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
}
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const dateFormatter = new Intl . DateTimeFormat ( "no-NO" , { day : "numeric" , month : "long" , year : "numeric" } )
2026-07-26 08:22:41 +02:00
// Viewer-relativt (ADR-036 fase 3-utvidelsen, 2026-07-26) -- se samme
// begrunnelse i round-detail.tsx sin playerLabel().
function participantLabel ( p : ApiParticipant , viewerId : string | null ) : string {
return viewerId !== null && p . user_id === viewerId ? "Deg" : p . display_name
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
}
// --- Scoring helpers -------------------------------------------------------
function netScore ( h : ApiHole ) : number | null {
return h . played && h . score !== null && h . strokes_received !== null ? h . score - h.strokes_received : null
}
// Stableford: 2 pts for net par, +/- 1 per stroke, floored at 0.
function stablefordPoints ( h : ApiHole ) : number | null {
const net = netScore ( h )
if ( net === null ) return null
return Math . max ( 0 , h . par - net + 2 )
}
2026-08-03 17:30:57 +02:00
// Samme GIR-formel som round-stats.tsx sin isGir/round-detail.tsx sin
// GIR-auto-inferens: slag minus putt garanterer green i regulering når
// resultatet er par-2 eller bedre. Krever kjent slag+putt-tall.
function isGir ( h : ApiHole ) : boolean {
return h . score !== null && h . putts !== null && h . score - h . putts <= h . par - 2
}
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
type ScoreClass = "eagle" | "birdie" | "par" | "bogey" | "double"
function classify ( gross : number , par : number ) : ScoreClass {
const diff = gross - par
if ( diff <= - 2 ) return "eagle"
if ( diff === - 1 ) return "birdie"
if ( diff === 0 ) return "par"
if ( diff === 1 ) return "bogey"
return "double"
}
function sum ( values : number [ ] ) : number {
return values . reduce ( ( a , b ) = > a + b , 0 )
}
function signedToPar ( score : number , par : number ) : string {
const diff = score - par
if ( diff === 0 ) return "E"
return diff > 0 ? ` + ${ diff } ` : ` − ${ Math . abs ( diff ) } `
}
// --- Score mark (the visual language for the Score row) --------------------
// Shape encodes direction (circle = under par, square = over par) so meaning
// survives without color; fill encodes magnitude (filled = 2+ strokes off).
Stableford is now a real spilleform for frittstående runder, alongside Slagspill/Match: selectable at round creation, editable afterward, shown as a badge everywhere the round appears.
"Plukket opp" — a new button in the scoring wizard's Slag step (only for Slagspill/Stableford, when handicap is known). Tapping it auto-hops forward just like picking a stroke count, and the server writes the exact Net Double Bogey score (par+2+mottatte slag) — so it flows through the existing HCP/AGS pipeline unchanged, always nets to exactly 0 Stableford points. Shown everywhere as a "PU" badge instead of a raw number: scorekortet, leaderboardet, "Så langt i runden".
Along the way, browser testing caught two real bugs (not just theoretical): the new-round form briefly showed a nonsensical "set up sides" notice under Stableford, and — more seriously — the match/skins territory-bar panel was rendering empty "Side A/Side B" bars on a Stableford round. Both traced to the same root cause (=== "stroke" checks that needed to also exclude the new format), and a full grep caught three more of the same pattern in watch-round.tsx before they could reach production.
Everything verified in scratch (hand-calculated math matched exactly) and in the browser (all four display surfaces, plus a regression check on an existing match round). Migration 038 applied to the real database, both containers redeployed, teeoff.no unaffected.
2026-07-29 19:46:17 +02:00
function ScoreMark ( { gross , par , pickedUp } : { gross : number | null ; par : number ; pickedUp? : boolean } ) {
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const shared =
"flex size-6 items-center justify-center text-sm font-extrabold tabular-nums sm:size-7"
Stableford is now a real spilleform for frittstående runder, alongside Slagspill/Match: selectable at round creation, editable afterward, shown as a badge everywhere the round appears.
"Plukket opp" — a new button in the scoring wizard's Slag step (only for Slagspill/Stableford, when handicap is known). Tapping it auto-hops forward just like picking a stroke count, and the server writes the exact Net Double Bogey score (par+2+mottatte slag) — so it flows through the existing HCP/AGS pipeline unchanged, always nets to exactly 0 Stableford points. Shown everywhere as a "PU" badge instead of a raw number: scorekortet, leaderboardet, "Så langt i runden".
Along the way, browser testing caught two real bugs (not just theoretical): the new-round form briefly showed a nonsensical "set up sides" notice under Stableford, and — more seriously — the match/skins territory-bar panel was rendering empty "Side A/Side B" bars on a Stableford round. Both traced to the same root cause (=== "stroke" checks that needed to also exclude the new format), and a full grep caught three more of the same pattern in watch-round.tsx before they could reach production.
Everything verified in scratch (hand-calculated math matched exactly) and in the browser (all four display surfaces, plus a regression check on an existing match round). Migration 038 applied to the real database, both containers redeployed, teeoff.no unaffected.
2026-07-29 19:46:17 +02:00
// "Plukket opp" (migrasjon 038, Stableford) -- 0 poeng er impliserte,
// vises som "PU" i stedet for det underliggende Net Double Bogey-tallet.
if ( pickedUp ) {
return (
< span className = { cn ( shared , "rounded-[4px] border-2 border-brand-orange bg-brand-orange/10 text-[10px] text-brand-orange" ) } >
PU
< / span >
)
}
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
if ( gross === null ) {
return < span className = { cn ( shared , "text-muted-foreground" ) } > { "– " } < / span >
}
const kind = classify ( gross , par )
if ( kind === "eagle" ) {
return (
< span className = { cn ( shared , "rounded-full bg-primary text-primary-foreground" ) } > { gross } < / span >
)
}
if ( kind === "birdie" ) {
return (
< span className = { cn ( shared , "rounded-full border-2 border-primary bg-primary/10 text-primary" ) } >
{ gross }
< / span >
)
}
if ( kind === "bogey" ) {
return (
< span
className = { cn (
shared ,
"rounded-[4px] border-2 border-brand-orange bg-brand-orange/10 text-brand-orange" ,
) }
>
{ gross }
< / span >
)
}
if ( kind === "double" ) {
return (
< span className = { cn ( shared , "rounded-[4px] bg-brand-orange text-brand-orange-foreground" ) } >
{ gross }
< / span >
)
}
// par
return < span className = { cn ( shared , "font-bold text-foreground" ) } > { gross } < / span >
}
// --- One nine-hole block (a real table for row/column semantics) -----------
2026-08-03 17:30:57 +02:00
// Kompakte retnings-/treff-ikoner for de nye detaljradene (2026-08-03) --
// samme ikonvalg som DirectionCross (round-detail.tsx sin registrerings-
// veiviser) allerede bruker, kun skalert ned for en tett tabellcelle.
// Bøyde piler for Fairway (utslaget DRIVER av til en side, ulikt et
// innspill som bommer rett til siden -- derfor ArrowUpLeft/-Right her,
// ikke de rette ArrowLeft/-Right Innspill-raden bruker).
function FairwayIcon ( { result } : { result : ApiHole [ "tee_shot_result" ] } ) {
if ( result === null ) return null
if ( result === "fairway" ) return < Target aria-hidden = "true" className = "mx-auto size-3.5 text-primary" / >
if ( result === "left" ) return < ArrowUpLeft aria-hidden = "true" className = "mx-auto size-3.5 text-brand-orange" / >
return < ArrowUpRight aria-hidden = "true" className = "mx-auto size-3.5 text-brand-orange" / >
}
function ApproachIcon ( { result } : { result : ApiHole [ "approach_result" ] } ) {
if ( result === null ) return null
const cls = "mx-auto size-3.5"
if ( result === "hit" ) return < Target aria-hidden = "true" className = { cn ( cls , "text-primary" ) } / >
if ( result === "long" ) return < ArrowUp aria-hidden = "true" className = { cn ( cls , "text-brand-orange" ) } / >
if ( result === "short" ) return < ArrowDown aria-hidden = "true" className = { cn ( cls , "text-brand-orange" ) } / >
if ( result === "left" ) return < ArrowLeft aria-hidden = "true" className = { cn ( cls , "text-brand-orange" ) } / >
return < ArrowRight aria-hidden = "true" className = { cn ( cls , "text-brand-orange" ) } / >
}
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
function ScoreBlock ( {
holes ,
summaryLabel ,
showStableford ,
2026-08-03 17:30:57 +02:00
showFairway ,
showPutts ,
showGir ,
showApproach ,
showChip ,
showBunker ,
showPenalty ,
showAnyway ,
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
} : {
holes : ApiHole [ ]
summaryLabel : string
showStableford : boolean
2026-08-03 17:30:57 +02:00
showFairway : boolean
showPutts : boolean
showGir : boolean
showApproach : boolean
showChip : boolean
showBunker : boolean
showPenalty : boolean
showAnyway : boolean
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
} ) {
const parSum = sum ( holes . map ( ( h ) = > h . par ) )
const playedHoles = holes . filter ( ( h ) = > h . played && h . score !== null )
const grossSum = playedHoles . length > 0 ? sum ( playedHoles . map ( ( h ) = > h . score as number ) ) : null
const nettoValues = holes . map ( netScore ) . filter ( ( n ) : n is number = > n !== null )
const nettoSum = nettoValues . length > 0 ? sum ( nettoValues ) : null
const pointsValues = holes . map ( stablefordPoints ) . filter ( ( n ) : n is number = > n !== null )
const pointsSum = pointsValues . length > 0 ? sum ( pointsValues ) : null
2026-08-03 17:30:57 +02:00
// Fairwaytreff spores kun på ikke-par-3-hull (samme regel som
// round-detail.tsx sin "Så langt i runden"), summen teller kun "Blink".
const fairwayEligible = holes . filter ( ( h ) = > h . par !== 3 && h . tee_shot_result !== null )
const fairwayHitSum = fairwayEligible . length > 0 ? fairwayEligible . filter ( ( h ) = > h . tee_shot_result === "fairway" ) . length : null
const puttsValues = holes . filter ( ( h ) = > h . putts !== null ) . map ( ( h ) = > h . putts as number )
const puttsSum = puttsValues . length > 0 ? sum ( puttsValues ) : null
const girEligible = holes . filter ( ( h ) = > h . score !== null && h . putts !== null )
const girSum = girEligible . length > 0 ? girEligible . filter ( isGir ) . length : null
const chipValues = holes . filter ( ( h ) = > h . chip_count !== null ) . map ( ( h ) = > h . chip_count as number )
const chipSum = chipValues . length > 0 ? sum ( chipValues ) : null
const bunkerValues = holes . filter ( ( h ) = > h . bunker_shot_count !== null ) . map ( ( h ) = > h . bunker_shot_count as number )
const bunkerSum = bunkerValues . length > 0 ? sum ( bunkerValues ) : null
const penaltyValues = holes . filter ( ( h ) = > h . penalty_strokes !== null ) . map ( ( h ) = > h . penalty_strokes as number )
const penaltySum = penaltyValues . length > 0 ? sum ( penaltyValues ) : null
const anywayValues = holes . filter ( ( h ) = > h . anyway_strokes !== null ) . map ( ( h ) = > h . anyway_strokes as number )
const anywaySum = anywayValues . length > 0 ? sum ( anywayValues ) : null
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const cell = "border border-border text-center tabular-nums"
const sumCell = "border border-border bg-muted text-center font-extrabold tabular-nums"
2026-08-03 17:30:57 +02:00
// whitespace-nowrap + overflow-hidden (2026-08-03, rapportert av bruker --
// "Score"/"Netto" bløuted ut over kolonnegrensen) -- w-11 gir litt mer
// rom enn tidligere w-9, men de VIRKELIG korte etikettene (forkortelser)
// under er den egentlige fiksen, ikke bare bredden alene.
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const rowLabel =
2026-08-03 17:30:57 +02:00
"border border-border px-1 text-left text-xs font-bold text-muted-foreground whitespace-nowrap overflow-hidden"
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
return (
< table className = "w-full table-fixed border-collapse" >
< caption className = "sr-only" >
Scorekort hull { holes [ 0 ] . hole_number } til { holes [ holes . length - 1 ] . hole_number }
< / caption >
< colgroup >
2026-08-03 17:30:57 +02:00
< col className = "w-11" / >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
{ holes . map ( ( h ) = > (
< col key = { h . hole_number } / >
) ) }
< col className = "w-[11%]" / >
< / colgroup >
< thead >
< tr >
< th scope = "col" className = "border border-border bg-muted px-1 py-1 text-left" >
< span className = "sr-only" > Rad < / span >
< span aria-hidden = "true" className = "text-xs font-extrabold text-muted-foreground" >
Hull
< / span >
< / th >
{ holes . map ( ( h ) = > (
< th
key = { h . hole_number }
scope = "col"
className = "border border-border bg-foreground py-1 text-center text-xs font-extrabold tabular-nums text-background"
>
{ h . hole_number }
< / th >
) ) }
< th
scope = "col"
className = "border border-border bg-primary py-1 text-center text-xs font-extrabold uppercase text-primary-foreground"
>
{ summaryLabel }
< / th >
< / tr >
< / thead >
< tbody >
{ /* Hcp (stroke index) */ }
< tr >
< th scope = "row" className = { rowLabel } >
Hcp
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . stroke_index }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-muted-foreground" ) } aria-hidden = "true" >
{ "– " }
< / td >
< / tr >
{ /* Par */ }
< tr >
< th scope = "row" className = { rowLabel } >
Par
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . par }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { parSum } < / td >
< / tr >
{ /* Score — the hero row: highlighted band + shape marks */ }
< tr className = "bg-primary/5" >
< th scope = "row" className = { cn ( rowLabel , "text-sm text-foreground" ) } >
Score
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "px-0.5 py-1" ) } >
< span className = "flex items-center justify-center" >
Stableford is now a real spilleform for frittstående runder, alongside Slagspill/Match: selectable at round creation, editable afterward, shown as a badge everywhere the round appears.
"Plukket opp" — a new button in the scoring wizard's Slag step (only for Slagspill/Stableford, when handicap is known). Tapping it auto-hops forward just like picking a stroke count, and the server writes the exact Net Double Bogey score (par+2+mottatte slag) — so it flows through the existing HCP/AGS pipeline unchanged, always nets to exactly 0 Stableford points. Shown everywhere as a "PU" badge instead of a raw number: scorekortet, leaderboardet, "Så langt i runden".
Along the way, browser testing caught two real bugs (not just theoretical): the new-round form briefly showed a nonsensical "set up sides" notice under Stableford, and — more seriously — the match/skins territory-bar panel was rendering empty "Side A/Side B" bars on a Stableford round. Both traced to the same root cause (=== "stroke" checks that needed to also exclude the new format), and a full grep caught three more of the same pattern in watch-round.tsx before they could reach production.
Everything verified in scratch (hand-calculated math matched exactly) and in the browser (all four display surfaces, plus a regression check on an existing match round). Migration 038 applied to the real database, both containers redeployed, teeoff.no unaffected.
2026-07-29 19:46:17 +02:00
< ScoreMark gross = { h . played ? h.score : null } par = { h . par } pickedUp = { h . picked_up } / >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / span >
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-base text-foreground" ) } > { grossSum ? ? "– " } < / td >
< / tr >
{ /* Netto */ }
< tr >
< th scope = "row" className = { cn ( rowLabel , "text-foreground" ) } >
Netto
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-bold text-foreground" ) } >
{ netScore ( h ) ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { nettoSum ? ? "– " } < / td >
< / tr >
{ /* Stableford (only when relevant) */ }
{ showStableford && (
< tr >
< th scope = "row" className = { rowLabel } title = "Stableford-poeng" >
Poeng
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ stablefordPoints ( h ) ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { pointsSum ? ? "– " } < / td >
< / tr >
) }
2026-08-03 17:30:57 +02:00
{ / * F a i r w a y - - i k o n p e r h u l l ( b ø y d p i l = u t s l a g e t d r e v t i l s i d e n ,
blink = fairwaytreff ) , sum = antall fairwaytreff . * / }
{ showFairway && (
< tr >
< th scope = "row" className = { rowLabel } title = "Fairwaytreff" >
Fw
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1" ) } >
{ h . par !== 3 ? < FairwayIcon result = { h . tee_shot_result } / > : < span aria-hidden = "true" > – < / span > }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { fairwayHitSum ? ? "– " } < / td >
< / tr >
) }
{ /* Putter -- antall per hull, summert. */ }
{ showPutts && (
< tr >
< th scope = "row" className = { rowLabel } title = "Putter" >
Putt
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . putts ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { puttsSum ? ? "– " } < / td >
< / tr >
) }
{ /* GIR -- sjekkmerke når hullet er nådd i regulering, summert. */ }
{ showGir && (
< tr >
< th scope = "row" className = { rowLabel } title = "Green i regulering" >
GIR
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1" ) } >
{ h . score !== null && h . putts !== null ? (
isGir ( h ) ? (
< Check aria-hidden = "true" className = "mx-auto size-3.5 text-primary" / >
) : (
< span aria-hidden = "true" className = "text-muted-foreground" >
–
< / span >
)
) : (
< span aria-hidden = "true" > – < / span >
) }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { girSum ? ? "– " } < / td >
< / tr >
) }
{ / * I n n s p i l l - - 5 - v e i s r e t n i n g , i n g e n m e n i n g s f u l l s u m ( r e t n i n g , i k k e
et tall ) . * / }
{ showApproach && (
< tr >
< th scope = "row" className = { rowLabel } title = "Innspill" >
Appr .
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1" ) } >
< ApproachIcon result = { h . approach_result } / >
{ h . approach_result === null && < span aria-hidden = "true" > – < / span > }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-muted-foreground" ) } aria-hidden = "true" >
–
< / td >
< / tr >
) }
{ /* Chip -- antall per hull, summert. */ }
{ showChip && (
< tr >
< th scope = "row" className = { rowLabel } title = "Chip" >
Chip
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . chip_count ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { chipSum ? ? "– " } < / td >
< / tr >
) }
{ /* Bunkerslag -- antall per hull, summert. */ }
{ showBunker && (
< tr >
< th scope = "row" className = { rowLabel } title = "Bunkerslag" >
Bnk
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . bunker_shot_count ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { bunkerSum ? ? "– " } < / td >
< / tr >
) }
{ /* Straffeslag -- antall per hull, summert. */ }
{ showPenalty && (
< tr >
< th scope = "row" className = { rowLabel } title = "Straffeslag" >
Str
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . penalty_strokes ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { penaltySum ? ? "– " } < / td >
< / tr >
) }
{ /* Anywayslag -- antall per hull, summert. */ }
{ showAnyway && (
< tr >
< th scope = "row" className = { rowLabel } title = "Anywayslag" >
Any .
< / th >
{ holes . map ( ( h ) = > (
< td key = { h . hole_number } className = { cn ( cell , "py-1 text-xs font-semibold text-muted-foreground" ) } >
{ h . anyway_strokes ? ? "– " }
< / td >
) ) }
< td className = { cn ( sumCell , "py-1 text-xs text-foreground" ) } > { anywaySum ? ? "– " } < / td >
< / tr >
) }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / tbody >
< / table >
)
}
// --- Combined total --------------------------------------------------------
function TotalTile ( { label , value , tone } : { label : string ; value : string ; tone ? : "orange" | "green" } ) {
return (
< div className = "flex flex-col items-center gap-0.5 rounded-2xl border border-border bg-card px-2 py-3" >
< span
className = { cn (
"text-2xl font-extrabold tabular-nums" ,
tone === "orange" ? "text-brand-orange" : tone === "green" ? "text-primary" : "text-foreground" ,
) }
>
{ value }
< / span >
< span className = "text-xs font-semibold uppercase tracking-wide text-muted-foreground" > { label } < / span >
< / div >
)
}
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
// --- Matchforløp / skins-forløp (2026-07-28) ---------------------------------
// Avledet ved LESING fra GET .../format-result -- viser HVORFOR et hull ble
// avgjort som det ble (brutto vs. netto, slag mottatt, hvem sitt netto
// talte for siden i fourball, hvem som vant/hvilket hull som rullet videre
// i skins) -- ikke bare et vinn/tap-merke.
type ApiFormatHoleEntry = {
id : string
label : string
side : "a" | "b" | null
gross : number | null
net : number | null
strokes_received : number | null
counted : boolean
}
type ApiFormatHoleOut = {
hole_number : number
par : number
stroke_index : number
entries : ApiFormatHoleEntry [ ]
result : string | null
winner_ids : string [ ] | null
carried : boolean | null
}
type ApiFormatResult = {
play_format : string
ready : boolean
match_status_text : string | null
skins_won : Record < string , number > | null
holes : ApiFormatHoleOut [ ] | null
}
2026-08-07 22:02:56 +02:00
function useFormatResult ( roundId : string , refreshKey : number , apiPrefix : string = "/rounds" ) : ApiFormatResult | null {
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const [ result , setResult ] = useState < ApiFormatResult | null > ( null )
useEffect ( ( ) = > {
let cancelled = false
2026-08-07 22:02:56 +02:00
fetch ( ` ${ apiPrefix } / ${ roundId } /format-result ` , { credentials : "include" } )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
. then ( ( res ) = > ( res . ok ? res . json ( ) : null ) )
. then ( ( data : ApiFormatResult | null ) = > {
if ( ! cancelled ) setResult ( data )
} )
. catch ( ( ) = > { } )
return ( ) = > {
cancelled = true
}
2026-08-07 22:02:56 +02:00
} , [ roundId , refreshKey , apiPrefix ] )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
return result
}
2026-07-29 12:44:51 +02:00
// --- Matchforløp: horisontalt scorekort med løpende stilling ---------------
// Egen visuell utforming (ikke en kopi av noe referansebilde) -- gjenbruker
// appens etablerte vinn/tap-språk (grønn=side A, oransje=side B, nøytral=delt,
// se ScoreMark/ResultChip andre steder) fremfor referansens rød/blå, og
// erstatter den tidligere vertikale hull-for-hull-listen med et horisontalt
// rutenett (Hull/Par/enhet-rader/Stilling) + en identitets-/resultatbanner --
// samme informasjon (hvem vant hvilket hull, AS/X UP/X&Y), annen presentasjon.
type RunningState = {
lead : number
label : string
tone : "a" | "b" | "neutral"
isClosed : boolean
}
// Speiler handicap_engine.py sin compute_match_state()/describe() presist,
// men regner ett PREFIKS om gangen slik at hvert hull får sin egen løpende
// stilling (backend cacher i dag kun SLUTT-tilstanden -- se ADR-039-notatet).
function computeRunning ( results : ( "a" | "b" | "halved" ) [ ] , totalHoles : number ) : RunningState [ ] {
const out : RunningState [ ] = [ ]
let lead = 0
for ( let i = 0 ; i < results . length ; i ++ ) {
lead += results [ i ] === "a" ? 1 : results [ i ] === "b" ? - 1 : 0
const holesPlayed = i + 1
const holesRemaining = totalHoles - holesPlayed
const isClosed = Math . abs ( lead ) > holesRemaining
const isDormie = ! isClosed && holesRemaining > 0 && Math . abs ( lead ) === holesRemaining
const margin = Math . abs ( lead )
let label : string
if ( isClosed ) {
label = holesRemaining === 0 && margin > 0 ? ` ${ margin } UP ` : ` ${ margin } & ${ holesRemaining } `
} else if ( lead === 0 ) {
label = "AS"
} else {
label = isDormie ? ` Dormie ${ margin } ` : ` ${ margin } UP `
}
out . push ( { lead , label , tone : lead > 0 ? "a" : lead < 0 ? "b" : "neutral" , isClosed } )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
}
2026-07-29 12:44:51 +02:00
return out
}
type HeaderIdentity = { name : string ; hcp : number | null }
2026-07-29 16:26:31 +02:00
// Territorium-bar (2026-07-29, brukerens eget forslag: den ledende sidens
// sone strekker seg proporsjonalt forbi midtlinjen inn på motstanderens
// halvdel, i stedet for en statisk 50/50-boks med tekst i midten). Ved AS
// eller ingen hull avgjort ennå er begge soner like store og nøytralt
// farget. Egen lokal kopi av samme idé som round-detail.tsx sin
// FormatResultPanel, per prosjektets "én fil, én kopi"-konvensjon.
function leadZoneFraction ( lead : number , totalHoles : number ) : number {
if ( totalHoles <= 0 ) return 0.5
const fraction = 0.5 + ( lead / totalHoles ) * 0.5
return Math . min ( 0.82 , Math . max ( 0.18 , fraction ) )
}
function LeadZone ( { identity , side , dominant } : { identity : HeaderIdentity ; side : "a" | "b" ; dominant : boolean } ) {
const textTone = dominant ? ( side === "a" ? "text-primary-foreground" : "text-brand-orange-foreground" ) : "text-foreground"
const subTone = dominant
? side === "a"
? "text-primary-foreground/75"
: "text-brand-orange-foreground/75"
: "text-muted-foreground"
// Boksen STREKKER SEG (ingen items-start/items-end) -- ellers sizes den
// etter innholdets egen bredde, ikke sonens faktiske tildelte bredde, og
// kan visuelt lekke inn i midt-kolonnen på smale skjermer. Justering skjer
// med justify-start/justify-end + text-align inni en boks som alltid har
// full, korrekt bredde -- truncate virker da presist.
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
return (
2026-07-29 16:26:31 +02:00
< div className = "flex h-full min-w-0 w-full flex-col justify-center gap-0.5 px-3" >
< div
className = { cn (
"flex min-w-0 items-center gap-1.5" ,
side === "a" ? "justify-start" : "justify-end" ,
side === "b" && "flex-row-reverse" ,
) }
>
{ ! dominant && (
< span
aria - hidden = "true"
className = { cn ( "size-2 shrink-0 rounded-full" , side === "a" ? "bg-primary" : "bg-brand-orange" ) }
/ >
) }
< span className = { cn ( "min-w-0 truncate text-sm font-extrabold" , textTone ) } > { identity . name } < / span >
2026-07-29 12:44:51 +02:00
< / div >
{ identity . hcp !== null && (
2026-07-29 16:26:31 +02:00
< span
className = { cn (
"truncate text-xs font-bold tabular-nums" ,
subTone ,
side === "a" ? "text-left" : "text-right" ,
) }
>
HCP { identity . hcp }
< / span >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
) }
2026-07-29 12:44:51 +02:00
< / div >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
)
}
2026-07-29 16:26:31 +02:00
function LeadBar ( {
identityA ,
identityB ,
state ,
holesPlayed ,
totalHoles ,
} : {
identityA : HeaderIdentity
identityB : HeaderIdentity
state : RunningState | null
holesPlayed : number
totalHoles : number
} ) {
const lead = state ? . lead ? ? 0
const tone = state ? . tone ? ? "neutral"
const widthA = state ? leadZoneFraction ( lead , totalHoles ) * 100 : 50
const widthB = 100 - widthA
const zoneAClass = tone === "a" ? "bg-primary" : tone === "b" ? "bg-primary/12" : "bg-muted"
const zoneBClass = tone === "b" ? "bg-brand-orange" : tone === "a" ? "bg-brand-orange/12" : "bg-muted"
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
return (
2026-07-29 16:26:31 +02:00
// CSS Grid, ikke absolutt overlegg (2026-07-29-fiks, se round-detail.tsx
// sin FormatResultPanel for full begrunnelse) -- midt-kolonnen (status)
// er `auto`-bredde, de to sonene `minmax(0, X fr)` -- reserverer alltid
// nøyaktig plass til statusboksen, kan aldri overlappe et langt navn.
< div
className = "grid h-[76px] w-full overflow-hidden rounded-2xl sm:h-20"
style = { { gridTemplateColumns : ` minmax(0, ${ widthA } fr) auto minmax(0, ${ widthB } fr) ` } }
>
< div className = { cn ( "h-full min-w-0 transition-[grid-template-columns] duration-300" , zoneAClass ) } >
< LeadZone identity = { identityA } side = "a" dominant = { tone === "a" } / >
< / div >
< div className = "flex h-full items-center justify-center px-2" >
< div className = "flex flex-col items-center rounded-xl border border-border/60 bg-card/95 px-3 py-1.5 shadow-sm shadow-black/10 backdrop-blur-sm" >
{ state ? (
< >
< span
className = { cn (
"text-xl font-extrabold leading-none tabular-nums sm:text-2xl" ,
tone === "a" ? "text-primary" : tone === "b" ? "text-brand-orange" : "text-foreground" ,
) }
>
{ state . label }
< / span >
{ state . isClosed ? (
< span className = "mt-1 rounded-full bg-muted px-2 py-0.5 text-[10px] font-extrabold uppercase tracking-wide text-muted-foreground" >
Ferdig
< / span >
) : (
< span className = "mt-1 text-[11px] font-semibold text-muted-foreground" > { holesPlayed } hull spilt < / span >
) }
< / >
) : (
< span className = "text-xs font-bold text-muted-foreground text-pretty" > Ingen hull spilt ennå < / span >
) }
< / div >
< / div >
< div className = { cn ( "h-full min-w-0 transition-[grid-template-columns] duration-300" , zoneBClass ) } >
< LeadZone identity = { identityB } side = "b" dominant = { tone === "b" } / >
< / div >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< / div >
)
}
2026-07-29 12:44:51 +02:00
type MatchRow = { id : string ; side : "a" | "b" ; label : string ; hcp : number | null }
2026-08-07 22:02:56 +02:00
export function MatchScorecardGrid ( {
2026-07-29 12:44:51 +02:00
round ,
roundId ,
viewerId ,
refreshKey ,
2026-08-07 22:02:56 +02:00
apiPrefix = "/rounds" ,
2026-07-29 12:44:51 +02:00
} : {
round : ApiRound
roundId : string
viewerId : string | null
refreshKey : number
2026-08-07 22:02:56 +02:00
apiPrefix? : string
2026-07-29 12:44:51 +02:00
} ) {
2026-08-07 22:02:56 +02:00
const result = useFormatResult ( roundId , refreshKey , apiPrefix )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! result ) return null
2026-07-29 12:44:51 +02:00
const isSharedBall = SHARED_BALL_FORMATS . includes ( round . play_format )
2026-08-05 21:37:32 +02:00
// scramble_solo_match (migrasjon 057) -- ÉN rad per SIDE (som
// delt-ball-grenen under), IKKE én per deltaker, siden laget kan ha
// vilkårlig mange medlemmer som alle deler samme TeamAverage-verdi --
// uten denne egne grenen ville "else"-grenen under vist N dupliserte
// rader for laget. Individualsidens rad viser spillerens EGET navn
// (ikke bare sidens "Individuell motstander"-label) siden den siden
// alltid har nøyaktig én deltaker.
const isScrambleSoloMatch = SCRAMBLE_SOLO_FORMATS . has ( round . play_format )
const rows : MatchRow [ ] = isScrambleSoloMatch
? round . sides . map ( ( s , idx ) = > {
// side="a"/"b" er POSISJONELL (idx===0 -> "a"), samme sorterte-
// etter-id-konvensjon som backend sin _build_scramble_solo_match_
// result bruker (round.sides hentes ALLTID `ORDER BY id`, samme
// sortering backend legger til grunn for "a"/"b"-tildelingen --
// IKKE en fast lag=a/individuell=b-tildeling, som ville gitt feil
// ledelsesfarge når laget ikke er den lavest-sorterte UUID-en).
// row.id må for individualsiden være DELTAKERENS id (ikke sidens),
// siden FormatHoleEntry.id for den siden er individual_
// participant["id"] på backend-siden -- ellers finner
// h.entries.find(e => e.id === row.id) under aldri en match.
const sideParticipants = round . participants . filter ( ( p ) = > p . round_side_id === s . id )
const isTeam = s . side_role === "team"
const label =
! isTeam && sideParticipants . length === 1
? participantLabel ( sideParticipants [ 0 ] , viewerId )
: s . label ? . trim ( ) || ( isTeam ? "Laget" : "Individuell motstander" )
return {
id : isTeam ? s . id : ( sideParticipants [ 0 ] ? . id ? ? s . id ) ,
side : idx === 0 ? "a" : ( "b" as const ) ,
label ,
hcp : sideParticipants [ 0 ] ? . playing_handicap ? ? null ,
}
} )
: isSharedBall
? round . sides . map ( ( s , idx ) = > ( {
id : s.id ,
side : idx === 0 ? "a" : ( "b" as const ) ,
label : s.label?.trim ( ) || ( idx === 0 ? "Side A" : "Side B" ) ,
hcp : round.participants.find ( ( p ) = > p . round_side_id === s . id ) ? . playing_handicap ? ? null ,
2026-07-29 12:44:51 +02:00
} ) )
2026-08-05 21:37:32 +02:00
: round . participants
. filter ( ( p ) = > p . round_side_id )
. map ( ( p ) = > ( {
id : p.id ,
side : ( p . round_side_id === round . sides [ 0 ] ? . id ? "a" : "b" ) as "a" | "b" ,
label : participantLabel ( p , viewerId ) ,
hcp : p.playing_handicap ,
} ) )
2026-07-29 12:44:51 +02:00
Ja, jeg forsto rekkefølgen — steg 1 og 2 er nå ferdig og scratch-verifisert:
Steg 1 (backend, HCP-prosent + Match-HCP): ny migrasjon 051_round_allowance_override.sql (round.allowance_override jsonb), koblet inn i _recompute_side_handicaps/_relative_strokes_for_round + POST/PATCH /rounds. Verifisert presist i scratch: 100%→50%-prosent ga playing_handicap 24/10 → 12/5 nøyaktig som beregnet for hånd, og use_matchplay_handicap slått av ga rå 12/5 i stedet for differensial 7/0. Slagspill upåvirket (regresjon bekreftet).
Steg 2 (kode-fiks, lag-gruppering): ScorecardGrid (live-scoring) og MatchScorecardGrid (post-runde/fremtidig sammenslått side) sorterer nå stabilt på round_side_id før rendering. Bygget en fersk scratch-fourball-runde med akkurat ditt bug-scenario (A→Rødt, B→Blått, C→Rødt, D→Blått, lagt til i den rekkefølgen) og bekreftet visuelt i nettleseren i begge visningene: Rødt lag vises samlet, deretter Blått — ikke lenger interleaved.
Typesjekk + full produksjonsbuild kompilerte rent gjennom hele runden.
Gjenstår før jeg går videre til V0-promptene: migrasjon 051 er kun kjørt i scratch, ikke mot ekte teecup_db. Planen er:
docker exec -i teeoff_db psql -U teeoff_admin -d teecup_db -v ON_ERROR_STOP=1 < 051_round_allowance_override.sql
— ett rent additivt ALTER TABLE round ADD COLUMN allowance_override jsonb, ingen eksisterende rader berøres. Deretter docker compose up -d --build teecup_api teecup_frontend (backend for allowance-koblingen, frontend for gruppering-fiksen).
Bekreft så kjører jeg dette, og går videre til V0-prompt 1 (rundeoppsett-veiviseren).
2026-08-02 08:24:01 +02:00
// Lagvis gruppering (2026-08-02, "det store grepet") -- individuell-ball-
// formater (match/fourball) bygde tidligere rader i ren
// innsettingsrekkefølge (round.participants sin egen orden), ikke lagvis.
// Stabil sortering på side holder original rekkefølge INNAD i hver
// gruppe. Delt-ball-formater har allerede nøyaktig én rad per side
// (rows[0]="a", rows[1]="b" fra konstruksjonen over) -- no-op der.
rows . sort ( ( a , b ) = > ( a . side === b . side ? 0 : a.side === "a" ? - 1 : 1 ) )
2026-07-29 12:44:51 +02:00
function headerIdentity ( side : "a" | "b" ) : HeaderIdentity {
const sideRows = rows . filter ( ( r ) = > r . side === side )
if ( sideRows . length === 1 ) return { name : sideRows [ 0 ] . label , hcp : sideRows [ 0 ] . hcp }
const idx = side === "a" ? 0 : 1
return { name : round.sides [ idx ] ? . label ? . trim ( ) || ( side === "a" ? "Side A" : "Side B" ) , hcp : null }
}
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! result . ready || ! result . holes ) {
return (
< div className = "rounded-3xl border border-dashed border-border bg-card p-4 text-sm text-muted-foreground sm:p-5" >
Venter på at begge sider er komplette og har beregnet handicap før matchforløpet kan vises .
< / div >
)
}
2026-07-29 12:44:51 +02:00
const decidedHoles = result . holes
const running = computeRunning ( decidedHoles . map ( ( h ) = > h . result as "a" | "b" | "halved" ) , round . holes_planned )
const lastState = running . length > 0 ? running [ running . length - 1 ] : null
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
return (
2026-07-29 12:44:51 +02:00
< div className = "flex flex-col gap-3 rounded-3xl border border-border bg-card p-3 shadow-md shadow-black/8 sm:p-4" >
2026-07-29 16:26:31 +02:00
< LeadBar
identityA = { headerIdentity ( "a" ) }
identityB = { headerIdentity ( "b" ) }
state = { lastState }
holesPlayed = { decidedHoles . length }
totalHoles = { round . holes_planned }
/ >
2026-07-29 12:44:51 +02:00
{ decidedHoles . length === 0 ? (
< p className = "text-sm text-muted-foreground" >
Ingen hull er avgjort ennå . Matchforløpet vises her hull for hull etter hvert som begge sider har
registrert .
< / p >
) : (
< div className = "-mx-3 overflow-x-auto px-3 sm:-mx-4 sm:px-4" >
< table
className = "w-full border-collapse text-sm"
style = { { minWidth : ` ${ 64 + decidedHoles . length * 40 } px ` } }
>
< colgroup >
< col className = "w-16" / >
{ decidedHoles . map ( ( h ) = > (
< col key = { h . hole_number } className = "w-10" / >
) ) }
< / colgroup >
< thead >
< tr >
< th
scope = "col"
className = "border border-border bg-muted px-2 py-1.5 text-left text-xs font-extrabold text-muted-foreground"
>
Hull
< / th >
{ decidedHoles . map ( ( h ) = > (
< th
key = { h . hole_number }
scope = "col"
className = "border border-border bg-foreground py-1.5 text-center text-xs font-extrabold tabular-nums text-background"
>
{ h . hole_number }
< / th >
) ) }
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< / tr >
2026-07-29 12:44:51 +02:00
< / thead >
< tbody >
< tr >
< th
scope = "row"
className = "border border-border px-2 py-1.5 text-left text-xs font-bold text-muted-foreground"
>
Par
< / th >
{ decidedHoles . map ( ( h ) = > (
< td
key = { h . hole_number }
className = "border border-border py-1.5 text-center text-xs font-semibold text-muted-foreground"
>
{ h . par }
< / td >
) ) }
< / tr >
{ rows . map ( ( row ) = > (
< tr key = { row . id } >
< th scope = "row" className = "border border-border px-2 py-1.5 text-left" >
< span className = "flex min-w-0 items-center gap-1.5" >
< span
aria - hidden = "true"
className = { cn (
"size-2 shrink-0 rounded-full" ,
row . side === "a" ? "bg-primary" : "bg-brand-orange" ,
) }
/ >
< span className = "min-w-0 truncate text-xs font-bold text-foreground" > { row . label } < / span >
< / span >
< / th >
{ decidedHoles . map ( ( h ) = > {
const entry = h . entries . find ( ( e ) = > e . id === row . id )
const won = ! ! entry && h . result === row . side && entry . counted !== false
const shown = entry ? ( entry . net ? ? entry . gross ) : null
return (
< td key = { h . hole_number } className = "border border-border p-0.5 text-center" >
< span
aria - label = {
entry
? ` ${ row . label } : ${ shown } netto ${ entry . gross !== null && entry . gross !== shown ? ` , ${ entry . gross } brutto ` : "" } ${ won ? " -- vant hullet" : "" } `
: undefined
}
className = { cn (
"mx-auto flex size-7 items-center justify-center rounded-full text-xs font-extrabold tabular-nums" ,
won
? row . side === "a"
? "bg-primary text-primary-foreground"
: "bg-brand-orange text-brand-orange-foreground"
: entry && entry . counted === false
? "text-muted-foreground/50"
: "text-foreground" ,
) }
>
{ shown ? ? "– " }
< / span >
< / td >
)
} ) }
< / tr >
) ) }
< tr className = "bg-muted/30" >
< th scope = "row" className = "border border-border px-2 py-1.5 text-left text-xs font-extrabold text-foreground" >
Stilling
< / th >
{ running . map ( ( s , i ) = > (
< td
key = { decidedHoles [ i ] . hole_number }
className = { cn (
"border border-border py-1.5 text-center text-xs font-extrabold tabular-nums" ,
s . tone === "a" ? "text-primary" : s . tone === "b" ? "text-brand-orange" : "text-muted-foreground" ,
) }
>
{ s . label }
< / td >
) ) }
< / tr >
< / tbody >
< / table >
< / div >
) }
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< p className = "text-xs text-muted-foreground" >
2026-07-29 12:44:51 +02:00
Fylt sirkel = vunnet hull ( grønn = { headerIdentity ( "a" ) . name } , oransje = { headerIdentity ( "b" ) . name } ) . Nedtonet
tall talte ikke for siden det hullet ( laveste netto teller , gjelder fourball ) .
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< / p >
< / div >
)
}
2026-08-07 22:02:56 +02:00
function SkinsProgressTable ( {
roundId ,
refreshKey ,
apiPrefix = "/rounds" ,
} : {
roundId : string
refreshKey : number
apiPrefix? : string
} ) {
const result = useFormatResult ( roundId , refreshKey , apiPrefix )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! result || ! result . holes || result . holes . length === 0 ) return null
const hasNet = result . holes . some ( ( h ) = > h . entries . some ( ( e ) = > e . net !== null ) )
return (
2026-07-29 12:44:51 +02:00
< div className = "flex flex-col gap-3 rounded-3xl border border-border bg-card p-3 shadow-md shadow-black/8 sm:p-4" >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< h2 className = "text-base font-bold text-foreground" > Skins , hull for hull < / h2 >
< div className = "flex flex-col divide-y divide-border overflow-hidden rounded-2xl border border-border" >
{ result . holes . map ( ( h ) = > (
< div key = { h . hole_number } className = "flex flex-col gap-1.5 px-3 py-2.5" >
< div className = "flex flex-wrap items-center justify-between gap-2" >
< span className = "text-xs font-bold text-muted-foreground" >
Hull { h . hole_number } · Par { h . par }
< / span >
{ h . carried ? (
< span className = "rounded-full border border-border bg-muted px-2 py-0.5 text-[11px] font-bold text-muted-foreground" >
Uavgjort — rullet videre
< / span >
) : h . winner_ids && h . winner_ids . length > 0 ? (
< span className = "rounded-full bg-primary px-2 py-0.5 text-[11px] font-bold text-primary-foreground" >
{ h . winner_ids . length === 1
? ` ${ h . entries . find ( ( e ) = > e . id === h . winner_ids ? . [ 0 ] ) ? . label ? ? "?" } vant skinnet `
: ` Delt: ${ h . winner_ids . map ( ( id ) = > h . entries . find ( ( e ) = > e . id === id ) ? . label ? ? "?" ) . join ( ", " ) } ` }
< / span >
) : null }
< / div >
< div className = "flex flex-wrap gap-x-4 gap-y-1" >
{ h . entries . map ( ( e ) = > {
const isWinner = h . winner_ids ? . includes ( e . id ) ? ? false
const shown = hasNet && e . net !== null ? e.net : e.gross
return (
< span
key = { e . id }
className = { cn (
"flex items-baseline gap-1 text-sm" ,
isWinner ? "font-extrabold text-primary" : "text-foreground" ,
) }
>
{ e . label } : < span className = "tabular-nums" > { shown ? ? "– " } < / span >
{ hasNet && e . net !== null && e . gross !== null && e . net !== e . gross && (
< span className = "text-xs font-normal text-muted-foreground" > ( { e . gross } brutto ) < / span >
) }
< / span >
)
} ) }
< / div >
< / div >
) ) }
< / div >
< p className = "text-xs text-muted-foreground" >
{ hasNet ? "Skins avgjøres på netto (brutto vist i parentes)." : "Skins avgjøres på brutto." } Et uavgjort hull
ruller potten videre til neste hull .
< / p >
< / div >
)
}
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
// --- Screen ----------------------------------------------------------------
2026-08-02 16:34:54 +02:00
export function RoundScorecard ( {
roundId ,
embedded = false ,
2026-08-07 22:02:56 +02:00
publicMode = false ,
2026-08-02 16:34:54 +02:00
} : {
roundId : string
// ADR-040 Beslutning D ("det store grepet") -- Scorekort+Statistikk
// slått sammen til ÉN side. `embedded` dropper denne komponentens egen
// sticky header (den delte `RoundHeader`, wired inn av
// `RoundPageShell`, dekker det nå) når den rendres som øverste halvdel
// av den slåtte sammen siden, i stedet for standalone.
embedded? : boolean
2026-08-07 22:02:56 +02:00
// ADR-044 (tilskuer-visning, 2026-08-06) -- gjenbruker DENNE komponenten
// uendret for `/watch/{id}/scorecard`, kun med annen datakilde: alle
// `/rounds/*`-kall byttes til `/public/rounds/*` (samme respons-form,
// `_can_view_round`-autorisert i stedet for eier/medspiller-only), og
// WS-kanalen byttes til den offentlige. INGEN visuell/atferdsmessig
// endring når `publicMode` er `false` (standard) -- eiersiden er
// uberørt.
publicMode? : boolean
2026-08-02 16:34:54 +02:00
} ) {
2026-08-07 22:02:56 +02:00
const apiPrefix = publicMode ? "/public/rounds" : "/rounds"
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const [ round , setRound ] = useState < ApiRound | null > ( null )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const [ unitId , setUnitId ] = useState < string | null > ( null )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const [ holes , setHoles ] = useState < ApiHole [ ] | null > ( null )
const [ error , setError ] = useState < string | null > ( null )
2026-07-26 08:22:41 +02:00
const [ viewerId , setViewerId ] = useState < string | null > ( null )
2026-07-26 08:49:37 +02:00
// Sanntid (2026-07-26, oppfølging av ADR-027): et rent "noe endret seg"-
// signal over WebSocket -- bumper denne, som er med i begge fetch-
// effektene under, slik at de henter på nytt akkurat som ved
// førstegangslasting (samme mønster som public-live.tsx).
const [ refreshKey , setRefreshKey ] = useState ( 0 )
2026-07-26 08:22:41 +02:00
useEffect ( ( ) = > {
let cancelled = false
fetch ( "/auth/me" , { credentials : "include" } )
. then ( ( res ) = > ( res . ok ? res . json ( ) : null ) )
. then ( ( data : { id : string } | null ) = > {
if ( ! cancelled && data ) setViewerId ( data . id )
} )
. catch ( ( ) = > { } )
return ( ) = > {
cancelled = true
}
} , [ ] )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
2026-07-26 08:49:37 +02:00
useEffect ( ( ) = > {
const protocol = window . location . protocol === "https:" ? "wss:" : "ws:"
2026-08-07 22:02:56 +02:00
const wsPath = publicMode ? "ws/public/rounds" : "ws/rounds"
const socket = new WebSocket ( ` ${ protocol } // ${ window . location . host } / ${ wsPath } / ${ roundId } /live ` )
2026-07-26 08:49:37 +02:00
socket . onmessage = ( ) = > setRefreshKey ( ( k ) = > k + 1 )
return ( ) = > socket . close ( )
2026-08-07 22:02:56 +02:00
} , [ roundId , publicMode ] )
2026-07-26 08:49:37 +02:00
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
useEffect ( ( ) = > {
let cancelled = false
async function load() {
2026-08-07 22:02:56 +02:00
const res = await fetch ( ` ${ apiPrefix } / ${ roundId } ` , { credentials : "include" } )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
if ( res . status === 403 || res . status === 404 ) {
if ( ! cancelled ) setError ( "Denne runden finnes ikke, eller du har ikke tilgang til den." )
return
}
if ( ! res . ok ) {
if ( ! cancelled ) setError ( "Klarte ikke å hente runden. Prøv igjen om litt." )
return
}
const data : ApiRound = await res . json ( )
if ( cancelled ) return
setRound ( data )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const isSharedBall = SHARED_BALL_FORMATS . includes ( data . play_format )
setUnitId ( ( prev ) = > {
if ( prev ) return prev
2026-08-05 21:37:32 +02:00
// scramble_solo-familien (migrasjon 056/057) -- blandet enhetstype
// (laget = en SIDE, individualspilleren = en PARTICIPANT, se
// units-bygging under). Standardvalg: individualspillerens egen
// rad hvis DET er den spørrende brukeren, ellers lagsiden.
if ( SCRAMBLE_SOLO_FORMATS . has ( data . play_format ) ) {
const individualSide = data . sides . find ( ( s ) = > s . side_role === "individual" )
const individualParticipant = individualSide
? data . participants . find ( ( p ) = > p . round_side_id === individualSide . id )
: undefined
if ( viewerId && individualParticipant ? . user_id === viewerId ) return individualParticipant . id
const teamSide = data . sides . find ( ( s ) = > s . side_role === "team" )
return teamSide ? . id ? ? data . sides [ 0 ] ? . id ? ? null
}
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( isSharedBall ) {
const viewerParticipant = viewerId ? data . participants . find ( ( p ) = > p . user_id === viewerId ) : undefined
return viewerParticipant ? . round_side_id ? ? data . sides [ 0 ] ? . id ? ? null
}
// Standardvalg: SIN EGEN rad hvis man er en lenket medspiller,
// ellers eieren (samme som før ADR-036 fase 3-utvidelsen).
return (
2026-07-26 08:22:41 +02:00
( viewerId && data . participants . find ( ( p ) = > p . user_id === viewerId ) ? . id ) ? ?
data . participants . find ( ( p ) = > p . is_owner ) ? . id ? ?
data . participants [ 0 ] ? . id ? ?
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
null
)
} )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
}
void load ( )
return ( ) = > {
cancelled = true
}
2026-08-07 22:02:56 +02:00
} , [ roundId , viewerId , refreshKey , apiPrefix ] )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
useEffect ( ( ) = > {
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! unitId || ! round ) return
2026-08-05 21:37:32 +02:00
// scramble_solo (migrasjon 056) har BLANDEDE enhetstyper i samme
// fane-liste (laget = side, individualspilleren = participant) -- slå
// opp faktisk type fra selve unitId i stedet for et format-bredt
// isSharedBall-flagg, som ikke kan uttrykke en blanding. Denne
// oppslags-tilnærmingen er samtidig korrekt uendret for de rene
// delt-ball-/individuell-ball-formatene (alle enheter er da alltid
// den ene eller den andre typen).
const isSideUnit = round . sides . some ( ( s ) = > s . id === unitId )
const endpoint = isSideUnit
2026-08-07 22:02:56 +02:00
? ` ${ apiPrefix } / ${ roundId } /sides/ ${ unitId } /holes `
: ` ${ apiPrefix } / ${ roundId } /participants/ ${ unitId } /holes `
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
let cancelled = false
async function loadHoles() {
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const res = await fetch ( endpoint , { credentials : "include" } )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
if ( ! res . ok ) return
const data : ApiHole [ ] = await res . json ( )
if ( ! cancelled ) setHoles ( data )
}
void loadHoles ( )
return ( ) = > {
cancelled = true
}
2026-08-07 22:02:56 +02:00
} , [ roundId , unitId , round ? . play_format , refreshKey , apiPrefix ] )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
if ( error ) {
return (
< div className = "flex min-h-dvh flex-col items-center justify-center gap-4 bg-background px-5 text-center" >
< p className = "text-base font-medium text-destructive" > { error } < / p >
2026-08-07 22:02:56 +02:00
< Link
href = { publicMode ? "/dashboard" : "/my-rounds" }
className = "text-base font-semibold text-primary underline underline-offset-2"
>
{ publicMode ? "Tilbake til dashbordet" : "Tilbake til egne runder" }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / Link >
< / div >
)
}
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! round ) {
return (
< div className = "flex min-h-dvh flex-col items-center justify-center bg-background" >
< div aria-hidden = "true" className = "size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary" / >
< / div >
)
}
const isSharedBall = SHARED_BALL_FORMATS . includes ( round . play_format )
const isTwoSided = TWO_SIDED_FORMATS . includes ( round . play_format )
const isSkins = round . play_format === "skins"
2026-08-05 21:37:32 +02:00
const isScrambleSolo = SCRAMBLE_SOLO_FORMATS . has ( round . play_format )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
const formatLabel = FORMAT_LABELS [ round . play_format ] ? ? round . play_format
2026-08-05 21:37:32 +02:00
// Delt-ball-formater OG scramble_solo trenger sidene opprettet (via
// runde-siden sin "Spillere og runde"-fane) FØR noe scorekort gir
// mening her -- vis en forklarende melding i stedet for en evig
// lastespinner.
if ( ( isSharedBall || isScrambleSolo ) && round . sides . length < 2 ) {
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
return (
2026-08-02 16:34:54 +02:00
< div className = { cn ( ! embedded && "min-h-dvh bg-background" ) } >
{ ! embedded && (
< header className = "sticky top-0 z-10 border-b border-border bg-background/95 backdrop-blur" >
< div className = "mx-auto flex min-h-14 max-w-xl items-center gap-2 px-4 py-2" >
< Link
2026-08-07 22:02:56 +02:00
href = { publicMode ? ` /watch/ ${ roundId } ` : ` /my-rounds/ ${ roundId } ` }
2026-08-02 16:34:54 +02:00
className = "flex min-h-11 items-center gap-1.5 rounded-xl pr-3 text-base font-bold text-foreground transition-colors hover:text-primary"
>
< ArrowLeft aria-hidden = "true" className = "size-6" / >
Scorekort
< / Link >
< / div >
< / header >
) }
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< main className = "mx-auto flex max-w-xl flex-col gap-4 px-4 py-5" >
< div className = "rounded-3xl border border-dashed border-border bg-card p-4 text-sm text-muted-foreground" >
2026-08-05 21:37:32 +02:00
{ isScrambleSolo
? ` ${ formatLabel } krever at både laget og individualspilleren er satt opp som egne sider. Opprett dem på selve runde-siden (fanen "Spillere og runde") før scorekortet kan vises her. `
: ` ${ formatLabel } spilles med to sider (ett felles slagtall per side). Opprett sidene på selve runde-siden (fanen "Spillere og runde") før scorekortet kan vises her. ` }
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< / div >
< / main >
< / div >
)
}
2026-08-05 21:37:32 +02:00
// scramble_solo (migrasjon 056) -- blandet enhetsliste: laget er en
// SIDE-fane (delt ball), individualspilleren er en PARTICIPANT-fane
// (egen ball) -- IKKE lagt til SHARED_BALL_FORMATS, det ville feilaktig
// behandlet BEGGE fanene som sider (se hull-hente-effekten over, som
// slår opp faktisk type fra unitId).
const units : { id : string ; label : string } [ ] = isScrambleSolo
? ( ( ) = > {
const teamSide = round . sides . find ( ( s ) = > s . side_role === "team" )
const individualSide = round . sides . find ( ( s ) = > s . side_role === "individual" )
const individualParticipant = individualSide
? round . participants . find ( ( p ) = > p . round_side_id === individualSide . id )
: undefined
const list : { id : string ; label : string } [ ] = [ ]
if ( teamSide ) list . push ( { id : teamSide.id , label : teamSide.label?.trim ( ) || "Laget" } )
if ( individualParticipant ) list . push ( { id : individualParticipant.id , label : participantLabel ( individualParticipant , viewerId ) } )
return list
} ) ( )
: isSharedBall
? round . sides . map ( ( s , idx ) = > ( { id : s.id , label : s.label?.trim ( ) || ( idx === 0 ? "Side A" : "Side B" ) } ) )
: round . participants . map ( ( p ) = > ( { id : p.id , label : participantLabel ( p , viewerId ) } ) )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
if ( ! holes ) {
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
return (
< div className = "flex min-h-dvh flex-col items-center justify-center bg-background" >
< div aria-hidden = "true" className = "size-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary" / >
< / div >
)
}
// Samme sirkulære start_hole-rekkefølge som round-detail.tsx/round-stats.tsx
// -- "Ut"/"Inn" er dermed første/andre halvdel AV SPILLEREKKEFØLGEN, ikke
// nødvendigvis fysisk hull 1-9/10-18 (relevant kun for en 18-hulls runde
// med et annet starthull enn 1, uvanlig men strukturelt tillatt).
const holeOrder = Array . from (
{ length : round.holes_planned } ,
( _ , i ) = > ( ( round . start_hole - 1 + i ) % 18 ) + 1 ,
)
const orderedHoles = holeOrder
. map ( ( n ) = > holes . find ( ( h ) = > h . hole_number === n ) )
. filter ( ( h ) : h is ApiHole = > h !== undefined )
const front = orderedHoles . slice ( 0 , 9 )
const back = orderedHoles . slice ( 9 , 18 )
const showStableford = holes . some ( ( h ) = > h . strokes_received !== null )
2026-08-03 17:30:57 +02:00
// Detaljrader (2026-08-03) -- vis kun rader som faktisk har data et sted
// i runden (samme "vis kun det som faktisk finnes"-prinsipp som resten
// av appen), regnet ut fra HELE runden (ikke bare front/back for seg)
// slik at begge blokkene konsekvent viser/skjuler de samme radene.
const showFairway = holes . some ( ( h ) = > h . par !== 3 && h . tee_shot_result !== null )
const showPutts = holes . some ( ( h ) = > h . putts !== null )
const showGir = holes . some ( ( h ) = > h . score !== null && h . putts !== null )
const showApproach = holes . some ( ( h ) = > h . approach_result !== null )
const showChip = holes . some ( ( h ) = > h . chip_count !== null )
const showBunker = holes . some ( ( h ) = > h . bunker_shot_count !== null )
const showPenalty = holes . some ( ( h ) = > h . penalty_strokes !== null )
const showAnyway = holes . some ( ( h ) = > h . anyway_strokes !== null )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const playedHoles = orderedHoles . filter ( ( h ) = > h . played && h . score !== null )
All done and verified live in the browser. Summary of this round:
"Kommende runder" → "Runder" on the dashboard.
Tjøme course-name duplicate fixed in the real database (one round's stale course_name_snapshot corrected) — all three of your rounds now group under one "Tjøme Golfklubb" entry.
Two new colors, per your request for two: lifted the already-validated --chart-3 (blue → --info) and --chart-4 (gold → --gold) into core design tokens. First real uses: a blue "Hcp spilt til X" badge on round cards, and a gold "Personlig rekord" badge on your best completed round.
Clicking a course under "Spilte baner" now opens a new page listing every round played there (/my-rounds/course/[name]) — caught and fixed a real double-encoding bug here via an actual browser screenshot before shipping.
Aggregated statistics, clickable from the dashboard's "Statistikk" section (/my-rounds/stats): rounds completed, avg to-par, putts/18 holes (implementing your padding rule exactly — unplayed holes count as 2 putts, only for rounds where putt-tracking was on), fairway%, GIR%, one-putt%, scrambling%, sand save%, and chip/bunker/penalty/anywayslag averages per round.
Everything is typechecked, the putts-padding logic is verified against a hand-computed synthetic dataset, and all new screens were checked live in the browser with no console errors.
2026-07-28 07:04:56 +02:00
// Full rundens par (statisk referanse, f.eks. "Par 72") -- ALDRI brukt til
// en til-par-utregning, kun til "Par"-feltet nederst som viser hele
// runden uansett hvor langt man har kommet.
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const totalPar = sum ( orderedHoles . map ( ( h ) = > h . par ) )
All done and verified live in the browser. Summary of this round:
"Kommende runder" → "Runder" on the dashboard.
Tjøme course-name duplicate fixed in the real database (one round's stale course_name_snapshot corrected) — all three of your rounds now group under one "Tjøme Golfklubb" entry.
Two new colors, per your request for two: lifted the already-validated --chart-3 (blue → --info) and --chart-4 (gold → --gold) into core design tokens. First real uses: a blue "Hcp spilt til X" badge on round cards, and a gold "Personlig rekord" badge on your best completed round.
Clicking a course under "Spilte baner" now opens a new page listing every round played there (/my-rounds/course/[name]) — caught and fixed a real double-encoding bug here via an actual browser screenshot before shipping.
Aggregated statistics, clickable from the dashboard's "Statistikk" section (/my-rounds/stats): rounds completed, avg to-par, putts/18 holes (implementing your padding rule exactly — unplayed holes count as 2 putts, only for rounds where putt-tracking was on), fairway%, GIR%, one-putt%, scrambling%, sand save%, and chip/bunker/penalty/anywayslag averages per round.
Everything is typechecked, the putts-padding logic is verified against a hand-computed synthetic dataset, and all new screens were checked live in the browser with no console errors.
2026-07-28 07:04:56 +02:00
// Til-par MÅ regnes mot paret for kun de SPILTE hullene -- ellers blir
// "til par" meningsløst midt i runden (f.eks. 19 slag på 4 hull ville vist
// "− 53 til par" mot en 72-par bane i stedet for korrekt "+2", funnet ved
// faktisk nettleser-testing 2026-07-27).
const playedPar = playedHoles . length > 0 ? sum ( playedHoles . map ( ( h ) = > h . par ) ) : 0
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
const totalGross = playedHoles . length > 0 ? sum ( playedHoles . map ( ( h ) = > h . score as number ) ) : null
const totalPointsValues = orderedHoles . map ( stablefordPoints ) . filter ( ( n ) : n is number = > n !== null )
const totalPoints = totalPointsValues . length > 0 ? sum ( totalPointsValues ) : null
return (
2026-08-02 16:34:54 +02:00
< div className = { cn ( ! embedded && "min-h-dvh bg-background" ) } >
{ ! embedded && (
< header className = "sticky top-0 z-10 border-b border-border bg-background/95 backdrop-blur" >
< div className = "mx-auto flex min-h-14 max-w-xl items-center gap-2 px-4 py-2" >
< Link
2026-08-07 22:02:56 +02:00
href = { publicMode ? ` /watch/ ${ roundId } ` : ` /my-rounds/ ${ roundId } ` }
2026-08-02 16:34:54 +02:00
className = "flex min-h-11 items-center gap-1.5 rounded-xl pr-3 text-base font-bold text-foreground transition-colors hover:text-primary"
>
< ArrowLeft aria-hidden = "true" className = "size-6" / >
Scorekort
< / Link >
< / div >
< / header >
) }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< main className = "mx-auto flex max-w-xl flex-col gap-4 px-4 py-5 pb-16" >
{ /* Round summary strip */ }
2026-07-29 12:44:51 +02:00
< div className = "flex flex-wrap items-baseline justify-between gap-2 rounded-3xl border border-border bg-card p-4 shadow-md shadow-black/8" >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< div className = "flex flex-col" >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
< span className = "flex flex-wrap items-center gap-2" >
< span className = "text-xl font-extrabold tracking-tight text-foreground text-balance" >
{ round . name ? . trim ( ) || round . course_name_snapshot }
< / span >
{ round . play_format !== "stroke" && (
< span className = "rounded-full bg-muted px-2 py-0.5 text-xs font-bold text-muted-foreground" >
{ formatLabel }
< / span >
) }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / span >
< span className = "text-sm font-semibold text-muted-foreground" >
2026-07-25 06:29:09 +02:00
{ round . name ? . trim ( ) ? ` ${ round . course_name_snapshot } · ` : "" }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
{ round . tee_name_snapshot } { "·" } { round . holes_planned } hull { "·" } { " " }
{ dateFormatter . format ( new Date ( round . played_at ) ) }
< / span >
< / div >
{ totalGross !== null && (
< div className = "flex flex-col items-end" >
< span className = "text-3xl font-extrabold tabular-nums text-foreground" > { totalGross } < / span >
All done and verified live in the browser. Summary of this round:
"Kommende runder" → "Runder" on the dashboard.
Tjøme course-name duplicate fixed in the real database (one round's stale course_name_snapshot corrected) — all three of your rounds now group under one "Tjøme Golfklubb" entry.
Two new colors, per your request for two: lifted the already-validated --chart-3 (blue → --info) and --chart-4 (gold → --gold) into core design tokens. First real uses: a blue "Hcp spilt til X" badge on round cards, and a gold "Personlig rekord" badge on your best completed round.
Clicking a course under "Spilte baner" now opens a new page listing every round played there (/my-rounds/course/[name]) — caught and fixed a real double-encoding bug here via an actual browser screenshot before shipping.
Aggregated statistics, clickable from the dashboard's "Statistikk" section (/my-rounds/stats): rounds completed, avg to-par, putts/18 holes (implementing your padding rule exactly — unplayed holes count as 2 putts, only for rounds where putt-tracking was on), fairway%, GIR%, one-putt%, scrambling%, sand save%, and chip/bunker/penalty/anywayslag averages per round.
Everything is typechecked, the putts-padding logic is verified against a hand-computed synthetic dataset, and all new screens were checked live in the browser with no console errors.
2026-07-28 07:04:56 +02:00
< span className = "text-sm font-bold text-brand-orange" > { signedToPar ( totalGross , playedPar ) } til par < / span >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / div >
) }
< / div >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
{ /* Enhets-velger (spillere, eller SIDER for delt-ball-formater) */ }
{ units . length > 1 && (
2026-08-05 21:37:32 +02:00
< div role = "tablist" aria-label = { isScrambleSolo ? "Velg lag eller motstander" : isSharedBall ? "Velg side" : "Velg spiller" } className = "-mx-4 overflow-x-auto px-4" >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< div className = "flex gap-2" >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
{ units . map ( ( u ) = > {
const active = u . id === unitId
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
return (
< button
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
key = { u . id }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
type = "button"
role = "tab"
aria - selected = { active }
onClick = { ( ) = > {
setHoles ( null )
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
setUnitId ( u . id )
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
} }
className = { cn (
"flex min-h-11 shrink-0 items-center rounded-2xl border px-4 text-base font-bold transition-colors" ,
active
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-card text-foreground hover:bg-accent/50" ,
) }
>
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
{ u . label }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / button >
)
} ) }
< / div >
< / div >
) }
{ /* Scorecard blocks */ }
2026-08-03 17:30:57 +02:00
< div className = "flex flex-col gap-3 overflow-x-auto rounded-3xl border border-border bg-card p-3 shadow-md shadow-black/8 sm:p-4" >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
{ front . length > 0 && (
2026-08-03 17:30:57 +02:00
< ScoreBlock
holes = { front }
summaryLabel = { back . length === 0 ? "Tot" : "Ut" }
showStableford = { showStableford }
showFairway = { showFairway }
showPutts = { showPutts }
showGir = { showGir }
showApproach = { showApproach }
showChip = { showChip }
showBunker = { showBunker }
showPenalty = { showPenalty }
showAnyway = { showAnyway }
/ >
) }
{ back . length > 0 && (
< ScoreBlock
holes = { back }
summaryLabel = "Inn"
showStableford = { showStableford }
showFairway = { showFairway }
showPutts = { showPutts }
showGir = { showGir }
showApproach = { showApproach }
showChip = { showChip }
showBunker = { showBunker }
showPenalty = { showPenalty }
showAnyway = { showAnyway }
/ >
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
) }
< / div >
{ /* Combined total */ }
< div className = { cn ( "grid gap-2" , showStableford ? "grid-cols-4" : "grid-cols-3" ) } >
< TotalTile label = "Par" value = { String ( totalPar ) } / >
< TotalTile label = "Score" value = { totalGross !== null ? String ( totalGross ) : "– " } / >
< TotalTile
label = "Til par"
All done and verified live in the browser. Summary of this round:
"Kommende runder" → "Runder" on the dashboard.
Tjøme course-name duplicate fixed in the real database (one round's stale course_name_snapshot corrected) — all three of your rounds now group under one "Tjøme Golfklubb" entry.
Two new colors, per your request for two: lifted the already-validated --chart-3 (blue → --info) and --chart-4 (gold → --gold) into core design tokens. First real uses: a blue "Hcp spilt til X" badge on round cards, and a gold "Personlig rekord" badge on your best completed round.
Clicking a course under "Spilte baner" now opens a new page listing every round played there (/my-rounds/course/[name]) — caught and fixed a real double-encoding bug here via an actual browser screenshot before shipping.
Aggregated statistics, clickable from the dashboard's "Statistikk" section (/my-rounds/stats): rounds completed, avg to-par, putts/18 holes (implementing your padding rule exactly — unplayed holes count as 2 putts, only for rounds where putt-tracking was on), fairway%, GIR%, one-putt%, scrambling%, sand save%, and chip/bunker/penalty/anywayslag averages per round.
Everything is typechecked, the putts-padding logic is verified against a hand-computed synthetic dataset, and all new screens were checked live in the browser with no console errors.
2026-07-28 07:04:56 +02:00
value = { totalGross !== null ? signedToPar ( totalGross , playedPar ) : "– " }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
tone = "orange"
/ >
{ showStableford && < TotalTile label = "Poeng" value = { totalPoints !== null ? String ( totalPoints ) : "– " } tone = "green" / > }
< / div >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
{ /* Matchforløp / skins - forløp -- HVORFOR ble resultatet som det ble
( brutto / netto / slag mottatt per hull ) , ikke bare et sluttall . * / }
{ isTwoSided && round . sides . length === 2 && (
2026-08-07 22:02:56 +02:00
< MatchScorecardGrid round = { round } roundId = { roundId } viewerId = { viewerId } refreshKey = { refreshKey } apiPrefix = { apiPrefix } / >
Ferdig og live. Oppsummert:
Offline-køen fra ADR-028 (turnering-scorekortet) er nå portert til frittstående runder — begge scoringsveivisere (vanlig og delt-ball) fungerer offline.
Portingen ble faktisk enklere enn originalen: siden PATCH-endepunktene for frittstående runder erstatter hele hull-raden per kall, kunne en køet skriving speiles direkte inn i lokal state uten egne verdi-overlays.
Samme mønster som originalen: navigator.onLine-sjekk, nettverksfeil fanges og køes, automatisk synk når nettet kommer tilbake, manuell "Synkroniser nå"-knapp, og en "Lagret lokalt · venter på synk"-indikator i selve veiviseren.
Faktisk browserverifisert denne gangen (i motsetning til den opprinnelige ADR-028-runden, som aldri ble testet i praksis) — brukte Chrome DevTools sin ekte offline-emulering: registrerte score offline, bekreftet kø i IndexedDB, gikk online igjen, bekreftet automatisk synk og at serveren faktisk mottok riktige verdier. Gjort for begge veivisertypene.
Ingen migrasjon — rullet ut mot ekte systemer, begge containere boot-et rent, teeoff.no upåvirket.
2026-07-28 18:17:49 +02:00
) }
2026-08-07 22:02:56 +02:00
{ isSkins && < SkinsProgressTable roundId = { roundId } refreshKey = { refreshKey } apiPrefix = { apiPrefix } / > }
Nytt horisontalt scorekort (/my-rounds/[id]/scorecard) — ekte HTML-tabell med faste kolonnebredder, ingen scroll i det hele tatt. Score-cellene bruker form (sirkel = under par, firkant = over par) + fylt/ufylt i stedet for farge alene, med egen symbolforklaring. Ut/Inn-blokker for 18-hulls runder, én blokk for 9-hulls. Egen dedikert side (ikke sammenslått med statistikk-siden), lenket fra både "Runde fullført"-banneret og fra statistikk-siden. Byttet ut V0s egen forenklede HCP-formel med backends allerede beregnede strokes_received, så det ikke finnes to ulike slagfordelings-implementasjoner i appen. Den gamle vertikale scorekort-tabellen i statistikk-siden er fjernet — nå bor det rå scorekortet kun ett sted.
Anywayslag-fiksen din: lagt til som en tredje flis ved siden av Bunkerslag/Straffeslag, og seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" — notert i .md-filene at et notatfelt trolig kommer dit senere.
Ekte typesjekket build, ingen backend-endring nødvendig, teeoff.no upåvirket.
2026-07-24 23:33:41 +02:00
< / main >
< / div >
)
}