- Archive v2.0 phases (07-10) under .planning/milestones/ - v2.1 REQUIREMENTS/ROADMAP (Phases 11-17: Offer Studio + Proposal AI) - DESIGN-SYSTEM.md (database-view UI contract for Phases 11-14) - Phase 11 CONTEXT, DISCUSSION-LOG, PATTERNS Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.7 KiB
Phase 11: Catalog Database-View UX & Legacy Consolidation - Context
Gathered: 2026-06-13 Status: Ready for planning
## Phase BoundaryTrasformare /admin/catalog (tabella services) in una vista database stile Notion/Airtable — inline edit su ogni cella, tag multi-select con creazione al volo, quick-add row, filtro/ricerca istantanei (client-side) — e consolidare i dati storici di service_catalog e offer_services/offer_micro_services dentro services in modo additivo, senza perdita (verificabile via conteggio righe).
Esplicitamente FUORI scope per Phase 11 (deferiti a fasi successive, vedi <deferred>):
- Rewiring di
/admin/offerseOffersSection(dashboard cliente) per leggere daservices— Phase 12 - Composizione drag&drop offerte e import CSV — Phase 12
- Riuso del sistema tag per i lead — Phase 14 (schema pronto ora, UI lead dopo)
Consolidamento Legacy (service_catalog, offer_services)
- D-01: Migrazione additiva (pattern Phase 7): copia le righe di
service_catalogeoffer_servicesdentroservices, popolandomigrated_from/migrated_idper audit trail. Zero behavior change a/admin/offerseOffersSection— quelle UI restano sulle tabelle legacy (offer_services/offer_micro_services), che NON vengono toccate/droppate. - D-02: Le righe migrate da
offer_servicesricevono automaticamente il tag "Offerta" (tag normale, vedi D-08) per distinguerle nella tabella unificata dai servizi a costo interno. - D-03:
/admin/offersresta status quo — continua a creare nuove voci inoffer_services/offer_micro_servicescome oggi. Il rewiring per leggere/scrivere daservicesè Phase 12 (già dipende da "catalogo unificato e tabellare"). - D-04: Verifica "senza perdita" (OFFER-13, conteggio righe) tramite script/log one-shot durante la migrazione (come Phase 7) — nessun indicatore permanente in
/admin/catalog.
Sistema Tag
- D-05: Nuova tabella
tags+ junction polimorfica (entity_type+entity_id, pattern simile acommentsinsrc/db/schema.ts) — costruita ora per essere riusata da Phase 14 (CRM-09, tag sui lead) senza rifare lo schema. - D-06: Pool di tag scoped per
entity_type— i tag del catalogo (services) e i tag dei lead (futuro) sono pool separati, anche se condividono la tabellatags. Il dropdown "+" per creare/assegnare un tag mostra solo i tag dell'entity_type corrente. - D-07: Colore badge derivato deterministicamente dal nome del tag (hash → palette fissa 6-8 colori pastello, da
.planning/DESIGN-SYSTEM.md) — nessuna colonnacolorintags. - D-08: Il tag "Offerta" (D-02) è un tag normale del pool
services— rinominabile/eliminabile dall'utente come ogni altro tag, nessuna logica di protezione/system-tag.
Campo category
- D-09:
services.category(testo libero, esistente) resta un campo separato, accanto ai tag multi-select — due dimensioni di classificazione indipendenti (categoria primaria + tag flessibili). NON viene migrato/fuso nei tag. - D-10: Servizi senza
categoryrestano senza tag corrispondente — nessun tag di default ("Senza categoria"/"Generale") viene creato.
Tabella database-view — colonne e comportamenti
- D-11: "Descrizione" resta una colonna piena della tabella — testo troncato con ellipsis, click-to-edit inline (textarea espansa al click), stesso pattern
EditableCelldelle altre colonne. Non esce dalla riga principale. - D-12: Quick-add row (OFFER-09, "nome + invio"): scrivere solo il nome e premere invio crea il servizio con
unit_price = 0. La riga diventa immediatamente una riga normale ed editabile — il prezzo (mostrato "€0,00") si corregge inline subito dopo, click sulla cella prezzo. - D-13: Servizi disattivati (
active=false): restano visibili, attenuati (opacità ridotta, comportamento attuale diServiceTable.tsx), ma ordinati in fondo alla tabella sotto una riga divisoria che li separa visivamente dai servizi attivi. - D-14: Nessuna colonna "azioni" per riga. Lo stato attivo/disattivo diventa una cella inline (toggle/checkbox cliccabile, stesso pattern EditableCell). Tutte le modifiche avvengono via click-to-edit sulle celle — stile Notion/Airtable puro, zero bottoni per riga.
Claude's Discretion
- Implementazione esatta dei componenti
EditableCelleTagMultiSelect(entrambi previsti in.planning/DESIGN-SYSTEM.md, non ancora costruiti —command/popovershadcn da valutare). - Mapping esatto dei campi nella migrazione
offer_services→services(es.price→unit_price,transformation_description→description). - Verifica del JOIN
quote_items↔service_cataloginsrc/lib/admin-queries.ts(righe 335/343, 531/539) — oggi l'unico consumer rimasto diservice_catalog, possibile disallineamento conquote_items.service_id(che secondoschema.tsreferenziaservices.id, nonservice_catalog.id). Il researcher deve verificare se il join è ancora funzionante; se rotto, trattarlo come bugfix separato e a basso rischio, non bloccante per i success criteria di Phase 11. - Palette colori esatta per i badge tag (6-8 pastello, da DESIGN-SYSTEM.md) e algoritmo hash nome→colore.
- Posizionamento/stile esatto della riga divisoria "inattivi" (D-13).
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Requisiti e roadmap
.planning/REQUIREMENTS.md— sezione "Offer Studio — Catalogo & Offerte (v1)": OFFER-07, OFFER-08, OFFER-09, OFFER-10, OFFER-13 sono i requisiti di questa fase.planning/ROADMAP.md— sezione "Phase 11: Catalog Database-View UX & Legacy Consolidation" per goal e success criteria
Design contract (UI)
.planning/DESIGN-SYSTEM.md— vincolante: direzione ClickUp/Pipedrive flat, token brand invariati (#1A463C/#DEF168/#e5e7eb/etc.), pattern tabella (riga ~40px, inline edit conring-1 ring-primary, badge tag a rotazione colori, quick-add row, header sticky), componenti da costruire (EditableCell,TagMultiSelect), checklist pre-delivery (contrasto, focus ring, transizioni 150-250ms, responsive)
Decisioni di progetto
.planning/PROJECT.md— sezione "Key Decisions": ordine Offer Studio→Proposal AI, "Catalogo/Offerte UX = database view custom (non Notion-clone)", catalogo unificatoservicesda Phase 7
No external specs beyond questi — requisiti/decisioni catturati sopra.
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
src/components/ui/badge.tsx,select.tsx,input.tsx,table.tsx— base per costruireEditableCelleTagMultiSelect(DESIGN-SYSTEM.md)src/lib/admin-queries.ts→getAllServices()— query layer esistente suservices, da estendere con join sulla nuova tabellatagssrc/db/schema.ts→commentstable (polimorficoentity_type/entity_id) — precedente diretto per la junctiontags(D-05)src/db/schema.ts→services.migrated_from/migrated_id(Phase 7) — pattern di audit trail da riusare per la migrazioneservice_catalog/offer_services→services
Established Patterns
src/app/admin/catalog/actions.ts(createService/updateService/toggleServiceActive) — patternrequireAdmin()+ validazione zod +revalidatePath("/admin/catalog"), da estendere per inline edit (probabilmente una action per campo o un'action genericaupdateServiceField)- Migrations manuali via SSH+docker exec, applicate a prod PRIMA del push del codice dipendente (vedi
.planning/HANDOFF.md)
Integration Points
src/app/admin/catalog/page.tsx→ServiceTable/ServiceForm(src/components/admin/catalog/) — punto di sostituzione principale per la nuova tabella database-viewoffer_phase_services(Phase 8, già esistente) collegaoffer_phases↔services— riferimento utile per Phase 12 quando comporrà offerte direttamente daservicessrc/lib/admin-queries.tsrighe ~250-345 e ~520-545 — JOIN legacy suservice_catalogper labelquote_items(vedi Claude's Discretion)
Tabelle legacy coinvolte (stato attuale)
service_catalog(src/db/schema.ts:170) — solo consumer rimasto: JOIN per labelquote_itemslegacy inadmin-queries.tsoffer_services+offer_micro_services(src/db/schema.ts:259-283) — ATTIVI: usati da/admin/offers(src/app/admin/offers/,src/lib/offer-queries.ts) e daOffersSectionlato cliente (src/lib/client-view.ts, cumulative_price)
</code_context>
## Specific Ideas- "compartimenti stagni" + Data Safety LOCKED (CLAUDE.md) → ogni migrazione di questa fase è additiva, nessun drop/truncate di
service_catalog,offer_services,offer_micro_services - DESIGN-SYSTEM.md è stato prodotto appositamente per questa fase (e per 12-14) via skill
ui-ux-pro-max— è il contratto visivo, non solo un suggerimento
- Rewiring completo di
/admin/offers+OffersSectionper leggere/scrivere daservices(invece dioffer_services/offer_micro_services) → Phase 12 (Offer Composition Drag&Drop & CSV Import), che già dipende dal "catalogo unificato e tabellare" prodotto da questa fase - Riuso della tabella
tags/junction polimorfica per i lead (CRM-09) → Phase 14 (CRM Attio-style & Fix) — schema già pronto (D-05/D-06), serve solo la UI lato lead - Fix del JOIN
quote_items↔service_catalogse il researcher lo trova rotto → bugfix separato, non parte dei success criteria di Phase 11
None — discussion stayed within phase scope (oltre ai punti sopra, già tracciati per fasi specifiche).
Phase: 11-catalog-database-view-ux-legacy-consolidation Context gathered: 2026-06-13