Quattro fix di tipi che emergono solo durante `next build` (con Next.js che esegue typecheck stretto su tutta l'app), pre-esistenti su main:
- `fast-timer.tsx`: l'omitted-vs-undefined di `exactOptionalPropertyTypes`
rifiuta `{other: undefined}` per un campo opzionale. Costruisco l'oggetto
symptoms condizionalmente.
- `plan-week.tsx`: `slots[0]` con `noUncheckedIndexedAccess` è `Slot |
undefined`. Optional chaining `slots[0]?.meal`.
- `profile-form.tsx` e `weight-entry-form.tsx`: il mismatch Zod 3 + RHF
+ `exactOptionalPropertyTypes` sul tipo del Resolver è noto e non sistemabile
senza upgrade. Cast locale del solo zodResolver, runtime invariato.
Lint pulito, 99/99 test verdi, `next build` ok in locale.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
New /fasting route. Editorial layout matching the rest of the app
("CAPITOLO VII / Digiuno intermittente.").
When no active session:
- "Pronto a iniziare" eyebrow + italic call-to-action
- Protocol Select (16:8 default; full set FASTING_PROTOCOLS, hours derived
from PROTOCOL_DEFAULT_MINUTES)
- "Avvia digiuno" CTA → server action that POSTs to /me/fast-events
- Right column: Roman-numeral guide (I-IV) for the four most common protocols
with title + description from messages.json
When a session is active (status=IN_PROGRESS, no endedAt):
- Live timer in massive monospace clamp(3rem,9vw,6.25rem), tabular numerals,
ticking once per second via setInterval
- Italic remaining-time line ("Mancano HH:MM:SS") or "Obiettivo raggiunto."
once the protocol target is reached
- Hairline progress bar; ink while running, pomodoro after target
- "Concludi adesso" / "Concludi" CTA → PATCH with status=COMPLETED
- "Annulla sessione" ghost link → PATCH with status=ABORTED (with confirm())
- Right column: "FASE METABOLICA" with current phase title in pomodoro and
italic description (postprandial 0-4h / glycogenolysis 4-12h / lipolysis
12-18h / ketogenesis 18-24h / autophagy 24h+, PRD §5.3)
- "INIZIATO" and "OBIETTIVO" stats in mono
History below:
- Three big mono stats: completed sessions count, total hours, total sessions
- Last 12 events listed with protocol label in pomodoro italic, italian
short date, status eyebrow, duration in mono
Home gains a fourth NavItem ("Digiuno — Digiuno intermittente").
Verified end-to-end in Chrome: started a 16:8 → live ticking timer at
00:00:04, "Mancano 15:59:55", "Post-prandiale" phase shown.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>