Documenta il ruolo allenatore (specifica, DD-034, roadmap)
L'allenatore è uno slot di giocatori_squadra con tipo diverso: registrato dall'admin per email, gestisce gli eventi e sollecita le presenze, ha un profilo ridotto (dati personali e foto, senza stagione e badge), compare in Rosa come «Allenatore» e non vede badge né cacche. Solo documentazione, nessuna implementazione. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e1e4ca0df6
commit
dda4aff746
3 files changed
+278
-38
No files matched your search
@@ -0,0 +1,191 @@
|
||||
# Modulo — Ruolo Allenatore
|
||||
|
||||
**Stato:** da implementare (specifica)
|
||||
**Decisione:** [DD-034](../DESIGN_DECISIONS.md#dd-034--lallenatore-è-uno-slot-della-squadra-con-tipo-diverso-non-un-giocatore)
|
||||
**File coinvolti (previsti):** `src/lib/ruoli.ts`, `src/lib/auth-route.server.ts`,
|
||||
`src/routes/profilo.tsx`, `src/routes/eventi.tsx`, `src/routes/admin.tsx`,
|
||||
`src/lib/profili-core.ts`, i punti che leggono la rosa (vedi [Esclusione dalla rosa](#esclusione-dalla-rosa))
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Dare accesso all'app all'allenatore, con permessi diversi da quelli di un giocatore: gestisce
|
||||
gli eventi (allenamenti, partite, amichevoli) e sollecita le presenze, ma non gioca: compare
|
||||
in Squadra come membro con la dicitura «Allenatore», però non è convocabile, non vota, non
|
||||
riceve voti e non ha statistiche, badge o stagione.
|
||||
|
||||
## Registrazione
|
||||
|
||||
Stesso flusso dei giocatori (DD-018), senza passaggi in più:
|
||||
|
||||
1. L'admin, da `/admin` → **Aggiungi**, sceglie il tipo **Allenatore** invece di Giocatore e
|
||||
inserisce nome, cognome ed email Gmail. Numero di maglia e ruolo in campo non si chiedono.
|
||||
2. L'allenatore accede con Google; l'email corrisponde allo slot e il collegamento è
|
||||
automatico. Se l'email non corrisponde, stesso messaggio di errore dei giocatori.
|
||||
3. Entra in Home.
|
||||
|
||||
Il permesso nasce dalla registrazione fatta dall'admin: l'allenatore non può
|
||||
auto-promuoversi, perché il tipo dello slot lo scrive solo un admin (come oggi numero e ruolo).
|
||||
|
||||
## Profilo
|
||||
|
||||
Il profilo dell'allenatore ha solo due tab (in `TAB_PROFILO` oggi sono quattro):
|
||||
|
||||
| Tab | Giocatore | Allenatore |
|
||||
| ------------ | --------- | ---------------------------------------------- |
|
||||
| Stagione | sì | **no** |
|
||||
| Badge | sì | **no** |
|
||||
| Documenti | sì | sì, ridotta (vedi sotto); tab iniziale |
|
||||
| Impostazioni | sì | sì, identica (logout, notifiche, segnalazioni) |
|
||||
|
||||
Un link diretto a `/profilo?tab=stagione` o `?tab=badge` apre Documenti.
|
||||
|
||||
### Dati modificabili dall'allenatore
|
||||
|
||||
| Campo | Dove sta oggi | Nota |
|
||||
| ---------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| Nome, cognome | `giocatori_squadra` | per un giocatore li scrive solo l'admin; per l'allenatore anche lui sul proprio slot |
|
||||
| Email (contatto) | `profili_giocatore.email` | non è l'email di login, che resta quella registrata dall'admin |
|
||||
| Data di nascita | `profili_giocatore.data_nascita` | sincronizzata in `giocatori_squadra.nascita` come per tutti (DD-031): compleanno in Calendario |
|
||||
| Luogo di nascita | `profili_giocatore.luogo_nascita` | |
|
||||
| Telefono | `profili_giocatore.telefono` | |
|
||||
| Foto profilo | bucket `avatar-giocatori` | stesso cerchio avatar e stesso upload dei giocatori |
|
||||
|
||||
**Non** si mostrano: indirizzo di residenza, documento d'identità, certificato medico, foto
|
||||
tessera, tesseramento CSI.
|
||||
|
||||
### Completamento profilo
|
||||
|
||||
Per l'allenatore il completamento conta solo i dati personali della tabella sopra (100%).
|
||||
Il widget in Home segue la stessa regola: sparisce quando quei campi sono compilati.
|
||||
|
||||
## Squadra
|
||||
|
||||
L'allenatore compare nella tab **Rosa** insieme ai giocatori, con foto, nome e cognome. Dove
|
||||
per un giocatore c'è il ruolo in campo (palleggiatore, schiacciatore…) per lui c'è scritto
|
||||
**Allenatore**, ricavato da `tipo` e non dal campo `ruolo`. Non ha numero di maglia né
|
||||
statistiche, e non compare nella tab Stats né nelle classifiche.
|
||||
|
||||
Da allenatore, in `/squadra` vede solo **Rosa** e **Stats**. Le tab **Obiettivi** e **Badge**
|
||||
non compaiono, e un link diretto a una delle due apre Rosa.
|
||||
|
||||
| Tab | Giocatore | Allenatore |
|
||||
| --------- | --------- | ---------- |
|
||||
| Rosa | sì | sì |
|
||||
| Stats | sì | sì |
|
||||
| Obiettivi | sì | **no** |
|
||||
| Badge | sì | **no** |
|
||||
|
||||
## Badge e cacche nascosti
|
||||
|
||||
L'allenatore non vede **nessun badge** e **nessuna classifica o dato sulle cacche**, in
|
||||
nessuna schermata:
|
||||
|
||||
| Dove | Cosa si nasconde all'allenatore |
|
||||
| ----------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| `/squadra` → Stats | il criterio di ordinamento «Cacche» (`cacchePartita`) |
|
||||
| `/squadra` → Rosa, scheda giocatore | la riga «Cacche/partita 💩» |
|
||||
| `/partita/$id` | la sezione «Badge votati dai compagni» e il sondaggio cacche (`SondaggioCacche`) |
|
||||
| `/profilo`, `/squadra` | le tab Badge (già escluse sopra) |
|
||||
|
||||
Presenze, media voto, MVP e palloni restano visibili.
|
||||
|
||||
## Gestione eventi
|
||||
|
||||
L'allenatore ha su `/eventi` gli stessi poteri dell'admin: crea, modifica, sposta ed elimina
|
||||
eventi e sceglie i convocati. Nel database la policy di scrittura su `eventi_app` passa da
|
||||
"solo admin" a "admin o allenatore" (oggi `m11_scritture_per_ruolo`); la cancellazione a
|
||||
cascata (DD-029) resta invariata.
|
||||
|
||||
Il link a `/eventi` compare dove oggi compare per l'admin.
|
||||
|
||||
Può anche **sollecitare le presenze** di un evento, come l'admin: la route
|
||||
`sollecita-presenze.ts` accetta admin o allenatore (oggi `richiediAdmin()`), e il sollecito
|
||||
arriva solo ai giocatori che non hanno risposto, mai all'allenatore stesso.
|
||||
|
||||
**Restano solo admin:** dashboard `/admin`, dati e documenti dei giocatori, export CSI,
|
||||
notifica personalizzata, promemoria palloni, apertura sondaggio cacche, correzione delle
|
||||
risposte presenze altrui, gestione dei ruoli.
|
||||
|
||||
## Notifiche
|
||||
|
||||
L'allenatore riceve i promemoria degli eventi (24h e 3h prima, push e centro notifiche
|
||||
in-app) come i giocatori, anche se non è convocato, e può attivare le push dal proprio
|
||||
Profilo. Non riceve il sollecito presenze né il turno palloni, che riguardano chi gioca.
|
||||
|
||||
## Esclusione dalla rosa
|
||||
|
||||
L'allenatore ha uno slot in `giocatori_squadra` (DD-034), quindi ogni lettura della "rosa di
|
||||
gioco" deve escluderlo: oggi il filtro è `attivo`, diventa `attivo e tipo = giocatore`. Fanno
|
||||
eccezione la tab Rosa di Squadra, i compleanni del Calendario e i destinatari dei promemoria
|
||||
evento, che lo includono. Punti da coprire, da verificare uno per uno in implementazione:
|
||||
|
||||
- client: `useRosa()`, `useGiocatoriSquadra()` (dove usata come rosa), `useAnagraficaRosa()`
|
||||
— Squadra (Stats, Obiettivi, Badge), Presenze, Palloni, Pagelle, MVP, Badge, Classifica,
|
||||
Scout, form convocati di `/eventi`;
|
||||
- server e condivisi: `leggiGiocatoriSquadra()`, `convocatiEvento()` (`eventi.ts`, riceve la
|
||||
rosa già filtrata), route API che notificano "tutta la rosa";
|
||||
- database: `evento_permette_voto()` (M13), che con `convocati` vuoto intende "tutta la rosa
|
||||
attiva"; i cron dei promemoria evento (M17) invece aggiungono sempre l'allenatore ai
|
||||
destinatari, convocato o no;
|
||||
- admin: tab Profili (conteggi di completamento e tesseramento), export CSI.
|
||||
|
||||
Il compleanno dell'allenatore resta visibile in Calendario (è un membro della squadra, non un
|
||||
giocatore).
|
||||
|
||||
## Permessi (riepilogo)
|
||||
|
||||
| Azione | Giocatore | Allenatore | Admin |
|
||||
| ----------------------------------------------- | --------- | ------------------ | ------------------ |
|
||||
| Modificare nome e cognome | no | sì, i propri | tutti |
|
||||
| Dati personali e foto profilo | i propri | i propri (ridotti) | tutti (non i file) |
|
||||
| Documento, certificato, foto tessera | i propri | — | lettura/download |
|
||||
| Creare/modificare/eliminare eventi, convocati | no | sì | sì |
|
||||
| Sollecitare le presenze | no | sì | sì |
|
||||
| Promemoria palloni, notifica personalizzata | no | no | sì |
|
||||
| Rispondere alle presenze, votare, essere votato | sì | no | sì (se giocatore) |
|
||||
| Tab Stagione e Badge del profilo | sì | no | sì |
|
||||
| Tab Obiettivi e Badge di Squadra | sì | no | sì |
|
||||
| Badge e classifiche/dati sulle cacche | sì | no | sì |
|
||||
| Dashboard `/admin` | no | no | sì |
|
||||
|
||||
## Cosa implementare
|
||||
|
||||
1. **Migration** (nuova, non si riscrivono le esistenti):
|
||||
- `giocatori_squadra.tipo` (`giocatore` | `allenatore`, default `giocatore`, non nullo);
|
||||
- valore `allenatore` nell'enum `app_role`, assegnato in `user_roles` da una funzione
|
||||
`SECURITY DEFINER` al momento del collegamento di uno slot con `tipo = allenatore`
|
||||
(i permessi restano letti da `user_roles`, DD-011);
|
||||
- trigger `enforce_giocatori_squadra_update`: `tipo` scrivibile solo dall'admin; `nome` e
|
||||
`cognome` scrivibili dall'allenatore sul proprio slot;
|
||||
- policy di scrittura `eventi_app`: admin o allenatore;
|
||||
- `evento_permette_voto()`: escludere `tipo = allenatore`;
|
||||
- cron promemoria evento: includere sempre gli allenatori attivi tra i destinatari.
|
||||
2. **`src/lib/ruoli.ts`**: `useIsAllenatore()` e `usePuoGestireEventi()` (admin o allenatore),
|
||||
stessa lettura di `user_roles` e stessa cache.
|
||||
3. **`/eventi`**: gate `usePuoGestireEventi()` al posto di `useIsAdmin()`, anche per il link di accesso.
|
||||
Il bottone del sollecito presenze usa lo stesso gate; lato server `sollecita-presenze.ts`
|
||||
passa da `richiediAdmin()` a un controllo "admin o allenatore" in `auth-route.server.ts`.
|
||||
4. **`/profilo`**: tab e campi in base al tipo; nome e cognome modificabili per l'allenatore.
|
||||
5. **`/squadra`**: l'allenatore compare in Rosa con la dicitura «Allenatore», senza numero né
|
||||
statistiche; da allenatore non si vedono le tab Obiettivi e Badge, né il criterio e la riga
|
||||
delle cacche.
|
||||
**`/partita/$id`**: niente sezione badge né sondaggio cacche per l'allenatore.
|
||||
6. **`profili-core.ts`**: completamento dedicato all'allenatore (solo dati personali).
|
||||
7. **`/admin`**: scelta del tipo in "Aggiungi"; allenatori mostrati a parte, fuori dai conteggi
|
||||
di completamento e tesseramento; nessun export CSI per loro.
|
||||
8. **Filtro rosa** in tutti i punti elencati sopra.
|
||||
9. **Test**: unit sul completamento e sul filtro rosa; integration in
|
||||
`test/integration/permessi.test.ts` (l'allenatore scrive `eventi_app`, non vota, non cambia
|
||||
il proprio `tipo`, non scrive slot altrui).
|
||||
10. **Documentazione** alla consegna: `DATABASE.md` (colonna, enum, tabella permessi),
|
||||
`profilo-giocatore.md`, `squadra.md`, `calendario.md`, `CHANGELOG.md`, `ROADMAP.md`, DD-034 → Accettata.
|
||||
|
||||
## Scelte confermate
|
||||
|
||||
- Riceve i promemoria degli eventi: sì.
|
||||
- Sollecita le presenze: sì. Promemoria palloni: no.
|
||||
- Badge e cacche: mai visibili all'allenatore, né classifiche né sondaggio.
|
||||
- In Squadra: nessuna sezione Staff; compare in Rosa come gli altri, con «Allenatore» al
|
||||
posto del ruolo.
|
||||
- Vede le risposte presenze e le pagelle dei giocatori: sì, la lettura è già aperta a tutti
|
||||
gli autenticati.
|
||||
Reference in new issue
Block a user