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:
1 parent
9327e75395
commit
83bab7b6d5
14 files changed
+347
-3
No files matched your search
@@ -22,6 +22,8 @@ export interface PlanSlot {
|
||||
recipeId: string | null;
|
||||
status: string;
|
||||
isFreeMeal: boolean;
|
||||
consumed: boolean;
|
||||
consumedAt: string | null;
|
||||
selected: SlotRecipe | null;
|
||||
alternatives: SlotRecipe[];
|
||||
}
|
||||
@@ -88,6 +90,17 @@ export async function regenerateSlot(slotId: string): Promise<SwapResult> {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
export async function toggleConsumed(slotId: string): Promise<SwapResult> {
|
||||
const res = await fetch(`${API_URL}/me/meal-plans/slots/${slotId}/consumed`, {
|
||||
method: 'POST',
|
||||
headers: { cookie: cookieHeader() },
|
||||
cache: 'no-store',
|
||||
});
|
||||
if (!res.ok) return { ok: false, error: `api_error_${res.status}` };
|
||||
revalidatePath('/plan');
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
export async function toggleFreeMeal(slotId: string): Promise<SwapResult> {
|
||||
const res = await fetch(`${API_URL}/me/meal-plans/slots/${slotId}/free-meal`, {
|
||||
method: 'POST',
|
||||
|
||||
Reference in new issue
Block a user