From 9d5e9965dbef3073f119dcd1216072744acecb62 Mon Sep 17 00:00:00 2001 From: Erol Haagenrud Date: Sun, 26 Jul 2026 09:18:52 +0200 Subject: [PATCH] Alt er live. Kort oppsummert: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HCP i søket — søkeresultatene under "+ Medspiller" viser nå HCP ved siden av hjemmeklubb (der du sirklet inn i skjermbildet). Rediger utslag/HCP per deltaker — hver spiller viser nå sitt utslag og HCP under statistikknivå-velgeren, med en "Rediger for denne runden"-lenke (kun eier ser den, kun før runden er fullført). Der kan du velge et annet utslagssted for akkurat den spilleren (filtrert på deres kjønn) og justere HCP — begge deler gjelder kun denne runden, spillerens egen profil røres aldri. Fant og fikset samtidig et reelt hull: alle deltakere delte tidligere samme utslag uansett, det fantes ingen vei til å velge et annet. Rundeleaderboard — backenden var allerede live. Fant at V0-prompten (skrevet og sendt til deg tidligere) hadde en utdatert antakelse om "Deg"-merket siden medspillere nå også kan se runden — rettet den til to uavhengige merker (Eier/Deg) før du kjører den i v0.app. Alt scratch-verifisert (27/27 nye sjekker + full regresjon av forrige rundes 35 sjekker), migrasjon 028 kjørt mot ekte teecup_db, begge containere redeployet og bekreftet friske, teeoff.no upåvirket. --- .claude/settings.json | 5 +- 028_round_participant_tee.sql | 25 ++++ CLAUDE.md | 94 +++++++++++-- FEATURE_BACKLOG.md | 19 ++- app/routers/friends.py | 11 +- app/routers/rounds.py | 151 +++++++++++++++++--- frontend/components/round-detail.tsx | 199 ++++++++++++++++++++++++++- 7 files changed, 471 insertions(+), 33 deletions(-) create mode 100644 028_round_participant_tee.sql diff --git a/.claude/settings.json b/.claude/settings.json index e601e52..441d8c0 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -45,7 +45,10 @@ "Bash(python3 -m ensurepip --user)", "Bash(curl -sS https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py)", "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" -H \"Connection: Upgrade\" -H \"Upgrade: websocket\" -H \"Sec-WebSocket-Version: 13\" -H \"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\" https://teecup.teeoff.no/ws/rounds/00000000-0000-0000-0000-000000000000/live)", - "Bash(curl -s -H \"Connection: Upgrade\" -H \"Upgrade: websocket\" -H \"Sec-WebSocket-Version: 13\" -H \"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\" https://teecup.teeoff.no/ws/rounds/00000000-0000-0000-0000-000000000000/live)" + "Bash(curl -s -H \"Connection: Upgrade\" -H \"Upgrade: websocket\" -H \"Sec-WebSocket-Version: 13\" -H \"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\" https://teecup.teeoff.no/ws/rounds/00000000-0000-0000-0000-000000000000/live)", + "Bash(grep -n \"participants/\\\\${\" /opt/teecup/frontend/components/round-detail.tsx)", + "Bash(python3 -)", + "Bash(curl -s -o /dev/null -w \"teeoff.no: %{http_code}\\\\n\" https://teeoff.no/)" ] } } diff --git a/028_round_participant_tee.sql b/028_round_participant_tee.sql new file mode 100644 index 0000000..0807975 --- /dev/null +++ b/028_round_participant_tee.sql @@ -0,0 +1,25 @@ +-- ===================================================================== +-- TeeCup — utslagssted PER DELTAKER på en frittstående runde (migrasjon 028) +-- ===================================================================== +-- Reelt hull rapportert av bruker 2026-07-26: round_participant har i +-- dag INGEN egen tee -- alle deltakere spiller fra samme utslag som +-- round.tee_name_snapshot, uansett kjønn/faktisk valg. Rating-tallene +-- (course_rating_snapshot/slope_rating_snapshot/tee_par_snapshot) har +-- vært PER DELTAKER siden migrasjon 021 (nødvendig pga. kjønnsspesifikk +-- rating, ADR-029) -- selve NAVNET på utslaget manglet likevel helt. +-- +-- Backfylles fra rundens eksisterende tee (samme fysiske utslag alle +-- deltakere allerede regnes ut fra i praksis) -- ingen data endres, kun +-- navnet gjøres eksplisitt per rad slik at det kan avvike fremover. +-- ===================================================================== + +\set ON_ERROR_STOP on + +ALTER TABLE round_participant ADD COLUMN tee_name_snapshot text; + +UPDATE round_participant rp +SET tee_name_snapshot = r.tee_name_snapshot +FROM round r +WHERE r.id = rp.round_id; + +ALTER TABLE round_participant ALTER COLUMN tee_name_snapshot SET NOT NULL; diff --git a/CLAUDE.md b/CLAUDE.md index f865dff..d388076 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3084,18 +3084,92 @@ Ferdig og verifisert: produksjons-https ga FastAPI sin egen JSON-`{"detail":"Not Found"}`, ikke Next.js sin HTML-404 — samme verifiseringsmønster som ADR-027s tournament-live-rute. +- **HCP i medspiller-søk + rediger utslag/HCP per deltaker, BYGGET OG + SCRATCH-VERIFISERT (2026-07-26), IKKE ENNÅ RULLET UT:** brukeren viste et + skjermbilde av "+ Medspiller"-søket og påpekte at spillerens HCP burde + vises der (kun navn+klubb vistes), og ba samtidig om å kunne endre + utslagssted og HCP for medspillere -- "det er ikke sikkert de spiller fra + samme utslagssted som meg, og det er ikke sikkert HCP er riktig", eksplisitt + presisert som en endring KUN for denne runden/turneringen, ikke spillerens + faktiske profil. + **Reelt hull bekreftet ved kodegjennomgang FØR bygging:** ALLE deltakere + på en runde har i dag brukt SAMME `round.tee_name_snapshot` -- ingen + per-deltaker-tee har noensinne eksistert (rating-tallene har vært per + deltaker siden migrasjon 021, men selve utslags-NAVNET var aldri + eksplisitt per rad). + **Bygget:** `PersonMatch` (`app/routers/friends.py`, delt av vennesøk OG + medspiller-søk) fikk `handicap_index: float | None`. Ny migrasjon + `028_round_participant_tee.sql` -- `round_participant.tee_name_snapshot`, + backfylt fra rundens eksisterende tee for alle eksisterende rader. `_create_ + participant` skriver nå tee-navnet eksplisitt; `ParticipantCreate` (add_ + participant) fikk et valgfritt `tee_name` som faller tilbake til rundens + tee hvis utelatt. Ny `GET /rounds/{id}/tee-options` (gjenbruker + `_ResolvedCourse` sin rating-dict via en ny `tee_options()`-metode) -- + brukt av "rediger spiller"-panelet til å liste banens faktiske utslag. + `ParticipantUpdate` skrevet om til vanlig `exclude_unset`-PATCH-semantikk + (var tidligere kun `stat_level`, alltid påkrevd) -- nye valgfrie + `tee_name`/`handicap_index`-felt trigger en full re-beregning av + rating-snapshottene + `course_handicap_snapshot` for AKKURAT den + deltakeren, uten å røre spillerens egen `app_user.handicap_index`. + Eksplisitt `null` på `handicap_index` fjerner HCP-sporing for denne + deltakeren i denne runden (samme mønster som profil-PATCH). **Bevisst + avvist etter at runden er fullført** (409 `ALREADY_COMPLETED`, samme + presedens som `RoundUpdate` sitt bane-bytte -- differensialen er da + allerede beregnet fra det gamle grunnlaget); `stat_level` alene er + fortsatt tillatt uansett fullført-status. `RoundUpdate` sitt eksisterende + bane-bytte (ADR-033-oppfølging 2026-07-24) nullstiller nå eksplisitt ALLE + deltakeres `tee_name_snapshot` til rundens nye utslag (et bane-bytte gjør + individuelle tee-valg fra den gamle banen meningsløse). + **Frontend (`round-detail.tsx`):** søkeresultatene i "+ Medspiller" viser + nå HCP ved siden av hjemmeklubb. Ny "Utslag: X · HCP: Y"-rad under + statistikknivå-velgeren for aktiv spiller, med en "Rediger for denne + runden"-lenke (kun eier, kun før fullført) som åpner en ny + `EditParticipantPanel` -- utslagssted som en ` setTeeName(e.target.value)} + disabled={teeOptions === null} + className="h-11 rounded-xl border border-border bg-background px-3 text-base font-semibold text-foreground disabled:opacity-60" + > + {!availableTees.some((t) => t.name === teeName) && } + {availableTees.map((t) => ( + + ))} + + {teeOptions !== null && availableTees.length === 0 && ( +

Fant ingen andre utslag med rating for dette kjønnet på denne banen.

+ )} + + +
+ + setHcp(e.target.value)} + placeholder="F.eks. 18" + className="h-12 rounded-2xl text-base" + /> +
+ + + + ) +} + function ChangeCourseForm({ onPatch, onCancel,