Commit Graph
2 Commits
Author SHA1 Message Date
lucianoandClaude Opus 4.7 feb54c1f9a feat: piano sensibile al protocollo digiuno (PRD §5.6 + §9.4)
Finora il fastingProtocol era una preferenza salvata ma ignorata dal
planner — ogni giorno generava 4 pasti. Ora cambia struttura per protocollo
e per giorno della settimana.

@ketopath/shared/planner
- protocolPlanForDay(protocol, dayOfWeek) → { share, kcalMultiplier }
- 14:10  → tutti e 4 i pasti, share default
- 16:8   → niente colazione: pranzo 50%, spuntino 10%, cena 40%
- 18:6   → niente colazione: pranzo 55%, spuntino 5%, cena 40%
- 20:4   → solo spuntino+cena (10/90)
- ESE 24h → mercoledì kcalMultiplier=0 (giorno saltato), altri default
- 5:2    → lunedì + giovedì kcalMultiplier=0.25, share 100% cena
- 7 unit test in protocol.test.ts

apps/api/plan
- POST /me/meal-plans: legge preferences.fastingProtocol, deriva il piano
  per ogni giorno, salta MealSlot con share=0 e giorni a kcalMultiplier=0
- GET /me/meal-plans/current: include fastingProtocol nella risposta
- baseDailyTarget restituito invariato per il client

apps/web
- /plan mostra "Finestra alimentare 16:8" sotto il titolo della settimana
- plan-week distingue i giorni "fasting" (digiuno completo) e "leggeri"
  (5:2 fasting day) con copy dedicato; rimuove totali calorici inappropriati
- i18n: Plan.protocolLabel + Plan.fastingDay/lightDay

Smoke tested: settato 16:8 da /profile, rigenerato il piano, verificato
che l'etichetta appaia e che ogni giorno abbia esattamente 3 pasti
(Pranzo / Spuntino / Cena, niente Colazione).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 22:27:49 +02:00
lucianoandClaude Opus 4.7 4b6c3f6ae9 feat: V1 tracking endpoints + meal plan generation (PRD §5.1, §5.2, §5.3)
@ketopath/shared:
- tracking/schema.ts — Zod schemas for WeightEntry input (weight, optional
  measurements/notes/energy/sleep/hunger, photo URLs) and FastEvent start /
  update, plus PROTOCOL_DEFAULT_MINUTES table
- planner/macros.ts — macrosForPhase(): protein 1.6-1.8g/kg, netCarb 25/60/120g
  by phase, fat = remainder (PRD §9.3)
- planner/matchmaking.ts — pure matchMeals() that filters by exclusion tags,
  phase compatibility and meal category, then scores by euclidean distance
  from the meal's macro target with a 1.5 penalty for recently-consumed recipes;
  DEFAULT_MEAL_SHARE constant (25/35/10/30 %)
- 5 new unit tests cover exclusion, phase, recency, topN, category mismatch

apps/api:
- modules/tracking/weight.routes.ts — GET /me/weight-entries (last 60),
  POST /me/weight-entries with upsert on (userId, date); encrypted fields
  serialised to/from JSON strings
- modules/tracking/fast.routes.ts — GET, POST (start) and PATCH (update) on
  fast events; symptoms stored as encrypted JSON
- modules/plan/plan.routes.ts — POST /me/meal-plans:
  - reads profile + preferences, computes BMR (Mifflin-St Jeor), TDEE, daily
    kcal target with the phase-dependent deficit, then macros via macrosForPhase
  - upserts a MealPlan rooted at Monday-of-this-week, wipes prior slots, and
    fills 28 slots running matchMeals per (day, meal) with a recent-2-day
    rolling exclusion list to keep variety
  - selected recipe + 4 alternatives per slot
- GET /me/meal-plans/current returns the active plan with selected/alternatives

@ketopath/db:
- prisma/seed-recipes.ts — 16 italian keto recipes (4 per meal type) with
  estimated macros per serving and phase compatibility
- prisma/seed.ts — idempotent insertion (skip on existing name match)

Verified end-to-end with sign-up → create profile (Michele PRD persona) →
generate plan: 28 slots filled, daily target 1399 kcal / 137 P / 83 F / 25 C,
matchmaking distributes 4 different breakfasts across the first 4 days as
the recent-consumed penalty kicks in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:07:56 +02:00