longevity: #15 API della prima consulenza e flusso guidato nel check-up
Nuova API consulenza.ts (POST, autore da locals.user, redirect a checkup?flusso=nuovo o alla scheda cliente). clienti.ts ora apre il flusso guidato verso /consulenza?flusso=nuovo invece della scheda. checkup.ts: un check-up NUOVO con flusso=nuovo prosegue con flusso=questionario; una correzione lo ignora sempre. Refs #15 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -165,5 +165,9 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
||||
|
||||
const params = new URLSearchParams({ salvato: String(esito.sessioneId) });
|
||||
if (esito.fuoriRange.length > 0) params.set('fuori', String(esito.fuoriRange.length));
|
||||
// Passo 3 → 4 del flusso guidato (#15): solo un check-up NUOVO (mai una correzione, che
|
||||
// non passa da questo ramo) con flusso=nuovo prosegue verso il questionario.
|
||||
const flusso = String(form.get('flusso') ?? '').trim();
|
||||
if (flusso === 'nuovo') params.set('flusso', 'questionario');
|
||||
return redirect(`/longevity/gestionale/cliente/${clientCode}?${params.toString()}`);
|
||||
};
|
||||
|
||||
@@ -52,5 +52,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
telefono: telefono || undefined,
|
||||
});
|
||||
|
||||
return redirect(`/longevity/gestionale/cliente/${code}`);
|
||||
// Dopo l'apertura del fascicolo comincia il flusso guidato (#15, passo 1 → 2): prima
|
||||
// consulenza, poi check-up, poi questionario — non più direttamente alla scheda.
|
||||
return redirect(`/longevity/gestionale/cliente/${code}/consulenza?flusso=nuovo`);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { getLongevityDb } from '../../../../lib/longevity/db';
|
||||
import { salvaConsulenza } from '../../../../lib/longevity/consulenza';
|
||||
|
||||
export const prerender = false;
|
||||
|
||||
// Riservato a admin+trainer da src/lib/auth.ts (RULES, /^\/api\/longevity\/gestionale(\/|$)/).
|
||||
|
||||
const REGEX_CODE = /^ISL-\d{4}$/;
|
||||
|
||||
const redirect = (location: string): Response => new Response(null, { status: 303, headers: { Location: location } });
|
||||
|
||||
/**
|
||||
* Salva la scheda di prima consulenza (#15). Autore SEMPRE da `locals.user`, mai dal form —
|
||||
* stesso principio di giornale.ts e checkup.ts. Il flusso guidato (`flusso=nuovo`, passo 1
|
||||
* → 2) prosegue verso il check-up; fuori dal flusso torna alla scheda cliente, sezione
|
||||
* #consulenza dove il form e la lettura vivono.
|
||||
*/
|
||||
export const POST: APIRoute = async ({ request, locals }) => {
|
||||
const form = await request.formData();
|
||||
const clientCode = String(form.get('client_code') ?? '').trim();
|
||||
const flusso = String(form.get('flusso') ?? '').trim();
|
||||
|
||||
if (!REGEX_CODE.test(clientCode)) {
|
||||
return redirect(`/longevity/gestionale?errore=${encodeURIComponent('Codice cliente non valido.')}`);
|
||||
}
|
||||
|
||||
// Il ritorno in caso di errore resta sulla stessa pagina del form, conservando `flusso`:
|
||||
// altrimenti un errore fuori dal flusso guidato riporterebbe dentro il flusso, o viceversa.
|
||||
const query = new URLSearchParams();
|
||||
if (flusso !== '') query.set('flusso', flusso);
|
||||
const tornaAlModulo = (testo: string) => {
|
||||
const q = new URLSearchParams(query);
|
||||
q.set('errore', testo);
|
||||
return redirect(`/longevity/gestionale/cliente/${clientCode}/consulenza?${q.toString()}`);
|
||||
};
|
||||
|
||||
const db = getLongevityDb();
|
||||
const autore = locals.user!.username;
|
||||
|
||||
const esito = salvaConsulenza(db, {
|
||||
clientCode,
|
||||
autore,
|
||||
campi: {
|
||||
livello: String(form.get('livello') ?? ''),
|
||||
obiettivoPrimario: String(form.get('obiettivo_primario') ?? ''),
|
||||
obiettivoSpecifico: String(form.get('obiettivo_specifico') ?? ''),
|
||||
dataTarget: String(form.get('data_target') ?? ''),
|
||||
noteMediche: String(form.get('note_mediche') ?? ''),
|
||||
storiaSportiva: String(form.get('storia_sportiva') ?? ''),
|
||||
limitazioni: String(form.get('limitazioni') ?? ''),
|
||||
disponibilitaGiorni: String(form.get('disponibilita_giorni') ?? ''),
|
||||
fasciaOraria: String(form.get('fascia_oraria') ?? ''),
|
||||
noteScreening: String(form.get('note_screening') ?? ''),
|
||||
},
|
||||
});
|
||||
if (!esito.ok) return tornaAlModulo(esito.errore);
|
||||
|
||||
if (flusso === 'nuovo') {
|
||||
// Passo 2 → 3 del flusso guidato (#15): dopo la consulenza si va al check-up.
|
||||
return redirect(`/longevity/gestionale/cliente/${clientCode}/checkup?flusso=nuovo`);
|
||||
}
|
||||
return redirect(`/longevity/gestionale/cliente/${clientCode}?consulenza=salvata#consulenza`);
|
||||
};
|
||||
Reference in New Issue
Block a user