Files
CRAPP/docs/modules/allenatore.md
T
davideandClaude Sonnet 5.5 986098d933 DD-050: «Presenza modificata» anche agli allenatori (m33)
Fine della fase di prova: la funzione avvisa admin e allenatori attivi. Test
aggiornato (l'allenatore ora è tra i destinatari), DD-050, notifiche, allenatore,
DATABASE, CHANGELOG, ROADMAP e PROJECT_STATE allineati. m33 non ancora applicata
in produzione.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 11:06:46 +02:00

18 KiB

Modulo — Ruolo Allenatore

Stato: implementato Decisione: DD-034 Migration: m20_ruolo_allenatore_enum, m21_ruolo_allenatore File principali: src/lib/giocatori-squadra.ts (tipo, inRosa, isAllenatore, ruoloVisibile), src/lib/ruoli.ts, src/lib/user-store.ts (useSonoAllenatore, useGiocatoreInCampo), src/lib/auth-route.server.ts, src/routes/profilo.tsx, src/routes/admin.tsx, src/routes/squadra.tsx, src/routes/index.tsx Test: test/unit/giocatori-squadra.test.ts, test/unit/profili-core.test.ts, test/unit/presenze.test.ts, test/integration/permessi-allenatore.test.ts, test/integration/permessi-route.test.ts

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 (quelle del giocatore 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, tesseramento CSI.

Completamento profilo

Per l'allenatore il completamento conta solo data e luogo di nascita, telefono ed email, 25% ciascuno (completamentoAllenatore()). Il widget in Home segue la stessa regola: sparisce quando quei campi sono compilati.

Home

La Home dell'allenatore tiene ciò che riguarda la squadra e toglie ciò che riguarda il giocatore: restano classifica e bilancio, prossimo impegno e ultima partita; spariscono lo streak personale, il promemoria palloni, «Da confermare», l'obiettivo di squadra e il «Colpo d'occhio» con le statistiche personali. Non compare nemmeno l'avviso certificati: lo vedono solo gli admin e il giocatore interessato (DD-035).

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.

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/$id la sezione «Badge votati dai compagni» e il sondaggio cacche (SondaggioCacche)
push «Sondaggio pre-partita aperto» non parte verso i dispositivi degli allenatori (apri-sondaggio.ts)
/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 (l'elenco dei convocati contiene solo giocatori). Nel database la policy di scrittura su eventi_app è "admin o allenatore" (M21); la cancellazione a cascata (DD-029) resta invariata. Il bottone «Gestisci eventi» del Calendario compare anche a lui (usePuoGestireEventi()).

Può anche sollecitare le presenze di un evento, come l'admin: la route sollecita-presenze.ts accetta admin o allenatore (richiediGestoreEventi()), e il sollecito arriva solo ai giocatori che non hanno risposto, mai all'allenatore stesso. Con DD-040 si aggiungono un sollecito automatico 24 ore prima dell'evento, ma il pulsante resta.

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

Cosa riceve l'allenatore, notifica per notifica (il catalogo completo, con i canali di tutti, sta in notifiche.md):

Notifica L'allenatore la riceve? Note
Promemoria a 24 e 3 ore prima di un evento (rimosso, DD-043) no Dal 29/09/2026 (m25, DD-039) giocatori_destinatari_evento() include solo i giocatori attivi: l'allenatore non può rispondere alle presenze né essere convocato, quindi il promemoria non gli chiederebbe nulla che possa fare (per esempio una cena di squadra). Prima gli arrivava sempre, convocato o no (m21).
Messaggio dello staff sì In-app ed email vanno a tutta la rosa attiva, allenatori compresi; la push ai suoi dispositivi iscritti, o solo a lui se il messaggio è per lui.
Sollecito presenze no L'allenatore non risponde alle presenze (DD-034). Può invece far partire il sollecito .
Turno palloni no I turni riguardano solo i giocatori.
Sondaggio pre-partita no Né la push né l'avviso in-app e per email (DD-038): il sondaggio non lo riguarda.
Compleanno (DD-047) sì Riceve l'avviso «Oggi è il compleanno di …» come tutta la squadra, e gli auguri nel giorno del proprio compleanno (la nascita è pubblica, DD-031). In-app, email e push come per i giocatori.
Presenza modificata (DD-050, m33) sì Riceve l'avviso quando un giocatore cambia, mette o ritira la risposta a meno di 6 ore da una partita o un allenamento, come gli admin. In-app, email e push.
Notifiche smart (badge, serie, obiettivi, social) no Le mostra CelebrazioneBadge per il giocatore selezionato, letto da useIo(), che cerca l'id in useRosa(), da cui l'allenatore è escluso: per lui useIo() è null e useNotificheSmart() non fa nulla. Non ha statistiche da cui calcolarle.

Le email arrivano solo se il suo slot ha un account collegato e un'email registrata e se non ha spento l'interruttore «Email»; la push solo sui dispositivi su cui ha attivato «Notifiche» dal proprio Profilo (l'interruttore è identico a quello dei giocatori). Il centro notifiche in-app funziona come per i giocatori, con i soli messaggi dello staff.

Esclusione dalla rosa

L'allenatore ha uno slot in giocatori_squadra (DD-034), quindi ogni lettura della "rosa di gioco" lo esclude con inRosa() (attivo e tipo = giocatore) al posto del vecchio filtro su attivo. Fanno eccezione la tab Rosa di Squadra, i compleanni del Calendario (useAnagraficaRosa({ conAllenatori: true })) e i destinatari dei messaggi admin, che lo includono.

Livello Dove si esclude l'allenatore
client useRosa(), useAnagraficaRosa(), useTurniPalloni(), usePresenzeUltimoMeseTutti(), form convocati di /eventi, EventoCard, TurnoPalloni, VotazioneMvp, VotoSocial, useIo() e useGiocatoreCorrente() (quindi le notifiche smart)
identità useGiocatoreInCampo() è null per l'allenatore: niente risposta presenze, voti, pagelle, cacche, promemoria palloni
server destinatariSollecito(), promemoria-palloni.ts, apri-sondaggio.ts
database policy presenze e cacche «la propria riga» solo per tipo = giocatore; evento_permette_voto() rifiuta votante o votato allenatore
admin tab Squadra (conteggi, export CSI) e Profili (allenatori in un gruppo a parte, senza documenti né tesseramento)

Il compleanno dell'allenatore resta visibile in Calendario (è un membro della squadra, non un giocatore).

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 i propri — lettura/download
Avviso certificati in Home il proprio no tutta la rosa
Creare/modificare/eliminare eventi, convocati no sì sì
Sollecitare le presenze no sì sì
Promemoria palloni, notifica personalizzata no no sì
Ricevere i promemoria automatici degli eventi (in-app, email, push) sì no (DD-039) secondo il proprio slot
Ricevere i messaggi dello staff sì sì secondo il proprio slot
Ricevere sollecito presenze, turno palloni, sondaggio cacche sì no solo con uno slot giocatore in rosa
Ricevere le notifiche smart (badge, serie, obiettivi) sì no solo con uno slot giocatore in rosa
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ì

Le notifiche sono legate allo slot (giocatori_squadra), non al ruolo di admin: chi è admin le riceve secondo il proprio slot, come giocatore o come allenatore, e non ne riceve se non ha uno slot.

Implementazione

  • Migration M20 aggiunge allenatore all'enum app_role: sta da sola perché Postgres non lascia usare un valore di enum nella transazione che lo crea.
  • Migration M21: colonna giocatori_squadra.tipo; numero nullabile solo per gli allenatori (vincolo giocatori_squadra_numero_giocatori); trigger enforce_giocatori_squadra_update con tipo bloccato e nome/cognome liberi solo sullo slot del proprio allenatore; policy «L'allenatore aggiorna il proprio slot»; trigger sincronizza_ruolo_allenatore che aggiunge o toglie la riga allenatore in user_roles al collegamento, scollegamento, disattivazione o cambio di tipo; policy eventi_app admin o allenatore; presenze, cacche e voti chiusi all'allenatore.
  • Client: nell'app numero resta un number (0 per l'allenatore, NULL a database). I permessi (eventi, sollecito) leggono user_roles con usePuoGestireEventi(); cosa si vede dipende dal tipo del proprio slot (useSonoAllenatore()), che è immediato.
  • Admin: «Aggiungi giocatore o allenatore» con il campo Tipo; per l'allenatore il form non chiede numero e ruolo. Il tipo si sceglie solo alla creazione.

Scelte confermate

  • Non riceve i promemoria degli eventi (DD-039; fino alla m24 li riceveva sempre, DD-034). Riceve i messaggi dello staff.
  • 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.