feat: §5.3 completion — stats, symptoms, milestones, pause, break-fast

Cinque feature che chiudono il PRD §5.3 (gestione digiuno).

§5.3.1 Streak + statistiche settimanali/mensili
- @ketopath/shared/tracking/fasting-stats: computeFastingStats(events) ritorna
  weeklyHours, monthlyHours, currentStreak, longestStreak, completionRate,
  totalSessions, completedSessions
- 6 unit test (currentStreak consecutivo, longestStreak storico, completionRate
  ignora IN_PROGRESS, range temporali)
- /fasting: la striscia di stat passa da 3 a 5 (settimanali, mensili, streak
  attuale, streak record, % completamento)

§5.3.2 Diario sintomi durante il digiuno
- updateFastSymptoms server action → PATCH /me/fast-events/:id { symptoms }
- SymptomsDiary component nel timer attivo: checkbox "Mal di testa" + 3 slider
  1-10 (Energia, Fame, Lucidità) + textarea note libere; "Salva" non
  interrompe il timer

§5.3.3 Notifiche per-fast
- FastEvent.notifiedMilestones String[] (idempotenza)
- Cron */5 * * * * `runFastingMilestonesJob` scansiona le sessioni IN_PROGRESS
  e invia push secondo le milestone:
  · hydration_2h / 4h / 6h — promemoria idratazione
  · electrolyte_18h — alert elettroliti per digiuni lunghi
  · ending_soon — 30 min prima della fine
- Skip automatico se l'utente ha fastingPausedUntil futuro
- Skip se l'utente non ha attivato `fastingMilestones` nelle preferenze
- Server.ts gestisce ora 2 ScheduledTask (weekly + fasting)

§5.3.4 Modalità giorno libero
- User.fastingPausedUntil DateTime?
- POST /me/fasting/pause con body { until?: ISO|null } — default: domani 06:00
- GET /me/fasting/pause ritorna { fastingPausedUntil, paused }
- /fasting: FastingPauseToggle bottone "Pausa per oggi" → banner con countdown +
  "Riprendi adesso" per terminare prima

§5.3.5 Pasto di rottura intelligente
- GET /me/fast-events/:id/break-fast-suggestions: solo per digiuni >= 24h,
  ritorna 3 ricette con prepMinutes ≤ 20, kcal ≤ 350, categoria
  COLAZIONE/SPUNTINO. Heuristica per "facile da digerire".
- /fasting history: per le sessioni completate >= 24h aggiunge un disclosure
  "Suggerimenti per riprendere a mangiare" che fetcha on-demand e linka alle
  ricette

Schema migrations: add_fasting_paused_until, add_fast_event_milestones.

72/72 unit test verdi (6 nuovi). Lint, typecheck, build verdi.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Opus 4.7 committed 2026-04-29 23:41:20 +02:00
1 parent c37dc5d717
commit ea88ed8775
16 files changed
+810 -54

No files matched your search

+6
View File
@@ -89,6 +89,9 @@ model User {
// PRD §5.1 — momento in cui l'utente è entrato nella fase 2 (TRANSITION).
// Serve a calcolare la "settimana di fase" per la reintroduzione progressiva.
phase2StartedAt DateTime? @map("phase2_started_at")
// PRD §5.3 — modalità "giorno libero" del digiuno: niente reminder, niente
// start automatico finché il timestamp non è passato. NULL = nessuna pausa.
fastingPausedUntil DateTime? @map("fasting_paused_until")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@ -263,6 +266,9 @@ model FastEvent {
symptoms String?
/// @encrypted
notes String?
// PRD §5.3 — milestone già notificate per evitare duplicati. Array di chiavi
// tipo "hydration_2h", "hydration_4h", "electrolyte_18h", "ending_soon".
notifiedMilestones String[] @default([]) @map("notified_milestones")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")