[FEAT] UI V3 — flotta: chrome top-nav + design system su 32 pagine app

Migrazione UI dal V2 (Bootstrap Italia, sidebar) al V3 (top-nav mega-menu
navy/oro, Inter+Lucide self-host) fedele ai mockup docs/mockup Ui/.
- 32 pagine app convertite (incl. admin/*): head Inter+v3.css, chrome
  topnav-v3, contenuti in card V3, dati REALI preservati (id/data-* intatti),
  i18n/help/FAB reali invariati, nessun CDN esterno.
- v3.css: aggiunti widget condivisi (modal/toast/form/btn-variant/spinner/
  progress/tag/badge) + utility (.btn base, .text-muted, .sr-only) + alias
  variabili V2->token V3, così modali/form/toast di common.js funzionano
  ovunque senza style.css.
- maintenance.html: finestra estesa a ~12:15.
- docs/UI_V3_FLEET_BRIEF.md: ricetta operativa della flotta.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-27 15:57:35 +02:00
co-authored by Claude Opus 4.8
parent b0fc190704
commit a4150b5389
37 changed files with 4655 additions and 4922 deletions
+93
View File
@@ -0,0 +1,93 @@
# UI V3 — BRIEF OPERATIVO FLOTTA (FASE 1)
Migri pagine NIS2 dal V2 (Bootstrap Italia, sidebar) al **V3** (top-nav navy/oro, Inter, Lucide).
La **FASE 0 è già fatta e in prod**: `public/css/v3.css`, `public/js/topnav-v3.js`, `public/vendor/inter/`,
`public/vendor/lucide/lucide.min.js`, e la **pilota `public/dashboard.html` + `public/js/dashboard.js`**.
**Replica quel pattern.** Il sito è in MANUTENZIONE: testa SEMPRE con `?mnt=efc088d042032889b64b887d2e562ec8`.
## REGOLE D'ORO (vincolanti)
- **NON usare git** (no add/commit/push). **Solo scrivere file.** Il commit lo fa l'orchestratore.
- **NON toccare**: `public/css/v3.css`, `public/js/topnav-v3.js`, `public/js/common.js`, `public/js/api.js`,
`public/js/i18n.js`, `public/js/help.js`, qualunque `.php`, DB, migrazioni. Sono condivisi/già pronti.
- **NON toccare** `/var/www/nis2-agile/.maintenance` né `/tmp/agent-working.lock`.
- **Modifichi SOLO le pagine assegnate** (e, se serve, il loro `<pagina>.js` dedicato — non condiviso).
- **Dati REALI** via `api.js` (quelli che la pagina già usa). Zero numeri finti dei mockup.
Se un dato non esiste nel backend → placeholder "—"/empty, **non inventarlo**.
- **Self-host only**: nessun `googleapis.com`, `gstatic.com`, `unpkg.com`, CDN Bootstrap Italia.
- Mantieni: `checkAuth`, i18n IT/EN (`data-i18n`), help "?", **trittico FAB reale** (lo monta `common.js`).
- A11y/AGID: `focus-visible`, contrasto, touch ≥44px, `aria-label`, zoom non bloccato, responsive ≤900/≤560.
## RICETTA PER PAGINA — "reskin a rischio minimo"
L'obiettivo è cambiare **chrome + look**, **senza rompere il wiring**: **preserva ogni `id`/`data-*`
che il `<pagina>.js` legge** (non rinominarli). Cambi guscio e classi, non la logica.
### 1) `<head>` — sostituisci il caricamento CSS/font con (vedi `dashboard.html` righe 3–23):
```html
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>NomePagina · NIS2 Agile</title>
<link rel="stylesheet" href="/vendor/inter/inter.css?v=20260627">
<link rel="stylesheet" href="/css/v3.css?v=20260627">
<!-- mantieni il blocco PWA: manifest, theme-color #0066CC, icone, pwa.js (copia da dashboard.html) -->
```
**Rimuovi**: bundle Bootstrap Italia (CSS/JS), `/css/style.css`, Google Fonts, unpkg.
Se la pagina ha un `<style>` inline con regole essenziali non coperte da `v3.css`, puoi **tenerne una
versione minima** (nessun CDN), ma preferisci le classi di `v3.css`.
### 2) `<body>` — struttura V3:
```html
<div id="topnav"></div> <!-- host chrome: lo riempie topnav-v3.js -->
<main class="wrap">
<nav class="crumb" aria-label="breadcrumb">
<i data-lucide="home" class="ic"></i><a href="dashboard.html">Home</a>
<i data-lucide="chevron-right" class="ic"></i><span>NomePagina</span>
</nav>
<div class="page-head">
<div><h1 data-i18n="...">Titolo</h1><p class="sub">sottotitolo breve</p></div>
<!-- eventuali bottoni pagina: <button class="btn-primary">…</button> -->
</div>
<!-- CONTENUTO: avvolgi i blocchi in <section class="card card-pad">… ; preserva gli id dinamici -->
</main>
```
Mappa i componenti vecchi → classi `v3.css`: contenitori → `.card`/`.card-pad`; KPI → `.stat`
(`.green/.amber/.blue/.red`, `.ibox`,`.val`,`.lbl`,`.bar`); bottoni → `.btn-primary`/`.btn-ghost`;
stati → `.badge-t` (varianti colore); intestazioni sezione → `.sec-head`; griglie → `.grid3`/`.split2`.
Tabelle/liste: tienile dentro una `.card`; usa stili tabella di `v3.css` se presenti, altrimenti markup sobrio.
Stati **loading/empty/error**: usa `.v3-loading`/`.v3-empty`/`.v3-error` (come la dashboard) dove la pagina carica dati.
### 3) Scripts in fondo (ordine ESATTO come `dashboard.html` righe 112–140):
```html
<script src="/js/api.js?v=20260625d"></script>
<script src="/js/common.js?v=20260627v3"></script>
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260627"></script>
<script src="/js/i18n.js?v=20260631"></script>
<script src="/js/help.js?v=20260625d"></script>
<script src="/js/NOMEPAGINA.js?v=20260627"></script>
<script>
if (!checkAuth()) throw new Error('Not authenticated');
loadSidebar(); // = loadTopnavV3()
if (typeof I18n !== 'undefined') I18n.init();
if (typeof HelpSystem !== 'undefined') HelpSystem.init();
if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch(e){} }
/* poi l'init reale della pagina, es: if (typeof initPagina==='function') initPagina(); */
</script>
```
**Rimuovi** `common-bi.js` e il bundle Bootstrap Italia JS. Se il vecchio init chiamava `loadSidebar()`
funziona identico (topnav-v3.js ridefinisce `window.loadSidebar`). Mantieni l'init dati della pagina.
### 4) Pagine con MOCKUP (massima fedeltà)
- `assessment.html` → segui `docs/mockup Ui/assessment.html` (pattern pagina-modulo/GAP).
- `calendario.html` → segui `docs/mockup Ui/calendario.html` (app full-page: `.cal-app/.cal-main/.cal-side/.mv-grid/.view-switch/.legend`).
Le altre pagine: applica lo stile dashboard/card in modo **coerente** (non esiste un mockup dedicato).
## VALIDAZIONE (obbligatoria prima di riportare "fatto")
- `node --check public/js/<ogni-js-toccato>.js` → deve passare.
- HTTP: `curl -s -o /dev/null -w "%{http_code}\n" "https://nis2.agile.software/<pagina>?mnt=efc088d042032889b64b887d2e562ec8"` → **200**.
- HTML servito non deve contenere `googleapis|gstatic|unpkg|bootstrap-italia` (CDN):
`curl -s "https://nis2.agile.software/<pagina>?mnt=efc088d042032889b64b887d2e562ec8" | grep -Eo 'googleapis|gstatic|unpkg|cdn[^"]*bootstrap' | sort -u` → vuoto.
## REPORT FINALE
Elenca: pagine convertite (✓), eventuali `<pagina>.js` adattati e perché, gap/placeholder usati (dato mockup
inesistente nel backend), componenti `v3.css` che mancavano (NON aggiungerli tu — **segnalali**), e qualsiasi
pagina che NON sei riuscito a convertire fedelmente (spiega, non improvvisare).