diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md index cdfcbea..3b85461 100644 --- a/ARCHITECTURE_DECISIONS.md +++ b/ARCHITECTURE_DECISIONS.md @@ -8751,6 +8751,75 @@ bør vurderes nevnt i CLAUDE.md om det skjer igjen. --- +## ADR-085: Rediger organisasjonens hele spillerpool, når som helst (2026-08-18) + +Bruker meldte "lettere krise": ingen måte å redigere spillere i org- +turneringer utenom den tre-felts inline-formen fra 2026-07-19/20 +(`EditPlayerForm` i `tournament-detail.tsx`: kun navn/HCP/kjønn). Ba +eksplisitt om at tabellen fra spillerimporten (ADR-082) skal være +tilgjengelig for redigering NÅR SOM HELST, ikke bare under en fersk +CSV-import inni én bestemt turnering. + +**Undersøkt før bygging:** `PlayerImportPanel` fantes kun som en modal +inni to turnering-rostringsskjermer, alltid startet ved `step="upload"` +-- ingen rute, ingen vei til å åpne den med eksisterende spillere +forhåndsutfylt. **Kritisk funn i `POST .../players/bulk`** (ADR-082 sitt +lagre-endepunkt): bruker `COALESCE` per felt -- fyller KUN tomme felt på +en eksisterende match, og rører ALDRI `display_name`/`email`/`paid` i +det hele tatt (bevisst, for CSV-import). Dette endepunktet ville derfor +IKKE fungert som lagre-vei for en ekte "rett dette feltet"-skjerm -- +en korrigering av et allerede utfylt navn eller HCP ville stille feilet +(returnert 200, men ingenting endret). `PATCH /orgs/{id}/players/{id}` +gjør derimot ekte per-felt-overskriving, men kun ett spiller om gangen, +ingen bulk-variant. + +**Løsning: gjenbruk selve tabell-UI-et (`PlayerImportView`) uendret i +sin visuelle utforming, ny orkestrering rundt den.** Ny +`Mode.kind === "roster"` (ingen turneringskontekst -- skjuler lag-/ +klasse-kolonnene, endrer tittel/avslutningstekst). Ny +`org-player-roster-panel.tsx`: laster radene fra `GET /orgs/{id}/ +players` (i stedet for en opplastet CSV), differ hvert felt mot +originalverdien ved lagring, og sender KUN de faktisk endrede feltene +som `PATCH` per eksisterende spiller (ekte overskriving) -- helt nye +rader (lagt til i tabellen denne økten) oppretter med vanlig `POST`, +én om gangen. Ingen backend-endring, ingen migrasjon -- ren +klient-side orkestrering mot eksisterende endepunkter. + +**Bevisst utenfor omfang:** ekte sletting av en spiller fra +organisasjonen -- "Slett"-knappen i tabellen fjerner kun raden fra +DENNE redigeringsøkten (samme klient-side-only-oppførsel som i +import-flyten), IKKE spilleren fra databasen. Ingen slette-endepunkt +finnes. Gjort eksplisitt i UI-teksten (`player-import-view.tsx` sin +`EditTable`-beskrivelse, roster-modus) for å unngå at "Slett" feilaktig +oppfattes som en reell sletting. + +**Ny rute:** `/organizations/[id]/players` (`org-players.tsx` + +`app/organizations/[id]/players/page.tsx`, samme skall-mønster som +`org-members.tsx`/`members/page.tsx`), lenket fra en ny kort-lenke på +Medlemmer-siden (`org-members.tsx`, ved siden av Order of Merit). + +**Ingen ny V0-runde denne gangen** -- selve tabellen (`EditTable`) er +100% UENDRET gjenbruk av den allerede V0-designede komponenten fra +ADR-082, kun ny data-inn/data-ut-orkestrering og et par tekstlinjer +avhengig av modus. Vurdert IKKE å bryte "nye UI-flater går via V0"- +regelen, siden ingen ny visuell design faktisk lages her. + +**Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55. Scratch-runde +(database+API+next dev) med tre eksisterende spillere -- bekreftet at +tabellen laster reelle verdier (ikke bare navn), at HCP-korrigering på +en spiller MED allerede satt verdi (12.4→10.5) og navneendring på en +spiller UTEN e-post (dermed ingen bulk-matching mulig uansett) begge +faktisk persisterte i databasen ved reload, og at en helt ny rad +korrekt opprettet en ny spiller. Lys+mørk bekreftet. Måtte nedgradere +scratch-brukeren fra `owner` til `member` underveis -- org-eiere/ +-admins krever obligatorisk 2FA-oppsett ved innlogging (urelatert +funn, ikke en bug, bare et scratch-oppsett-hinder). Scratch-stacken +revet ned. + +**Rullet ut:** venter på bekreftelse (ren frontend, ingen migrasjon). + +--- + ## Utviklingsplan (rekkefølge) 1. ✅ Land tenant-modell → **Organisasjon** (ADR-001/002/003) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f363be..3c818f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12333,3 +12333,39 @@ Neste steg: **Ingen migrasjon** -- ren frontend-endring (`frontend/components/round-detail.tsx`). + +109. **Rediger organisasjonens hele spillerpool, når som helst (ADR-085) + — 2026-08-18.** "Lettere krise": bruker kunne ikke redigere spillere + i org-turneringer utenom en gammel tre-felts inline-form (navn/HCP/ + kjønn). Ba om at spillerimport-tabellen (ADR-082) skal være + tilgjengelig for redigering til enhver tid. + + **Kritisk funn:** `POST .../players/bulk` (import-lagringen) bruker + `COALESCE` per felt -- fyller KUN tomme felt på en eksisterende + match, rører ALDRI `display_name`/`email`/`paid`. Ubrukelig som + lagre-vei for ekte redigering (en korrigering av et allerede utfylt + navn/HCP ville stille feilet). Løsning: gjenbruker selve + `PlayerImportView`-tabellen UENDRET via en ny `mode.kind=== + "roster"`, men ny orkestrering (`org-player-roster-panel.tsx`) som + laster fra `GET /orgs/{id}/players` og lagrer med ekte `PATCH` + per endret felt (kun det som faktisk er rørt) -- nye rader + oppretter med vanlig `POST`. Ingen backend-endring, ingen + migrasjon. Ny rute `/organizations/[id]/players`, lenket fra + Medlemmer-siden. + + Ingen ny V0-runde -- selve tabellen er 100% uendret gjenbruk av en + allerede V0-designet komponent, kun ny data-orkestrering. + + **Bevisst utenfor omfang:** ekte sletting av en spiller -- "Slett" + fjerner kun raden fra redigeringsøkten, ikke fra databasen (ingen + slette-endepunkt finnes), gjort eksplisitt i UI-teksten. + + **Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55. Scratch- + runde med tre eksisterende spillere -- bekreftet at en HCP- + korrigering (12.4→10.5) OG en navneendring på en allerede utfylt + spiller begge faktisk persisterte ved reload (nøyaktig det bulk- + endepunktet ikke kunne), og at en ny rad korrekt opprettet en ny + spiller. Lys+mørk bekreftet. Scratch-stacken revet ned. + + **Rullet ut:** venter på bekreftelse (ren frontend, ingen + migrasjon). diff --git a/frontend/app/organizations/[id]/players/page.tsx b/frontend/app/organizations/[id]/players/page.tsx new file mode 100644 index 0000000..d8025d7 --- /dev/null +++ b/frontend/app/organizations/[id]/players/page.tsx @@ -0,0 +1,13 @@ +import { OrgPlayers } from "@/components/org-players" + +export default async function OrgPlayersPage({ + params, + searchParams, +}: { + params: Promise<{ id: string }> + searchParams: Promise<{ name?: string }> +}) { + const { id } = await params + const { name } = await searchParams + return +} diff --git a/frontend/components/org-members.tsx b/frontend/components/org-members.tsx index 701f598..98ecd63 100644 --- a/frontend/components/org-members.tsx +++ b/frontend/components/org-members.tsx @@ -8,7 +8,7 @@ import type React from "react" import { useEffect, useState } from "react" import Link from "next/link" -import { ArrowLeft, Mail, Trash2, Trophy, UserPlus, Users } from "lucide-react" +import { ArrowLeft, Mail, Trash2, Trophy, UserPlus, Users, UsersRound } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" @@ -182,8 +182,21 @@ export function OrgMembers({ organizationId, orgName }: { organizationId: string {canInvite && } +
+
+
+ Spillerpool + Se og rediger alle spillere organisasjonen har registrert +
+ + +