Commit Graph

6 Commits

Author SHA1 Message Date
Simone Cavalli 9ddb69929a feat(03-01): make quote_items.service_id nullable and add custom_label column
- Remove .notNull() from service_id to allow free-form items without catalog ref
- Add custom_label: text("custom_label") for free-form item label storage
- TypeScript compiles with zero errors (QuoteItem.service_id now string | null)
2026-05-17 11:36:43 +02:00
Simone Cavalli 0f48570cd7 feat: client edit/delete/archive + time tracker + analytics time section
Schema:
- clients.archived boolean (default false)
- time_entries table (client_id, started_at, ended_at, duration_seconds)

Client management:
- /admin/clients/[id]/edit — form pre-compilato con nome, brand, brief
- ClientActions: Modifica / Archivia / Elimina con doppia conferma
- setClientArchived: toggle archiviazione senza perdere dati
- deleteClient: elimina con cascade, redirect a /admin
- Admin list: toggle "Mostra archiviati" via ?archived=1, righe archiviate opache

Time tracker:
- startTimer: crea sessione, ferma automaticamente quella precedente
- stopTimer: chiude sessione, calcola duration_seconds
- TimerCell: ▶/⏹ per ogni cliente, contatore live in secondi, totale cumulativo
- Una sola sessione attiva alla volta su tutta la lista

Analytics:
- Sezione "Fatturato" (invariata) + sezione "Tempo tracciato" separata
- Ore totali per anno + barre orizzontali per cliente
- getTotalTrackedHours, getTimeByClient queries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 21:28:01 +02:00
Simone Cavalli abcbb5224e feat(01-02): [BLOCKING] drizzle-kit push — schema live on Postgres
- 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
2026-05-13 22:47:51 +02:00
Simone Cavalli a6ec599188 chore(01-02): generate Drizzle migration from schema (0000_pretty_typhoid_mary.sql)
- 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)
2026-05-13 22:46:54 +02:00
Simone Cavalli 1bdbe7ab5d feat(01-02): create complete Drizzle schema with all 10 tables
- 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)
2026-05-13 22:46:30 +02:00
Simone Cavalli 6b5609b0cb feat(01-01): install Drizzle ORM, postgres-js, and configure DB client
- drizzle-orm@0.45.2 + postgres@3.4.9 installed (postgres-js driver)
- drizzle-kit@0.31.10 installed as dev dependency
- nanoid@5, zod@4, react-hook-form, @hookform/resolvers installed
- src/db/index.ts: Drizzle client initialized with postgres-js driver
- drizzle.config.ts: configured for postgresql dialect + src/db/schema.ts
- .env.example: added as public template (no secrets)
- .gitignore: allow .env.example while blocking all other .env* files
2026-05-13 15:30:53 +02:00