De to gjenværende UI-hullene fra 2026-07-19-runden (ingen vei til å opprette en ANDRE organisasjon, og intet sammendrag for "alle runder har dato") er de mest opplagte å ta først — begge er ferdig diagnostisert, null designtvil, og rene tilføyelser i frontend uten backend-endring.
Det jeg egentlig vil trekke frem som det strategisk viktigste, er derimot deltaker-tilgang til lag-chat og scorekort uten org-medlemskap — den naturlige fortsettelsen av dagens ADR-031-arbeid («Mine runder» viser nå turneringen, men en ren spiller kan fortsatt ikke åpne laget sin chat eller scorekortet derfra, siden begge fortsatt krever get_authorized_org). Tradeoffen: det er en bredere og mer risikofylt endring enn dagens papirkutt, siden get_authorized_org brukes av dusinvis av endepunkter — bør gjøres som en egen, forsiktig gjennomgått runde, ikke tas i forbifarten.
This commit is contained in:
parent
45850a97fa
commit
3f888f1e10
6 changed files with 161 additions and 42 deletions
|
|
@ -331,7 +331,10 @@
|
|||
"Bash(python3 /tmp/claude-1000/-opt-teecup/a8bd2fc3-4b9c-4682-a2be-cf36e143de78/scratchpad/test_profile_and_myrounds.py)",
|
||||
"Bash(curl -s -o /dev/null -w \"account: %{http_code}\\\\n\" https://teecup.teeoff.no/account)",
|
||||
"Bash(python3 /tmp/claude-1000/-opt-teecup/a8bd2fc3-4b9c-4682-a2be-cf36e143de78/scratchpad/test_email_mobile.py)",
|
||||
"Bash(curl -s -o /dev/null -w \"verify-email: %{http_code}\\\\n\" https://teecup.teeoff.no/verify-email)"
|
||||
"Bash(curl -s -o /dev/null -w \"verify-email: %{http_code}\\\\n\" https://teecup.teeoff.no/verify-email)",
|
||||
"Bash(grep -rln \"orgs/\\\\[id\\\\]/members\\\\|orgs/\\\\${.*}/members\\\\|/orgs/\\\\\" .*members\" /opt/teecup/frontend --include=\"*.tsx\" --include=\"*.ts\")",
|
||||
"Bash(curl -s http://localhost:18734/organizations/00000000-0000-0000-0000-000000000000/members?name=Test)",
|
||||
"Bash(curl -s http://localhost:18734/orgs/00000000-0000-0000-0000-000000000000/members)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"/opt/teeoff/deploy",
|
||||
|
|
|
|||
54
CLAUDE.md
54
CLAUDE.md
|
|
@ -2067,33 +2067,59 @@ Ferdig og verifisert:
|
|||
boot-et rent, `/health`/`/dashboard`/`/account`/`/verify-email` → 200,
|
||||
`teeoff.no` upåvirket.
|
||||
|
||||
- **Medlemsside-ruten FIKSET OG LIVE (2026-07-20):** brukeren ba eksplisitt
|
||||
om å ta fatt på dette (det mest presserende av de fire UI-hullene notert
|
||||
2026-07-19 — siden var helt utilgjengelig). Root cause var allerede
|
||||
presist diagnostisert: `next.config.mjs` sin `rewrites()` (plain array,
|
||||
implisitt "afterFiles") fanger `/orgs/:path*` FØR Next.js sine egne
|
||||
DYNAMISKE sider sjekkes, så `app/orgs/[id]/members/page.tsx` ble aldri
|
||||
nådd — kallet gikk til FastAPI i stedet, som ga en rå 404.
|
||||
**Fikset:** siden flyttet til `app/organizations/[id]/members/page.tsx`
|
||||
(utenfor `/orgs/*`-prefikset), eneste lenke (`dashboard.tsx`) oppdatert.
|
||||
Lagt til en forklarende kommentar i `next.config.mjs` sin `rewrites()`
|
||||
for å forhindre samme feil ved en fremtidig ny side.
|
||||
**Verifisert med ekte produksjonsbuild + container-boot** (ikke bare
|
||||
typesjekk): den nye ruten (`/organizations/{id}/members`) rendrer
|
||||
faktisk `OrgMembers`-komponenten med riktig `organizationId`/`orgName`
|
||||
i RSC-payloaden, IKKE en 404 eller innloggingssiden.
|
||||
**Rullet ut live**, ren frontend-endring, ingen migrasjon, `teeoff.no`
|
||||
upåvirket.
|
||||
|
||||
Neste steg:
|
||||
1. **Personlig landingsside + profil (ADR-031) OG e-post/mobil (ADR-032)
|
||||
er BEGGE LIVE.** Naturlig oppfølging: deltaker-tilgang (uten
|
||||
org-medlemskap) til lag-chat/scorekort — bevisst utenfor omfang denne
|
||||
runden, se FEATURE_BACKLOG.md.
|
||||
2. **Punkt 2 fra samme 2026-07-20-runde (lavere prioritet enn #1):**
|
||||
midlertidige spillere + automatisk etter-runde-e-post — forslag klart
|
||||
1. **Venter på brukerens retningsbekreftelse:** redesign av dashbordets
|
||||
tom-tilstand ved første innlogging (mindre organisator-vridd, se
|
||||
FEATURE_BACKLOG.md) — forslag lagt frem 2026-07-20, ikke bygget.
|
||||
2. **Notert, IKKE designet i detalj:** én person med flere e-post-adresser
|
||||
— legge til en verifisert sekundær-adresse fra dashbordet, med
|
||||
turneringer/data som "dukker opp"/slås sammen deretter, og fremtidige
|
||||
innlogginger med enten adresse. Fanget grundig i FEATURE_BACKLOG.md,
|
||||
inkl. et reelt uløst spørsmål (ekte konto-sammenslåing hvis adressen
|
||||
allerede tilhører en annen eksisterende konto) som trenger egen,
|
||||
separat designrunde.
|
||||
3. Personlig landingsside + profil (ADR-031) OG e-post/mobil (ADR-032) er
|
||||
BEGGE LIVE. Naturlig oppfølging: deltaker-tilgang (uten org-medlemskap)
|
||||
til lag-chat/scorekort — bevisst utenfor omfang, se FEATURE_BACKLOG.md.
|
||||
4. **Punkt 2 fra 2026-07-20-runden (midlertidige spillere):** forslag klart
|
||||
i FEATURE_BACKLOG.md, tre åpne spørsmål, ingen kode skrevet.
|
||||
3. Oppfølgingspunkt fra PWA-runden, eksplisitt notert på brukerens
|
||||
5. Oppfølgingspunkt fra PWA-runden, eksplisitt notert på brukerens
|
||||
forespørsel: offline-scoreregistrering er ALDRI browser-testet i
|
||||
praksis (kun kodegjennomgang + build-verifisering, se ADR-028). Bruker
|
||||
bør selv åpne et scorekort, skru på Chrome DevTools sin Offline-bryter,
|
||||
registrere et par slag, skru nettet på igjen, og bekrefte at de faktisk
|
||||
synkes — først da er flyten reelt bevist.
|
||||
4. Fire UI-/UX-hull notert 2026-07-19 (se over) — ingen fikset ennå.
|
||||
Rewrite/medlemsside-bugen (#2) er den mest presserende siden siden er
|
||||
helt utilgjengelig i dag.
|
||||
5. Fortsatt åpne beslutninger fra FEATURE_BACKLOG.md: kode-regenerering for
|
||||
6. To av fire UI-/UX-hull notert 2026-07-19 er fikset (datovisning ADR-030,
|
||||
medlemsside-ruten). Gjenstår: "opprett en ANDRE organisasjon" (ingen UI
|
||||
ennå) og et sammendrag for "alle runder har dato".
|
||||
7. Fortsatt åpne beslutninger fra FEATURE_BACKLOG.md: kode-regenerering for
|
||||
ADR-020, korrigering-godkjenning fra motpart, video/1-til-1-meldinger
|
||||
(bevisst utsatt i ADR-025).
|
||||
6. Flere turneringsformater utover Ryder Cup (Københavner/High-low-high/
|
||||
8. Flere turneringsformater utover Ryder Cup (Københavner/High-low-high/
|
||||
Robbins/Try all, notert 2026-07-19) — ingen ADR-runde startet ennå.
|
||||
7. **Merk for neste økt:** `deploy/Caddyfile`-endringen (ny `/ws/*`-rute,
|
||||
9. **Merk for neste økt:** `deploy/Caddyfile`-endringen (ny `/ws/*`-rute,
|
||||
ADR-025) ligger uncommitted i det SEPARATE `/opt/teeoff`-repoet, ikke i
|
||||
`teecup`-repoet — samme fallgruve som ADR-016-runden sin Caddy-endring,
|
||||
lett å glemme siden denne økten ellers kun har jobbet i `/opt/teecup`.
|
||||
8. Ved fremtidige nye V0-skjermer/-design i V0 (fortsett i samme prosjekt),
|
||||
10. Ved fremtidige nye V0-skjermer/-design i V0 (fortsett i samme prosjekt),
|
||||
FORVENT en full re-eksport hver gang — diff mot live-treet i et
|
||||
scratch-område før noe pakkes ut over eksisterende filer, og sjekk om
|
||||
V0-skjermen bygger inn handlinger backend ikke støtter ennå FØR
|
||||
|
|
|
|||
|
|
@ -932,29 +932,22 @@ er fikset i denne runden — kun dokumentert slik at de ikke går i glemmeboken.
|
|||
satt `start_date`/`end_date`, som fortsatt vinner om det noensinne
|
||||
settes). Se ADR-030 for full detalj og verifisering.
|
||||
|
||||
2. **`/orgs/{id}/members`-siden gir en rå API-404 (`{"detail":"Not
|
||||
Found"}`), ikke medlemssiden.** Bekreftet root cause, ikke bare
|
||||
reprodusert: `frontend/next.config.mjs` sin `rewrites()` returnerer en
|
||||
PLAIN ARRAY (implisitt "afterFiles"-semantikk i Next.js) — det betyr at
|
||||
ikke-dynamiske filer/sider sjekkes FØR rewrites, men DYNAMISKE sider
|
||||
(som `app/orgs/[id]/members/page.tsx`) sjekkes ETTER. Rewrite-regelen
|
||||
`{ source: "/orgs/:path*", destination: ".../orgs/:path*" }` (satt opp i
|
||||
ADR-016 for å proxye API-kall) fanger derfor `/orgs/{id}/members` FØR
|
||||
Next.js noensinne når frem til den faktiske siden, og sender kallet til
|
||||
FastAPI i stedet — som naturligvis ikke har noen `GET /orgs/{id}/members`-
|
||||
rute (kun `/orgs/{id}/memberships`), derav den rå FastAPI-404-formen
|
||||
(ikke engang appens egen `app_error`-kontrakt, siden ruten ikke matcher
|
||||
noe sted i det hele tatt). Selve siden (`org-members.tsx`, lenken fra
|
||||
dashbordet) er ellers riktig bygget — dette er en ren
|
||||
rewrite/dynamisk-rute-presedens-krasj, samme klasse fallgruve som
|
||||
ADR-016 sin opprinnelige "alt nytt API-prefiks må inn i rewrites"-lærdom,
|
||||
bare i motsatt retning (en frontend-SIDE ble skjult AV en rewrite). Dette
|
||||
er den FØRSTE frontend-siden som noensinne har blitt nestet direkte under
|
||||
et allerede proxyet prefiks (`/orgs/*`) — ingen tidligere skjerm har
|
||||
truffet dette. Sannsynlig fiks: flytt siden til en ikke-proxyet sti
|
||||
(f.eks. `/organizations/[id]/members`), ELLER gjør rewrites-regelen mer
|
||||
presis (kun kjente API-undermønstre som `/orgs/:id/tournaments`,
|
||||
`/orgs/:id/memberships` osv., ikke et bredt `:path*`).
|
||||
2. **✅ FIKSET 2026-07-20: `/orgs/{id}/members`-siden ga en rå API-404
|
||||
(`{"detail":"Not Found"}`), ikke medlemssiden.** Bekreftet root cause,
|
||||
ikke bare reprodusert: `frontend/next.config.mjs` sin `rewrites()`
|
||||
returnerer en PLAIN ARRAY (implisitt "afterFiles"-semantikk i Next.js)
|
||||
— statiske filer/sider sjekkes FØR rewrites, men DYNAMISKE sider (som
|
||||
`app/orgs/[id]/members/page.tsx`) sjekkes ETTER. Rewrite-regelen
|
||||
`{ source: "/orgs/:path*", ... }` (ADR-016) fanget derfor kallet FØR
|
||||
Next.js noensinne nådde selve siden, og sendte det til FastAPI i
|
||||
stedet (som naturligvis ikke har noen `GET /orgs/{id}/members`-rute).
|
||||
**Fikset:** siden flyttet til `app/organizations/[id]/members/page.tsx`
|
||||
(utenfor det proxyede `/orgs/*`-prefikset), eneste lenke til den
|
||||
(`dashboard.tsx`) oppdatert tilsvarende. Lagt til en forklarende
|
||||
kommentar direkte i `next.config.mjs` sin `rewrites()` slik at samme
|
||||
feil ikke gjentas for en fremtidig ny side. Verifisert med ekte
|
||||
produksjonsbuild + container-boot: den nye ruten rendrer faktisk
|
||||
`OrgMembers`-komponenten (ikke en 404 eller innloggingssiden).
|
||||
|
||||
3. **Dashboard: ingen vei til å opprette/legge til en ANDRE organisasjon.**
|
||||
Bekreftet i `dashboard.tsx`: `CreateOrganizationState`
|
||||
|
|
@ -974,9 +967,9 @@ er fikset i denne runden — kun dokumentert slik at de ikke går i glemmeboken.
|
|||
bakenforliggende datamodell-begrensning (all nødvendig data finnes
|
||||
allerede i `GET .../sessions`).
|
||||
|
||||
**Ingenting av dette er fikset ennå** — kun diagnostisert og notert på
|
||||
brukerens eksplisitte instruks, for å ikke gå i glemmeboken mens PWA-runden
|
||||
prioriteres. Punkt 1 (datovisning) senere ✅ fikset, se over (ADR-030).
|
||||
Punkt 1 (datovisning, ADR-030) og punkt 2 (medlemsside-ruten) er nå ✅
|
||||
fikset, se over. Punkt 3 (opprett en ANDRE organisasjon) og punkt 4 (ingen
|
||||
sammendrag for "alle runder har dato") står fortsatt åpne.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1131,6 +1124,95 @@ koblingen skal skje).
|
|||
|
||||
---
|
||||
|
||||
## Dashboard: tom-tilstand ved første innlogging — 📋 FORESLÅTT 2026-07-20, IKKE bygget
|
||||
|
||||
Brukeren påpekte at dagens tomme-tilstand ("Du har ingen organisasjon ennå —
|
||||
opprett en") er organisator-vridd og ikke stemmer med hva en fersk bruker
|
||||
faktisk trenger å se/gjøre. Bedt om en refleksjon FØR bygging.
|
||||
|
||||
**Analyse av hvem som faktisk lander på tom-skjermen:** en spiller invitert
|
||||
med kode (ADR-020) går allerede utenom (login-siden sender dem rett til
|
||||
turneringen). En spiller som er ROSTRET på et lag dukker nå opp i "Mine
|
||||
runder" (ADR-031). Men en spiller som kun er PÅMELDT (`tournament_
|
||||
registration`, ADR-017) og ikke ennå rostret, dukker IKKE opp — "Mine
|
||||
runder" v1 ser kun på `team_roster` (kjent, allerede notert begrensning,
|
||||
se ADR-031 sitt "naturlig neste steg"-punkt over). Denne gruppen — trolig
|
||||
en av de vanligste måtene en helt fersk bruker faktisk møter TeeCup på —
|
||||
faller derfor rett igjennom til "opprett organisasjon"-skjermen i dag.
|
||||
|
||||
**Foreslått, IKKE bygget:**
|
||||
1. Utvid "Mine runder" til også å vise rene påmeldinger (ikke bare
|
||||
rostrede lag) — tetter selve hullet, reduserer hvor ofte noen i det
|
||||
hele tatt havner på tom-skjermen.
|
||||
2. Gjør selve tom-skjermen nøytral: to likestilte valg side ved side —
|
||||
"Har du en kode?" (gjenbruker samme oppslag som login-siden sin
|
||||
`JoinByCode`) og "Skal du arrangere selv? Opprett organisasjon" — i
|
||||
stedet for at organisator-veien er det eneste synlige alternativet.
|
||||
|
||||
**Venter på brukerens bekreftelse på retning** før bygging.
|
||||
|
||||
---
|
||||
|
||||
## Én person, flere e-postadresser — 📋 NOTERT 2026-07-20, IKKE designet/bygget
|
||||
|
||||
Reist av brukeren rett etter ADR-032 (verifisert e-postbytte). Et beslektet,
|
||||
men DISTINKT behov: én person kan ha flere e-postadresser i omløp samtidig
|
||||
(f.eks. registrert seg privat med én adresse, men fått en turnering-
|
||||
invitasjon rettet mot en jobb-adresse organisator la inn) — ikke et BYTTE
|
||||
(ADR-032 sin løsning), men en TILLEGGS-tilknytning. I dag oppretter et
|
||||
magic-link-innlogg på en ny adresse alltid en HELT NY, tom `app_user`-konto
|
||||
(ADR-009) — nøyaktig det som gjør at spilleren aldri "finner" turneringen
|
||||
sin med sin vanlige, primære konto.
|
||||
|
||||
**Brukerens beskrevne flyt, ordrett fanget:** innlogget med
|
||||
eksempel@domene.no, sier "jeg eier også test@domain.com". Ved dette kravet
|
||||
sendes en e-post til test@domain.com med en nøkkel som limes inn et sted på
|
||||
dashbordet. Etter bekreftelse dukker inviterte turneringer på den adressen
|
||||
opp. Annen data (spilte runder, personlig informasjon) skal "forespørres
|
||||
slått sammen eller justert". Fremtidige innlogginger skal kunne gjøres med
|
||||
ENHVER av de tilknyttede adressene.
|
||||
|
||||
**Foreslått retning, basert på gjenbruk av allerede bygget mønster:**
|
||||
samme token-i-e-post-bevis-eierskap-mekanisme som ADR-032 sin
|
||||
e-postbytte-flyt (`email_change_token`), men ADDITIV i stedet for
|
||||
ERSTATTENDE — en ny tabell for verifiserte SEKUNDÆRE e-poster knyttet til
|
||||
kontoen (i stedet for å overskrive `app_user.email`). Login (`/auth/
|
||||
request-link` m.fl.) må da slå opp BÅDE primær- og sekundær-e-poster.
|
||||
`link_player_by_email()`/organisasjonsinvitasjon-aksept (som i dag kun
|
||||
kjører mot `app_user.email`) må kjøres for HVER av kontoens verifiserte
|
||||
adresser — naturlig utløst rett etter en ny adresse er bekreftet, og
|
||||
sannsynligvis også trygt å kjøre på nytt ved hver innlogging (idempotent,
|
||||
samme mønster som i dag).
|
||||
|
||||
**Det virkelig vanskelige, uløste spørsmålet, IKKE adressert av brukerens
|
||||
beskrevne flyt:** hva skjer hvis den "krevde" adressen ALLEREDE er
|
||||
primær- (eller sekundær-)adressen til en ANNEN, eksisterende `app_user`-
|
||||
konto — altså at spilleren faktisk har logget inn med DEN adressen
|
||||
tidligere og dermed har to helt separate kontoer med egen historikk
|
||||
(ulike org-medlemskap, ulike spillerkoblinger, kanskje ulikt passord/2FA)?
|
||||
Da holder det ikke å bare "legge til" adressen — det er en ekte KONTO-
|
||||
SAMMENSLÅING (slå sammen organisasjonsmedlemskap uten å bryte "én rolle
|
||||
per bruker per org"-unikheten, deduplisere spiller-koblinger, avgjøre
|
||||
hvilken konto som "vinner" for tvetydige felt som `preferred_locale`/2FA
|
||||
når begge har satt noe ulikt). Dette er en betydelig større og mer
|
||||
risikofylt operasjon enn "legg til en frisk, ukrevd adresse" — bør
|
||||
utredes og besluttes som en egen, separat sak, ikke antas løst av samme
|
||||
runde som det enkle tilfellet.
|
||||
|
||||
**Plassering:** brukeren presiserte eksplisitt at dette må skje FRA
|
||||
dashbord-siden (ikke `/account`, der ADR-032 sin e-postbytte-flyt ellers
|
||||
naturlig ville hørt hjemme) — trolig fordi selve GEVINSTEN (nye turneringer
|
||||
dukker opp) er noe som vises på dashbordet, så handlingen bør ligge der
|
||||
resultatet vises.
|
||||
|
||||
**Ingenting designet i detalj eller bygget ennå** — kun fanget grundig her
|
||||
slik at det ikke går i glemmeboken. Bør trolig deles i to separate runder:
|
||||
(1) legg til en frisk, ukrevd sekundær-e-post (rimelig godt avgrenset,
|
||||
gjenbruker ADR-032 sitt mønster direkte), (2) ekte konto-sammenslåing for
|
||||
det vanskelige tilfellet over (egen, større designrunde).
|
||||
|
||||
---
|
||||
|
||||
## UX / frontend (senere fase)
|
||||
|
||||
- 📋 Høy kontrast, dark/light, store +/- knapper, stor «Neste hull»-knapp
|
||||
|
|
|
|||
|
|
@ -424,7 +424,7 @@ function OrganizationView({
|
|||
|
||||
<div className="flex items-center gap-2">
|
||||
<Link
|
||||
href={`/orgs/${org.organization_id}/members?name=${encodeURIComponent(org.name)}`}
|
||||
href={`/organizations/${org.organization_id}/members?name=${encodeURIComponent(org.name)}`}
|
||||
className="inline-flex h-11 items-center gap-1.5 rounded-2xl border border-border bg-card px-4 text-sm font-semibold text-foreground transition-colors hover:bg-accent/50"
|
||||
>
|
||||
<Users aria-hidden="true" className="size-4" />
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@ const nextConfig = {
|
|||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
// MERK (funnet 2026-07-19, se FEATURE_BACKLOG.md): en plain array her gir
|
||||
// implisitt "afterFiles"-semantikk -- statiske filer/sider sjekkes FØR
|
||||
// disse rewrites, men DYNAMISKE Next.js-sider (app/x/[id]/page.tsx)
|
||||
// sjekkes ETTER. En frontend-SIDE må derfor ALDRI nestes direkte under
|
||||
// et av prefiksene under (f.eks. /orgs/[id]/members) -- rewrite-regelen
|
||||
// vinner presedens og siden blir uoppnåelig (rå API-404 i stedet).
|
||||
// Legg nye frontend-sider et sted UTENFOR disse prefiksene (se
|
||||
// app/organizations/[id]/members for eksempelet dette ble rettet på).
|
||||
async rewrites() {
|
||||
return [
|
||||
{ source: "/auth/:path*", destination: `${API_ORIGIN}/auth/:path*` },
|
||||
|
|
|
|||
Loading…
Reference in a new issue