Dokumenter dashbord/BottomNav/veiviser/login/deling/slagmåling i CHANGELOG.md
Punkt 39-45: dashbord+BottomNav-reskin, ny-runde-veiviser + offisiell- banesøk-produksjonsbug, /logg-inn som ekte innloggingsside, rundedeling- kategoriregel-fiks (ADR-036 E), og slag-for-slag-avstandsmåling inngangspunkt 1. Se de fem foregående commitene for koden.
This commit is contained in:
parent
9538dfec7f
commit
2d1d0ba1d0
1 changed files with 425 additions and 7 deletions
432
CHANGELOG.md
432
CHANGELOG.md
|
|
@ -8683,9 +8683,10 @@ Neste steg:
|
|||
eksplisitt bekreftet at ekte `teecup_db` sin `datacl` var uendret
|
||||
etterpå).
|
||||
|
||||
**Ikke rullet ut ennå** -- venter på samlet bekreftelse sammen med
|
||||
resten av det som gjenstår i denne økten (slagmåling-frontend,
|
||||
dashbord-V0-beslutning).
|
||||
**Rullet ut 2026-08-08** sammen med punkt 40 og 41 (`docker compose
|
||||
build teecup_frontend` + `up -d` -- ingen migrasjon, kun ny
|
||||
frontend-image). Bekreftet ingen konsollfeil på
|
||||
`https://teecup.golf/` etter omstart.
|
||||
|
||||
39. **Dashbordet reskinnet til "clubhouse"-paletten — 2026-08-07, bruker
|
||||
bekreftet eksplisitt "full overtagelse, også bakgrunnen".** Egen,
|
||||
|
|
@ -8745,7 +8746,424 @@ Neste steg:
|
|||
utvidet korrekt og det eksisterende skjemaet (uendret) fungerte som før.
|
||||
Ingen konsollfeil. Scratch-miljøet ryddet opp fullstendig.
|
||||
|
||||
**Ikke rullet ut ennå** -- venter på BottomTabBar-V0-eksporten (så
|
||||
hele dashbordet, inkludert navigasjonen, kan rulles ut samlet i én
|
||||
omgang i stedet for i to synlig usammenhengende steg) og på samlet
|
||||
bekreftelse sammen med resten av det som gjenstår denne økten.
|
||||
**Rullet ut 2026-08-08** sammen med BottomNav (punkt 40) og
|
||||
ny-runde-veiviseren (punkt 41), som planlagt -- se punkt 41 for
|
||||
utrullingsdetaljer.
|
||||
|
||||
40. **BottomTabBar erstattet med `BottomNav` fra egen V0-prompt —
|
||||
2026-08-08.** Bruker ba eksplisitt om at bunn-navigasjonens utseende
|
||||
skulle avgjøres av V0 selv, ikke av meg (se punkt 39) -- prompt skrevet
|
||||
med eksplisitt kontekst om at komponenten deles mellom clubhouse- og
|
||||
Forest Green-sider og må fungere rimelig godt mot begge, uten å få
|
||||
oppgitt en fasit-retning. V0 valgte en bevisst palett-nøytral løsning:
|
||||
en "flytende hvit flate" (halvtransparent hvit, backdrop-blur, egen
|
||||
skygge) som ikke arver noen sideb palett -- kun den grønne
|
||||
`tee`/`tee-strong`-aksenten (felles for begge paletter) brukes for
|
||||
aktiv-tilstand.
|
||||
|
||||
Ny fil `components/teecup/bottom-nav.tsx`, eksporterer `BottomNav`
|
||||
(ikke lenger `BottomTabBar`). Strukturell endring fra forgjengeren:
|
||||
aktiv fane leses nå fra `usePathname()` internt (ikke en `active`-prop
|
||||
utenfra) -- hrefs rettet fra V0s plassholdere (`/hjem`, `/runder` osv.)
|
||||
til de faktiske rutene under integrering. Fjernet den gamle
|
||||
`BottomTabBar`-definisjonen (og dens nå-ubrukte `C`-fargekonstant og
|
||||
fire lucide-ikon-importer) fra `dashboard.tsx`; alle seks sider
|
||||
(`dashboard.tsx`, `own-rounds.tsx`, `friends.tsx`, `account-
|
||||
settings.tsx`, `feed.tsx`, `notifications.tsx`, `more-menu.tsx`)
|
||||
importerer nå `BottomNav` fra den nye filen i stedet, uten `active`-
|
||||
prop.
|
||||
|
||||
**To reelle bugs funnet og rettet UNDER scratch-verifisering (ikke i
|
||||
selve V0-eksporten -- begge i MIN EGEN integreringskode):**
|
||||
1. Forsøkte først å "forbedre" aktiv-fane-sammenligningen ved å
|
||||
strippe bort et evt. `#hash` før sammenligning (siden "Turneringer"
|
||||
sin href er `/dashboard#kommende-turneringer`). Dette var FEIL --
|
||||
browser-verifisert til å få BÅDE "Hjem" og "Turneringer" til å vise
|
||||
som aktive samtidig på `/dashboard`, siden begge da strippet til
|
||||
samme sti. Reversert til V0s opprinnelige, rå strengsammenligning
|
||||
(som aldri hadde dette problemet -- "Turneringer" matcher rett og
|
||||
slett aldri via ren pathname, akkurat som forgjengeren uansett aldri
|
||||
fremhevet den).
|
||||
2. `/my-friends`, `/my-feed` og `/my-notifications` viste INGEN fane
|
||||
som aktiv i det hele tatt (ren pathname-matching kjenner dem ikke
|
||||
igjen som noen fanes mål) -- forgjengeren løste dette implisitt ved
|
||||
at hver side selv sendte inn riktig `active`-prop. Lagt til en ny,
|
||||
liten `matchPaths`-mekanisme på `Tab`-typen; "Mer" sin oppføring
|
||||
fikk `matchPaths: ["/my-friends", "/my-feed", "/my-notifications"]`
|
||||
-- speiler nøyaktig hvilke tre sider `more-menu.tsx` selv allerede
|
||||
lister som sine undersider, ingen ny gruppering oppfunnet.
|
||||
|
||||
`tsc --noEmit` rent. **Scratch-verifisert i ekte nettleser** (tiende
|
||||
scratch-miljø denne økten, samme migrasjon-002-forsiktighet som
|
||||
punkt 37-39, `teecup_db` bekreftet uendret): logget inn, besøkt alle
|
||||
syv sider som bruker `BottomNav` (dashbord, my-rounds, my-friends,
|
||||
account, my-feed, my-notifications, more) -- riktig (og ETT AV GANGEN,
|
||||
etter fiks 1) fane fremhevet på hver, ingen konsollfeil. Scratch-miljøet
|
||||
ryddet opp fullstendig.
|
||||
|
||||
**Rullet ut 2026-08-08** sammen med punkt 39 og 41 -- se punkt 41 for
|
||||
utrullingsdetaljer.
|
||||
|
||||
41. **`/my-rounds/new` erstattet med ny-runde-veiviser fra egen V0-prompt
|
||||
— 2026-08-08.** Samme mønster som punkt 40: prompt skrevet med full
|
||||
teknisk spesifikasjon (alle 18 spilleformer, alle steg/felt/
|
||||
valideringsregler, alle 12 backend-endepunkt, `submitWizard()`-
|
||||
kontrakten) og eksplisitt UTEN visuell føring -- V0 fikk velge
|
||||
utseendet fritt. Resultat: en ny, selvstendig palett (`--nr-*` i
|
||||
`globals.css`, kald blå/grå, `--nr-accent: #1f5fd6`), additiv og
|
||||
scoped til veiviseren alene, samme "co-eksisterende paletter via
|
||||
Tailwind arbitrary-value-syntaks"-mønster som clubhouse-paletten
|
||||
(punkt 39) -- ingen `@theme inline`-kobling, ingen påvirkning på
|
||||
resten av appen.
|
||||
|
||||
Gammel `components/new-round.tsx` (3364 linjer) SLETTET -- bekreftet
|
||||
via grep at kun `app/my-rounds/new/page.tsx` importerte den (de tre
|
||||
andre grep-treffene, i `course-template-editor.tsx`/
|
||||
`round-leaderboard.tsx`/`round-detail.tsx`, var bare beskrivende
|
||||
norske kommentarer, urørt). Ny modul under
|
||||
`components/ny-runde/` (`wizard-shell.tsx`, `wizard-context.tsx`,
|
||||
fem steg-filer, `primitives.tsx`, `progress.tsx`, `footer-bar.tsx`,
|
||||
`create-course-form.tsx`) + `lib/ny-runde/` (`types.ts`,
|
||||
`formats.ts`, `api.ts`).
|
||||
|
||||
V0s eksport brukte mock-data gjennomgående -- hele portingsjobben
|
||||
var å koble hvert steg til de faktiske backend-kontraktene fra
|
||||
`app/routers/rounds.py` og den gamle `new-round.tsx`, IKKE bare et
|
||||
overflatisk bytte av komponentnavn: `Gender`-oversettelse
|
||||
(`"m"|"f"` API ↔ `"mann"|"kvinne"|"annet"` UI), `Tee`-formen
|
||||
forenklet til kun `{id, name, genders}` (aldri CR/Slope til klienten),
|
||||
`CourseMeta`-discriminated-union for teeoff- vs. egen-bane, ekte
|
||||
`POST /rounds` → `POST .../sides` → `POST .../participants` →
|
||||
`PATCH .../participants/{id}`-sekvens i `submit()`, ekte
|
||||
kontosøk/gjeste-oppslag i steg 3, ekte banesøk (teeoff-fasilitet +
|
||||
egne baner, inkl. geolokasjon for "i nærheten") i steg 1.
|
||||
|
||||
**Fire reelle bugs funnet og rettet under scratch-verifisering:**
|
||||
1. `TextInput` i `primitives.tsx` manglet `forwardRef` (feil i selve
|
||||
V0-eksporten, ikke i portingen) -- ga 3 TS-feil der nedstrøms kode
|
||||
sendte `ref` til komponenten. Rettet ved å pakke inn med
|
||||
`forwardRef`, `tsc --noEmit` gikk fra 3 feil til rent.
|
||||
2. Steg 3 viste "Utslag: Ikke valgt" for eieren selv etter at tee var
|
||||
valgt i steg 1 -- min egen portingsfeil, jeg hadde ikke tatt med
|
||||
den ekte `chooseCourse()`s side-effekt som synker valgt tee inn i
|
||||
spillerlisten. Rettet ved å legge `players:
|
||||
state.players.map(...)` til i `pickCourse()`
|
||||
(`step1-course-time.tsx`). Verifisert rettet ved reload.
|
||||
3. Manglende "Ingen"/"Alle"-hurtigknapp og "ingen kategori
|
||||
valgt"-advarsel i steg 5s kategorivelger (samme mangel som ble
|
||||
oppdaget og rettet i selve appen 2026-08-06, se punkt 36 -- V0s
|
||||
eksport hadde ikke fått denne konteksten). Lagt til i
|
||||
`step5-sharing.tsx`, samme mønster som punkt 36 (`role="group"`,
|
||||
`aria-pressed`, `role="alert"` ved null valgt). Browser-verifisert
|
||||
i scratch: "Ingen" tømmer alle 10 avkrysninger og viser advarselen,
|
||||
"Alle" gjenoppretter alle.
|
||||
4. Fulgte først en blindvei: trodde "Legg til gjest"-knappen i steg 3
|
||||
var usynlig/klikk-slukende bak den klissede (`sticky bottom-0`)
|
||||
`FooterBar`-en (samme feilklasse som `pb-32`-saken 2026-08-02,
|
||||
nevnt i den gamle `new-round.tsx`s egne kommentarer) -- la til
|
||||
`pb-28` på `<main>`. Padding-fiksen var faktisk RIKTIG og
|
||||
nødvendig (uten den er det for lite scroll-klaring til å noensinne
|
||||
få knappen helt fri av footeren), men den første reproduksjonen av
|
||||
"feilen" var selv et testverktøy-artefakt: et koordinat-basert
|
||||
klikk uten forutgående scroll traff footeren fordi den, ved
|
||||
`scrollY: 0`, visuelt ligger over knappen (klissete element som
|
||||
ikke har "festet seg" ennå fordi normal dokumentflyt allerede
|
||||
plasserer det nederst i viewport). Bekreftet ved å måle
|
||||
`getBoundingClientRect()` for begge før/etter scroll: uten scroll
|
||||
overlapper de nesten fullstendig (y:776 vs. top:775); etter
|
||||
`scrollIntoView` (174px, alt tilgjengelig scroll) står knappen på
|
||||
y:602, godt klar. Et ekte, koordinat-basert klikk etter scroll
|
||||
fungerte perfekt. Konklusjon: `pb-28`-fiksen var korrekt og er
|
||||
beholdt (den gir nødvendig klaring når brukeren scroller helt ned),
|
||||
ingen ytterligere kodefeil forelå.
|
||||
|
||||
`tsc --noEmit` rent. **Scratch-verifisert i ekte nettleser** (ellevte
|
||||
scratch-miljø denne økten, samme migrasjon-002-forsiktighet som
|
||||
punkt 37-40, `teecup_db`s ACL bekreftet uendret før og etter): full
|
||||
veiviser-gjennomkjøring for Fourball -- egen bane opprettet og valgt,
|
||||
tee/HCP riktig synket til eier, gjest uten konto lagt til, begge
|
||||
spillere tildelt hver sin side i steg 4, "Ingen"/"Alle"-toggle testet
|
||||
i steg 5, fullført innsending. **DB-verifisert direkte**: `round`-rad
|
||||
med riktig `play_format`/`visibility_mode`/bane-/tee-snapshot,
|
||||
to `round_side`-rader, begge `round_participant`-rader korrekt
|
||||
knyttet til hver sin `round_side_id` med riktig
|
||||
HCP-/tee-/stat_level-snapshot. Ingen konsollfeil. Scratch-miljøet
|
||||
(containere, images, DB, rolle) ryddet opp fullstendig etterpå.
|
||||
|
||||
**Rullet ut 2026-08-08** sammen med punkt 39 og 40, etter eksplisitt
|
||||
brukerbekreftelse ("Rull ut alle tre samlet"): `docker compose build
|
||||
teecup_frontend && docker compose up -d teecup_frontend` (kun
|
||||
frontend-image, ingen migrasjon). Bekreftet `teecup_api`s image
|
||||
UENDRET (bygget 2026-08-07, ikke i dag) -- containeren ble kun
|
||||
re-opprettet fra samme eksisterende image pga. avhengighetskjeden i
|
||||
`docker-compose.yml`, ikke bygget på nytt, så de uncommittede
|
||||
backend-endringene som lå i arbeidstreet (`rounds.py`,
|
||||
`handicap_engine.py` m.fl., urelatert til denne økten) ble IKKE
|
||||
utilsiktet rullet ut. `https://teecup.golf/` bekreftet oppe, ingen
|
||||
konsollfeil på innloggingssiden. Autentisert gjennomgang av
|
||||
dashbord/BottomNav/ny-runde-veiviseren i produksjon overlatt til
|
||||
brukeren selv (krever ekte pålogging).
|
||||
|
||||
42. **`/logg-inn` gjort til den EKTE innloggingssiden (erstatter `/` sin
|
||||
gamle `LoginForm`) — 2026-08-08.** Brukeren la merke til at
|
||||
innloggingssiden fortsatt viste "det gamle grensesnittet" etter
|
||||
punkt 39-41s utrulling -- undersøkelse avdekket at `/logg-inn`
|
||||
(clubhouse-palett, `TeeCupAuth`) var en fullstendig FORELDRELØS V0-
|
||||
utforskning: INGENTING i appen lenket eller redirectet dit (bekreftet
|
||||
ved grep), alle ~11 uautentisert-steder pekte fortsatt til `/` (gammel
|
||||
`LoginForm`, Forest Green). Se dashboard.tsx sin egen kommentar
|
||||
(linje 26-34) som allerede erkjente dette -- "fra en tidligere, ennå
|
||||
ikke integrert /logg-inn-utforskning".
|
||||
|
||||
**Kritisk oppdagelse FØR arbeidet startet:** `TeeCupAuth` var 100 %
|
||||
mock -- `apiSendMagicLink`/`apiPasswordLogin`/`apiJoinByCode` var alle
|
||||
`sleep()`-baserte stubber (hardkodet demo-passord `"teecup123"`,
|
||||
hardkodede demo-koder `TEECUP`/`RYDER-25`/`HOST2026`, en falsk
|
||||
"2FA-kode sendes"-tekst som ALDRI faktisk sendte noe). Dette ble
|
||||
eksplisitt flagget til brukeren (AskUserQuestion) FØR noe ble bygget,
|
||||
siden dette er sikkerhetskritisk kode og omfanget var langt større enn
|
||||
en ren redirect-ombytting -- brukeren bekreftet "gjør full port nå".
|
||||
|
||||
**Full port utført:**
|
||||
- `components/teecup/teecup-auth.tsx` skrevet om fra bunnen: ekte
|
||||
`POST /auth/request-link` (magic link), ekte
|
||||
`POST /auth/login-password` (med `LoginResult`-status-håndtering
|
||||
identisk med den gamle `LoginForm`), ekte
|
||||
`GET /public/tournaments/by-code/{code}`. Alle demo-hint/mock-tekster
|
||||
fjernet. `TwoFactorVerifyForm`/`TwoFactorSetupForm`
|
||||
(`components/two-factor-flow.tsx`) gjenbrukt UENDRET -- samme
|
||||
"delt komponent ikke re-stylet"-mønster som `RoundCard`/
|
||||
`TournamentCard` i dashbord-reskinnet (punkt 39) -- lavest mulig
|
||||
risiko for sikkerhetskritisk 2FA-kode.
|
||||
- `app/logg-inn/page.tsx`: fikk samme server-side allerede-innlogget-
|
||||
sjekk (`cookies()` + `/auth/me`) som `/`-siden hadde.
|
||||
- `app/page.tsx` (root): redusert til en tynn videresending
|
||||
(autentisert → `/dashboard`/`/account`, uautentisert → `/logg-inn`)
|
||||
-- beholdt for gamle bokmerker/lenker til `teecup.golf/`. Gamle
|
||||
`LoginForm`/`components/login-form.tsx` SLETTET (bekreftet ingen
|
||||
andre importer via grep).
|
||||
- Alle 11 `router.replace("/")`-steder (401-håndtering + logout) i
|
||||
`dashboard.tsx`, `friends.tsx`, `more-menu.tsx`,
|
||||
`account-settings.tsx`, `notifications.tsx`, `course-rounds.tsx`,
|
||||
`own-rounds.tsx`, `rounds-stats-summary.tsx` byttet til
|
||||
`router.replace("/logg-inn")`. `verify-form.tsx` sin
|
||||
"Be om en ny lenke"-fallback-lenke (`href="/"`) byttet til
|
||||
`/logg-inn`.
|
||||
|
||||
**Én reell bug funnet og rettet under scratch-verifisering:**
|
||||
`app/logg-inn/page.tsx` kalte `redirect()` INNI `try`-blokken som
|
||||
henter `/auth/me` -- Next.js sin `redirect()` fungerer ved å kaste en
|
||||
egen `NEXT_REDIRECT`-kontrollflyt-exception som MÅ boble videre
|
||||
urørt til Next.js sin render-maskineri. Den tomme `catch {}`-en rundt
|
||||
slukte denne stille, så en allerede innlogget bruker som besøkte
|
||||
`/logg-inn` fikk se innloggingsskjemaet på nytt i stedet for å bli
|
||||
sendt videre -- oppdaget fordi en ekte innlogget test-bruker IKKE ble
|
||||
omdirigert i scratch, mens en direkte nettleser-`fetch("/auth/me")`
|
||||
(som går via `next.config.mjs` sin rewrite, ikke gjennom denne
|
||||
server-komponentens egen kode) bekreftet sesjonen var helt gyldig --
|
||||
avslørte at feilen satt i AKKURAT denne serverkomponentens egen
|
||||
try/catch-struktur. Den opprinnelige `/`-sidens ekvivalente kode
|
||||
unngikk dette ved å KUN sette `authenticated`/`profileComplete`-
|
||||
variabler inni try/catch og kalle `redirect()` etterpå, UTENFOR
|
||||
blokken -- samme mønster gjeninnført her. `tsc --noEmit` rent etter
|
||||
fiks.
|
||||
|
||||
**Scratch-verifisert i ekte nettleser** (tolvte scratch-miljø denne
|
||||
økten, samme migrasjon-002-forsiktighet som punkt 37-41 --
|
||||
`teecup_db`s ACL bekreftet uendret før og etter; `TEECUP_DEV_LOG_MAGIC_LINKS=true`
|
||||
brukt for å hente ekte magic-link-tokens fra API-loggen i stedet for å
|
||||
sende ekte e-post til testadresser): full runde -- magic-link-
|
||||
forespørsel + `/verify?token=`-innlogging (ny bruker auto-opprettet,
|
||||
korrekt sendt til `/account` pga. ufullstendig profil), passord-
|
||||
innlogging med feil passord (ekte feilmelding "E-post eller passord
|
||||
er feil." fra `/auth/login-password`), invitasjonskode med ugyldig
|
||||
kode (ekte feilmelding fra `/public/tournaments/by-code/`), logout
|
||||
(→ `/logg-inn`), uautentisert besøk til `/dashboard` (→ `/logg-inn`,
|
||||
ikke lenger `/`), `/` og `/logg-inn` besøkt allerede innlogget med
|
||||
ufullstendig profil (→ `/account`) og med fullført profil
|
||||
(→ `/dashboard`, satt via direkte `PATCH /auth/profile`-kall for å
|
||||
unngå å klikke gjennom fødselsdato-datepickeren manuelt). Ingen
|
||||
konsollfeil. **Ikke click-through-testet:** `2fa_required`-grenen
|
||||
(krever en konto med 2FA allerede aktivert) -- vurdert lav risiko
|
||||
siden `TwoFactorVerifyForm`/`TwoFactorSetupForm` er gjenbrukt helt
|
||||
uendret fra den allerede beviste `LoginForm`-implementasjonen, kun
|
||||
kablingen frem til dem (`handleLoginResult`) er ny kode, og den er
|
||||
identisk portert fra `LoginForm`. Scratch-miljøet (containere, images,
|
||||
DB, rolle) ryddet opp fullstendig etterpå, inkl. en disk-full-hendelse
|
||||
underveis (`docker builder prune` frigjorde 11,75 GB build-cache fra
|
||||
denne øktens mange scratch-bygg -- ingen kjørende containere eller
|
||||
volumer berørt).
|
||||
|
||||
**Rullet ut 2026-08-08**, etter egen, eksplisitt brukerbekreftelse
|
||||
separat fra punkt 39-41s batch-bekreftelse (sikkerhetskritisk --
|
||||
autentisering). `docker compose build teecup_frontend && up -d` --
|
||||
denne gangen ble kun `teecup_frontend` gjenskapt (`teecup_api` forble
|
||||
"Running" med bekreftet uendret image-tidsstempel før/etter, ulikt
|
||||
forrige utrulling i punkt 39-41 der en avhengighets-kjede-bivirkning
|
||||
gjenskapte -- men ikke bygde om -- `teecup_api`). `https://teecup.golf/`
|
||||
bekreftet å redirecte til `/logg-inn` med clubhouse-designet, ingen
|
||||
konsollfeil.
|
||||
|
||||
43. **PRODUKSJONSBUG: "Laster baner…" hang for alltid ved offisiell
|
||||
banevalg i ny-runde-veiviseren — funnet og fikset 2026-08-08.**
|
||||
Brukeren rapporterte (skjermbilde) at steget etter å ha valgt et
|
||||
teeoff-anlegg ("Baner") aldri kom videre fra "Laster baner…". Dette
|
||||
hadde vært live siden punkt 41s utrulling -- treffer ALLE nye runder
|
||||
som starter fra en offisiell (teeoff-) bane, ikke egne baner.
|
||||
|
||||
**Rotårsak:** `fetchFacilityCourses()` i `lib/ny-runde/api.ts` antok
|
||||
at `GET /rounds/official-search/{slug}` returnerer banene direkte som
|
||||
en array (`data.map(...)`), men det ekte endepunktet returnerer et
|
||||
OBJEKT -- `OfficialFacilityDetail = {slug, name, courses: [...]}`
|
||||
(`app/routers/rounds.py` linje 530). `data.map` er ikke en funksjon
|
||||
på et objekt, så kallet kastet en `TypeError` -- og siden
|
||||
`OfficialCourses` sin `useEffect` i `step1-course-time.tsx` kun hadde
|
||||
`.then(...)` uten `.catch(...)`, ble denne exceptionen en stille,
|
||||
ufanget promise-rejection: `setCourses` ble aldri kalt, og
|
||||
`courses === null`-grenen ("Laster baner…") viste seg for alltid.
|
||||
Bug i min egen porting (punkt 41) -- **denne konkrete stien
|
||||
(offisiell teeoff-bane) ble aldri scratch-testet den runden**, kun
|
||||
"egen bane"-veien ble klikket gjennom (se punkt 41s test-notat).
|
||||
|
||||
**To rettelser:**
|
||||
1. `fetchFacilityCourses()`: leser nå `data.courses.map(...)` i
|
||||
stedet for `data.map(...)`.
|
||||
2. `OfficialCourses` (`step1-course-time.tsx`): la til en reell
|
||||
`.catch()` + en `loadError`-tilstand (`role="alert"`, samme
|
||||
`--nr-danger`-stil som resten av veiviseren) -- uten denne ville
|
||||
ENHVER fremtidig feil her (f.eks. teeoff nede, 502) gitt nøyaktig
|
||||
samme uendelige "Laster baner…"-hang på nytt, uansett om
|
||||
datakontrakt-bugen over er rettet. Dette er defensivt, ikke bare
|
||||
en fiks for det spesifikke tilfellet.
|
||||
|
||||
`tsc --noEmit` rent. **Scratch-verifisert i ekte nettleser** (trettende
|
||||
scratch-miljø denne økten, samme migrasjon-002-forsiktighet, `teecup_db`
|
||||
bekreftet uendret) MOT EKTE teeoff-data (samme `teeoff_db`/`teeoff_api`
|
||||
som produksjon deler, nådd direkte på `teeoff_default`-nettverket):
|
||||
søkte opp "Hvaler Golfklubb" (reell fasilitet), banen ("Hovedbanen, 2
|
||||
utslag") lastet korrekt i stedet for å henge, gikk videre til
|
||||
felt-steget og bekreftet ekte utslag (Gul/Rød) hentet riktig fra
|
||||
teeoff. Ingen konsollfeil (kun én forhåndseksisterende, ikke-relatert
|
||||
"Deprecated feature"-info-melding fra nettleseren selv). Scratch-miljøet
|
||||
ryddet opp fullstendig.
|
||||
|
||||
**Rullet ut umiddelbart** (produksjonsbug som traff alle live
|
||||
brukere som prøvde å starte en runde på en offisiell bane) --
|
||||
`docker compose build teecup_frontend && up -d`, kun frontend-image,
|
||||
`teecup_api`s image-tidsstempel bekreftet uendret før/etter. Kunne
|
||||
ikke click-through-verifisere selve produksjonssiden med ekte
|
||||
brukerkonto (krever brukerens egen pålogging) -- basert på grundig
|
||||
scratch-verifisering mot ekte teeoff-data rett før utrulling.
|
||||
|
||||
44. **PRODUKSJONSBUG: rundedeling med venner i flere kategorier virket
|
||||
ikke som forventet — funnet og fikset 2026-08-08, se ADR-036
|
||||
Beslutning E.** Brukeren rapporterte at en runde delt med kategorien
|
||||
"Make" ikke ble synlig for vedkommendes ektefelle, til tross for at
|
||||
"Make" var huket av. Diagnostisert direkte mot ekte `teecup_db`
|
||||
(skrivebeskyttede spørringer): eieren (Erol) hadde kategorisert
|
||||
ektefellen (Gina) under TRE kategorier (`close_family`,
|
||||
`extended_family`, `spouse`), mens runden kun delte
|
||||
(`close_family`, `golf_friends`, `spouse`) -- `extended_family`
|
||||
manglet. `_can_view_round` krevde den gang at ALLE en venns
|
||||
kategorier måtte være i rundens synlige sett (presisert av bruker
|
||||
2026-07-29, kun dokumentert i kode-kommentarer, ALDRI i
|
||||
ARCHITECTURE_DECISIONS.md -- selve dokumentasjonshullet som gjorde
|
||||
dette vanskelig å spore tilbake), ikke bare én relevant kategori.
|
||||
|
||||
Brukeren fikk vist mekanismen konkret (hvilke kategorier Gina var
|
||||
tagget i, hvilke runden delte, den strenge AND-regelen) og valgte via
|
||||
et eksplisitt spørsmål å reversere til "minst én kategori er nok"
|
||||
(som var den OPPRINNELIGE ADR-036 Beslutning B-regelen fra
|
||||
2026-07-25 -- 2026-07-29-presiseringen hadde altså strammet inn en
|
||||
regel utover det som noensinne ble ordentlig dokumentert som en
|
||||
bevisst arkitekturbeslutning).
|
||||
|
||||
**Rettet i alle fire duplikate SQL-steder** (samme
|
||||
kopier-inn-i-SQL-mønster som allerede omtalt i ADR-036 Beslutning B):
|
||||
`app/routers/rounds.py` sin `_can_view_round` (selve
|
||||
tilgangssjekken), `_friends_who_can_see_round` (varsel-fan-out ved
|
||||
rundeopprettelse/fullføring), `list_friends_on_course`
|
||||
(dashbordets "Venner på banen"); `app/routers/round_messages.py` sin
|
||||
`/feed`-listing. Alle gikk fra "`NOT EXISTS` en kategori UTENFOR
|
||||
synlig sett" til et enklere "`EXISTS` en kategori INNENFOR synlig
|
||||
sett" -- enklere spørringer, ikke bare annen semantikk.
|
||||
|
||||
**Scratch-verifisert i ekte API-kall** (fjortende scratch-miljø denne
|
||||
økten, samme migrasjon-002-forsiktighet, `teecup_db` bekreftet
|
||||
uendret): gjenskapte den ekte Erol/Gina-situasjonen (venn kategorisert
|
||||
i to kategorier, runde deler kun én av dem) -- vennen fikk nå 200 på
|
||||
`GET /public/rounds/{id}` (tidligere 403). Bekreftet at motsatt
|
||||
tilfelle (venn med INGEN overlappende kategori) fortsatt korrekt gir
|
||||
403 -- ingen utilsiktet åpning av tilgangskontrollen. `/friends/
|
||||
on-course` og `/feed` (de to andre endrede spørringene) begge 200
|
||||
uten SQL-feil. Scratch-miljøet ryddet opp fullstendig.
|
||||
|
||||
**Rullet ut umiddelbart** (produksjonsbug, brukerens egen delte runde
|
||||
var konkret berørt) -- `docker compose build teecup_api && up -d`,
|
||||
KUN backend-image (ingen migrasjon, `visibility_mode`/
|
||||
`round_visible_category` er uendret skjema), `teecup_frontend`s
|
||||
image-tidsstempel bekreftet uendret før/etter. **Bekreftet direkte
|
||||
mot ekte data etter utrulling**: samme spørring som
|
||||
`_can_view_round` nå bruker, kjørt skrivebeskyttet mot den ekte
|
||||
Erol/Gina/runde-situasjonen, returnerer nå `true`.
|
||||
|
||||
45. **Slag-for-slag GPS-avstandsmåling — inngangspunkt 1 av 2, i
|
||||
scoring-veiviseren — 2026-08-08 (ADR-048).** Backend (migrasjon
|
||||
`060_round_shot.sql`, `ShotIn`/`ShotOut`/`ShotShareIn`-endepunktene i
|
||||
`rounds.py`, `lib/geo.ts` Haversine, Mapbox-token-plumbing) var
|
||||
allerede bygget og scratch-verifisert fra tidligere i økten (se
|
||||
ADR-048 i ARCHITECTURE_DECISIONS.md). Denne runden: selve
|
||||
frontend-flaten.
|
||||
|
||||
V0-prompt skrevet med `DESIGN_SYSTEM.md`s tokens som en HARD
|
||||
begrensning (i motsetning til dashbord-/veiviser-/login-promptene
|
||||
tidligere i økten, som bevisst fikk null designføring) -- dette
|
||||
arket lever INNI den eksisterende Forest Green-skjermen
|
||||
(`round-detail.tsx`), ikke som en ny frittstående side. Eksporten
|
||||
(zip 4) var meget tro mot spesifikasjonen: `next/dynamic({ssr:false})`
|
||||
for kartsteget, ingen `mapbox-gl`-import i det hele tatt på
|
||||
GPS-only-stien, kartet mountes kun én gang per arkåpning
|
||||
(tom-deps `useEffect`, klikk/drag re-initialiserer aldri).
|
||||
|
||||
`components/shot/shot-measurement-sheet.tsx` +
|
||||
`components/shot/map-point-picker.tsx` kopiert inn uendret (kun
|
||||
én import-sti rettet: V0s egen plassholder-`ClubPicker` byttet til
|
||||
den nå faktisk utrukne, delte `components/teecup/club-picker.tsx`
|
||||
-- ren utrekking fra `round-detail.tsx`s tidligere lokale kopi,
|
||||
ingen atferdsendring for veiviserens eksisterende bruk). Ny
|
||||
`components/ui/textarea.tsx`-shadcn-primitiv lagt til (fantes ikke
|
||||
fra før).
|
||||
|
||||
Koblet inn som `ScoringWizard`s nye `roundId`-prop + lokal
|
||||
`shotSheetOpen`/`shotCount`-state: "Mål et slag"-knapp rett etter
|
||||
kølle-plukkeren i detalj-steget, henter eksisterende slag-antall on
|
||||
mount (`GET .../holes/{n}/shots`), sender til ekte
|
||||
`POST .../holes/{n}/shots` ved innsending og (hvis deling valgt)
|
||||
en påfølgende `POST /rounds/{id}/shots/{shot_id}/share`.
|
||||
|
||||
**Scratch-verifisert** (femtende scratch-miljø denne økten, samme
|
||||
migrasjon-002-forsiktighet, `teecup_db` bekreftet uendret): full
|
||||
klikk-gjennomgang fra "Mål et slag" til arket åpner riktig, korrekt
|
||||
feilmelding+"Prøv igjen" når GPS-tillatelse mangler (bekreftet ekte
|
||||
-- CDP-automatiserte nettlesersesjoner har `geolocation`-tillatelse
|
||||
permanent `denied` uten noen dialog å akseptere, en verktøy-
|
||||
begrensning i selve test-miljøet, ikke i appen). Siden selve
|
||||
GPS-suksess-stien derfor ikke lot seg klikke gjennom i denne
|
||||
økten, ble de eksakte kallene `submitShot()` sender (opprett slag,
|
||||
list slag, del) i stedet verifisert direkte mot API-et med samme
|
||||
data-kontrakt -- alle tre 200/201, ingen feil i API-loggen. Bekreftet
|
||||
i ekte nettleser at slag-tellingen faktisk oppdateres og vises i
|
||||
knappeteksten ("Mål et slag (1 målt)") etter et slag er opprettet.
|
||||
Scratch-miljøet ryddet opp fullstendig.
|
||||
|
||||
**Ikke rullet ut** -- `round_shot`-tabellen finnes ennå ikke i ekte
|
||||
`teecup_db` (migrasjonen er aldri kjørt der), og `.env` har fortsatt
|
||||
tomme Mapbox-token-plassholdere (kart-veien vil ikke fungere i
|
||||
produksjon før brukeren skaffer et ekte token). Gjenstår før dette
|
||||
kan vurderes for utrulling: inngangspunkt 2 (alltid-synlig
|
||||
"N slag målt"-merkelapp på selve hull-kortet, for retroaktiv måling
|
||||
OG for lagformater/side-eide hull -- denne `ScoringWizard`-veien
|
||||
dekker kun deltaker-eide hull, siden delt-ball-formater bruker en
|
||||
egen, enklere side-veiviser uten dette detalj-steget), ekte
|
||||
Mapbox-tokens, og migrering av `060_round_shot.sql` mot ekte
|
||||
`teecup_db` (krever egen, eksplisitt brukerbekreftelse).
|
||||
|
|
|
|||
Loading…
Reference in a new issue