Il testo della notifica viaggia ora cifrato dentro la push (aes128gcm, RFC
8188/8291) invece di essere recuperato dal service worker con una fetch al
risveglio. Era quella fetch a non chiudersi in tempo: ad app chiusa il browser
tiene vivo il worker pochi secondi, showNotification non veniva mai chiamata e
non compariva niente, mentre ad app aperta con la rete calda sembrava tutto a
posto. La POST porta anche Urgency: high, che chiede la consegna immediata
invece di far accumulare i messaggi fino al risveglio del dispositivo.
Cadono i pezzi che esistevano solo per rimediare al payload vuoto: la route
push-messaggio, la coda promemoria_push con la sua scadenza a 12 ore,
messaggioPalloniOggi() e il timeout nel worker. Tutti e tre i mittenti avevano
gia il testo pronto prima di inviare.
Il worker si aggiorna da solo all'avvio e a ogni ritorno in primo piano
(mantieniWorkerPushAggiornato): nella webapp installata quello vecchio puo
sopravvivere a lungo, e senza questo un dispositivo resterebbe fermo alla
versione che va a cercare il testo in rete.
Profilo -> Opzioni ha "Mandami una notifica di prova", visibile solo a notifiche
attive: manda una push a questo dispositivo e riporta stato HTTP, corpo della
risposta e se l'endpoint risulta davvero in push_subscriptions. Senza, "non
arriva" era cieco: ogni prova richiedeva un admin, un evento nello stato giusto
e una seconda persona, e la risposta del servizio push veniva buttata via.
inviaPush torna { stato, corpo } e logga il corpo sui rifiuti.
Dalle prove sul campo: a parita di server, iPhone installato da Home riceve ad
app chiusa. Su Android installato come webapp resta da verificare: il WebAPK e
un'app Android a se, con permesso notifiche (Android 13+) e voce batteria
distinti da quelli di Chrome. Annotato nei limiti noti.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
74 lines
3.0 KiB
Markdown
74 lines
3.0 KiB
Markdown
# Modulo — Palloni
|
|
|
|
**Stato:** implementato (v1.0)
|
|
**File principali:** `src/lib/palloni.ts`, `src/lib/palloni-core.ts`,
|
|
`src/components/crapp/TurnoPalloni.tsx`, `src/components/crapp/PromemoriaPalloni.tsx`,
|
|
`src/routes/api/public/promemoria-palloni.ts`
|
|
|
|
---
|
|
|
|
## Obiettivo
|
|
|
|
Gestire un turno a rotazione condiviso per chi porta e riporta i palloni ad allenamenti e
|
|
partite, con proposta automatica, possibilità di modifica manuale e promemoria push il
|
|
giorno stesso.
|
|
|
|
---
|
|
|
|
## Dati
|
|
|
|
Tabella `turni_palloni` (`evento_id`, `giocatore_id`, `aggiornato_da`, `aggiornato_il`) —
|
|
contiene solo i turni **confermati manualmente**; le proposte automatiche non salvate non vi
|
|
compaiono.
|
|
|
|
---
|
|
|
|
## Implementazione
|
|
|
|
- `completaTurni()` (`palloni-core.ts`) propone, per ogni **partita** o evento extra senza
|
|
turno già salvato, il candidato con meno turni fatti, poi quello che non lo fa da più
|
|
tempo, poi per ordine alfabetico — un algoritmo greedy, non un ordine fisso né solo per
|
|
data. Gli **allenamenti** non ricevono proposta automatica: restano «da assegnare» finché
|
|
qualcuno non sceglie un incaricato in `TurnoPalloni` (scelta della squadra).
|
|
- `useAssegnaTurno()` (`palloni.ts`) conferma una proposta o riassegna manualmente, con
|
|
upsert su `evento_id`.
|
|
- Il conteggio "quante volte hai portato i palloni" mostrato nel profilo e nei badge è
|
|
ricalcolato a runtime da `conteggioTurni()` su turni salvati **più proposte non ancora
|
|
confermate** (partite/eventi) — non è uno storico in tabella dedicata.
|
|
- `TurnoPalloni.tsx` mostra/assegna il turno sulla card di un evento; `PromemoriaPalloni.tsx`
|
|
è il banner in Home per il giocatore di turno.
|
|
|
|
---
|
|
|
|
## Route API pubblica `/api/public/promemoria-palloni`
|
|
|
|
La fa partire un **amministratore** dal pulsante «Avvisa chi è di turno» dentro il riquadro
|
|
palloni dell'evento (`TurnoPalloni.tsx`), riservato agli admin (DD-025). Riceve l'`eventoId`,
|
|
e `avvisiPalloniEvento()` calcola i due destinatari di _quell'evento_: chi deve **prendere** i
|
|
palloni e chi deve **riportarli** (l'incaricato dell'evento precedente), con un testo diverso
|
|
per ciascuno.
|
|
|
|
Titolo e testo viaggiano cifrati dentro la push, quindi il service worker li mostra senza
|
|
nessuna chiamata di rete. Stesso meccanismo di `apri-sondaggio` (vedi
|
|
[Notifiche](notifiche.md)).
|
|
|
|
---
|
|
|
|
## Limiti noti
|
|
|
|
- **L'invio è manuale**: nessun cron manda il promemoria da solo, se l'admin non preme il
|
|
pulsante non parte niente (DD-025). `destinatariPromemoriaPalloni()` — la versione "chi è di
|
|
turno oggi" — resta in `palloni-core.ts` ma non la chiama più nessuno.
|
|
- Il conteggio dei turni include anche le proposte non confermate: badge e statistiche
|
|
possono contare turni mai effettivamente convalidati da nessuno.
|
|
- La rotazione non considera le assenze dichiarate: può proporre il turno a chi ha risposto
|
|
"assente" o "infortunato" per quell'evento.
|
|
|
|
---
|
|
|
|
## Evoluzioni possibili
|
|
|
|
- Versionare il cron (es. una migration con `cron.schedule`) invece di configurarlo solo
|
|
lato dashboard.
|
|
- Escludere dalla rotazione chi ha già dichiarato assenza per l'evento.
|