I colori di stato non passavano WCAG AA con il testo bianco sopra: success
3.39:1, training 3.49:1, info ~3.7:1 (chip «Presente», «Allenamento», celle
del calendario). Le luminosità sono abbassate fino a superare 4.5:1.
I gradi dei badge erano il caso peggiore: `text-oro` su bianco sta a 1.9:1 e
`text-argento` a 2.5:1, cioè illeggibili. Nascono i token `--oro-testo`,
`--argento-testo` e `--bronzo-testo` per il testo, mentre le varianti chiare
restano dove servono davvero, su sfondi e bordi.
Il blocco `.dark` non veniva mai applicato — nessun interruttore, nessun
`prefers-color-scheme` — ed era anche incoerente: l'accento diventava
grigio-blu e mancavano success, warning, info, training, i metalli, i due
gradienti e le due ombre. Un tema mai attivato non si accorge di rompersi,
quindi via, con `color-scheme: light` dichiarato esplicitamente.
Nello stesso file:
- `:focus-visible` globale, prima non c'era nessuna regola di focus;
- tracking del display specifico per taglia (`font-display-sm/lg`): un solo
valore per tutte le dimensioni è sbagliato da qualche parte;
- utility `materiale` e `bordo-sfumato` per la chrome traslucida, con
`prefers-reduced-transparency` e `prefers-contrast`;
- movimento ridotto: dissolvenza breve invece dell'azzeramento di ogni
transizione, così resta un feedback che spiega cosa è cambiato;
- rimossi i token di chart e sidebar (i componenti che li usavano non ci sono
più) e l'import di tw-animate-css, che non era usato da nessuna classe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I riferimenti ai documenti in AGENTS.md erano rotti: una venticinquina di link
nella forma docs/[README.md](http://README.md), che spezzavano il nome del file
a meta e puntavano a domini inesistenti. Ora sono percorsi relativi verificati,
con CHANGELOG.md e DESIGN_DECISIONS.md sotto docs/ e PROJECT_STATE.md in root.
Tolte da AGENTS.md le sezioni Architettura, Documentazione e Struttura della
documentazione: duplicavano ARCHITECTURE.md e docs/README.md con uno stack ormai
parziale, contro la regola "ogni informazione ha una sola casa" che docs/README.md
stesso impone. Aggiunti invece i comandi, bun e la guardia minimumReleaseAge:
Codex e Cursor leggono solo AGENTS.md e non avevano modo di sapere come si
verifica una modifica. Scritta la checklist "Fine lavoro" che CLAUDE.md citava
senza che esistesse.
Nuova regola: chi aggiunge o modifica una funzione scrive o aggiorna il test nello
stesso lavoro, i test devono essere verdi e la doc del modulo va aggiornata se il
comportamento cambia (DD-020). Serve perche con main come branch di lavoro non
c'e piu un ambiente di prova tra il codice e i giocatori.
Il flusso git documentato non descriveva piu la realta: main e arrivato a 43
commit di vantaggio su develop, rimasto fermo. DD-003 e ora sostituita da DD-019:
il branch dei commit lo decide l'utente, l'assistente al massimo consiglia un
branch dedicato e non committa, non pusha e non apre PR di propria iniziativa.
Allineati di conseguenza ARCHITECTURE.md (sezione branch), README.md (flusso,
install con bun, comandi di test e lint), ROADMAP.md e TODO.md (le voci spuntate
sono in produzione, non su develop) e PROJECT_STATE.md (auth e profilo giocatore
in produzione, 20 migration fino a M9, passaggi 1-3 e 5 fatti).
Corretti poi sei disallineamenti tra documentazione e codice, ognuno verificato
sul sorgente:
- badge.md e obiettivi-squadra.md dicevano che le serie sono inerti e che
serieAllenamenti e sempre 0, quindi badge e obiettivo "Continuita di squadra"
non sbloccabili. Falso da 7237e8f: presenze.ts:48 le calcola e rosa.ts:64-67 le
attacca al Giocatore. Il limite che resta e un altro, ora scritto: risposto_il
non e ricostruibile prima di m9, quindi sulle risposte vecchie serieConferme e
un'approssimazione.
- TODO.md e PROJECT_STATE.md davano il tracciamento tesseramento CSI come da
fare, mentre ROADMAP, CHANGELOG e DATABASE lo davano per fatto. Lo e:
admin.tsx:264-278 registra numero e data, :472 mostra Tesserato/Da tesserare,
:676 il contatore.
- collegamento-csi.md indicava il check di parsing in src/lib/csi-core.test.ts;
sta in test/unit/csi-core.test.ts, in src/lib non esiste nessun .test.ts.
- profilo-giocatore.md annunciava cinque aree del profilo e ne elencava sette.
- "Segnala un bug" e "Suggerisci una nuova funzionalita" (profilo.tsx:259-276,
commit 72a9864) non erano documentati da nessuna parte, contro DD-002: ora
stanno in profilo-giocatore.md e nel CHANGELOG.
npm run test: 28/28 file ok. npm run lint: 12 problemi, identici a prima di
questa modifica e tutti in src/, non toccato qui.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I tre contatori (serieAllenamenti, seriePartite, serieConferme) e streak erano
zero fisso in useRosa(): la sezione Serie di presenze del profilo mostrava sempre
progresso nullo, i badge legati alla costanza erano impossibili da sbloccare e
l'obiettivo Continuita di squadra restava a 0/12.
serieConsecutiva() e serieConferme() (src/lib/presenze.ts) derivano le serie dagli
eventi passati e da risposte_presenze gia in cache, senza query aggiuntive.
Migration m9: nuova colonna risposto_il con l'istante della prima risposta, resa
immutabile da un trigger, confrontata con eventi_app.creato_il per le conferme
entro 24 ore. Serviva perche aggiornato_il registra l'ultima modifica, quindi chi
rispondeva subito e cambiava idea dopo risultava lento.
Corregge anche la barra di progresso, che misurava valore/prossimo e tornava
indietro a ogni traguardo raggiunto (2/3 = 67%, poi 3/6 = 50%).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Presenze, Serie di presenze, Scout Live, Pagelle, MVP, Badge, Palloni,
Obiettivi di squadra, Infortuni, Notifiche: chiudono il debito di
documentazione tracciato in TODO.md (DD-002). Le sei route API
pubbliche vengono descritte dentro il modulo a cui appartengono.
I template GitHub guidano chi apre una issue a fornire titolo,
descrizione strutturata ed eventuali screenshot invece di un campo
libero. Dal profilo, prima di "Esci", due link aprono direttamente
il template giusto su GitHub.
Con cacheControl: "60" l'immagine sostituita poteva restare quella
vecchia per un minuto se la CDN davanti allo storage non varia la
cache in base alla query string di cache-busting (?v=).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rinomina "Cacche/partita" in "Cacche" e passa i pill da flex-wrap a
flex-nowrap con flex-1/truncate, così entrano tutti su una riga sola
senza andare a capo né richiedere swipe orizzontale.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
I pill (Presenze, Media voto, MVP, Palloni, Cacche/partita) andavano su
una riga scrollabile orizzontalmente; ora vanno a capo con flex-wrap.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Il gate "M4 non applicabile finché la squadra non è collegata" è superato:
il login era già l'unica via d'accesso lato app, quindi i giocatori non
ancora collegati non erano comunque impattati dal residuo di accesso anon
che M4 chiudeva. Aggiorna anche DD-018, ormai stale: l'email dei giocatori
si imposta da /admin, non solo via migration.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
M3 esisteva solo come bozza archiviata in docs/archive/migrations/: il bucket
profili-giocatore è creato dalla migration M2 insieme alla tabella. Allinea
PROJECT_STATE.md (12 -> 18 migration), DATABASE.md, CHANGELOG.md, TODO.md,
DESIGN_DECISIONS.md, test/README.md e il test di integrazione dei profili.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
I dati dimostrativi in crapp-data.ts sono stati rimossi (DD-015); il fallback
reale oggi è classifica vuota (o ultimo dato in cache) e risultati dallo
Scout Live locale.
Co-Authored-By: Claude Mythos <noreply@anthropic.com>
Aggiorna DESIGN_DECISIONS.md (DD-015 da "In valutazione" ad "Accettata",
con le conseguenze reali: fallback nascita e crapp-data.ts come solo
seed/fallback), DATABASE.md, ARCHITECTURE.md e PROJECT_STATE.md di
conseguenza.
convocatiEvento() e compleanniEventi() prendono ora la rosa come parametro
invece di leggere la lista statica; csvScoutMatch() idem. Le schermate di
gestione eventi, dettaglio allenamento/partita, calendario e scout live,
più i widget di presenze/pagelle/voto MVP/voto social/sondaggio
cacche/turno palloni, passano tutte la rosa letta da useRosa() o
useGiocatoriSquadra(): un giocatore aggiunto o disattivato dalla dashboard
admin ora si riflette ovunque.
obiettivi.ts, palloni-core.ts, presenze-mese.ts e user-store.ts non
dipendono più dalla lista statica di crapp-data.ts ma ricevono/leggono la
rosa reale (percentuali obiettivo, rotazione turno palloni, riepilogo
presenze mensile, identità del dispositivo). Le route API per le notifiche
push (push-messaggio, promemoria-palloni, sollecita-presenze) leggono la
squadra lato server con leggiGiocatoriSquadra(), filtrando attivo.
useGiocatoreBase() ora interroga giocatori_squadra con useQuery, ma
RootComponent la chiamava prima di montare QueryClientProvider: ogni pagina
falliva in SSR con "No QueryClient set". Il provider avvolge ora tutto fin
dall'inizio; la logica di redirect/loading si sposta in un componente
AppShell interno, comportamento invariato.
useRosa()/useIo()/useObiettivi() leggono ora l'anagrafica da giocatori_squadra
tramite useGiocatoriSquadra(), filtrando solo i giocatori attivo. crapp-data.ts
resta il seed storico e il fallback (rosaFallback) e fornisce anche la data di
nascita per id, non ancora una colonna della tabella. Aggiunge
giocatori-squadra.server.ts per leggere la rosa lato route API (stesso pattern
di eventi.server.ts).
Numero e data della tessera arrivano dal comitato dopo l'iscrizione, quindi
li scrive solo un admin (come numero/ruolo): estende il trigger di M1/M5,
aggiunge il pannello dedicato in /admin con badge e conteggio in dashboard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copre la logica pura isolabile di avatar-store, error-capture, error-page,
lovable-error-reporting, profili (validazione upload), push-client (guardie
senza DOM), scout-stato e webpush.server (firma JWT VAPID con chiavi P-256
generate al volo, fetch intercettato). Alza i file di src/lib coperti da 19
a 28 su 37, senza introdurre nuove dipendenze.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sposta dividiNome in crapp-data.ts per riordinare la rosa di fallback per
cognome; la query a giocatori_squadra ora ordina per cognome, nome invece
che per id.
docs/CHANGELOG.md e PROJECT_STATE.md erano fermi al 30/08 e non riportavano
gli ultimi due commit: foto profilo su Supabase Storage (M6) e
sincronizzazione dello Scout Live tra dispositivi (M7).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Due bug architetturali, entrambi con la stessa causa: dati che vivevano
solo in localStorage, quindi visibili a un solo dispositivo.
- Il blocco "chi sta scoutando" (scout-live.ts) non funzionava mai tra
telefoni diversi: due persone potevano prendere il controllo insieme
da dispositivi diversi, sovrascrivendosi a vicenda le azioni nel
salvataggio condiviso. Ora usa scout_sessioni, tabella già presente
nello schema ma mai collegata al codice.
- La partita scoutata finita (scout-store.ts) veniva salvata solo in
localStorage: "Punti/Ace/Muri squadra" e le presenze derivate dallo
scout esistevano solo sul telefono di chi aveva chiuso la partita.
Nuova tabella scout_partite archivia la partita completa (azioni
incluse) per tutta la squadra.
useScoutMatches() mantiene la stessa firma di prima (ScoutMatch[]), ora
alimentata da una query invece che da localStorage: nessuna modifica
necessaria nei punti che la leggono (squadra, classifica, home,
dettaglio partita, rosa). Rigenerati i tipi Supabase.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le foto caricate in Profilo vivevano solo in localStorage: ogni giocatore
vedeva la propria foto solo sul proprio dispositivo, mai quella dei
compagni nella rosa (Squadra). Ora vengono caricate in un bucket
pubblico dedicato (avatar-giocatori, migration m6) e il componente
Avatar carica l'URL pubblico con fallback su numero/iniziali se assente
o non ancora caricata.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"Ultima partita" in home e le card di "Storico match" in squadra ora
sono link a /partita/$id quando esiste un evento di calendario con la
stessa data del risultato (CSI o scout), con un'indicazione "Vota MVP"
quando non è ancora stato eletto. Prima erano card statiche: per votare
bisognava trovare la partita a mano dal calendario.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tolti i check su `classifica`, `classificaConScout` e `storicoMatch`,
non più esportati da crapp-data.ts / scout-store.ts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Solo whitespace: tabelle allineate, enfasi normalizzata (* -> _), a capo
coerenti. Nessuna modifica di contenuto.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
La classifica e lo storico partite mostravano dati inventati (squadre e
risultati finti) come base, poi sovrascritti dai dati CSI quando
disponibili. Ora classifica, ultimi risultati, storico match e obiettivi
di squadra legati alle vittorie usano solo dati reali (CSI o scout live),
con stati vuoti quando i dati CSI non sono ancora disponibili.
Include anche la correzione di tutti gli errori di formattazione
prettier segnalati da `npm run lint` sul resto del codice sorgente.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Aggiungi giocatore: nuovo form in /admin (nome, cognome, numero,
ruolo, email opzionale), id g<N> calcolato in automatico.
- Email modificabile anche per i giocatori già in rosa dal pannello
Dati squadra, non solo alla creazione — completa quanto rimandato
da DD-018.
- Disattiva/Riattiva: un giocatore che lascia la squadra sparisce
dalla rosa attiva senza che la riga venga eliminata, così presenze,
voti, pagelle e badge della stagione restano agganciati al suo id.
Nuova sezione "Giocatori disattivati" per riattivarli.
- Messaggio d'errore leggibile per l'unico vincolo unique della
tabella (email duplicata) invece del codice Postgres grezzo.
Nessuna migration: sia l'inserimento sia la modifica passano dalla
policy admin FOR ALL già esistente su giocatori_squadra.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
useMeseNav aveva un default hardcoded (anno 2026, mese 7) invece di
calcolare oggi. Chiunque apra /calendario finiva sempre su agosto
2026, indipendentemente dalla data reale.
Co-Authored-By: Claude Mythos <noreply@anthropic.com>
Al primo accesso l'app collega da sola l'account Google al giocatore
la cui email registrata coincide (case-insensitive), invece di far
scegliere il nome da un elenco. Senza corrispondenza compare solo un
messaggio d'errore con un pulsante per uscire e riprovare con un altro
account: nessuna scelta manuale di ripiego.
- Migration m5: colonna `email` su giocatori_squadra, seed per Ivan
Cacciari e Davide Grilli, trigger esteso per richiedere anche il
match email oltre allo slot libero.
- slotPerEmail() sostituisce slotLiberi() (rimossa, senza più
chiamanti in produzione).
Co-Authored-By: Claude Mythos <noreply@anthropic.com>
Estrae in palloni-core.ts la logica pura di push-messaggio e
promemoria-palloni (finora mista alle chiamate Supabase), così da
poterla testare senza scrivere sul database. Aggiunge test per le
funzioni pure di giocatori-squadra.ts, finora senza copertura.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Remove the free player selection from /benvenuto: without a Supabase session
no screen renders, and the VITE_AUTH_OBBLIGATORIA bridge flag is gone.
Admin rights now come only from user_roles, so the hardcoded name list in
crapp-data.ts is deleted along with its tests.
Add migration m4_solo_autenticati, which revokes anon access to the v1.0
tables. Apply it only once the whole team has linked an account.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>