docs(01-04): complete client dashboard UI plan — SUMMARY.md
5 task completati: design token Tailwind v4, ClientDashboard wrapper, PhaseTimeline laterale, PaymentStatus (zero importi singoli), DocumentsSection e NotesSection. Build Next.js 16 senza errori TypeScript.
This commit is contained in:
@@ -0,0 +1,167 @@
|
|||||||
|
---
|
||||||
|
phase: 01-foundation-client-dashboard
|
||||||
|
plan: 04
|
||||||
|
subsystem: client-portal-ui
|
||||||
|
tags: [nextjs, tailwind-v4, shadcn-ui, server-components, client-dashboard, responsive]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- 01-01 (Next.js 16 bootstrap, Tailwind v4, shadcn/ui)
|
||||||
|
- 01-02 (schema DB: clients, phases, tasks, deliverables, payments, documents, notes)
|
||||||
|
- 01-03 (ClientView interface + getClientView(), route /c/[token] operativa)
|
||||||
|
provides:
|
||||||
|
- src/components/client-dashboard.tsx (layout wrapper completo)
|
||||||
|
- src/components/phase-timeline.tsx (timeline laterale con progress bar per fase)
|
||||||
|
- src/components/payment-status.tsx (stato pagamenti senza importi singoli)
|
||||||
|
- src/components/documents-section.tsx (link documenti esterni)
|
||||||
|
- src/components/notes-section.tsx (log decisioni read-only)
|
||||||
|
- src/app/globals.css (design token Tailwind v4 — palette light & clean)
|
||||||
|
- app/c/[token]/page.tsx (Server Component che renderizza ClientDashboard)
|
||||||
|
affects:
|
||||||
|
- 01-05-seed-deploy (la dashboard e' completa — il seed popola i dati, il deploy la espone)
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Tailwind v4: design token via @theme inline in globals.css (NON tailwind.config.ts)"
|
||||||
|
- "Colori arbitrari inline con sintassi [#hex] — compatibile Tailwind v4"
|
||||||
|
- "SVG inline al posto di lucide-react — compatibilita' massima con bundle size ridotto"
|
||||||
|
- "Server Components puri per tutti i componenti dashboard (nessun 'use client')"
|
||||||
|
- "React.cache() in page.tsx per deduplicare getClientView() tra generateMetadata e render"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- src/components/client-dashboard.tsx (99 righe — wrapper con header, progress, sezioni)
|
||||||
|
- src/components/phase-timeline.tsx (201 righe — timeline laterale con task e deliverable)
|
||||||
|
- src/components/payment-status.tsx (98 righe — totale + righe stato, zero importi singoli)
|
||||||
|
- src/components/documents-section.tsx (75 righe — link esterni sicuri)
|
||||||
|
- src/components/notes-section.tsx (68 righe — log decisioni read-only)
|
||||||
|
modified:
|
||||||
|
- src/app/globals.css (token Tailwind v4: primary, secondary, tertiary, bg-subtle, border-light, accent, success, warning, info)
|
||||||
|
- src/app/c/[token]/page.tsx (import ClientDashboard, generateMetadata dinamico, React.cache)
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Tailwind v4 usa @theme in globals.css — tailwind.config.ts non esiste in questo progetto"
|
||||||
|
- "SVG inline invece di lucide-react — evita dipendenza da icone e garantisce compatibilita'"
|
||||||
|
- "Colori arbitrari [#hex] in classi Tailwind invece di classi custom — piu' esplicito e manutenibile"
|
||||||
|
- "Server Components puri — nessun 'use client' necessario per componenti read-only"
|
||||||
|
- "React.cache() per deduplicare le due chiamate getClientView in generateMetadata + ClientPage"
|
||||||
|
|
||||||
|
duration: 45min
|
||||||
|
completed: 2026-05-14
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 1 Plan 04: Client Dashboard UI — Vertical Slice completo
|
||||||
|
|
||||||
|
**Tutti i componenti UI della dashboard cliente renderizzati come Server Components con design light & clean in Tailwind v4: header con logo iamcavalli + brand name cliente, progress bar globale, timeline laterale delle fasi con barre per fase e task list, sezione pagamenti con badge stato (zero importi singoli), link documenti esterni e log note read-only.**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** ~45 min
|
||||||
|
- **Started:** 2026-05-14T19:35:00Z
|
||||||
|
- **Completed:** 2026-05-14T20:20:00Z
|
||||||
|
- **Tasks:** 5/5
|
||||||
|
- **Files creati:** 5
|
||||||
|
- **Files modificati:** 2
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- **globals.css**: Token di design Tailwind v4 via `@theme inline` — palette light & clean con 9 variabili colore (primary, secondary, tertiary, bg-subtle, border-light, accent, success, warning, info). Adattamento critico: il progetto usa Tailwind v4 che non ha `tailwind.config.ts`.
|
||||||
|
|
||||||
|
- **app/c/[token]/page.tsx**: Server Component aggiornato con `ClientDashboard`, `generateMetadata` dinamico (titolo con brand_name), `React.cache()` per deduplicare le due chiamate a `getClientView`.
|
||||||
|
|
||||||
|
- **client-dashboard.tsx**: Layout wrapper completo. Header sticky con "iamcavalli" in angolo sinistro (xs, tracking-widest) e `brand_name` centrato e prominente (D-06). Progress bar globale con percentuale (D-09). Brief con accent bar sinistra. Sezioni ordinate: PhaseTimeline, PaymentStatus (sempre visibile — D-10), Documents e Notes (condizionali). Footer con avviso link privato.
|
||||||
|
|
||||||
|
- **phase-timeline.tsx**: Timeline laterale a due colonne (D-07). Colonna sinistra: cerchio con icona SVG per stato (checkmark verde per done, cerchio pieno blu per active, cerchio vuoto grigio per upcoming) + linea verticale tra fasi. Colonna destra: Card con badge stato, progress bar per fase con contatore "X di N task" (D-08), task list con icone stato e line-through per done. Deliverable annidati con badge "Approvato".
|
||||||
|
|
||||||
|
- **payment-status.tsx**: Card con `accepted_total` in EUR come unico importo visibile (vincolo LOCKED). Righe pagamento con dot colorato + badge stato semantico (blu=da_saldare, giallo=inviata, verde=saldato) — MAI importi singoli (T-04-001 mitigato, D-11 rispettato).
|
||||||
|
|
||||||
|
- **documents-section.tsx**: Link esterni con `target="_blank" rel="noopener noreferrer"` (T-04-002). Icone SVG inline per documento ed external link. Hover state con transizione colore accent.
|
||||||
|
|
||||||
|
- **notes-section.tsx**: Note read-only con timestamp in locale it-IT. Empty state informativo. Server Component puro (D-12: admin scrive in Phase 2, cliente legge).
|
||||||
|
|
||||||
|
- **npm run build**: completato senza errori TypeScript. 1 warning CSS da Lightning CSS optimizer (selettore con caratteri speciali) — noto, non bloccante, non dipendente dal nostro codice.
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
1. **Task 1: Design tokens + wire page.tsx** — `4e703d7`
|
||||||
|
2. **Task 2: ClientDashboard wrapper** — `debd391`
|
||||||
|
3. **Task 3: PhaseTimeline** — `5d5c8ea`
|
||||||
|
4. **Task 4: PaymentStatus** — `a4e2de0`
|
||||||
|
5. **Task 5: DocumentsSection + NotesSection** — `8602bfa`
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `src/app/globals.css` — @theme con 9 token colore light & clean
|
||||||
|
- `src/app/c/[token]/page.tsx` — ClientDashboard + generateMetadata + React.cache
|
||||||
|
- `src/components/client-dashboard.tsx` — layout wrapper completo
|
||||||
|
- `src/components/phase-timeline.tsx` — timeline laterale con progress per fase
|
||||||
|
- `src/components/payment-status.tsx` — totale accettato + badge stato (nessun importo)
|
||||||
|
- `src/components/documents-section.tsx` — link esterni sicuri
|
||||||
|
- `src/components/notes-section.tsx` — note read-only con timestamp italiano
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **Tailwind v4 senza tailwind.config.ts:** Il piano originale assumeva Tailwind v3 con `tailwind.config.ts`. Il progetto usa Tailwind v4 che gestisce i token via `@theme inline` in globals.css. Adattamento automatico.
|
||||||
|
- **SVG inline invece di lucide-react:** Lucide-react v1.14 ha alcune icone con nomi diversi. Usare SVG inline elimina la dipendenza ed e' compatibile con Server Components senza `'use client'`.
|
||||||
|
- **Server Components puri:** I componenti sono tutti read-only e non usano hooks React — nessun `'use client'` necessario, ottimizzazione del bundle.
|
||||||
|
- **Colori arbitrari [#hex]:** Usare classi come `text-[#1a1a1a]` invece di classi custom — piu' esplicito, nessun conflitto con shadcn/ui che usa le proprie variabili CSS (`bg-card`, `text-muted-foreground`, etc.).
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug] tailwind.config.ts non esiste — Tailwind v4 usa @theme in globals.css**
|
||||||
|
- **Found during:** Task 1
|
||||||
|
- **Issue:** Il piano indicava di aggiornare `tailwind.config.ts` con i color token. Questo file non esiste perche' il progetto usa Tailwind v4, che utilizza CSS `@theme inline` in `globals.css` invece del file di configurazione JavaScript.
|
||||||
|
- **Fix:** Token definiti in `globals.css` via `@theme inline { --color-primary: #1a1a1a; ... }`. Tailwind v4 mappa automaticamente queste variabili come classi utilitarie.
|
||||||
|
- **Files modified:** src/app/globals.css
|
||||||
|
- **Commit:** 4e703d7
|
||||||
|
|
||||||
|
**2. [Rule 1 - Bug] lucide-react usato come 'use client' — rimpiazzato con SVG inline**
|
||||||
|
- **Found during:** Task 2/3 (design)
|
||||||
|
- **Issue:** Il piano importava `CheckCircle2`, `Circle`, `Clock`, `ExternalLink` da `lucide-react`. I componenti sono Server Components puri — aggiungere `'use client'` solo per le icone avrebbe spostato tutto il rendering lato client inutilmente.
|
||||||
|
- **Fix:** SVG inline (Heroicons style) al posto di lucide-react per tutti i componenti. Mantiene i componenti come Server Components puri.
|
||||||
|
- **Files modified:** phase-timeline.tsx, payment-status.tsx, documents-section.tsx
|
||||||
|
- **Commit:** 5d5c8ea, a4e2de0, 8602bfa
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
Nessuno stub. Tutti i componenti ricevono dati reali dalla `ClientView` e li renderizzano completamente. Gli empty state (no documenti, no note) sono stati implementati come stati legittimi — non stub.
|
||||||
|
|
||||||
|
## Threat Surface Scan
|
||||||
|
|
||||||
|
| Flag | File | Description |
|
||||||
|
|------|------|-------------|
|
||||||
|
| Verificato T-04-001 | payment-status.tsx | `amount` assente dalla query e dal componente — solo `accepted_total` e `status` per riga |
|
||||||
|
| Verificato T-04-002 | documents-section.tsx | `rel="noopener noreferrer"` su tutti i link esterni |
|
||||||
|
|
||||||
|
Nessuna nuova superficie di sicurezza non prevista dal threat model 01-04.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- [x] `src/app/globals.css` esiste con @theme e token colore
|
||||||
|
- [x] `src/app/c/[token]/page.tsx` renderizza ClientDashboard con generateMetadata
|
||||||
|
- [x] `src/components/client-dashboard.tsx` esiste (99 righe)
|
||||||
|
- [x] `src/components/phase-timeline.tsx` esiste (201 righe)
|
||||||
|
- [x] `src/components/payment-status.tsx` esiste (98 righe) — nessun campo `amount`
|
||||||
|
- [x] `src/components/documents-section.tsx` esiste (75 righe)
|
||||||
|
- [x] `src/components/notes-section.tsx` esiste (68 righe)
|
||||||
|
- [x] Commit `4e703d7` esiste (Task 1)
|
||||||
|
- [x] Commit `debd391` esiste (Task 2)
|
||||||
|
- [x] Commit `5d5c8ea` esiste (Task 3)
|
||||||
|
- [x] Commit `a4e2de0` esiste (Task 4)
|
||||||
|
- [x] Commit `8602bfa` esiste (Task 5)
|
||||||
|
- [x] `npm run build` completato senza errori TypeScript
|
||||||
|
- [x] `payment-status.tsx` non contiene il campo `amount`
|
||||||
|
- [x] `documents-section.tsx` contiene `rel="noopener noreferrer"`
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Plan 05 (Seed script + DNS) puo' partire
|
||||||
|
- La dashboard e' pienamente funzionale: basta un cliente seedato per vederla operativa
|
||||||
|
- Il seed script deve inserire client, phases, tasks, deliverables, payments, documents, notes
|
||||||
|
- La route /c/[token] e' operativa dal Plan 03 — Plan 05 aggiunge il seed + configurazione DNS
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 01-foundation-client-dashboard*
|
||||||
|
*Completed: 2026-05-14*
|
||||||
Reference in New Issue
Block a user