@ketopath/shared — new module profile/schema:
- profileInputSchema (Zod): age 18-110, gender, height 120-230 cm, weights
35-300 kg, activityLevel, optional targetDate
- GENDERS / ACTIVITY_LEVELS string-literal arrays for UI iteration
- Re-exported from @ketopath/shared
apps/api — new module modules/profile:
- PUT /me/profile: requireAuth, validates body via profileInputSchema, upserts
the row, returns the saved profile + derived { bmr, tdee, activityMultiplier }
(BMR/TDEE computed via @ketopath/shared)
- GET /me/profile: requireAuth, returns the same shape, 404 when missing
- Decimal columns serialised back as numbers
apps/web — new /profile page:
- src/app/[locale]/profile/page.tsx (server): redirects unauthenticated users
to /sign-in, calls fetchProfile to hydrate the form
- profile-form.tsx (client): react-hook-form + zodResolver bound to the same
shared schema, native styled selects for gender/activityLevel until shadcn
Select arrives, post-submit panel showing BMR/TDEE/multiplier
- actions.ts: server actions saveProfile / fetchProfile that proxy the call
to API_URL via cookie passthrough (no CORS, no exposed token)
- Home page gains a "Completa il tuo profilo" CTA when signed in
- API_URL env var added to .env.example
- Italian copy in messages/it.json under Profile
Verified end-to-end with the "Michele" PRD persona (49, M, 170cm, 76kg, SEDENTARY):
BMR = 1583 kcal, TDEE = 1899 kcal, multiplier 1.2 — matches the unit tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
21 lines
625 B
Bash
21 lines
625 B
Bash
# Next.js
|
|
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
|
|
# API server URL (server-only — non esporre al browser)
|
|
API_URL=http://localhost:4000
|
|
|
|
# Better Auth (deve coincidere con apps/api/.env)
|
|
# Genera un secret a 32+ byte: `openssl rand -base64 32`
|
|
BETTER_AUTH_SECRET=
|
|
BETTER_AUTH_URL=http://localhost:3000
|
|
|
|
# Database (Better Auth usa @ketopath/db, che legge DATABASE_URL)
|
|
DATABASE_URL=postgresql://luciano:luciano%40@localhost:5432/ketopath?schema=public
|
|
|
|
# Google OAuth (configurato a fine progetto)
|
|
# GOOGLE_CLIENT_ID=
|
|
# GOOGLE_CLIENT_SECRET=
|
|
|
|
# Sentry (verrà configurato in uno step dedicato)
|
|
# NEXT_PUBLIC_SENTRY_DSN=
|