Files
CRAPP/docs/modules/squadra.md
T
davideandClaude Sonnet 5 04e80a3531 Allinea la documentazione al codice: migration, roadmap e moduli mancanti
Emerso da un audit doc↔codice: PROJECT_STATE.md era fermo a M12 (23 migration)
mentre supabase/migrations/ ne ha 27, fino a M16; ROADMAP.md non citava MVP,
Turno palloni, Infortuni e Profilo Giocatore come voci a sé pur essendo tutte
implementate; profilo-giocatore.md era l'unico modulo senza l'intestazione
Stato/File principali degli altri.

Aggiunge anche le due spec mancanti in docs/modules/: Squadra (anagrafica,
useRosa/useAnagraficaRosa, gestione admin, classifica interna) e Calendario ed
Eventi (vista mensile vs gestione admin, pulizia a cascata alla cancellazione).

Corregge inoltre la nota sul versionamento in CHANGELOG.md: sempre a tre cifre
(x.y.z), mai x.y.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 13:31:39 +02:00

5.4 KiB

Modulo — Squadra

Stato: implementato File principali: src/lib/giocatori-squadra.ts, src/lib/giocatori-squadra.server.ts, src/lib/rosa.ts, src/routes/squadra.tsx, src/routes/admin.tsx (sezione rosa) Test: test/unit/giocatori-squadra.test.ts, test/unit/rosa.test.ts


Obiettivo

Tenere l'anagrafica della rosa (nome, numero di maglia, ruolo, chi è collegato a quale account) in un unico posto — giocatori_squadra — e farla usare a tutte le schermate che hanno bisogno di sapere "chi c'è in squadra", invece di ciascuna avere la propria copia. Prima di DD-015 la lista viveva hardcoded in src/lib/crapp-data.ts: aggiungere o disattivare un giocatore dalla dashboard admin non aveva alcun effetto sul resto dell'app.


Due letture diverse, per non pagare due volte lo stesso costo

  • useAnagraficaRosa() (rosa.ts) — solo id, nome, ruolo, numero, data di nascita dei giocatori attivo. Serve dove basta sapere chi c'è, es. i compleanni nel Calendario o le liste presenze: non monta gli hook di MVP/pagelle/palloni/infortuni.
  • useRosa() (rosa.ts) — la stessa anagrafica arricchita con tutte le statistiche personali calcolate a runtime: presenze, partite giocate, serie (presenze, allenamenti, partite, conferme, palloni), MVP vinti, media voto pagelle, palloni, cacche, infortuni, ritardi. Non fa query aggiuntive: combina in un useMemo le cache già in memoria di mvp-voti.ts, pagelle.ts, cacche.ts, palloni.ts, infortuni.ts, presenze.ts, eventi.ts — la spec di ciascuna di queste statistiche sta nel modulo relativo (mvp.md, pagelle.md, palloni.md, infortuni.md, presenze.md). useRosa() è anche la base di useIo() (il giocatore sul dispositivo corrente) e useObiettivi() (obiettivi-squadra.md).

Entrambe filtrano solo i giocatori attivo: chi ha lasciato la squadra resta nel database (presenze, voti, pagelle e badge della stagione restano agganciati al suo id) ma sparisce dagli elenchi correnti.

Gestione dati squadra (solo amministratore)

Da /admin un amministratore può (DD-017):

Azione Hook Effetto
Modificare dati squadra useSalvaDatiSquadra() Nome, cognome, numero, ruolo, email (usata per il collegamento automatico, non il dato personale del profilo)
Aggiungere un giocatore useAggiungiGiocatore() Nuova riga con id progressivo g<N> (prossimoIdGiocatore()), non generato dal database
Attivare/disattivare useImpostaAttivo() Non elimina la riga: la storia della stagione resta intatta
Scollegare un account useScollegaAccount() Libera uno slot collegato per errore (DD-016 regola 2); il giocatore si ricollega al primo accesso successivo
Registrare il tesseramento CSI useSalvaTesseramento() Numero e data tessera, note solo dopo il tesseramento effettivo (vedi profilo-giocatore.md)

Il collegamento giocatore↔account, invece, non è manuale: avviene in automatico al primo accesso con Google, per corrispondenza email (DD-018). useCollegaGiocatore() esiste per completare quel flusso, non per una scelta libera dell'admin.

Le regole di validazione (validaDatiSquadra(), numeroGiaUsato()) rispecchiano i vincoli della tabella (numero maglia univoco tra gli attivi, campi obbligatori): l'obiettivo è mostrare un messaggio leggibile invece di far arrivare un errore Postgres grezzo all'amministratore.

Classifica interna di Squadra

La tab "Stats" di /squadra mostra una classifica interna ordinabile per 5 criteri (CriterioClassifica in rosa.ts): presenze, media voto, MVP, palloni, cacche/partita. classificaRank() calcola un "dense rank" (a parità di valore stessa posizione, il successivo non salta — 1, 1, 2, non 1, 1, 3); dettaglioClassifica() sceglie quale sottostatistica mostrare sotto il nome, coerente col criterio selezionato (es. "voti pagella" per il criterio media voto, non sempre "presenze consecutive").

Le altre tab di /squadra (Rosa, Obiettivi, Badge) sono viste diverse sugli stessi dati di useRosa()/useObiettivi()/badges.ts: non introducono altra logica di dominio, solo presentazione — le rispettive specifiche stanno in badge.md e obiettivi-squadra.md.


Limiti noti

  1. giocatori_squadra non ha ancora una colonna per la data di nascita. Per i giocatori storici (seed iniziale) la nascita viene letta da crapp-data.ts (nascitaPerId, lookup per id); un giocatore aggiunto dopo la migrazione non ha nascita nota finché la colonna non esiste (DD-015). Effetto visibile: niente compleanno nel Calendario per quei giocatori.
  2. src/lib/crapp-data.ts resta come fallback, non più come fonte viva: se il database non risponde o non è ancora popolato, rosaFallback() genera una rosa di riserva dai dati statici storici. Un ambiente nuovo senza dati in giocatori_squadra mostra quindi comunque una squadra, non una schermata vuota — ma è la rosa 2025/26 hardcoded, non quella reale.