diff --git a/apps/api/src/modules/tracking/fast.routes.ts b/apps/api/src/modules/tracking/fast.routes.ts index bef91bd..d1529a9 100644 --- a/apps/api/src/modules/tracking/fast.routes.ts +++ b/apps/api/src/modules/tracking/fast.routes.ts @@ -59,14 +59,17 @@ export const fastRoutes: FastifyPluginAsync = async (fastify) => { }); if (!owned) return reply.code(404).send({ error: 'fast_event_not_found' }); + // Costruiamo l'oggetto data omettendo le chiavi non fornite, perché con + // `exactOptionalPropertyTypes` Prisma rifiuta `undefined` esplicito. + const updateData: Parameters[0]['data'] = {}; + if (data.endedAt) updateData.endedAt = data.endedAt; + if (data.status) updateData.status = data.status; + if (data.symptoms) updateData.symptoms = JSON.stringify(data.symptoms); + if (data.notes != null) updateData.notes = data.notes; + const event = await fastify.prisma.fastEvent.update({ where: { id }, - data: { - endedAt: data.endedAt ?? undefined, - status: data.status ?? undefined, - symptoms: data.symptoms ? JSON.stringify(data.symptoms) : undefined, - notes: data.notes ?? undefined, - }, + data: updateData, }); return { event: { id: event.id, status: event.status } }; }); diff --git a/apps/web/src/app/[locale]/plan/actions.ts b/apps/web/src/app/[locale]/plan/actions.ts index 99d2374..9d41821 100644 --- a/apps/web/src/app/[locale]/plan/actions.ts +++ b/apps/web/src/app/[locale]/plan/actions.ts @@ -42,9 +42,9 @@ export async function fetchCurrentPlan(): Promise { return data.plan; } -export type RegenerateResult = { ok: true } | { ok: false; error: string }; - -export async function regeneratePlan(): Promise { +// Server action invocata via `
`. La firma è +// `(FormData) => Promise` per allinearsi al type richiesto da React 18. +export async function regeneratePlan(_formData?: FormData): Promise { const res = await fetch(`${API_URL}/me/meal-plans`, { method: 'POST', headers: { cookie: cookieHeader() }, @@ -52,10 +52,9 @@ export async function regeneratePlan(): Promise { }); if (!res.ok) { const body = (await res.json().catch(() => ({}))) as { error?: string }; - return { ok: false, error: body.error ?? `api_error_${res.status}` }; + throw new Error(body.error ?? `api_error_${res.status}`); } revalidatePath('/plan'); - return { ok: true }; } export type SwapResult = { ok: true } | { ok: false; error: string }; diff --git a/apps/web/src/app/[locale]/tracking/weight-entry-form.tsx b/apps/web/src/app/[locale]/tracking/weight-entry-form.tsx index 58c886d..7a7fa7a 100644 --- a/apps/web/src/app/[locale]/tracking/weight-entry-form.tsx +++ b/apps/web/src/app/[locale]/tracking/weight-entry-form.tsx @@ -29,12 +29,16 @@ export function WeightEntryForm({ latest }: { latest: WeightEntryRow | null }) { const [serverError, setServerError] = useState(null); const [savedAt, setSavedAt] = useState(null); + // L'input HTML type="date" passa stringhe ISO; zod le coerce a Date a runtime + // (vedi `weightEntryInputSchema.date = z.coerce.date()`). Il TS-side resta + // strict, perciò usiamo cast `unknown` agli ingressi dei defaultValues e di + // form.reset. const form = useForm({ resolver: zodResolver(weightEntryInputSchema), defaultValues: { date: todayISO(), weightKg: latest?.weightKg, - } as WeightEntryInput, + } as unknown as WeightEntryInput, }); const onSubmit = form.handleSubmit(async (input) => { @@ -45,7 +49,7 @@ export function WeightEntryForm({ latest }: { latest: WeightEntryRow | null }) { return; } setSavedAt(new Date().toISOString()); - form.reset({ date: todayISO(), weightKg: input.weightKg } as WeightEntryInput); + form.reset({ date: todayISO(), weightKg: input.weightKg } as unknown as WeightEntryInput); }); return ( @@ -59,7 +63,7 @@ export function WeightEntryForm({ latest }: { latest: WeightEntryRow | null }) { {t('date')} - +