registri dei piani in git (AI-OS#309)
Refs gitea:Adriano/AI-OS#310 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
### 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`, `canAccessAdminPath` da `src/lib/auth.ts`
|
||||
- Produces: il layout `Longevity.astro` con `title` e `crumbs`, 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**
|
||||
|
||||
```ts
|
||||
// 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:
|
||||
|
||||
```css
|
||||
--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**
|
||||
|
||||
```bash
|
||||
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"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user