95ffa08197
pages/api/longevity/gestionale/clienti.ts: POST del nuovo fascicolo (nome, cognome, sesso obbligatori; data di nascita/email/telefono facoltativi) → apriFascicolo → 303 alla scheda cliente, o 303 al modulo con ?errore=. pages/api/longevity/gestionale/checkup.ts: POST del check-up manuale, con misureDalForm (funzione pura, esportata e testata) per il parsing del form — virgola decimale accettata, campo vuoto = non misurato, valore non numerico ferma tutto, chiavi che non sono campi f_* attivi ignorate. operatore sempre da locals.user (mai dal corpo, stesso principio del client_code in questionario.ts); eta da etaDelCliente. Entrambi riservati a admin+trainer da RULES in auth.ts (già in vigore, verificato dal test su canAccessPath). tests/longevity/gestionale.test.ts: 17 test — salvaCheckup e il congelamento dei punteggi, il referto che combina check-up e questionario di sessioni diverse (#1), i rifiuti prima della scrittura, le misure fuori range, le versioni parametrizzate dell'anagrafica, apriFascicolo sul singleton (stesso trucco env-var di questionario-pagina.test.ts), misureDalForm, canAccessPath. vitest: 229 passed (212 di partenza + 17). tsc --noEmit: 0 errori. Refs #2 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import type { APIRoute } from 'astro';
|
|
import { apriFascicolo } from '../../../../lib/longevity/anagrafica';
|
|
|
|
export const prerender = false;
|
|
|
|
// Riservato a admin+trainer da src/lib/auth.ts (RULES, /^\/api\/longevity\/gestionale(\/|$)/):
|
|
// il middleware nega prima che questo file veda la richiesta.
|
|
|
|
const REGEX_DATA = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
|
const redirect = (location: string) => new Response(null, { status: 303, headers: { Location: location } });
|
|
|
|
/** Sempre la stessa pagina di partenza: questo endpoint ha un solo modulo che lo chiama
|
|
* (pages/longevity/gestionale/nuovo.astro, unità 2b), quindi il ritorno in caso di errore
|
|
* non serve dedurlo da un Referer — si scrive qui, una volta. */
|
|
const erroreAlModulo = (testo: string) =>
|
|
redirect(`/longevity/gestionale/nuovo?errore=${encodeURIComponent(testo)}`);
|
|
|
|
function isSesso(v: string): v is 'M' | 'F' {
|
|
return v === 'M' || v === 'F';
|
|
}
|
|
|
|
export const POST: APIRoute = async ({ request }) => {
|
|
const form = await request.formData();
|
|
const leggi = (chiave: string) => String(form.get(chiave) ?? '').trim();
|
|
|
|
const nome = leggi('nome');
|
|
const cognome = leggi('cognome');
|
|
const sesso = leggi('sesso');
|
|
const dataNascita = leggi('data_nascita');
|
|
const email = leggi('email');
|
|
const telefono = leggi('telefono');
|
|
|
|
if (!nome) return erroreAlModulo('Il nome è obbligatorio.');
|
|
if (!cognome) return erroreAlModulo('Il cognome è obbligatorio.');
|
|
if (!isSesso(sesso)) return erroreAlModulo('Il sesso deve essere M o F.');
|
|
|
|
if (dataNascita) {
|
|
if (!REGEX_DATA.test(dataNascita)) {
|
|
return erroreAlModulo('Data di nascita non valida (formato AAAA-MM-GG).');
|
|
}
|
|
// La data del server, non quella (manomettibile) del form: stesso criterio di
|
|
// pages/api/longevity/questionario.ts per "oggi".
|
|
const oggi = new Date().toISOString().slice(0, 10);
|
|
if (dataNascita > oggi) return erroreAlModulo('La data di nascita non può essere nel futuro.');
|
|
}
|
|
|
|
const code = apriFascicolo({
|
|
nome, cognome, sesso,
|
|
data_nascita: dataNascita || undefined,
|
|
email: email || undefined,
|
|
telefono: telefono || undefined,
|
|
});
|
|
|
|
return redirect(`/longevity/gestionale/cliente/${code}`);
|
|
};
|