longevity: sezione Giornale di bordo nella scheda cliente

Form (data, nota) ed elenco voci dopo Anagrafica, cancella visibile solo ad
autore o admin, messaggi per ?giornale=aggiunta|cancellata.
Refs #16

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 22:24:22 +02:00
parent cef08aaf9f
commit 2231a476c7
@@ -12,6 +12,7 @@ import { sessioniDi } from '../../../../lib/longevity/gestionale';
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';
export const prerender = false;
@@ -26,6 +27,7 @@ const sessioni = sessioniDi(db, cliente.client_code);
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 ETICHETTA_TIPO: Record<'checkup' | 'questionario', string> = {
checkup: 'Check-up',
@@ -46,6 +48,13 @@ const MESSAGGIO_VERIFICA: Record<'confermata' | 'scartata', string> = {
};
const messaggioVerifica =
verificata === 'confermata' || verificata === 'scartata' ? MESSAGGIO_VERIFICA[verificata] : null;
const giornaleEsito = params.get('giornale'); // #16: 'aggiunta' | 'cancellata', dal redirect dell'API
const MESSAGGIO_GIORNALE: Record<'aggiunta' | 'cancellata', string> = {
aggiunta: 'Nota aggiunta al giornale di bordo.',
cancellata: 'Nota cancellata dal giornale di bordo.',
};
const messaggioGiornale =
giornaleEsito === 'aggiunta' || giornaleEsito === 'cancellata' ? MESSAGGIO_GIORNALE[giornaleEsito] : null;
---
<Longevity
title={`${cliente.cognome} ${cliente.nome}`}
@@ -72,6 +81,7 @@ const messaggioVerifica =
{salvato && <p class="lg-card">Check-up salvato (sessione #{salvato}).</p>}
{corretto && <p class="lg-card">Check-up corretto (sessione #{corretto}): punteggi ricalcolati.</p>}
{messaggioVerifica && <p class="lg-card">{messaggioVerifica}</p>}
{messaggioGiornale && <p class="lg-card">{messaggioGiornale}</p>}
{fuoriCount && (
<p class="lg-misura--fuori-range">
{fuoriCount} {Number(fuoriCount) === 1 ? 'misura è' : 'misure sono'} fuori dal range di
@@ -86,6 +96,53 @@ const messaggioVerifica =
<p>Data di nascita: {cliente.data_nascita ? formattaData(cliente.data_nascita) : '—'}</p>
</div>
<div class="lg-card" id="giornale">
<p class="lg-score__label">Giornale di bordo</p>
<p class="lg-muted">Solo lo staff lo vede. Una nota sbagliata si cancella e si riscrive: non si modifica.</p>
<form class="lg-form" method="post" action="/api/longevity/gestionale/giornale">
<input type="hidden" name="azione" value="aggiungi" />
<input type="hidden" name="client_code" value={cliente.client_code} />
<label class="lg-field">
<span>Data</span>
<input type="date" name="data" value={oggi} max={oggi} required />
</label>
<label class="lg-field">
<span>Nota</span>
<textarea name="testo" rows="3" required></textarea>
</label>
<div class="lg-form__nav">
<button type="submit">Aggiungi nota</button>
</div>
</form>
{voci.length === 0 ? (
<p class="lg-muted">Nessuna nota ancora.</p>
) : (
<table class="lg-table">
<thead><tr><th>Data</th><th>Autore</th><th>Nota</th><th></th></tr></thead>
<tbody>
{voci.map((v) => (
<tr>
<td>{formattaData(v.data)}</td>
<td>{v.autore}</td>
<td style="white-space: pre-wrap;">{v.testo}</td>
<td>
{(v.autore === Astro.locals.user!.username || Astro.locals.user!.role === 'admin') && (
<form method="post" action="/api/longevity/gestionale/giornale">
<input type="hidden" name="azione" value="cancella" />
<input type="hidden" name="id" value={v.id} />
<button type="submit">Cancella</button>
</form>
)}
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
{!referto && (
<div class="lg-card lg-card--incompleto">
<p>Nessuna sessione ancora: apri un check-up per cominciare il fascicolo.</p>