- Create /admin/clients/[id]/page.tsx — Server Component using Radix Tabs (Fasi & Task, Pagamenti, Documenti, Commenti)
- Create PhasesTab: phases list with add-phase form, task lists with add-task form, status selects for phases and tasks
- Create PaymentsTab: accepted_total editor (splits to 50% on each payment), payment status selects with paid_at on saldato
- Create DocumentsTab: add document (label + URL) form, document list with delete action
- Create CommentsTab: chronological comment display (admin vs cliente style), admin reply form with entity selector
- All mutations via inline Server Action closures bound to action= props; revalidatePath ensures fresh data
- /admin page: Server Component fetching all clients with payment badges
- ClientRow component with Acconto/Saldo status badges and secret link
- /admin/clients/new: form wired to createClient Server Action
- createClient action: Zod validation, inserts client + 2 payment stubs (Acconto 50%, Saldo 50%)
- Token auto-generated server-side via nanoid $defaultFn
- Redirects to /admin/clients/[id] after creation; revalidates /admin
- src/lib/admin-queries.ts: getAllClientsWithPayments() and getClientById() for admin DB reads
- src/components/admin/NavBar.tsx: minimal nav with Clienti link and Esci (logout) button
- src/app/admin/layout.tsx: wraps all /admin/* pages with NavBar + centered main content area
- scripts/seed.ts: inserts one complete test client with 3 phases,
6 tasks, 4 deliverables, 2 payments, 2 documents, 2 notes; prints
shareable URL to console
- globals.css: add @source not directives to exclude .01_projects/
and .claude/ — Tailwind v4 was scanning the SparklingOrbit .venv
Python files and generating invalid CSS class [-:|] from a regex
pattern in a markdown-it table parser, causing dev server 500s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DocumentsSection: link clickabili con target="_blank" rel="noopener noreferrer"
icone SVG inline per documento ed external link, hover state con colore accent
- NotesSection: note read-only con timestamp in locale it-IT (D-12: cliente legge, admin scrive)
empty state informativo per entrambi i componenti
- SVG inline al posto di lucide-react per compatibilita' massima
- Mostra accepted_total formattato in EUR (unico importo permesso — LOCKED)
- Righe pagamento: solo label + badge stato (da_saldare/inviata/saldato)
- Nessun importo singolo visibile al cliente (T-04-001 mitigato)
- Dot colorato + badge per ogni riga: blu=da_saldare, giallo=inviata, verde=saldato
- Layout a due colonne: indicatore cerchio (sinistra) + card fase (destra)
- Icone SVG inline per stato fase (done/active/upcoming) e task (done/in_progress/todo)
- Badge stato fase con colori semantici (verde/blu/grigio)
- Progress bar per fase con contatore task done/totale
- Task list con line-through per done, testo grigio chiaro
- Deliverable annidati sotto ogni task con badge "Approvato" se approved
- Linea verticale tra fasi (non sull'ultima)
- 01-03-SUMMARY.md: 3/3 tasks complete, npm run build passes
- Edge proxy pattern (proxy.ts), validate-token API route, ClientView type system
- /c/[token] Server Component operational, ready for Plan 04 dashboard UI
- Connected to postgresql://178.104.27.55:5432/clienthub
- 10 tables created: clients, phases, tasks, deliverables, comments,
payments, documents, notes, service_catalog, quote_items
- UNIQUE constraint on clients.token active at DB level
- All FK constraints and CASCADE rules applied
- Verified via information_schema.tables query
- 10 tables: clients, phases, tasks, deliverables, comments, payments,
documents, notes, service_catalog, quote_items
- UNIQUE constraint on clients.token enforced at DB level
- All FK cascades correct (deliverables->tasks->phases->clients)
- approved_at: timestamp with time zone (nullable, immutable)
- drizzle.config.ts already correct from Plan 01 (no changes needed)
- clients: token as separate text field (notNull, unique, nanoid) — never PK
- accepted_total denormalized on clients — client API never touches quote_items
- deliverables.approved_at immutable timestamp (TIMESTAMPTZ) — audit trail
- payments: label (Acconto 50% / Saldo 50%), status (da_saldare/inviata/saldato)
- comments: polymorphic entity_type+entity_id pattern
- service_catalog + quote_items: admin-only, never exposed to client API
- Full relations defined for all FK chains
- TypeScript types exported: Client, Phase, Task, Deliverable, etc.
- ID strategy: text + nanoid() via $defaultFn (cryptographically secure, URL-safe)