Files
clienthub/.planning/phases/20-knowledge-base-cliente/20-CONTEXT.md
T
2026-06-19 18:26:02 +02:00

7.0 KiB

Phase 20: Knowledge Base Cliente — Context

Gathered: 2026-06-19 Status: Ready for planning

## Phase Boundary

Aggiungere uno store di transcript datati per lead: l'admin incolla il testo grezzo di ogni call con data e titolo libero, la lista appare in ordine cronologico nel dettaglio lead, e i dati sono pronti per essere letti dall'agente AI in Phase 21.

In scope: schema client_transcripts + server actions + UI nel LeadDetail Out of scope: UI per clienti (client_id FK presente ma non esposta), ricerca full-text sui transcript, trascrizione automatica da audio

## Implementation Decisions

Schema — client_transcripts

  • D-01: La tabella client_transcripts ha entrambe le FK nullable: lead_id (references leads, onDelete cascade) e client_id (references clients, onDelete cascade). Ragionamento: prepara la struttura per transcript post-conversione senza richiedere una migration futura.
  • D-02: Campi: id (nanoid PK), lead_id (nullable FK), client_id (nullable FK), title (text, optional — titolo libero es. "Discovery call 12 giugno"), content (text NOT NULL — testo incollato, lunghezza illimitata), call_date (date NOT NULL — giorno della call, non timestamp), created_at (timestamp with timezone, defaultNow).
  • D-03: Migration mano-scritta come 0009 — drizzle-kit generate è rotto. Applicata a prod via SSH prima di pushare il codice dipendente (invariante bloccante del progetto).

UI — Solo lato lead in Phase 20

  • D-04: In Phase 20 la UI espone solo il lato lead. La FK client_id è nello schema ma non ha form o lista in questa fase — si aggiunge in futuro se serve la pagina /admin/clients/[id].
  • D-05: I transcript sono listati in ordine call_date DESC nel dettaglio lead (chiamata più recente in cima).

Claude's Discretion

Le seguenti aree non sono state discusse — Claude ha flessibilità:

  • Metadati: No tipo enum — title libero (optional) è sufficiente. Il testo del transcript parla da solo.
  • Placement UI: Nuova sezione "Transcript" collassabile in LeadDetail, dopo la sezione Attività esistente. Stessa convenzione visiva (Card + lista). Form/modal per aggiungere seguendo il pattern LogActivityModal.
  • Nessun limite di lunghezza: content è text PostgreSQL (illimitato). Textarea nel form senza troncatura.

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Requirements & Roadmap

  • .planning/ROADMAP.md — Phase 20 goal, success criteria, schema spec (client_transcripts con lead_id/client_id, testo, data, titolo/tipo, created_at)
  • .planning/REQUIREMENTS.md — KB-01 (schema additivo transcript), KB-02 (UI incolla/elenca)

Schema & Migrations

  • src/db/schema.ts — pattern tabelle append-only CRM: activities (lead_id, type, notes, activity_date), reminders (lead_id, due_date). La nuova client_transcripts segue questo pattern.
  • src/db/migrations/0008_offer_tier_schema.sql — ultimo esempio di SQL migration a mano (struttura e convenzioni da seguire)
  • src/db/migrations/0005_phase_10_crm_leads_activities_reminders.sql — migration originale di activities e reminders (pattern più vicino alla nuova tabella)

UI & Components

  • src/components/admin/leads/LeadDetail.tsx — struttura UI esistente del dettaglio lead (dove va inserita la sezione Transcript)
  • src/components/admin/leads/LogActivityModal.tsx — pattern modal per aggiungere dati CRM (da seguire per il form transcript)
  • src/app/admin/leads/[id]/page.tsx — pattern page con Promise.all per fetch parallele (aggiungere getTranscripts(id))

Query & Actions Layer

  • src/lib/lead-service.ts — pattern query layer CRM (getActivityLog, getUpcomingReminders — aggiungere getTranscripts)
  • src/app/admin/leads/actions.ts — pattern server actions con requireAdmin guard (da seguire per addTranscript, deleteTranscript)

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • LogActivityModal.tsx — modal con form controllato (date picker + textarea + submit), pronto da clonare per il form transcript
  • activities / reminders pattern in schema.ts — FK lead_id con onDelete: cascade, nanoid() PK, created_at defaultNow — copia esatta per client_transcripts
  • getActivityLog(leadId) in lead-service.ts — query Drizzle con where(eq(activities.lead_id, leadId)) e orderBy(desc(activities.activity_date)) — pattern identico per getTranscripts
  • Card, CardContent, CardHeader, CardTitle da shadcn/ui — già usati nel LeadDetail per ogni sezione

Established Patterns

  • Migration a mano: ogni schema change è SQL scritto a mano (CREATE TABLE IF NOT EXISTS, tipi Postgres espliciti, FK con ON DELETE CASCADE). NON usare drizzle-kit generate.
  • requireAdmin guard: tutte le server actions in actions.ts iniziano con await requireAdmin() — obbligatorio anche per le nuove actions transcript.
  • revalidatePath dopo ogni mutation: revalidatePath(\/admin/leads/${leadId}`)`.
  • Promise.all fetch: page.tsx del dettaglio lead usa await Promise.all([...]) per fetch parallele — aggiungere getTranscripts(id) nello stesso array.

Integration Points

  • src/app/admin/leads/[id]/page.tsx — aggiungere getTranscripts(id) nel Promise.all, passare transcripts a <LeadDetail />
  • src/components/admin/leads/LeadDetail.tsx — aggiungere prop transcripts e sezione "Transcript" dopo <ActivitySection>
  • src/db/schema.ts — aggiungere definizione client_transcripts + relazioni Drizzle
  • src/lib/lead-service.ts — aggiungere getTranscripts(leadId: string)
  • src/app/admin/leads/actions.ts — aggiungere addTranscript(leadId, data) e deleteTranscript(transcriptId)

</code_context>

## Specific Ideas
  • Il testo del transcript può essere molto lungo (trascrizioni complete di call). Il form deve avere una <textarea> con altezza generosa (es. min-h-48 o più) senza limite di caratteri.
  • Il call_date è una date (non timestamp) — l'admin sceglie il giorno della call, non l'ora. Nel DB: DATE type PostgreSQL.
  • La lista transcript deve mostrare: call_date formattata (es. "12 giugno 2026"), title se presente, anteprima delle prime righe del content, e un'azione "Elimina". Espansione/collapse del testo completo.
  • Phase 21 leggerà i transcript via getTranscripts(leadId) — la query deve restituire tutti i campi incluso content completo.
## Deferred Ideas
  • UI transcript per clienti (/admin/clients/[id]): la FK client_id è nella tabella, ma la UI lato cliente è deferred a una fase futura (post v2.2 o su richiesta).
  • Ricerca full-text sui transcript: fuori scope v2.2 — i transcript vengono letti dall'AI in blocco, non cercati dall'admin.
  • Trascrizione automatica da audio: fuori scope — l'admin incolla manualmente il testo.

Phase: 20-Knowledge Base Cliente Context gathered: 2026-06-19