# Phase 4: Progetti — Multi-Project per Cliente - Context

**Gathered:** 2026-05-20
**Status:** Ready for planning

<domain>
## 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.

</domain>

<decisions>
## 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.

</decisions>

<canonical_refs>
## 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.

</canonical_refs>

<code_context>
## 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.

</code_context>

<specifics>
## 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.

</specifics>

<deferred>
## 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.

</deferred>

---

*Phase: 4 — Progetti Multi-Project*
*Context gathered: 2026-05-20*
