Files
simone fdcc938252 feat(21-22): agente AI generazione preventivo + pagina pubblica deck
- Migration 0010: tabella proposals (id, slug, lead_id, client_id,
  offer_macro_id, content jsonb, state, selected_tier, accepted_at)
  applicata a prod via SSH tunnel
- @anthropic-ai/sdk@0.105.0 installato; ANTHROPIC_API_KEY in .env.local
- src/lib/proposal/: schema Zod ProposalContent, agente Claude Opus 4.8,
  assemble (AI + offerta DB + config consulente), queries, profile.ts
- Admin: /admin/preventivi lista + /genera (pre-fill ?lead_id=X) + /[id] review
- Sidebar: voce Preventivi + CTA globale lime "Genera preventivo"
- LeadDetail: pulsante "Genera preventivo" → /admin/preventivi/genera?lead_id=X
- Pagina pubblica /preventivo/[slug]: deck 20+ slide light-mode iamcavalli,
  navigazione frecce + dot + keyboard, accept/reject con guard immutabilità
- STATE.md aggiornato (80%), 21-PLAN.md scritto nel formato GSD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 14:37:05 +02:00

4.0 KiB

Phase 21+22 — Agente AI Preventivo + Pagina Pubblica Deck

Executed: 2026-06-20 Status: Code complete — pending migration 0010 to prod Model used: claude-opus-4-8 Note: Le fasi 21 (AI generation) e 22 (public page) sono state eseguite in un'unica sessione per coerenza architetturale.


Scope eseguito

Fase 21 — Agente AI (AI-01 / AI-02)

  • @anthropic-ai/sdk@0.105.0 installato
  • ANTHROPIC_API_KEY aggiunta a .env.local
  • src/lib/proposal/schema.ts — Zod schema ProposalContent (sezioni AI)
  • src/lib/proposal/agent.tsgenerateProposalContent() → Claude Opus 4.8, JSON strutturato validato Zod
  • src/lib/proposal/assemble.tsassembleProposal() fonde AI + offerta DB + config consulente
  • src/lib/proposal/profile.ts — config statica consulente (bio, fatti, testimonianze, legal) — editare con dati reali
  • src/lib/proposal/queries.tslistProposals, getProposalById, getProposalBySlug
  • src/app/admin/preventivi/actions.tsgenerateProposalDraft, publishProposal, updateProposalTitle, deleteProposal
  • src/app/admin/preventivi/page.tsx — lista preventivi admin
  • src/app/admin/preventivi/genera/page.tsx + GeneraProposalForm.tsx — builder con pre-fill ?lead_id=X
  • src/app/admin/preventivi/[id]/page.tsx — review bozza + pubblica + elimina
  • src/components/admin/AdminSidebar.tsx — voce "Preventivi" + CTA globale lime "Genera preventivo"
  • src/components/admin/leads/LeadDetail.tsx — pulsante "Genera preventivo" → /admin/preventivi/genera?lead_id=X

Fase 22 — Pagina pubblica deck (PUB-01 / PUB-02)

  • src/app/preventivo/[slug]/page.tsx — server component pubblico, gestisce stati draft/published/accepted/rejected
  • src/app/preventivo/[slug]/actions.tsacceptProposal + rejectProposal con guard immutabilità accepted_at
  • src/components/public/proposal/ProposalDeck.tsx — deck navigabile (frecce ←/→ + dot cliccabili + keyboard), light mode iamcavalli
  • Sezioni (20+): Cover, Vision, Index, ChapterDivider, Strategist, Facts, Testimonials, ProblemNode, SynthesisDiagram, SolutionNode, SolutionSynthesis, Scope, Deliverables, Timeline, Pricing, StagesRecap, ComparisonMatrix, NextSteps, Accept, Closing

Schema DB

  • src/db/migrations/0010_proposals.sqlCREATE TABLE IF NOT EXISTS proposals (...)applicare a prod via SSH prima del push
  • src/db/schema.ts — tabella proposals + relations + Proposal/NewProposal types

Flusso end-to-end

Lead (con transcript) → LeadDetail "Genera preventivo"
→ /admin/preventivi/genera?lead_id=X
→ seleziona offerta → "Genera con AI"
→ server action: legge transcript + offerta → chiama Claude Opus 4.8 → Zod validate
→ assembla AssembledProposal (AI + offerta + config) → salva in proposals (draft)
→ redirect /admin/preventivi/[id] → review bozza → "Pubblica"
→ pagina pubblica /preventivo/[slug] — deck 20+ slide
→ cliente sceglie tier A/B/C → accetta → accepted_at IMMUTABILE

Pending post-push

  1. Migration 0010 a prod via ssh -L 54321:localhost:54321 root@178.104.27.55 + script node
  2. Dati reali in src/lib/proposal/profile.ts — bio, credenziali, testimonianze, contatti, foto URL
  3. ANTHROPIC_API_KEY in Coolify (già in .env.local per dev)
  4. Wave 5 (opzionale) — badge CRM su accept/reject + email Resend

Decisioni architetturali

Decisione Scelta Motivo
Output AI JSON strutturato → template fisso Coerenza visiva garantita, zero rischio HTML rotto
Bio/testimonianze File config profile.ts Editing semplice, no UI v1
Entry point LeadDetail + sidebar globale GSD prescrive LeadDetail; sidebar è additive
content jsonb (non text) Parser automatico postgres-js, type-safe
Modello claude-opus-4-8 Migliore qualità copywriting strategico
Phase split 21+22 eseguite insieme Dipendenza diretta, nessun vantaggio a splitparle