From 05599aafe6485c2972c4e81b938f5cdea1697378 Mon Sep 17 00:00:00 2001 From: Erol Haagenrud Date: Thu, 20 Aug 2026 05:54:20 +0200 Subject: [PATCH] =?UTF-8?q?Fiks=20skjult=20score-registrering=20og=20doble?= =?UTF-8?q?=20Score-faner=20p=C3=A5=20rundens=20Score-fane?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avstandsmåleren fylte hele mobilskjermen uten å antyde at score- registrering fantes lenger ned (funnet via brukers skjermbilde). Viser nå kompakt som standard med en "Vis banekart"-utvidelse og en alltid synlig "Registrer score"-snarvei. Den separate, duplikate "Score"-pillefanen inni round-detail.tsx (visuelt identisk med RoundHeader sin egen Score/ Scorekort/Leaderboard-rad) er erstattet med én tydelig annerledes veksle-knapp -- fikser samtidig et reelt navigasjonshull der det ikke fantes noen vei tilbake til Score fra en ekstern "?tab=manage"-lenke. --- CHANGELOG.md | 62 +++++++++++++ frontend/components/hole-target-distance.tsx | 11 +++ frontend/components/round-detail.tsx | 98 ++++++++++++++------ 3 files changed, 144 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56e1bf2..0b6dccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13230,3 +13230,65 @@ Neste steg: **Rullet ut 2026-08-19** -- bruker bekreftet. Ren frontend. `docker compose build teecup_frontend && up -d`, rene logger, 200 OK. + +133. **Score-fanen (egen runde): skjult score-registrering + doble + "Score"-faner -- funnet via brukers skjermbilde, 2026-08-20.** Bruker + viste et ekte skjermbilde: på et hull med koordinatdata fylte + avstandsmåleren/hull-diagrammet HELE den synlige mobilskjermen, uten + noe som antydet at spillerkortene (selve score-registreringen) fantes + lenger ned -- en førstegangsbruker skjønte ikke at de måtte scrolle. + Samtidig lå det to visuelt identiske pille-fanerader rett oppå + hverandre: RoundHeader sin Score/Scorekort/Leaderboard, og en HELT + SEPARAT, egen "Score"/"Spillere og runde"-fanerad bygget inni + `round-detail.tsx` selv -- begge kalte én fane "Score", leste som + duplikate kontroller. + + Løst via en Claude-skrevet V0-prompt (samme etablerte + "Claude skriver prompt, bruker kjører V0, Claude kobler inn"-mønster + som resten av appen) -- V0-eksporten (`round-score-top.tsx`) traff + begge problemene presist og ble brukt som fasit for restrukturering + av de EKTE komponentene (ikke V0s egen mock-`HoleDiagram`, men den + ekte `HoleTargetDistance`/`HoleDiagram`, som allerede -- upåaktet -- + støttet en "compact"-modus, aldri faktisk brukt noe sted i kodebasen + før nå): + + - `hole-target-distance.tsx`: ny valgfri `onAvailabilityChange`-prop + -- kalleren får vite om banen faktisk har koordinatdata for hullet, + uten å duplisere fetch-en selv. + - `round-detail.tsx` (`PlayerHoleCards`): avstandsmåleren vises nå + `size="compact"` som standard (kun de tre store avstandstallene), + med en "Vis banekart og hindringer"-knapp som utvider til det fulle + diagrammet -- knappen vises KUN når `onAvailabilityChange` faktisk + har meldt at det finnes data (ikke en død knapp på baner uten + koordinater). En alltid synlig "Registrer score ↓"-knapp scroller + rett til spillerkortene. + - `round-detail.tsx` (hovedkomponenten): den separate + "Score"/"Spillere og runde"-pille-fanen er fjernet, erstattet med + ÉN sekundær, tydelig ANNERLEDES knapp (ramme + ikon, ikke en pille) + som veksler `pageTab` mellom de to visningene, med tekst som endrer + seg etter tilstand ("Spillere og runde" / "Tilbake til score"). + + **Reelt funn underveis, ikke bare kosmetikk:** før denne fiksen + fantes det INGEN pålitelig vei tilbake fra "Spillere og runde" til + "Score" dersom brukeren kom dit via en ekstern lenke (f.eks. + RoundHeader sin Administrer-dialog, som lenker til `?tab=manage`) -- + `pageTab`-tilstanden ble aldri tilbakestilt automatisk, og den gamle + fanen for å bytte tilbake fantes ikke i den konteksten. Den nye + veksle-knappen løser dette som et biprodukt, siden den er ren + klient-tilstand, ikke avhengig av URL. + + **Verifisert i scratch:** en midlertidig forhåndsvisningsrute som + rendret den EKTE `RoundDetail`-komponenten (ikke en isolert mock) med + et fullstendig mocket `fetch` (runde, deltakere, hull, avstandspunkter + for hull 1 -- IKKE for hull 2, bevisst, for å teste begge + tilstander) og emulert GPS-posisjon (Chrome DevTools). Bekreftet: + spillerkort synlig uten scrolling på mobilviewport (402px), "Vis + banekart"-knappen vises for hull 1 og er HELT fraværende for hull 2, + fanebytte-knappen veksler korrekt begge veier med riktig + tekst/ikon, hele administrasjonspanelet (Flighter/Rediger runde/ + Fullfør/Slett/full spillerliste) fortsatt fullt funksjonelt etter + fjerningen av den gamle faneraden. Ingen konsollfeil. `tsc --noEmit` + rent, `vitest run` 55/55. + + **Rullet ut 2026-08-20** -- bruker bekreftet. Ren frontend. + `docker compose build teecup_frontend && up -d`, rene logger, 200 OK. diff --git a/frontend/components/hole-target-distance.tsx b/frontend/components/hole-target-distance.tsx index 0311be0..00ccd02 100644 --- a/frontend/components/hole-target-distance.tsx +++ b/frontend/components/hole-target-distance.tsx @@ -187,11 +187,16 @@ export function HoleTargetDistance({ holeNumber, size = "compact", className, + onAvailabilityChange, }: { baseUrl: string holeNumber: number size?: "compact" | "full" className?: string + /** Kalles hver gang det blir klart om banen faktisk har koordinatdata for + * hullet eller ikke -- lar en kaller (f.eks. en utvid/skjul-knapp rundt + * komponenten) vite om det er noe å vise, uten selv å duplisere fetch-en. */ + onAvailabilityChange?: (available: boolean) => void }) { const [points, setPoints] = useState(null) const [livePosition, setLivePosition] = useState(null) @@ -213,6 +218,12 @@ export function HoleTargetDistance({ } }, [baseUrl, holeNumber]) + useEffect(() => { + if (points === null) return + onAvailabilityChange?.(points.length > 0) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [points]) + useEffect(() => { // Ingen vits å spore GPS når banen uansett ikke har koordinatdata for // dette hullet -- unngår unødvendig batteribruk/tillatelses-prompt. diff --git a/frontend/components/round-detail.tsx b/frontend/components/round-detail.tsx index 66251b9..b4106f4 100644 --- a/frontend/components/round-detail.tsx +++ b/frontend/components/round-detail.tsx @@ -17,6 +17,7 @@ import { RoundPageShell } from "@/components/round-page-shell" import { RoundMessages } from "@/components/round-messages" import type { FlagMapEntry } from "@/components/flag-map-overview" import { + ArrowDown, ArrowRight, Check, ChevronDown, @@ -1502,32 +1503,32 @@ export function RoundDetail({ roundId }: { roundId: string }) { )} - {/* To faner: "Score" (default, KUN hull-navigasjon + registrering -- - det eneste de fleste trenger midt i en runde) og "Spillere og - runde" (alt administrativt, samlet ett sted i stedet for å ligge - i veien øverst på scoringssiden). */} -
+ {/* Ett enkelt, sekundært veksle-valg -- IKKE en fanerad (2026-08-20, + reelt brukerfunn: en andre pille-fanerad her, rett under + RoundHeader sin egen Score/Scorekort/Leaderboard-rad, leste som + to duplikate "Score"-kontroller rett oppå hverandre). "Score" + (hull-navigasjon + registrering, default) og "Spillere og runde" + (alt administrativt) er fortsatt to distinkte visninger på denne + siden -- kun selve KONTROLLEN er nå en enkelt, tydelig ANNERLEDES + knapp (ramme + ikon, ikke en pille) i stedet for en segmentert + fanerad som konkurrerer visuelt med hovedfanene over. */} +
-
@@ -6616,6 +6617,14 @@ function PlayerHoleCards({ // sitter her i kortet (skjermen FØR slagvinduet), åpner denne fullskjerm- // visningen ved klikk i stedet for å ekspandere inline. const [historyPlayerId, setHistoryPlayerId] = useState(null) + // Avstandsmåler-utvidelse (2026-08-20): kompakt som standard, slik at + // spillerkortene under peker inn i synlig område med det samme -- en + // førstegangsbruker skal ikke måtte oppdage ved et tilfeldig sveip at + // score-registrering finnes lenger ned. "Vis banekart"-knappen vises kun + // når banen faktisk HAR koordinatdata (ellers ingenting å utvide til). + const [mapExpanded, setMapExpanded] = useState(false) + const [distanceAvailable, setDistanceAvailable] = useState(false) + const playerListRef = useRef(null) const holeMeta: Record = {} for (const list of Object.values(holesByParticipant)) { for (const h of list) { @@ -6719,10 +6728,45 @@ function PlayerHoleCards({ {/* Avstand til grønn (ADR-064, utvidet til ekte teeoff-baner i migrasjon 079) -- kun for baner med koordinatdata; ingen synlig rad i det hele tatt for andre baner (HoleTargetDistance returnerer - null da). Full bredde, samme plassering brukeren pekte ut (rett - under hull-navigatoren, over spillerkortene) -- ikke den smale - kompaktvarianten. */} - + null da, "Vis banekart"-knappen skjules da også via + distanceAvailable). Kompakt som standard (2026-08-20, reelt + brukerfunn: det store diagrammet fylte hele skjermen på mobil, og + ingenting antydet at spillerkortene under fantes) -- kan utvides + til det fulle diagrammet med hindringer på forespørsel. */} + + + {distanceAvailable && ( + + )} + + {/* Alltid synlig, tydelig snarvei rett til score-registreringen under + -- samme grunn som knappen over: en førstegangsbruker skal ikke + måtte oppdage ved et tilfeldig sveip at dette finnes. */} + {isTwoSided && sides.length === 2 && (
@@ -6734,7 +6778,7 @@ function PlayerHoleCards({
)} -
    +
      {sortedPlayers.map((player) => { const list = holesByParticipant[player.id] const apiHole = list?.find((h) => h.hole_number === currentHole) ?? null