# Phase 4: Progetti — Multi-Project per Cliente - Context **Gathered:** 2026-05-20 **Status:** Ready for planning ## Phase Boundary Ristrutturazione del modello dati per supportare N progetti per cliente. Un cliente può avere più brand/progetti; ogni progetto ha il proprio workspace (fasi, task, pagamenti, preventivo, timer). Il timer si sposta dal livello cliente al livello progetto. La dashboard cliente mostra i suoi progetti con tabs se multipli. Il link cliente diventa personalizzabile tramite slug opzionale. **Sostituisce la Fase 4 AI Onboarding** (spostata a Fase 5) perché è prerequisito architetturale per tutto ciò che viene dopo. Tutti i dati attuali sono di test — nessuna migrazione soft necessaria. Schema ricreato da zero dove serve. ## Implementation Decisions ### Modello dati - **D-01:** Nuova tabella `projects` con campi: `id`, `client_id` (FK → clients), `name` (nome brand/progetto), `archived` (bool), `created_at`. Nessun `accepted_total` diretto — viene calcolato/denormalizzato dai quote_items a livello progetto. - **D-02:** Le seguenti tabelle spostano la FK da `client_id` a `project_id`: `phases`, `payments`, `quote_items`, `time_entries`, `documents`, `notes`. La tabella `comments` rimane su `entity_id` generico — invariata. - **D-03:** `clients` perde i campi che diventano di pertinenza del progetto: `accepted_total` si sposta su `projects`. Il cliente mantiene: `id`, `name`, `brand_name` (riutilizzato come nome display), `token`, `slug` (nuovo), `archived`, `created_at`. - **D-04:** Campo `slug` aggiunto a `clients` — testo opzionale, univoco, URL-safe (es. `mario-rossi`). Se assente, il link usa il token random come prima. URL: `/c/[slug-o-token]`. - **D-05:** `projects.accepted_total` (text, nullable) — denormalizzato come ora su clients, ma al livello progetto. L'admin lo imposta manualmente nel tab Preventivo del progetto. ### Link e accesso cliente - **D-06:** Il token rimane su `clients` per l'autenticazione middleware — non è il campo slug. Il middleware controlla prima lo slug (lookup DB), poi il token (come ora). Entrambi portano alla dashboard del cliente. - **D-07:** Lo slug si imposta nella pagina `/admin/clients/[id]/edit` — campo opzionale con preview del link risultante. - **D-08:** La route `/c/[token-or-slug]` rimane invariata nel path — il middleware risolve entrambi. ### Dashboard cliente (frontend) - **D-09:** Se il cliente ha 1 progetto → la dashboard mostra direttamente quel progetto (nessun selettore). - **D-10:** Se il cliente ha 2+ progetti → tabs in cima con i nomi dei brand (es. "Brand Blu | Brand Verde"). Le tab usano il componente Tabs di shadcn/ui già presente. - **D-11:** La struttura della dashboard cliente cambia: la vista di un singolo progetto mostra le stesse sezioni di oggi (stato fasi/task, pagamenti, approvazioni deliverable, commenti) ma scoped al progetto. ### Admin — vista Clienti - **D-12:** La lista `/admin/clients` mostra ogni cliente con i nomi dei brand sotto il nome (es. "Mario Rossi" + riga sottile "Brand Blu | Brand Verde"). Life Time Value = somma degli `accepted_total` di tutti i progetti del cliente. - **D-13:** Cliccando un cliente si apre `/admin/clients/[id]` che mostra la lista progetti di quel cliente (cards o righe), non più il workspace direttamente. ### Admin — vista Progetti - **D-14:** Nuova pagina `/admin/projects` (link nel NavBar) — lista di tutti i progetti con colonne: Nome progetto, Cliente genitore, Valore progetto (accepted_total), Acconto (stato), Saldo (stato), Timer (play/stop), €/h calcolato. - **D-15:** Il timer nella lista Progetti mostra il bottone play/stop per il progetto corrente. Solo un timer attivo alla volta (come ora, ma scoped al progetto). - **D-16:** Cliccando un progetto si apre `/admin/projects/[id]` — workspace identico all'attuale `/admin/clients/[id]` ma al livello progetto: tabs Panoramica, Fasi, Documenti, Pagamenti, Note, Preventivo, Timer, Commenti. ### Creazione progetto (admin) - **D-17:** Progetto creabile da due punti: (1) dal dettaglio cliente `/admin/clients/[id]` con un bottone "+ Nuovo Progetto", (2) dalla lista `/admin/projects` con "+ Nuovo Progetto" che chiede prima il cliente. - **D-18:** Form di creazione progetto: Nome progetto (brand name) + selezione cliente (se creato dalla lista globale). Nessun campo aggiuntivo al momento della creazione — tutto il resto si configura nel workspace del progetto. ### Timer e analytics profittabilità - **D-19:** `time_entries.client_id` diventa `time_entries.project_id`. Il timer gira per progetto. - **D-20:** Analytics profittabilità nel tab Timer di ogni progetto — card con: ore totali, accepted_total, €/h reale (accepted_total ÷ ore), target_rate × ore (costo ideale), delta (guadagno/perdita vs target). - **D-21:** `target_hourly_rate` è un valore globale impostato dall'admin — stored in una tabella `settings` (key-value) o direttamente come env var configurabile. Impostabile da una nuova sezione "Impostazioni" nel NavBar admin. - **D-22:** La Statistiche page mostra la profittabilità aggregata per tutti i progetti + breakdown per cliente. ### Claude's Discretion - Struttura esatta della tabella `settings` (key-value o colonne specifiche) — scegliere l'approccio più semplice (probabile: tabella `settings` con `key text PK, value text`). - Ordine delle tabs nel dettaglio progetto — seguire l'ordine attuale del dettaglio cliente. - Stile delle cards progetto nel dettaglio cliente — seguire i pattern UI esistenti. ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Schema attuale (punto di partenza) - `src/db/schema.ts` — schema completo con tutte le tabelle e relazioni. Le FK da migrare: phases.client_id → project_id, payments.client_id → project_id, quote_items.client_id → project_id, time_entries.client_id → project_id, documents.client_id → project_id, notes.client_id → project_id. ### Architettura constraints (LOCKED) - `CLAUDE.md` §Architecture Constraints — specialmente: token rotatable (mai PK), quote_items mai esposti via client API, deliverables.approved_at immutable. Questi vincoli si applicano anche al livello progetto. ### Patterns UI esistenti da replicare - `src/components/admin/tabs/` — pattern tab workspace esistente (QuoteTab, ecc.) da replicare per il dettaglio progetto. - `src/components/admin/TimerCell.tsx` — timer da adattare da client_id a project_id. - `src/components/admin/ClientRow.tsx` — pattern riga lista da replicare per ProjectRow. - `src/app/admin/clients/[id]/page.tsx` — layout tabs workspace da replicare per /admin/projects/[id]. ### Dashboard cliente - `src/lib/client-view.ts` — la query che alimenta la dashboard cliente. Va riscritta per supportare progetto singolo e multi-progetto. - `src/app/c/[token]/page.tsx` — dashboard cliente da ristrutturare per mostrare tabs progetto. ### Phase 3 artifacts (prerequisito) - `.planning/phases/03-service-catalog-quote-builder/03-CONTEXT.md` — decisioni sul preventivo e catalogo (quote_items → project_id in questa fase). - `.planning/phases/03-service-catalog-quote-builder/03-03-SUMMARY.md` — implementazione QuoteTab. ## Existing Code Insights ### Reusable Assets - `src/components/ui/tabs.tsx` — Tabs shadcn già presente, usato in dettaglio cliente. Riutilizzare per il selettore progetto nella dashboard cliente e per il workspace progetto admin. - `src/components/admin/TimerCell.tsx` — implementazione timer completa, da adattare con project_id invece di client_id. - `src/components/admin/tabs/QuoteTab.tsx` — quote builder completo, da ri-wiring con project_id. - `src/lib/admin-queries.ts` — `getClientFullDetail` è il template per `getProjectFullDetail`. - `src/app/admin/clients/[id]/page.tsx` — layout workspace admin con tabs, da clonare per /admin/projects/[id]. ### Established Patterns - Server Actions con `requireAdmin()` per tutte le operazioni admin-only. - Query pattern: un'unica funzione `getXFullDetail` che recupera tutto in parallelo per ridurre round-trip. - `drizzle-kit push` per applicare le modifiche schema al DB Neon live. - Token middleware in `src/proxy.ts` — da estendere per slug lookup. ### Integration Points - Il middleware `src/proxy.ts` deve risolvere `/c/[slug-o-token]` → lookup slug prima, poi token. - `src/lib/client-view.ts` va riscritta completamente per il modello multi-progetto. - `src/components/admin/NavBar.tsx` — aggiungere link "Progetti" e "Impostazioni". - `getAllClientsWithPayments` in admin-queries.ts va riscritta per includere i progetti annidati. ## Specific Ideas - **Screenshot di riferimento (utente):** Lista Clienti mostra "Mario Rossi" in bold con "Brand Blu | Brand Verde" come testo secondario sotto, Life Time Value come somma, link /c/slug. - **Screenshot di riferimento (utente):** Lista Progetti mostra "Brand Blu" in bold con "Mario Rossi" come testo secondario, colonne Valore, Acconto, Saldo, Timer (play icon), €/h calcolato. - **Analytics formula (utente):** accepted_total ÷ ore_lavorate = €/h reale. target_rate × ore = costo ideale. Delta = accepted - costo_ideale. Mostra se si guadagna, perde, o break-even. - **Target rate:** valore globale (es. 50€/h) che l'admin imposta una volta. Non per progetto. - **Link cliente:** preferibilmente con nome cliente (es. /c/mario-rossi). Customizzabile dall'admin. Fallback al token se non impostato. ## Deferred Ideas - **Fatturazione per progetto** — calcolo automatico fatture basato su pagamenti. Fuori scope (out of scope globale del progetto). - **Export PDF preventivo per progetto** — utile ma separato. Fase futura. - **AI Onboarding (ex Fase 4)** — spostato a Fase 5. Richiede questa ristrutturazione come prerequisito. - **Notifiche email al cliente** — quando le fasi cambiano stato. Fase futura. --- *Phase: 4 — Progetti Multi-Project* *Context gathered: 2026-05-20*