6301f521fd
Campus, Stress Index e Longevity escono dal sito e diventano apps.insanitylab.it, con utenti, sessioni, login e database propri. Deciso da Adriano il 03/09/2026: una repo sola, due applicazioni autosufficienti, cosi' che ognuna resti estraibile. Misura che ha guidato il taglio: le tre aree condividevano col sito SOLO l'identita' - ~170 righe fra auth.ts, middleware.ts e safe-next.ts. Layout, librerie e dati erano gia' disgiunti. Lato piattaforme: - ruoli piattaforme/cliente/trainer/admin, senza quelli redazionali - canAccessPath con default CHIUSO (nel sito era aperto: li' le rotte non elencate erano di chiunque fosse loggato, qui ogni sezione e' di qualcuno) - tutta l'app protetta, si elencano le eccezioni invece dei prefissi protetti - /api risponde 401/403, non un redirect verso una pagina di login - tre database distinti: utenti, dati clinici senza nomi, mappatura coi nomi Lato sito: - ROLES tornano i tre redazionali; via le regole e il login pubblico - il login del pannello RESPINGE un account emigrato invece di aprirgli una sessione: senza, landingFor lo mandava su /admin, il middleware glielo negava, e si formava un ciclo di redirect che sembra un guasto del sito - l'header non mostra piu' un menu delle piattaforme: un link che esce Verificato: sito 20 file / 146 test, piattaforme 26 file / 197 test, entrambi i build passano, e l'app girata davvero in locale - il ruolo piattaforme entra in Campus e viene rimbalzato da Longevity, il cliente il contrario. Non ancora in produzione: manca il record DNS di apps.insanitylab.it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
73 lines
2.9 KiB
Plaintext
73 lines
2.9 KiB
Plaintext
---
|
|
// Il referto del cliente: il radar a sette assi, la Fitness Age, le carte dei macro-score.
|
|
// La pagina non interroga il database da sola (c'è un test che lo verifica): il codice
|
|
// cliente arriva da codicePerUtenteLoggato (anagrafica.ts, l'unico modulo autorizzato a
|
|
// toccare identity), la sessione più recente e il referto stesso da vista.ts.
|
|
import Longevity from '../../layouts/Longevity.astro';
|
|
import Radar from '../../components/longevity/Radar';
|
|
import MacroScore from '../../components/longevity/MacroScore.astro';
|
|
import { getLongevityDb } from '../../lib/longevity/db';
|
|
import { codicePerUtenteLoggato } from '../../lib/longevity/anagrafica';
|
|
import { refertoDi, ultimaSessioneDi } from '../../lib/longevity/vista';
|
|
import { formattaNumero } from '../../lib/longevity/formato';
|
|
|
|
export const prerender = false;
|
|
|
|
const user = Astro.locals.user!;
|
|
const codice = codicePerUtenteLoggato(user.id);
|
|
const db = getLongevityDb();
|
|
const sessioneId = codice ? ultimaSessioneDi(db, codice) : null;
|
|
const referto = sessioneId !== null ? refertoDi(db, sessioneId) : null;
|
|
---
|
|
<Longevity title="Il tuo referto" crumbs={['Il tuo referto']}>
|
|
{!codice && (
|
|
<div class="lg-card">
|
|
<p>Nessun fascicolo è ancora collegato al tuo account. Contatta lo staff InsanityLab.</p>
|
|
</div>
|
|
)}
|
|
|
|
{codice && !referto && (
|
|
<div class="lg-card lg-card--incompleto">
|
|
<p>Non hai ancora compilato il questionario: senza quello non c'è ancora un referto da mostrare.</p>
|
|
<p><a href="/longevity/questionario">Comincia da qui</a>.</p>
|
|
</div>
|
|
)}
|
|
|
|
{referto && (
|
|
<div class="lg-referto">
|
|
<section class:list={['lg-card', { 'lg-card--incompleto': referto.fitnessAge === null }]}>
|
|
<p class="lg-score__label">Fitness Age</p>
|
|
<div class="lg-score">
|
|
<span class="lg-score__value lg-num">
|
|
{referto.fitnessAge !== null ? formattaNumero(referto.fitnessAge) : '—'}
|
|
</span>
|
|
{referto.fitnessAge !== null && <span class="lg-score__max">anni</span>}
|
|
</div>
|
|
<p class="lg-muted lg-macro__nota">
|
|
Copertura dati: {Math.round(referto.fitnessAgeCopertura * 100)}%
|
|
{referto.fitnessAge === null && ' — non ancora sufficiente per un numero.'}
|
|
</p>
|
|
</section>
|
|
|
|
<section class="lg-card">
|
|
<h2>Il tuo radar</h2>
|
|
<Radar client:load assi={referto.assi} />
|
|
</section>
|
|
|
|
<section class="lg-macro">
|
|
{referto.macro.map((m) => (
|
|
<MacroScore nome={m.nome} valore={m.valore} copertura={m.copertura} />
|
|
))}
|
|
</section>
|
|
|
|
<section class="lg-card">
|
|
<p>
|
|
InsanityLab Longevity monitora il tuo percorso nel tempo: più compilazioni
|
|
raccontano come cambi, non solo come stai oggi.
|
|
<a href="/longevity/questionario">Compila di nuovo il questionario</a>.
|
|
</p>
|
|
</section>
|
|
</div>
|
|
)}
|
|
</Longevity>
|