Implementa la voce "Dashboard amministratore" della roadmap v1.1, come descritta
in docs/modules/profilo-giocatore.md, insieme alla parte di profilo che la
alimenta.
- /admin: stato dei profili della squadra, download di documento, certificato e
foto tessera, export CSV con i 12 campi del tesseramento CSI. Un certificato
scaduto non conta come valido.
- Profilo giocatore: dati personali, documento (fronte e retro), certificato e
foto tessera, con widget di completamento in Home che sparisce al 100%.
- I permessi di amministrazione arrivano da user_roles (DD-011) e non più dalla
lista di nomi in crapp-data.ts, che resta come ponte finché
VITE_AUTH_OBBLIGATORIA non viene acceso in produzione.
- Login Google via Supabase Auth: al primo accesso l'account si collega a uno
slot libero di giocatori_squadra, e il vincolo lo fa rispettare il trigger di
M1 (DD-016 regola 2).
Migration additive: M2 crea profili_giocatore, M3 il bucket privato
profili-giocatore. Nessuna tabella v1.0 viene toccata, quindi si possono
applicare senza cambiare il comportamento attuale dell'app.
supabase/config.toml e seed.sql configurano lo stack locale: serve perché il
progetto Supabase è uno solo, condiviso tra sviluppo e produzione.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds .claude/settings.json so every clone gets the same Claude Code
plugins: the official vercel and supabase ones already in use locally,
plus claude-md-management for maintaining CLAUDE.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Documentation:
- Add docs/README.md, the documentation index that AGENTS.md pointed to as the
first file to read but which did not exist.
- One home per piece of information: the feature list stays in ROADMAP.md,
CHANGELOG.md records only when something shipped, TODO.md only ongoing work.
Reconcile the entries that had drifted (CSI was both done and pending;
pagelle, badge social and serie were missing from the roadmap).
- Rewrite DATABASE.md as tables: add giocatori_squadra (already created by a
migration) and profili_giocatore (planned in DD-016), fix the wrong heading
levels, drop the duplicated roadmap.
- DESIGN_DECISIONS.md: move the index to the top and sort it, extract the
template into _template-dd.md.
- ARCHITECTURE.md becomes the technical reference; CLAUDE.md no longer
duplicates it.
- Add docs/EFFICIENZA_CLOUD.md with the rules previously kept in mem/,
separating what the code enforces from the goals not yet implemented.
- Fix statements the code contradicted: mutations use setQueryData rather than
invalidateQueries, and scout_sessioni and giocatori_squadra are not read by
the code yet.
- Track the v1.0 modules with no spec in docs/modules/ from TODO.md.
AI assistants:
- AGENTS.md is the single source of the rules, now including the technical
constraints only Claude Code knew about (generated files, Vite plugins, data
access) and an end-of-work checklist that applies to every assistant.
- CLAUDE.md and .cursor/rules/crapp.mdc point to AGENTS.md instead of
restating it.
- Remove the five .cursor/*.md files, which Cursor never loaded.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test/README.md covers the commands, what each folder verifies, whether it
needs the network, and the one real limit: the app renders after
hydration, so the end-to-end tests check HTTP responses and the data
behind the pages, not the rendered interface.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sessioneScaduta compared Date.now() against NaN when aggiornato_il was
not a valid date, and every comparison with NaN is false: the session
was reported as still active, so the Scout Live table stayed locked to a
player who could no longer release it.
An unreadable timestamp now frees the session, which is the safe
direction: at worst someone takes over a scouting session that was
already unattended.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The project had no automated verification at all, so the "Test" step in
the AGENTS.md workflow rested entirely on clicking through the app.
The suite runs on bun with node:assert and adds no dependency: every file
is a script that exits non-zero when a check fails, and test/run.ts runs
each one in its own process. Unit tests cover the rules that decide what
players see (badges, streaks, ball duty rotation, ratings, MVP ties,
scouting totals, goals, notifications, CSI parsing); integration and
end-to-end tests drive the real dev server. Nothing writes to the
database, so both can be pointed at a live environment.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Campionato page showed hardcoded demo data. It now reads the real
2025/26 season (Campionato Open Misto Eccellenza, project 767, team
3359, Girone B) from the Livescore CSI Bologna portal.
The portal has no documented API: we call the same endpoints its own
pages call over ajax, so parsing must degrade gracefully. A single
server route fetches them, caches for 6 hours and serves the last good
payload on failure; the page falls back to the previous data when
nothing is available. No browser ever contacts the portal, keeping the
request count independent of how many players open the app.
Also fixes the header, which claimed "Girone C - CSI Milano".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>