longevity: nuovo cliente con prima consulenza e scheda rapida, follow-up solo questionario e check-up #15

Closed
opened 2026-09-27 19:55:58 +00:00 by Adriano · 5 comments
Owner

COSA: flusso del nuovo cliente e dei follow-up.

  • Nuovo cliente: anagrafica → prima consulenza (screening, obiettivi) → Scheda Rapida Profilazione Fisica (il primo check-up, modulo dell'issue dedicata) → questionario.
  • Follow-up (ogni 3-4 mesi): questionario + check-up fisico; della prima consulenza solo obiettivi aggiornabili; le note libere vanno nel giornale di bordo del cliente (issue dedicata).
  • Uso su tablet: pagine utilizzabili a touch; il cliente può compilare il questionario sul tablet del centro.
    PERCHÉ: Nicola, call 27/09 (min 51-56); Adriano 27/09: «Scheda Rapida Profilazione Fisica da aggiungere quando si aggiunge un nuovo cliente».
    OGGI: pages/longevity/gestionale/nuovo.astro crea solo l'anagrafica; il check-up si apre a parte dalla scheda cliente.
    DA CHIARIRE: elenco obiettivi (oggi performance sportiva, energia quotidiana, recupero e benessere, riabilitazione, ricomposizione corporea, dimagrimento, altro: Nicola vuole aggiungerne); campi dello screening iniziale (ISL_Scheda_CheckUp.xlsx, foglio Profilo Cliente, su Wasabi in Longevity_Project/docs/).
    FATTO QUANDO: creare un cliente porta in sequenza a prima consulenza, scheda rapida e questionario; un follow-up non richiede di rifare la prima consulenza.
    FONTE: call Adriano–Nicola 27/09/2026, trascrizione e allegati in wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/2026-09-27_call/
COSA: flusso del nuovo cliente e dei follow-up. - Nuovo cliente: anagrafica → prima consulenza (screening, obiettivi) → Scheda Rapida Profilazione Fisica (il primo check-up, modulo dell'issue dedicata) → questionario. - Follow-up (ogni 3-4 mesi): questionario + check-up fisico; della prima consulenza solo obiettivi aggiornabili; le note libere vanno nel giornale di bordo del cliente (issue dedicata). - Uso su tablet: pagine utilizzabili a touch; il cliente può compilare il questionario sul tablet del centro. PERCHÉ: Nicola, call 27/09 (min 51-56); Adriano 27/09: «Scheda Rapida Profilazione Fisica da aggiungere quando si aggiunge un nuovo cliente». OGGI: pages/longevity/gestionale/nuovo.astro crea solo l'anagrafica; il check-up si apre a parte dalla scheda cliente. DA CHIARIRE: elenco obiettivi (oggi performance sportiva, energia quotidiana, recupero e benessere, riabilitazione, ricomposizione corporea, dimagrimento, altro: Nicola vuole aggiungerne); campi dello screening iniziale (ISL_Scheda_CheckUp.xlsx, foglio Profilo Cliente, su Wasabi in Longevity_Project/docs/). FATTO QUANDO: creare un cliente porta in sequenza a prima consulenza, scheda rapida e questionario; un follow-up non richiede di rifare la prima consulenza. FONTE: call Adriano–Nicola 27/09/2026, trascrizione e allegati in wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/2026-09-27_call/
Adriano added the sviluppo label 2026-09-27 19:55:58 +00:00
Author
Owner

DECISIONE (Adriano, 27/09/2026): il cliente NON vede la scheda di profilazione (prima consulenza + scheda rapida): solo staff. Il cliente continua a vedere referto, progressione e il questionario da compilare.

DECISIONE (Adriano, 27/09/2026): il cliente NON vede la scheda di profilazione (prima consulenza + scheda rapida): solo staff. Il cliente continua a vedere referto, progressione e il questionario da compilare.
Adriano added the assegnata:daitarn label 2026-09-28 06:14:43 +00:00
Author
Owner

🔵 daitarn — preso in carico 2026-09-28T06:14:44Z
ramo: lavoro/daitarn · capacità: build-windows, gpu

🔵 daitarn — **preso in carico** 2026-09-28T06:14:44Z ramo: `lavoro/daitarn` · capacità: build-windows, gpu
Author
Owner

ANALISI (passo 1, Opus) — gitea:Adriano/InsanityLab-web#15
RAMO: lavoro/daitarn a b0f30f9 (= origin/main, #13 in produzione). Cartella: apps/platforms.
FONTI: foglio «Profilo Cliente» di ISL_Scheda_CheckUp.xlsx (wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/), call 27/09.

DECISIONI

  • Adriano 27/09: prima consulenza e scheda rapida solo staff; correggere e salvare sovrascrive, nessuno storico.
  • Nostre, da confermare con Nicola (aggiungere le domande a gitea:Adriano/InsanityLab-web#18):
    a. Prima consulenza = una sola scheda per cliente, modificabile in ogni follow-up (gli obiettivi si aggiornano lì); il racconto dei cambi va nel giornale (#16), non in uno storico della scheda.
    b. Campi (dal foglio Profilo Cliente, meno anagrafica e altezza che stanno altrove): livello (1/2/3), obiettivo primario (radio: performance sportiva, energia quotidiana, recupero e benessere, riabilitazione, ricomposizione corporea, dimagrimento, altro), obiettivo specifico concordato (testo), data target (data), note mediche/allergie/infortuni pregressi, storia sportiva, limitazioni fisiche attuali, disponibilità giorni/settimana (0-7), fascia oraria preferita (testo), note screening. Tutti facoltativi.
    c. Il questionario resta del cliente: nel flusso l'ultimo passo porta a «Crea accesso» (pagina esistente) e dice che il cliente lo compila dal suo accesso, anche sul tablet del centro. Nessuna compilazione per conto del cliente.
    d. Flusso guidato con parametro flusso=nuovo passato di pagina in pagina; ogni passo ha «Salta».

MODIFICHE

  1. src/lib/longevity/db.ts: tabella consulenza in longevity.db (solo client_code, niente nomi): client_code TEXT PRIMARY KEY REFERENCES soggetti(client_code), livello INTEGER CHECK (livello IN (1,2,3)), obiettivo_primario TEXT, obiettivo_specifico TEXT, data_target TEXT, note_mediche TEXT, storia_sportiva TEXT, limitazioni TEXT, disponibilita_giorni INTEGER CHECK (disponibilita_giorni BETWEEN 0 AND 7), fascia_oraria TEXT, note_screening TEXT, aggiornata_da TEXT NOT NULL, aggiornata_at TEXT NOT NULL DEFAULT (datetime('now')). CREATE TABLE IF NOT EXISTS basta su un DB esistente (stesso ragionamento del giornale in #16).
  2. Nuovo src/lib/longevity/consulenza.ts: OBIETTIVI (elenco chiave → etichetta); consulenzaDi(db, clientCode) → riga | null; salvaConsulenza(db, { clientCode, autore, campi }) → { ok } | { ok: false, errore }: UPSERT; rifiuta soggetto inesistente, livello fuori 1-3, obiettivo fuori elenco, data_target non AAAA-MM-GG, disponibilità fuori 0-7 o non intera, testo > 5000 caratteri; stringhe vuote → NULL.
  3. Nuova API src/pages/api/longevity/gestionale/consulenza.ts (POST form): autore da locals.user, client_code validato e esistente. Redirect 303: con flusso=nuovo → /longevity/gestionale/cliente//checkup?flusso=nuovo; senza → scheda cliente ?consulenza=salvata#consulenza. Errore → torna alla pagina con ?errore= (conservando flusso).
  4. Nuova pagina src/pages/longevity/gestionale/cliente/[code]/consulenza.astro: form precompilato se la scheda esiste; radio per livello e obiettivo (niente , tests/longevity/referto.test.ts); con flusso=nuovo mostra «Passo 2 di 4 — Prima consulenza» e un link «Salta» al check-up con flusso. src/pages/api/longevity/gestionale/clienti.ts: dopo la creazione redirect a /cliente//consulenza?flusso=nuovo (oggi va alla scheda). Check-up (#13): checkup.astro con flusso=nuovo mostra «Passo 3 di 4 — Scheda Rapida», hidden flusso, link «Salta» alla scheda cliente con flusso=questionario. api/.../checkup.ts: check-up NUOVO riuscito con flusso=nuovo → redirect alla scheda cliente con ?salvato=<id>&flusso=questionario (gli altri parametri come oggi). La correzione (#12) ignora flusso. src/pages/longevity/gestionale/cliente/[code].astro: sezione «Prima consulenza» (id="consulenza") con i campi in lettura e «Modifica»/«Compila»; con flusso=questionario un riquadro «Passo 4 di 4 — Questionario»: se il cliente non ha accesso, link a «Crea accesso» e testo che il questionario lo compila il cliente dal suo accesso; se lo ha, solo il testo. Tablet: in src/styles/longevity.css bersagli touch ≥ 44px per radio, checkbox, pulsanti e link-pulsante del gestionale (min-height/padding), senza cambiare l'aspetto desktop oltre il necessario. Il cliente: nessuna pagina sotto /longevity/io, /longevity/progressione, /longevity/questionario legge consulenza.ts — test sul testo dei file come per giornale.ts in #16. TEST (tests/longevity/consulenza.test.ts + API) salvaConsulenza: inserimento, sovrascrittura (una riga sola), ogni rifiuto senza scrittura, vuoti → NULL. API: autore da locals.user e non dal form; redirect con e senza flusso; client_code inesistente → errore. clienti.ts: dopo la creazione redirect alla consulenza con flusso=nuovo (adeguare il test esistente se ne controlla il Location). checkup.ts: nuovo check-up con flusso=nuovo → Location con flusso=questionario; correzione con flusso → invariata. nessuna pagina cliente importa consulenza. NON TOCCARE: motore, registro, misure/score, questionario e sua API, anagrafica/identity (tests/longevity/anagrafica.test.ts: niente parole identity e longevity insieme nei file nuovi), accesso.ts, pagine cliente. PROVA: in apps/platforms npx vitest run (baseline Windows: 314 verdi, 4 rossi di piattaforma — campus-lib resolveAsset; anagrafica.test.ts separatori \; EPERM in gestionale.test.ts e questionario-pagina.test.ts; nessun rosso nuovo), npx tsc --noEmit, npm run build. DEPLOY: nessuna migrazione a mano (tabella nuova IF NOT EXISTS); backup dei tre DB prima.
ANALISI (passo 1, Opus) — gitea:Adriano/InsanityLab-web#15 RAMO: lavoro/daitarn a b0f30f9 (= origin/main, #13 in produzione). Cartella: apps/platforms. FONTI: foglio «Profilo Cliente» di ISL_Scheda_CheckUp.xlsx (wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/), call 27/09. DECISIONI - Adriano 27/09: prima consulenza e scheda rapida solo staff; correggere e salvare sovrascrive, nessuno storico. - Nostre, da confermare con Nicola (aggiungere le domande a gitea:Adriano/InsanityLab-web#18): a. Prima consulenza = una sola scheda per cliente, modificabile in ogni follow-up (gli obiettivi si aggiornano lì); il racconto dei cambi va nel giornale (#16), non in uno storico della scheda. b. Campi (dal foglio Profilo Cliente, meno anagrafica e altezza che stanno altrove): livello (1/2/3), obiettivo primario (radio: performance sportiva, energia quotidiana, recupero e benessere, riabilitazione, ricomposizione corporea, dimagrimento, altro), obiettivo specifico concordato (testo), data target (data), note mediche/allergie/infortuni pregressi, storia sportiva, limitazioni fisiche attuali, disponibilità giorni/settimana (0-7), fascia oraria preferita (testo), note screening. Tutti facoltativi. c. Il questionario resta del cliente: nel flusso l'ultimo passo porta a «Crea accesso» (pagina esistente) e dice che il cliente lo compila dal suo accesso, anche sul tablet del centro. Nessuna compilazione per conto del cliente. d. Flusso guidato con parametro `flusso=nuovo` passato di pagina in pagina; ogni passo ha «Salta». MODIFICHE 1. src/lib/longevity/db.ts: tabella `consulenza` in longevity.db (solo client_code, niente nomi): client_code TEXT PRIMARY KEY REFERENCES soggetti(client_code), livello INTEGER CHECK (livello IN (1,2,3)), obiettivo_primario TEXT, obiettivo_specifico TEXT, data_target TEXT, note_mediche TEXT, storia_sportiva TEXT, limitazioni TEXT, disponibilita_giorni INTEGER CHECK (disponibilita_giorni BETWEEN 0 AND 7), fascia_oraria TEXT, note_screening TEXT, aggiornata_da TEXT NOT NULL, aggiornata_at TEXT NOT NULL DEFAULT (datetime('now')). CREATE TABLE IF NOT EXISTS basta su un DB esistente (stesso ragionamento del giornale in #16). 2. Nuovo src/lib/longevity/consulenza.ts: OBIETTIVI (elenco chiave → etichetta); `consulenzaDi(db, clientCode)` → riga | null; `salvaConsulenza(db, { clientCode, autore, campi })` → { ok } | { ok: false, errore }: UPSERT; rifiuta soggetto inesistente, livello fuori 1-3, obiettivo fuori elenco, data_target non AAAA-MM-GG, disponibilità fuori 0-7 o non intera, testo > 5000 caratteri; stringhe vuote → NULL. 3. Nuova API src/pages/api/longevity/gestionale/consulenza.ts (POST form): autore da locals.user, client_code validato e esistente. Redirect 303: con `flusso=nuovo` → /longevity/gestionale/cliente/<code>/checkup?flusso=nuovo; senza → scheda cliente `?consulenza=salvata#consulenza`. Errore → torna alla pagina con `?errore=` (conservando flusso). 4. Nuova pagina src/pages/longevity/gestionale/cliente/[code]/consulenza.astro: form precompilato se la scheda esiste; radio per livello e obiettivo (niente <select>, tests/longevity/referto.test.ts); con flusso=nuovo mostra «Passo 2 di 4 — Prima consulenza» e un link «Salta» al check-up con flusso. 5. src/pages/api/longevity/gestionale/clienti.ts: dopo la creazione redirect a /cliente/<code>/consulenza?flusso=nuovo (oggi va alla scheda). 6. Check-up (#13): checkup.astro con flusso=nuovo mostra «Passo 3 di 4 — Scheda Rapida», hidden `flusso`, link «Salta» alla scheda cliente con flusso=questionario. api/.../checkup.ts: check-up NUOVO riuscito con flusso=nuovo → redirect alla scheda cliente con `?salvato=<id>&flusso=questionario` (gli altri parametri come oggi). La correzione (#12) ignora flusso. 7. src/pages/longevity/gestionale/cliente/[code].astro: sezione «Prima consulenza» (id="consulenza") con i campi in lettura e «Modifica»/«Compila»; con flusso=questionario un riquadro «Passo 4 di 4 — Questionario»: se il cliente non ha accesso, link a «Crea accesso» e testo che il questionario lo compila il cliente dal suo accesso; se lo ha, solo il testo. 8. Tablet: in src/styles/longevity.css bersagli touch ≥ 44px per radio, checkbox, pulsanti e link-pulsante del gestionale (min-height/padding), senza cambiare l'aspetto desktop oltre il necessario. Il cliente: nessuna pagina sotto /longevity/io, /longevity/progressione, /longevity/questionario legge consulenza.ts — test sul testo dei file come per giornale.ts in #16. TEST (tests/longevity/consulenza.test.ts + API) - salvaConsulenza: inserimento, sovrascrittura (una riga sola), ogni rifiuto senza scrittura, vuoti → NULL. - API: autore da locals.user e non dal form; redirect con e senza flusso; client_code inesistente → errore. - clienti.ts: dopo la creazione redirect alla consulenza con flusso=nuovo (adeguare il test esistente se ne controlla il Location). - checkup.ts: nuovo check-up con flusso=nuovo → Location con flusso=questionario; correzione con flusso → invariata. - nessuna pagina cliente importa consulenza. NON TOCCARE: motore, registro, misure/score, questionario e sua API, anagrafica/identity (tests/longevity/anagrafica.test.ts: niente parole identity e longevity insieme nei file nuovi), accesso.ts, pagine cliente. PROVA: in apps/platforms `npx vitest run` (baseline Windows: 314 verdi, 4 rossi di piattaforma — campus-lib resolveAsset; anagrafica.test.ts separatori `\`; EPERM in gestionale.test.ts e questionario-pagina.test.ts; nessun rosso nuovo), `npx tsc --noEmit`, `npm run build`. DEPLOY: nessuna migrazione a mano (tabella nuova IF NOT EXISTS); backup dei tre DB prima.
Author
Owner

ESITO: fatto sul ramo, non in main né in produzione
RIF: gitea:Adriano/InsanityLab-web#15
COSA: controllo finale (passo 3, Opus) del codice Sonnet: il diff fa quello che dice l'analisi e solo quello.
COMMIT (ramo lavoro/daitarn, pushato): 498395d tabella consulenza + consulenza.ts + test; 575a398 API consulenza, redirect clienti.ts al flusso, checkup.ts flusso→questionario; 8aeb25f pagine (consulenza.astro, passo 3 in checkup.astro, sezione Prima consulenza e passo 4 nella scheda cliente); 680224e CSS bersagli touch 44px.
VERIFICATO A OCCHIO: UPSERT una riga per cliente; validazioni prima della scrittura; autore da locals.user; flusso propagato solo per un check-up nuovo, la correzione (#12) lo ignora; nessuna pagina cliente importa consulenza.ts (test).
PROVA: apps/platforms npx vitest run → 336 verdi, 4 rossi = baseline Windows (anagrafica.test.ts segnala solo anagrafica.ts e db.ts); npx tsc --noEmit → 0 errori; build ok (rapporto agente).
LIMITE NOTO: nella scheda cliente i campi testo della consulenza non conservano gli a capo (cosmetico).
DA CONFERMARE CON NICOLA: domande g-j in gitea:Adriano/InsanityLab-web#18.
MANCA: via di Adriano per merge su main e deploy (backup DB prima; tabella nuova IF NOT EXISTS, nessuna migrazione a mano).

ESITO: fatto sul ramo, non in main né in produzione RIF: gitea:Adriano/InsanityLab-web#15 COSA: controllo finale (passo 3, Opus) del codice Sonnet: il diff fa quello che dice l'analisi e solo quello. COMMIT (ramo lavoro/daitarn, pushato): 498395d tabella consulenza + consulenza.ts + test; 575a398 API consulenza, redirect clienti.ts al flusso, checkup.ts flusso→questionario; 8aeb25f pagine (consulenza.astro, passo 3 in checkup.astro, sezione Prima consulenza e passo 4 nella scheda cliente); 680224e CSS bersagli touch 44px. VERIFICATO A OCCHIO: UPSERT una riga per cliente; validazioni prima della scrittura; autore da locals.user; flusso propagato solo per un check-up nuovo, la correzione (#12) lo ignora; nessuna pagina cliente importa consulenza.ts (test). PROVA: apps/platforms `npx vitest run` → 336 verdi, 4 rossi = baseline Windows (anagrafica.test.ts segnala solo anagrafica.ts e db.ts); `npx tsc --noEmit` → 0 errori; build ok (rapporto agente). LIMITE NOTO: nella scheda cliente i campi testo della consulenza non conservano gli a capo (cosmetico). DA CONFERMARE CON NICOLA: domande g-j in gitea:Adriano/InsanityLab-web#18. MANCA: via di Adriano per merge su main e deploy (backup DB prima; tabella nuova IF NOT EXISTS, nessuna migrazione a mano).
Author
Owner

Soluzione

ESITO: fatto, in produzione
RIF: gitea:Adriano/InsanityLab-web#15
COSA: flusso guidato del nuovo cliente (anagrafica → prima consulenza → Scheda Rapida → accesso per il questionario, ogni passo saltabile); prima consulenza = una scheda per cliente (tabella consulenza in longevity.db, UPSERT, solo staff), modificabile nei follow-up dalla scheda cliente; bersagli touch 44px per il tablet.
FILE: apps/platforms/src/lib/longevity/consulenza.ts; lib/longevity/db.ts (tabella consulenza); pages/api/longevity/gestionale/consulenza.ts, clienti.ts, checkup.ts; pages/longevity/gestionale/cliente/[code]/consulenza.astro, [code]/checkup.astro, [code].astro; styles/longevity.css; tests/longevity/consulenza.test.ts.
COMMIT: 498395d, 575a398, 8aeb25f, 680224e — main 680224e.
PROVA: vitest 336 verdi + 4 rossi di baseline Windows; tsc 0 errori. VPS 28/09 06:27 UTC: backup /opt/docker/insanitylab-platforms/backup/20260928T062724-pre-15 (3 DB, integrity ok), container ricostruito, tabella consulenza creata all'apertura, integrity ok, /longevity/gestionale/nuovo → 302 al login.
MANCA: prova in browser loggato; a capo dei testi consulenza nella scheda cliente (cosmetico); conferme di Nicola in #18.

**Soluzione** ESITO: fatto, in produzione RIF: gitea:Adriano/InsanityLab-web#15 COSA: flusso guidato del nuovo cliente (anagrafica → prima consulenza → Scheda Rapida → accesso per il questionario, ogni passo saltabile); prima consulenza = una scheda per cliente (tabella consulenza in longevity.db, UPSERT, solo staff), modificabile nei follow-up dalla scheda cliente; bersagli touch 44px per il tablet. FILE: apps/platforms/src/lib/longevity/consulenza.ts; lib/longevity/db.ts (tabella consulenza); pages/api/longevity/gestionale/consulenza.ts, clienti.ts, checkup.ts; pages/longevity/gestionale/cliente/[code]/consulenza.astro, [code]/checkup.astro, [code].astro; styles/longevity.css; tests/longevity/consulenza.test.ts. COMMIT: 498395d, 575a398, 8aeb25f, 680224e — main 680224e. PROVA: vitest 336 verdi + 4 rossi di baseline Windows; tsc 0 errori. VPS 28/09 06:27 UTC: backup /opt/docker/insanitylab-platforms/backup/20260928T062724-pre-15 (3 DB, integrity ok), container ricostruito, tabella consulenza creata all'apertura, integrity ok, /longevity/gestionale/nuovo → 302 al login. MANCA: prova in browser loggato; a capo dei testi consulenza nella scheda cliente (cosmetico); conferme di Nicola in #18.
Adriano removed the assegnata:daitarn label 2026-09-28 06:28:02 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/InsanityLab-web#15