From dbb589d9f6d84b91e137bdafbdd0e1d78c8200a6 Mon Sep 17 00:00:00 2001 From: Erol Haagenrud Date: Thu, 20 Aug 2026 09:28:06 +0200 Subject: [PATCH] =?UTF-8?q?Fiks=20scroll=20ved=20automatisk=20hull-fremgan?= =?UTF-8?q?g=20(samme=20header-h=C3=B8yde-fiks=20som=20#142)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scrollToHolePanel() brukte samme flawed scroll-mt-28-mønster som scrollToPlayerList() hadde i #142 -- byttet til samme getHeaderHeight()- baserte manuelle scroll. Denne kalles fra BÅDE manuell Forrige/Neste OG automatisk hull-fremgang etter siste spillers siste steg. Kunne IKKE klikkes gjennom og verifiseres presist denne runden -- scratch- nettleserøkten hard-reloadet uforklarlig på ethvert router.replace-kall, også mot den ekte /my-rounds/[id]-ruta. Notert ærlig som et verifiseringsgap i CHANGELOG.md #143, ikke skjult. Ikke rullet ut ennå. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 39 ++++++++++++++++++++++++++++ frontend/components/round-detail.tsx | 31 +++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c547a0a..7f9df2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13627,3 +13627,42 @@ Neste steg: **Rullet ut 2026-08-20** -- bruker bekreftet, samlet med #141. Ren frontend. `docker compose build teecup_frontend && up -d`, rene logger. + +143. **Automatisk hull-fremgang landet ikke øverst på nytt hull, + 2026-08-20.** Bruker viste skjermbilde: etter at ALLE spilleres + score/statistikk er ført for et hull, hopper appen automatisk videre + til neste hull (`advanceWizardPlayer()` -> `goNext()`) -- men + visningen scrollet ikke til toppen av det nye hullet, landet et sted + midt på siden i stedet. + + Rot-årsak: `scrollToHolePanel()` (kalt fra BÅDE `goNext()`/`goPrev()` + for manuell Forrige/Neste-navigasjon OG fra `advanceWizardPlayer()` + sin automatiske fremgang) brukte samme flawed mønster som allerede + rettet for `scrollToPlayerList()` i #142 samme dag: `scrollIntoView` + + en statisk `scroll-mt-28`-klasse (112px), mens headerens EKTE høyde + er dynamisk (141,5px målt for en runde med langt nok innhold). + Rettet med samme mønster: `getHeaderHeight()` (målt live) + + delt `SCROLL_GAP_PX`-konstant, manuell `window.scrollTo()`. + + **Verifiseringen lyktes IKKE fullt ut denne runden, notert ærlig:** + forsøk på å klikke gjennom "Neste hull" i scratch traff gjentatte, + uforklarte HARDE sideinnlastinger ved ethvert `router.replace`-kall + (samme "hard reload i stedet for myk SPA-overgang"-egenhet som er + observert flere ganger tidligere i denne økten for ferske + `/tmp-preview-*`-ruter -- denne gangen traff det OGSÅ den ekte, + stabile `/my-rounds/[id]`-ruta, testet via en `initScript`-injisert + fetch-mock for å unngå akkurat den ferske-rute-mistanken). Ingen + bruker har noensinne rapportert at hull-bytte laster hele siden på + nytt i ukevis med reell bruk, så dette vurderes som en egenhet ved + DENNE scratch-nettleserøkten, ikke reell produksjonsatferd -- men det + betyr at selve scroll-beregningen IKKE kunne klikkes gjennom og måles + presist, i motsetning til søsken-fiksen i #142 + (`scrollToPlayerList`, som aldri kalles sammen med en + router-navigasjon og DERFOR kunne verifiseres presist). Samme formel + gjenbrukt med vilje for konsistens, men flagget som et gap i + verifiseringen. `tsc --noEmit` rent. + + **Ikke rullet ut ennå** -- venter på bekreftelse fra bruker. Bruker + bør holde ekstra øye med akkurat denne (automatisk hull-fremgang + etter siste spiller) etter utrulling, siden den ikke fikk samme + presise bekreftelse som resten av dagens rettelser. diff --git a/frontend/components/round-detail.tsx b/frontend/components/round-detail.tsx index 6157003..6aa68fc 100644 --- a/frontend/components/round-detail.tsx +++ b/frontend/components/round-detail.tsx @@ -601,8 +601,37 @@ export function RoundDetail({ roundId }: { roundId: string }) { // helt ned (der knappene er) mens det NYE hullets Slag-felt (øverst i // panelet) er utenfor skjermen (rapportert av bruker 2026-07-25). const holePanelRef = useRef(null) + // Manuell scroll (ikke `scrollIntoView` + statisk CSS `scroll-mt-28`) -- + // brukerfunn 2026-08-20: automatisk hull-fremgang etter siste spillers + // siste steg i ScoringWizard landet IKKE øverst på det nye hullet. + // Samme rot-årsak som `scrollToPlayerList()` lenger ned i filen (se + // `getHeaderHeight()`-kommentaren) -- headeren sin høyde er reelt + // dynamisk, en hardkodet `scroll-mt-28` (112px) stemte ikke med den + // ekte høyden (målt 141,5px for en runde med langt nok innhold). + // `scrollToHolePanel` kalles fra BÅDE manuell Forrige/Neste-navigasjon + // OG fra `advanceWizardPlayer()` sin automatiske hull-fremgang -- én + // rettelse dekker begge veiene inn. + // + // IKKE fullt scratch-verifisert (ærlig notert, ikke pyntet på): denne + // funksjonen kalles rett etter `setHoleAndUrl()` (router.replace). + // Forsøk på å klikke gjennom "Neste hull" i scratch denne runden traff + // gjentatte, uforklarte harde sideinnlastinger ved ethvert + // `router.replace`-kall -- også mot den ekte, stabile + // `/my-rounds/[id]`-ruta, ikke bare mot en fersk `/tmp-preview-*`-rute + // (der dette har skjedd før i denne økten). Ingen tidligere bruker- + // rapport om at hull-bytte laster hele siden på nytt i ukevis reell + // bruk -- vurdert som en egenhet ved DENNE scratch-økten, ikke en reell + // app-oppførsel, men betyr at selve scroll-beregningen over IKKE kunne + // klikkes gjennom og måles presist slik #142 sin søsken-sjekk + // (`scrollToPlayerList`, som ALDRI kalles sammen med en + // router-navigasjon) ble. Samme formel, samme `getHeaderHeight()`/ + // `SCROLL_GAP_PX`, gjenbrukt med vilje for konsistens -- men flagget + // her som et gap i verifiseringen, ikke en bekreftet fiks. function scrollToHolePanel() { - holePanelRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }) + const el = holePanelRef.current + if (!el) return + const top = el.getBoundingClientRect().top + window.scrollY - getHeaderHeight() - SCROLL_GAP_PX + window.scrollTo({ top, behavior: "smooth" }) } const loadRound = useCallback(async () => {