Nuovo MessagesWidget nella colonna 1/3 della dashboard: riusa
getConversations() filtrando le conversazioni unread, mostra le prime 4
con anteprima e deep-link "Rispondi" a /admin/conversazioni?c=<clientId>.
Pill emerald "N Nuovi" + pallino pulsante, empty state quando non c'è nulla
in attesa. Stessa fonte di verità (clients.admin_last_read_at) del badge
sidebar. Aggiornato DESIGN-SYSTEM.md (inventory + note Conversazioni/dashboard)
e il mock design-reference/pagina-dashboard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nuova pagina admin /admin/conversazioni: vista WhatsApp-style (lista
conversazioni a sinistra, thread + risposta a destra) che aggrega i
messaggi di tutti i clienti dalla tabella comments, cross-cliente.
- Migration additiva 0014: clients.admin_last_read_at per tracciare
letto/non-letto (pallini + badge in sidebar). Applicata a prod.
- conversations-queries.ts: aggregazione entity_id → cliente
(general/phase/task/deliverable), getConversations /
getConversationThread / getUnreadConversationsCount.
- Risposte admin salvate come commento "general" (visibili anche nella
chat cliente e nel CommentsTab della scheda).
- Voce di menu + badge non-letti (AdminSidebar/AdminShell/layout).
- Token semantici per dual light/dark; refresh manuale (no polling).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Allinea la dashboard alla rifinitura del mock (finezza bordi/colori/badge):
- Card su border-border-light (slate-100) per il bordo sottile
- KPI: valore verde su Incassato Reale, delta verde "+N questo mese" su
Clienti Attivi (nuova metrica getDashboardStats.clientiNuoviMese)
- Redditività: badge "Ottimo" con tint emerald soft (non brand primary)
- Follow-up: righe come box bordati (no avatar), link "Apri →" primary
- Forecast: selettore anno (pill interattiva) spostato nell'header della card,
barre non-picco grigie (bg-border), rimosso il numero "mese prossimo"
- Offerte Più Richieste: rimossa la pill totale nell'header
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite /admin/pipeline/[id] LeadDetail with token-based dual-theme layout:
bespoke header with inline StatusBadge, asymmetric 1/3 profile + 2/3 content
columns, and a unified reverse-chronological timeline merging activities and
transcripts (transcript node highlighted + expandable + deletable).
Restyle modal triggers (Registra Attività, Aggiungi Transcript, Modifica-as-icon)
to the mock outline style. Remove the confusing "Invia Preventivo" button (it only
linked a token + advanced stage, no email). Keep Converti in cliente for won leads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel z-index raised to z-[60] so it sits above the sticky page header
(z-50) that was covering the close control. Replaced the header X with a
notebook-divider-style vertical "Chiudi" tab protruding from the left edge.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Sidebar: expanded 256->200px, collapsed 80->64px; collapsed state now
renders icon-only (label removed from flow) so icons are centered, not
pushed left by an invisible text span
- Kanban cards: add StatusBadge + email line to match design reference
- Lead table: add "Mostrando N lead" footer and center/right-align
Stato/Tag/Azioni headers per reference
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Design system foundations: Plus Jakarta Sans font, shadow-card/radius
tokens in @theme, design-reference/DESIGN-SYSTEM.md with component inventory
- Collapsible admin shell (AdminShell): smooth w-64<->w-20 sidebar, new top
header with "Admin" + avatar placeholder, localStorage-persisted state
- Rename route /admin/leads -> /admin/pipeline (redirect stubs preserved),
nav label Lead -> Pipeline; DB table unchanged
- Reusable primitives: StatusBadge, SearchInput, SegmentedToggle (dual-theme)
- Luxury restyle of lead table, kanban (6 stages + @dnd-kit intact), PageHeader
- Tokenize editable-cell / option-multi-select for dark-mode legibility
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- offer editor: per-tier name input (mirrors public_name/internal_name)
- offer list cards: show 3-tier services total + manual public price
- shared PageHeader component, full-width layout across all admin pages
- UI-RULES.md design conventions doc
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Client detail offers: show offer macro name ("Mantenimento") instead of tier letter
- Forecast: retainers project the monthly fee across every month from start_date
(no longer capped by duration_months); una_tantum unchanged
- Clients list LTV: per project max(accepted_total, sum of assigned offers) so a
retainer with unset quote still counts
- Dashboard: new "Offerte vendute" chart (count by offer + tier)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Client detail: category + tier badges on active offers
- Dashboard: remove top KPI cards + recent activity; fold current KPIs into
bottom MetricCard style; add 12-month income forecast chart
- Forecast query: branch by offer_type (retainer = monthly fee, una_tantum =
spread over duration), filter archived projects
- Payments: set the month a payment was collected (paid_at) from PaymentsTab
- Redesign FollowUpWidget in clean Pipedrive style (brand green, no orange)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a "Modello AI" toggle (Opus default, Sonnet option) styled like the
existing Soggetto toggle. The server action validates the keyword and maps
it to the real model id; the agent receives the resolved id and uses it in
the Anthropic messages.create call. The proposals DB record stores the
actual model used.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- client-view.ts: read cumulative_price + services list from offer_tier_services→services
(Phase 12 catalog); legacy fallback to offer_micro_services→offer_services when no
new-style rows exist. Extend activeOffers type with services[] in both ProjectView and ClientView.
- OffersSection.tsx: extract OfferCard client component with useState accordion;
hide "Valore incluso" row when price is 0; add "Cosa è compreso" chevron toggle
listing included services (name + description when present).
- client-dashboard.tsx: hide progress bar and PhaseViewToggle when hasRetainer;
render polished empty-state placeholder with RefreshCw icon instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. AdminSidebar: removed yellow "Genera preventivo" CTA (duplicated Preventivi tab nav item)
2. Delete phase/task: new deletePhase/deleteTask server actions with FK cascade and phase-status recompute; DeletePhaseTaskButton client component with window.confirm; trash icons in PhasesTab per phase and per task
3. Public dashboard: extend activeOffers query with offer_macros join (offer_name, offer_type); reorder sidebar 1°Offerte 2°Pagamenti 3°Documenti; OffersSection shows macro public_name as heading (never tier letter/internal_name); PaymentStatus gains totalLabel/overrideAmount/hideRows props — retainer=monthly label + no Acconto/Saldo rows
4. Offer editor: Descrizione textarea (nota interna) and Modalità toggle moved directly under title; Tags section now contains only Categoria/Ticket/Tipo/Obiettivo
5. Basecamp chat: API route supports entity_type="phase" with authorization scoping; comments scope in client-view broadened to include phaseIds and client_id (general); CommentsTab updated with phase/general entities; ChatProvider React context; ChatPanel fixed slide-in panel with FAB (bottom-right) and composer tag selector (Generale + phases); PhaseCard gets chat-bubble icon pre-tagging that phase; inline ChatSection block removed from dashboard main column
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Pagamenti: totale ereditato dalla somma accepted_total delle offerte
attive (con override) + selettore schema rate 1/2/3 step; nuova colonna
payments.percent per rescalare gli importi preservando label/stato
- Fasi & Task: recomputePhaseStatus auto-cascade (task -> fase) su
updateTaskStatus/addTask, fix UI stale, etichette Da iniziare/In corso/Completata
- Pagina pubblica: colori fasi (grigio/blu/#1A463C) + fasi collassabili
- Transcript del cliente visibili in tab Documenti admin e dashboard pubblica
- Timer: inserimento manuale (+30/+60, minuti liberi, data) + elimina entry
- CLAUDE.md: procedura Deploy & DB Access; push su main automatico
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blocco A+B (milestone v2.3). Migration 0011 is additive (ADD COLUMN only):
clients.email, clients.phone, leads.archived.
- createClientCore() extracted from createClient and reused by conversion
- clients.email/phone added to create + edit forms and shown on client header
(never exposed on the public /client/[token] page)
- convertLeadToClient(): reuses core, carries over lead transcripts
(client_transcripts.client_id), links project.created_from_lead_id,
archives the lead while keeping its "won" status; idempotent
- "Converti in cliente" button on won leads; "Convertito → Apri cliente"
once converted (clientId resolved via created_from_lead_id)
- archived leads hidden from list/kanban; detail page fetches by id incl. archived
Migration must be applied to the prod DB BEFORE this is deployed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- PoolManager: defined field cells with value count, refined chips,
inline ghost + button, focus ring, pending/empty states
- TaxonomyManager: icon-badged section headers, ordered 2-col grid,
sync explainer note
- Settings page: wider container (max-w-4xl) for the grid to breathe
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Single persistent option pool per taxonomy (7 fields: offer
categoria/ticket/tipo/obiettivo + catalog fase/offerta/pacchetto),
stored as JSON in the settings table (no DB migration).
- src/lib/taxonomy.ts: pools with lazy seed from in-use values,
add/remove(cascade)/rename helpers
- Inline creation anywhere registers into the pool (save offer,
addServiceOption, updateServiceField fase, quickAdd, create macro)
- Deselecting on a row never touches the pool; global delete only
from settings (cascade-strips tags / nulls columns)
- getOfferFieldOptions + getCatalogFieldOptions read from pools
- Settings: TaxonomyManager (offer + catalog groups), confirm on delete
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ProposalDeck: outer div h-screen overflow-hidden, content wrapper h-full
- Rimosso il div interno ridondante min-h-screen
- useEffect blocca body overflow mentre la deck è aperta
- Tutti i 20 componenti slide: min-h-screen → h-full
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DDL for client_transcripts table: id (nanoid PK), lead_id/client_id
(nullable FKs with ON DELETE CASCADE), title, content (NOT NULL),
call_date (date NOT NULL), created_at (timestamptz). Three indexes on
lead_id, client_id, call_date DESC. APPLY TO PROD via SSH before
pushing schema-dependent code (Plan 20-02/20-03).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LeadsViewToggle: client wrapper with useState<list|kanban>, useMemo filtered
- Search input (left) + pill toggle Lista/Kanban (right) on single row
- Filters leads by name/email/company/status/tags across both views
- Search state preserved when switching between Lista and Kanban
- LeadsSearch.tsx: replaced with re-export of LeadsViewToggle (backward compat)