From 8aeb25f930efc5b6326f36995e15cfbd4d973c54 Mon Sep 17 00:00:00 2001 From: "Adriano (daitarn)" Date: Mon, 28 Sep 2026 08:21:33 +0200 Subject: [PATCH] longevity: #15 pagine del flusso guidato: consulenza, check-up, scheda cliente MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuova pagina consulenza.astro (radio per livello e obiettivo, niente select). checkup.astro mostra "Passo 3 di 4" e porta avanti flusso=nuovo, con «Salta» verso la scheda. La scheda cliente ([code].astro) mostra la sezione "Prima consulenza" (letta, Modifica/Compila) e, con flusso=questionario, il riquadro "Passo 4 di 4" che rimanda a "Crea accesso" se il cliente non lo ha ancora. Refs #15 Co-Authored-By: Claude Sonnet 5 --- .../longevity/gestionale/cliente/[code].astro | 46 +++++++ .../gestionale/cliente/[code]/checkup.astro | 11 +- .../cliente/[code]/consulenza.astro | 113 ++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 apps/platforms/src/pages/longevity/gestionale/cliente/[code]/consulenza.astro diff --git a/apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro b/apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro index b5debe4..c773d3f 100644 --- a/apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro +++ b/apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro @@ -13,6 +13,7 @@ import { misureDaVerificare } from '../../../../lib/longevity/misure'; import { refertoDi, ultimaSessioneDi } from '../../../../lib/longevity/vista'; import { formattaNumero } from '../../../../lib/longevity/formato'; import { vociDelGiornale } from '../../../../lib/longevity/giornale'; +import { consulenzaDi, OBIETTIVI } from '../../../../lib/longevity/consulenza'; export const prerender = false; @@ -28,6 +29,8 @@ const daVerificare = misureDaVerificare(db, cliente.client_code); const ultimaId = ultimaSessioneDi(db, cliente.client_code); const referto = ultimaId !== null ? refertoDi(db, ultimaId) : null; const voci = vociDelGiornale(db, cliente.client_code); // #16: giornale di bordo, solo staff +const consulenza = consulenzaDi(db, cliente.client_code); // #15: prima consulenza, solo staff +const ETICHETTA_OBIETTIVO = new Map(OBIETTIVI.map((o) => [o.chiave, o.etichetta])); const ETICHETTA_TIPO: Record<'checkup' | 'questionario', string> = { checkup: 'Check-up', @@ -55,6 +58,10 @@ const MESSAGGIO_GIORNALE: Record<'aggiunta' | 'cancellata', string> = { }; const messaggioGiornale = giornaleEsito === 'aggiunta' || giornaleEsito === 'cancellata' ? MESSAGGIO_GIORNALE[giornaleEsito] : null; +const consulenzaEsito = params.get('consulenza'); // #15: 'salvata', dal redirect dell'API consulenza +// Passo 4 del flusso guidato per un cliente nuovo (#15): dopo il check-up si torna qui con +// ?flusso=questionario — il questionario resta del cliente, quindi qui c'è solo l'indicazione. +const flusso = params.get('flusso'); --- Check-up corretto (sessione #{corretto}): punteggi ricalcolati.

} {messaggioVerifica &&

{messaggioVerifica}

} {messaggioGiornale &&

{messaggioGiornale}

} + {consulenzaEsito === 'salvata' &&

Prima consulenza salvata.

} + {flusso === 'questionario' && ( +
+

Passo 4 di 4 — Questionario

+ {cliente.ha_accesso ? ( +

Il questionario lo compila il cliente dal suo accesso, anche sul tablet del centro.

+ ) : ( + <> +

Il questionario lo compila il cliente dal suo accesso, anche sul tablet del centro: crealo per continuare.

+ Crea accesso al referto + + )} +
+ )} {fuoriCount && (

{fuoriCount} {Number(fuoriCount) === 1 ? 'misura è' : 'misure sono'} fuori dal range di @@ -96,6 +117,31 @@ const messaggioGiornale =

Data di nascita: {cliente.data_nascita ? formattaData(cliente.data_nascita) : '—'}

+
+ + {!consulenza ? ( +

Non ancora compilata.

+ ) : ( + <> +

Livello: {consulenza.livello ?? '—'}

+

Obiettivo primario: {consulenza.obiettivo_primario ? ETICHETTA_OBIETTIVO.get(consulenza.obiettivo_primario) ?? consulenza.obiettivo_primario : '—'}

+

Obiettivo specifico: {consulenza.obiettivo_specifico ?? '—'}

+

Data target: {consulenza.data_target ? formattaData(consulenza.data_target) : '—'}

+

Note mediche: {consulenza.note_mediche ?? '—'}

+

Storia sportiva: {consulenza.storia_sportiva ?? '—'}

+

Limitazioni fisiche attuali: {consulenza.limitazioni ?? '—'}

+

Disponibilità: {consulenza.disponibilita_giorni ?? '—'} giorni/settimana

+

Fascia oraria preferita: {consulenza.fascia_oraria ?? '—'}

+

Note screening: {consulenza.note_screening ?? '—'}

+ + )} +
+

Giornale di bordo

Solo lo staff lo vede. Una nota sbagliata si cancella e si riscrive: non si modifica.

diff --git a/apps/platforms/src/pages/longevity/gestionale/cliente/[code]/checkup.astro b/apps/platforms/src/pages/longevity/gestionale/cliente/[code]/checkup.astro index 8616422..0a8fed8 100644 --- a/apps/platforms/src/pages/longevity/gestionale/cliente/[code]/checkup.astro +++ b/apps/platforms/src/pages/longevity/gestionale/cliente/[code]/checkup.astro @@ -40,6 +40,9 @@ const valoriPreselezione = sessione ? new Map([...valori.entries()].filter((kv): kv is [string, number] => kv[1] !== null)) : valoriUltimoCheckup(db, cliente.client_code); const errore = Astro.url.searchParams.get('errore'); +// Passo 3 del flusso guidato per un cliente nuovo (?flusso=nuovo, #15): solo per un +// check-up NUOVO — in correzione (?sessione=) non si è mai dentro il flusso guidato. +const flusso = !sessione ? Astro.url.searchParams.get('flusso') ?? '' : ''; ---

{sessione ? 'Modifica check-up' : 'Nuovo check-up'}

{cliente.cognome} {cliente.nome} — {cliente.client_code}. Lascia vuoto ciò che non hai misurato.

+ {flusso === 'nuovo' &&

Passo 3 di 4 — Scheda Rapida

}
{errore &&

{errore}

} @@ -56,6 +60,7 @@ const errore = Astro.url.searchParams.get('errore');
{sessione && } + {flusso === 'nuovo' && }