Refs gitea:Adriano/AI-OS#310 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.4 KiB
Task 1: Il guscio — layout, stile, e una rotta che risponde
Files:
- Create:
src/layouts/Longevity.astro,src/styles/longevity.css,src/pages/longevity/index.astro - Test:
tests/longevity/pagine.test.ts
Interfaces:
- Consumes:
isProtectedPath,canAccessAdminPathdasrc/lib/auth.ts - Produces: il layout
Longevity.astrocontitleecrumbs, e le classi.lg-*
Il modello da seguire: src/layouts/StressIndex.astro e src/styles/stress-index.css. Leggili prima di scrivere. Il foglio di stile va globale e prefissato, non in <style> scoped: le stesse classi servono ai componenti Astro e alle isole React, che lo scope di Astro non raggiunge — la ragione è scritta in testa al foglio di Stress Index.
La differenza voluta rispetto a Stress Index. Quella piattaforma ha una barra laterale con sette voci, giusta per chi ci lavora dentro. Qui i pubblici sono due e uno non è staff: il cliente entra tre o quattro volte l'anno per guardare il proprio referto, e una barra di navigazione è l'arredamento di uno strumento di lavoro. Quindi il layout prevede due forme: variante="referto" (una colonna che scorre, nessuna navigazione) e variante="gestionale" (barra laterale come Stress Index). Questo task realizza la prima; la seconda arriva col piano del gestionale.
- Step 1: Write the failing test
// tests/longevity/pagine.test.ts
import { describe, it, expect } from 'vitest';
import { readFileSync, existsSync } from 'node:fs';
import { join } from 'node:path';
const leggi = (p: string) => readFileSync(join(process.cwd(), p), 'utf8');
describe('il guscio della piattaforma', () => {
it('il layout esiste e non monta header e footer pubblici', () => {
const l = leggi('src/layouts/Longevity.astro');
expect(l).not.toMatch(/import\s+Header/);
expect(l).not.toMatch(/import\s+Footer/);
expect(l).toMatch(/noindex/); // area riservata: mai indicizzata
});
it('il foglio di stile e globale e prefissato, non scoped', () => {
expect(existsSync(join(process.cwd(), 'src/styles/longevity.css'))).toBe(true);
const css = leggi('src/styles/longevity.css');
const classi = [...css.matchAll(/^\.([a-z-]+)/gm)].map((m) => m[1]);
expect(classi.length).toBeGreaterThan(3);
expect(classi.every((c) => c.startsWith('lg'))).toBe(true);
});
it('usa i token del sito invece di inventare colori', () => {
const css = leggi('src/styles/longevity.css');
expect(css).toMatch(/var\(--c-/);
});
it('nessun semaforo sui punteggi: il colore non giudica il corpo', () => {
const css = leggi('src/styles/longevity.css').toLowerCase();
// il mattone del fuori range e ammesso; un verde "tutto bene" no
expect(css).not.toMatch(/--lg-ok|--lg-buono|--lg-verde/);
});
it('la rotta del cliente e sotto /longevity, dove le regole la proteggono', () => {
expect(existsSync(join(process.cwd(), 'src/pages/longevity/index.astro'))).toBe(true);
});
});
- Step 2: Run test to verify it fails
Run: npm test -- tests/longevity/pagine.test.ts
Expected: FAIL — i file non esistono
- Step 3: Write minimal implementation
Il layout prende title, crumbs e variante, importa i font e i due fogli di stile (global.css e longevity.css), e dichiara noindex. Nessun Header/Footer pubblico: la navigazione è interna.
Il foglio longevity.css definisce, tutte prefissate lg: il guscio del referto (una colonna centrata, larghezza leggibile), l'intestazione, la carta di un punteggio, e i token locali. Le variabili locali riprendono quelle del sito (--c-accent, --c-dark, --c-bg-alt) e ne aggiungono due sole:
--lg-tratteggio: #d8d2c8; /* il perimetro di cio che non sappiamo */
--lg-fuori-range: #b05a4e; /* SOLO per una misura sospetta, mai per un punteggio */
⚠️ Non definire un colore «buono» o «cattivo» per i punteggi: l'intensità si ottiene variando l'opacità dell'accento. È la regola di prodotto, e il test la controlla.
src/pages/longevity/index.astro reindirizza a /longevity/io.
- Step 4: Run test to verify it passes
Run: npm test -- tests/longevity/pagine.test.ts → PASS (5 test)
Poi: npm test per intero e npx tsc --noEmit.
- Step 5: Commit
git add src/layouts/Longevity.astro src/styles/longevity.css src/pages/longevity/index.astro tests/longevity/pagine.test.ts
git commit -m "longevity: il guscio della piattaforma, senza semaforo sui punteggi"