Avviso certificati: il giocatore è avvisato 30 giorni prima (DD-041)

Il giocatore vede l'avviso giallo da 30 giorni prima della scadenza del
certificato medico; per lo staff resta 7 giorni, nero dopo la scadenza per
tutti. L'admin che è anche giocatore vede il proprio avviso personale oltre
a quello dello staff, da cui è escluso il suo nome.

La scelta degli avvisi per utente è in avvisiCertificatiUtente()
(profili-core) con test; documentati DD-041, DD-035, modulo e changelog.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-01 14:21:25 +02:00
1 parent 8f25143aa5
commit 4b5ffc6664
8 files changed
+285 -117

No files matched your search

+36 -2
View File
@@ -216,9 +216,12 @@ export function etichettaGiocatore(g: GiocatoreSquadra): string {
return `#${g.numero} ${nomeCompleto(g)}`;
}
/** Soglia dell'avviso certificati in Home (DD-035). */
/** Soglia dell'avviso certificati dello staff in Home (DD-035). */
export const GIORNI_AVVISO_CERTIFICATO = 7;
/** Soglia dell'avviso personale: il giocatore è avvisato un mese prima dello staff (DD-041). */
export const GIORNI_AVVISO_CERTIFICATO_GIOCATORE = 30;
/** Giorni di calendario tra due date `AAAA-MM-GG` (ora locale): negativo se `scadenza` è passata. */
export function giorniAllaScadenza(scadenza: string, oggi: string): number {
const a = new Date(`${scadenza}T00:00:00`);
@@ -258,11 +261,13 @@ function confrontaAvvisi(a: AvvisoCertificato, b: AvvisoCertificato): number {
* Certificati in scadenza o scaduti nella rosa (DD-035): calcolato al volo da
* `certificato_scadenza`, niente stato salvato. Esclude chi non è in rosa e chi non ha
* ancora un certificato caricato (è un problema diverso, non un avviso di scadenza).
* `soglia` sono i giorni di preavviso: 7 per lo staff, 30 per il giocatore (DD-041).
*/
export function avvisiCertificati(
rosa: GiocatoreSquadra[],
profili: Record<string, Profilo>,
oggi: string,
soglia: number = GIORNI_AVVISO_CERTIFICATO,
): { scaduti: AvvisoCertificato[]; inScadenza: AvvisoCertificato[] } {
const scaduti: AvvisoCertificato[] = [];
const inScadenza: AvvisoCertificato[] = [];
@@ -271,7 +276,7 @@ export function avvisiCertificati(
const p = profili[g.id];
if (!p?.certificatoScadenza || !p.certificatoPath) continue;
const giorni = giorniAllaScadenza(p.certificatoScadenza, oggi);
if (giorni > GIORNI_AVVISO_CERTIFICATO) continue;
if (giorni > soglia) continue;
const avviso: AvvisoCertificato = {
giocatoreId: g.id,
nome: g.nome,
@@ -285,3 +290,32 @@ export function avvisiCertificati(
inScadenza.sort(confrontaAvvisi);
return { scaduti, inScadenza };
}
/**
* Avvisi certificati per chi guarda la Home (DD-035, DD-041): `personale` è il proprio
* certificato (soglia 30 giorni), per chiunque sia un giocatore in rosa; `staff` sono gli
* altri della rosa (soglia 7 giorni), solo per l'admin, senza il suo nome perché già nel
* personale.
*/
export function avvisiCertificatiUtente(
rosa: GiocatoreSquadra[],
profili: Record<string, Profilo>,
oggi: string,
utente: { admin: boolean; base: GiocatoreSquadra | null },
): {
personale: AvvisoCertificato | undefined;
staff: { scaduti: AvvisoCertificato[]; inScadenza: AvvisoCertificato[] } | null;
} {
const mio = utente.base
? avvisiCertificati([utente.base], profili, oggi, GIORNI_AVVISO_CERTIFICATO_GIOCATORE)
: null;
const personale = mio ? (mio.scaduti[0] ?? mio.inScadenza[0]) : undefined;
const staff = utente.admin
? avvisiCertificati(
rosa.filter((g) => g.id !== utente.base?.id),
profili,
oggi,
)
: null;
return { personale, staff };
}