import { fail, type ActionFailure } from '@sveltejs/kit'; import { archive, complete, edit, loadCurrent } from './routines'; import { parseFormString, parseFrequencyDays } from './validation'; /** * Shared implementations of the routine edit/complete form actions, used by * both the project dashboard (/projects/[id]) and the routine page * (/projects/[projectId]/routine/[routineId]). Guarding and failure messages * are the strictest common denominator: a missing or archived routine is * rejected before any write. */ export type EditRoutineResult = ActionFailure<{ error: string }> | { success: boolean; type?: 'edit' }; export async function editRoutineAction( data: FormData, routineId: number, extra?: { type: 'edit' }, ): Promise { const current = await loadCurrent(routineId); if (!current) { return fail(400, { error: 'Routine introuvable' }); } if (current.archived) { return fail(400, { error: 'Routine archivée' }); } const name = parseFormString(data.get('name')); if (!name) { return fail(400, { error: 'Le nom est requis' }); } let frequencyDays: number; try { frequencyDays = parseFrequencyDays(data.get('frequencyDays')); } catch { return fail(400, { error: 'Fréquence invalide' }); } // The dashboard row form has no description field; only touch it when the // form actually sends one, so list edits never wipe a description. const fields: { name: string; frequencyDays: number; description?: string } = { name, frequencyDays }; const description = data.get('description'); if (description !== null) { fields.description = description.toString(); } try { await edit(routineId, fields); } catch { return fail(400, { error: 'Routine introuvable' }); } return { success: true, type: extra?.type }; } export async function completeRoutineAction(data: FormData, routineId: number) { const current = await loadCurrent(routineId); if (!current) { return fail(400, { error: 'Routine introuvable' }); } if (current.archived) { return fail(400, { error: 'Routine archivée' }); } try { await complete( routineId, parseFormString(data.get('note')), Temporal.Now.instant().toString({ smallestUnit: 'millisecond' }), ); } catch { return fail(400, { error: 'Routine introuvable' }); } return { success: true }; } export async function archiveRoutineAction(routineId: number) { try { await archive(routineId); } catch { return fail(400, { error: 'Routine introuvable' }); } return { success: true }; }