Trekkspillet på statistikk-siden viser nå sammenslått som default — alle seksjonene (Scorer, Fairway, GIR, osv.) er kollapset til man trykker på dem. Rullet ut live.

Notert i FEATURE_BACKLOG.md: Flaggturnering lagt til som et femte fremtidig turneringsformat, med kravet om en gjenstående-slag-visning (oppdatert per hull) og den betingede fremtidsideen om GPS-basert markering av hvor langt spilleren kom — ingenting bygget, bare fanget opp slik at det ikke går i glemmeboken.
This commit is contained in:
Erol Haagenrud 2026-07-25 05:32:23 +02:00
parent bba63b6cc9
commit 714c64e82e
4 changed files with 87 additions and 42 deletions

View file

@ -2570,16 +2570,27 @@ uendret bortsett fra å rette `/rounds/...`-hrefs til `/my-rounds/...`.
Anywayslag manglet helt fra `round-stats.tsx` sin "Chip, bunker og
straffeslag"-seksjon (verken `anyway_strokes` i `ApiHole`-typen eller
noe utledet total fantes). Lagt til `anyway_strokes` i typen, ny
`anywayPerRound`-aggregat i `computeStats()`, ny generalisert
`StatTileRow`-komponent (2 ELLER 3 fliser -- `StatTilePair` var fast to)
brukt for Bunkerslag/Straffeslag/(Anywayslag når tilgjengelig).
Seksjonen omdøpt fra "Chip, bunker og straffeslag" til "Annet" (bredere
navn, bruker nevnte at et fritekst-notatfelt trolig havner der senere).
`anywayPerRound`-aggregat i `computeStats()`.
**Feilrettet SAMME dag, rett etterpå:** min første fiks slo sammen
Anywayslag-tallet INN I den eksisterende "Chip, bunker og
straffeslag"-seksjonen og omdøpte HELE seksjonen til "Annet" -- feil,
påpekt av bruker. Rettet: "Chip, bunker og straffeslag" beholder sitt
opprinnelige navn og innhold UENDRET (Bunkerslag/Straffeslag-flisene
tilbake til to, ikke tre). Ny, EGEN "Annet"-seksjon lagt til RETT ETTER
den (ikke slått sammen), med kun Anywayslag-statistikk: total per runde
+ andel hull med minst ett anywayslag (samme "andel hull med..."-mønster
som straffeslag-statistikken). Ny `pctHolesWithAnyway`-beregning i
`computeStats()`. Den midlertidige `StatTileRow`-komponenten (bygget for
den feilaktig sammenslåtte tre-flis-varianten) fjernet igjen som dødt
kode -- `StatTilePair` (fast to fliser) er tilstrekkelig for begge
seksjonene nå. Notert for senere: brukeren ser for seg at et
fritekst-notatfelt havner i "Annet"-seksjonen etter hvert.
**Verifisert:** ekte typesjekket produksjonsbuild kjørt og bekreftet,
ny rute `/my-rounds/[id]/scorecard` listet. Ingen ny backend-endring
(`anyway_strokes`/`strokes_received` fantes allerede i `RoundHoleOut`).
**Rullet ut live 2026-07-25**, ren frontend-endring, ingen migrasjon,
`teeoff.no` upåvirket.
**Rullet ut live 2026-07-25** (to runder, feilrettingen rullet ut rett
etter originalen), ren frontend-endring, ingen migrasjon, `teeoff.no`
upåvirket.
**Motor-komponenten (punkt 1-11) er ✅ BYGGET OG TESTET 2026-07-22,**
som første, isolerte byggesteg (ren Python, ingen DB/API/frontend ennå —

View file

@ -2533,12 +2533,29 @@ Ferdig og verifisert:
til en "Se scorekort"-knapp i `CompletedBanner` (round-detail.tsx) ved
siden av den eksisterende "Se full rundestatistikk" -- tatt inn.
**Samtidig, rapportert av bruker:** Anywayslag manglet helt fra
rundestatistikk-siden sin "Chip, bunker og straffeslag"-seksjon --
lagt til som en tredje per-runde-flis, og seksjonen omdøpt til "Annet"
(bredere navn, siden et notatfelt trolig havner der senere også).
Ekte typesjekket build kjørt og bekreftet (ny rute
`/my-rounds/[id]/scorecard` listet). Rullet ut, ren frontend-endring,
ingen backend/migrasjon, `teeoff.no` upåvirket.
rundestatistikk-siden sin "Chip, bunker og straffeslag"-seksjon.
**Feilrettet rett etterpå, samme dag:** min første fiks slo feilaktig
sammen Anywayslag-tallet i DEN eksisterende seksjonen og omdøpte hele
seksjonen til "Annet" -- brukeren påpekte at "Chip, bunker og
straffeslag" skulle beholde navn+innhold uendret, og at "Annet" skulle
være en EGEN, ny seksjon RETT ETTER med kun anywayslag-tall (total per
runde + andel hull med anywayslag). Rettet umiddelbart. Notert at et
fritekst-notatfelt trolig havner i "Annet" senere. Ekte typesjekket
build kjørt og bekreftet (ny rute `/my-rounds/[id]/scorecard` listet).
Rullet ut (to runder), ren frontend-endring, ingen backend/migrasjon,
`teeoff.no` upåvirket.
- **Rundestatistikk-seksjonene starter nå kollapset, LIVE samme dag
(2026-07-25):** brukeren ba om at "trekkspillet" (StatCard-seksjonene
`/my-rounds/[id]/stats`) skal vises sammenslått -- må klikkes for å
se innholdet. `StatCard` sin `defaultOpen` endret fra `true` til
`false` (ingen kallsted overstyrte den, så én linje dekket alle
seksjonene). Ekte typesjekket build, rullet ut, `teeoff.no` upåvirket.
- **Notert i FEATURE_BACKLOG.md, IKKE bygget:** brukeren ba om et notat
om et femte fremtidig turneringsformat, "Flaggturnering" (utover de
fire fra 2026-07-19-runden) -- krever en visning av GJENSTÅENDE slag
for spilleren, oppdatert etter hvert hull, pluss en fremtidig idé om
å bruke GPS (når/hvis integrert) til å markere hvor langt spilleren
faktisk kom. Lagt til i samme seksjon som de fire andre formatene.
Neste steg:
1. **Pauset, venter på retning:** dashbordets tom-tilstand ved første

View file

@ -545,6 +545,21 @@
poengmodell, bare en annen fremgangsmåte de to første slagene) — trenger
trolig ikke ny datamodell, bare en presisering i regelverket/UI-teksten.
**«Flaggturnering»** (Flag tournament), reist av bruker 2026-07-25 —
IKKE del av den opprinnelige fire-formater-listen over, notert som et
eget femte format. Hver spiller får et fast antall slag (typisk par +
handicap for hele runden) og spiller til slagene er brukt opp — den som
kommer lengst rundt banen før slagene tar slutt, vinner ("planter
flagget" der siste slag ble brukt). **Konkret krav fra bruker, eksplisitt
formulert:** en visning som viser GJENSTÅENDE slag for spilleren,
oppdatert etter hvert spilte hull (nedtelling, ikke bare et sluttall).
**Fremtidig idé, uttrykkelig betinget av at GPS er integrert i appen
først** (se GPS/avstandsmåling-notatet lenger opp i denne filen, ADR-033-
seksjonen — samme avhengighet): bruk GPS til å markere/registrere HVOR på
banen spilleren faktisk endte opp når slagene tok slutt, ikke bare hvilket
hull. Ingen datamodell eller UI designet ennå for noen del av dette —
rent notat.
- **Ingenting av dette er designet eller bygget ennå** — kun fanget her slik
at det ikke går i glemmeboken. Naturlig neste steg når dette tas fatt på:
vurder de fire hver for seg (ikke som én stor runde), start med «Try all»

View file

@ -18,6 +18,7 @@ import {
ChevronRight,
Flag,
Info,
MoreHorizontal,
MoveHorizontal,
Target,
Wind,
@ -56,7 +57,10 @@ const C = {
function StatCard({
title,
icon: Icon,
defaultOpen = true,
// Alle seksjonene starter kollapset (etterspurt av bruker 2026-07-25:
// "trekkspillet skal vises sammenslått") -- må trykkes på hver enkelt
// for å se innholdet, i stedet for at hele siden lastes åpen.
defaultOpen = false,
children,
}: {
title: string
@ -252,22 +256,6 @@ function ProgressRow({
)
}
// --- Row of N stat tiles (2 eller 3 -- StatTilePair er en fast to-tiles-
// variant, denne generaliserer for "Annet"-seksjonens tre per-runde-tall) ---
function StatTileRow({ tiles }: { tiles: { label: string; value: string }[] }) {
return (
<div className={cn("grid gap-3", tiles.length === 3 ? "grid-cols-3" : "grid-cols-2")}>
{tiles.map((t) => (
<div key={t.label} className="flex flex-col gap-1 rounded-2xl border border-border bg-muted/40 p-4">
<span className="text-3xl font-extrabold tabular-nums text-foreground">{t.value}</span>
<span className="text-sm font-semibold leading-snug text-muted-foreground text-pretty">{t.label}</span>
</div>
))}
</div>
)
}
// --- Paired stat tiles -----------------------------------------------------
function StatTilePair({
@ -519,6 +507,10 @@ function computeStats(holes: ApiHole[]) {
const anywayEligible = played.filter((h) => h.anyway_strokes !== null)
const anywayPerRound =
anywayEligible.length > 0 ? anywayEligible.reduce((s, h) => s + (h.anyway_strokes as number), 0) : null
const pctHolesWithAnyway =
anywayEligible.length > 0
? (anywayEligible.filter((h) => (h.anyway_strokes as number) >= 1).length / anywayEligible.length) * 100
: null
return {
playedCount: played.length,
@ -560,6 +552,7 @@ function computeStats(holes: ApiHole[]) {
avgToParWithoutBunker,
pctHolesWithPenalty,
anywayPerRound,
pctHolesWithAnyway,
}
}
@ -939,12 +932,8 @@ export function RoundStats({ roundId }: { roundId: string }) {
</StatCard>
)}
{/* 7. Annet -- "catch all" for chip/bunker/straffeslag/anywayslag
(het tidligere "Chip, bunker og straffeslag", men Anywayslag
manglet helt fra oppsummeringen -- rettet + omdøpt til noe
bredere 2026-07-25, siden et fritekst-notatfelt trolig havner
her senere også). */}
<StatCard title="Annet" icon={Waves}>
{/* 7. Chip, bunker og straffeslag */}
<StatCard title="Chip, bunker og straffeslag" icon={Waves}>
{(s.scramblingPct !== null || s.sandSavePct !== null) && (
<div className="grid grid-cols-2 gap-3">
<InfoStat
@ -979,12 +968,9 @@ export function RoundStats({ roundId }: { roundId: string }) {
</div>
)}
<StatTileRow
tiles={[
{ label: "Bunkerslag per runde", value: String(s.bunkerPerRound) },
{ label: "Straffeslag per runde", value: String(s.penaltyPerRound) },
...(s.anywayPerRound !== null ? [{ label: "Anywayslag per runde", value: String(s.anywayPerRound) }] : []),
]}
<StatTilePair
a={{ label: "Bunkerslag per runde", value: String(s.bunkerPerRound) }}
b={{ label: "Straffeslag per runde", value: String(s.penaltyPerRound) }}
/>
{(s.avgToParWithBunker !== null || s.avgToParWithoutBunker !== null) && (
<StatTilePair
@ -999,6 +985,22 @@ export function RoundStats({ roundId }: { roundId: string }) {
</div>
)}
</StatCard>
{/* 8. Annet -- egen seksjon for rundens anywayslag, ETTER
chip/bunker/straffeslag (rettet 2026-07-25 -- feilaktig slått
sammen med den seksjonen i forrige runde). Notatfelt kommer
trolig hit senere. */}
{s.anywayPerRound !== null && (
<StatCard title="Annet" icon={MoreHorizontal}>
<StatTilePair
a={{ label: "Anywayslag per runde", value: String(s.anywayPerRound) }}
b={{
label: "Andel hull med anywayslag",
value: s.pctHolesWithAnyway !== null ? pct(s.pctHolesWithAnyway) : "",
}}
/>
</StatCard>
)}
</>
)}
</main>