feat: §5.2 finale — aderenza piano + export PDF

§5.2.5 Aderenza al piano alimentare
- MealSlot.consumed Boolean + consumedAt DateTime? (migration)
- POST /me/meal-plans/slots/:id/consumed (toggle, idempotente con body opzionale)
- @ketopath/shared/planner/adherence: computeAdherence() su slot dei giorni
  passati, free-meal contati come "rispettati"
- /plan: bottone ✓ in ogni SlotCard (oliva quando attivo) + 5° card nel
  summary settimanale "Aderenza: X% (n/m)"

§5.2.6 Export PDF per medico/nutrizionista
- pdfkit (Node, no headless Chrome) + @types/pdfkit
- GET /me/tracking/export.pdf: profilo, storico peso (30 entries),
  piano corrente con aderenza, footer con disclaimer medico
- Proxy Next.js /api/tracking-export per same-origin + cookie sessione
- /tracking: link "Esporta PDF per medico/nutrizionista" sotto subtitle

Schema migration: add_meal_slot_consumed.

81/81 unit test verdi. Lint, typecheck 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-30 00:01:28 +02:00
1 parent 9327e75395
commit 83bab7b6d5
14 files changed
+347 -3

No files matched your search

@@ -73,6 +73,17 @@ function TrackingPageContent({
{t('subtitle')}
</p>
<p className="animate-fade-up mt-4 [animation-delay:300ms]">
<a
href="/api/tracking-export"
target="_blank"
rel="noopener noreferrer"
className="text-ink-soft decoration-pomodoro hover:text-ink font-mono text-[11px] uppercase tracking-widest underline decoration-[1.5px] underline-offset-[5px] transition-colors"
>
{t('exportPdf')} ↗
</a>
</p>
<div className="rule animate-rule-in my-10 [animation-delay:360ms]" />
<DailyCheckIn initial={todayCheckIn} />