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>
This commit is contained in:
@@ -12,16 +12,18 @@ import {
|
||||
Settings,
|
||||
LogOut,
|
||||
Zap,
|
||||
FileText,
|
||||
} from "lucide-react";
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ href: "/admin", label: "Dashboard", icon: LayoutDashboard, exact: true },
|
||||
{ href: "/admin/clients", label: "Clienti", icon: Users },
|
||||
{ href: "/admin/leads", label: "Lead", icon: Zap },
|
||||
{ href: "/admin/projects", label: "Progetti", icon: FolderOpen },
|
||||
{ href: "/admin/offers", label: "Offerte", icon: Tag },
|
||||
{ href: "/admin/catalog", label: "Catalogo", icon: BookOpen },
|
||||
{ href: "/admin/impostazioni", label: "Impostazioni", icon: Settings },
|
||||
{ href: "/admin", label: "Dashboard", icon: LayoutDashboard, exact: true },
|
||||
{ href: "/admin/clients", label: "Clienti", icon: Users },
|
||||
{ href: "/admin/leads", label: "Lead", icon: Zap },
|
||||
{ href: "/admin/projects", label: "Progetti", icon: FolderOpen },
|
||||
{ href: "/admin/preventivi", label: "Preventivi", icon: FileText },
|
||||
{ href: "/admin/offers", label: "Offerte", icon: Tag },
|
||||
{ href: "/admin/catalog", label: "Catalogo", icon: BookOpen },
|
||||
{ href: "/admin/impostazioni", label: "Impostazioni", icon: Settings },
|
||||
];
|
||||
|
||||
export function AdminSidebar() {
|
||||
@@ -37,6 +39,17 @@ export function AdminSidebar() {
|
||||
<span className="font-bold text-white tracking-tight text-sm">iamcavalli</span>
|
||||
</div>
|
||||
|
||||
{/* CTA globale — genera preventivo */}
|
||||
<div className="px-3 py-3 border-b border-white/10">
|
||||
<Link
|
||||
href="/admin/preventivi/genera"
|
||||
className="flex items-center justify-center gap-2 w-full px-3 py-2 rounded-md text-xs font-semibold bg-[#DEF168] text-[#1A463C] hover:bg-[#d4e85e] transition-colors"
|
||||
>
|
||||
<FileText size={13} />
|
||||
Genera preventivo
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Nav links */}
|
||||
<nav className="flex-1 px-3 py-4 flex flex-col gap-0.5">
|
||||
{NAV_ITEMS.map(({ href, label, icon: Icon, exact }) => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { OptionMultiSelect } from "@/components/ui/option-multi-select";
|
||||
import { addLeadTag, removeLeadTag, renameLeadTag, deleteTranscript } from "@/app/admin/leads/actions";
|
||||
import { formatDistanceToNow, format } from "date-fns";
|
||||
import { it } from "date-fns/locale";
|
||||
import Link from "next/link";
|
||||
import { LogActivityModal } from "./LogActivityModal";
|
||||
import { SendQuoteModal } from "./SendQuoteModal";
|
||||
import { EditLeadModal } from "./LeadForm";
|
||||
@@ -99,6 +100,12 @@ export function LeadDetail({
|
||||
<LogActivityModal leadId={lead.id} />
|
||||
<TranscriptModal leadId={lead.id} />
|
||||
<SendQuoteModal leadId={lead.id} />
|
||||
<Link
|
||||
href={`/admin/preventivi/genera?lead_id=${lead.id}`}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-2 bg-[#DEF168] text-[#1A463C] rounded-md text-sm font-semibold hover:bg-[#d4e85e] transition-colors"
|
||||
>
|
||||
Genera preventivo
|
||||
</Link>
|
||||
<EditLeadModal lead={lead} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user