"use client"; import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { Lead, Activity, Reminder, ClientTranscript } from "@/db/schema"; import { StatusBadge } from "@/components/ui/StatusBadge"; import { OptionMultiSelect } from "@/components/ui/option-multi-select"; import { addLeadTag, removeLeadTag, renameLeadTag, deleteTranscript, convertLeadToClient, } from "@/app/admin/pipeline/actions"; import { formatDistanceToNow, format } from "date-fns"; import { it } from "date-fns/locale"; import Link from "next/link"; import { Mail, Phone, Clock, CalendarDays, Calendar, StickyNote, Mic, Trash2, Sparkles, type LucideIcon, } from "lucide-react"; import { LogActivityModal } from "./LogActivityModal"; import { TranscriptModal } from "./TranscriptModal"; import { EditLeadModal } from "./LeadForm"; const ACTIVITY_META: Record = { call: { label: "Chiamata effettuata", Icon: Phone }, email: { label: "E-mail inviata", Icon: Mail }, meeting: { label: "Meeting", Icon: Calendar }, note: { label: "Nota", Icon: StickyNote }, }; type TimelineItem = | { kind: "transcript"; date: Date; data: ClientTranscript } | { kind: "activity"; date: Date; data: Activity }; export function LeadDetail({ lead, activities, reminders, tags, tagOptions, transcripts, convertedClientId, }: { lead: Lead; activities: Activity[]; reminders: Reminder[]; tags: string[]; tagOptions: string[]; transcripts: ClientTranscript[]; convertedClientId?: string | null; }) { const router = useRouter(); const [, startTransition] = useTransition(); const [converting, startConvert] = useTransition(); const [tagError, setTagError] = useState(null); const [expandedIds, setExpandedIds] = useState>(new Set()); const [deletingId, setDeletingId] = useState(null); function handleConvert() { const ok = window.confirm( `Convertire "${lead.name}" in cliente?\n\nVerrà creato un cliente (con email, telefono e transcript del lead) e il lead verrà archiviato mantenendo lo stato "vinto".` ); if (!ok) return; startConvert(() => convertLeadToClient(lead.id)); } function run(fn: () => Promise) { setTagError(null); startTransition(async () => { try { await fn(); router.refresh(); } catch (e) { setTagError(e instanceof Error ? e.message : "Errore nel salvataggio"); } }); } function toggleExpand(id: string) { setExpandedIds((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); } function handleDeleteTranscript(transcriptId: string) { setDeletingId(transcriptId); startTransition(async () => { try { await deleteTranscript(transcriptId, lead.id); router.refresh(); } catch (e) { console.error("deleteTranscript error:", e); } finally { setDeletingId(null); } }); } // Unified, reverse-chronological timeline of activities + transcripts. const timeline: TimelineItem[] = [ ...activities.map((a) => ({ kind: "activity" as const, date: new Date(a.activity_date), data: a, })), ...transcripts.map((t) => ({ kind: "transcript" as const, date: new Date(t.call_date + "T00:00:00"), data: t, })), ].sort((a, b) => b.date.getTime() - a.date.getTime()); return (
{/* Header + Actions */}

{lead.name}

{lead.company || "Azienda non specificata"}

{convertedClientId ? ( ✓ Convertito → Apri cliente ) : ( lead.status === "won" && ( ) )} {/* Primary action */} Genera preventivo
{/* Body: asymmetric columns */}
{/* Left (1/3): Profile card */}

Profilo Lead

{lead.email ? ( {lead.email} ) : ( )} {lead.phone || "—"} {lead.last_contact_date ? formatDistanceToNow(new Date(lead.last_contact_date), { addSuffix: true, locale: it, }) : "—"} {lead.next_action || "—"}
{/* Tags */}

Tag Lead

run(() => addLeadTag(lead.id, v))} onRemove={(v) => run(() => removeLeadTag(lead.id, v))} onRename={(o, n) => run(() => renameLeadTag(o, n))} /> {tagError &&

{tagError}

}
{/* Right (2/3): Note, Follow-up, Timeline */}
{/* Note */}

Note

{lead.notes ? (
{lead.notes}
) : (
Nessuna nota
)}
{/* Next follow-up */}

Prossimo Follow-up

{reminders.length > 0 ? (
    {reminders.map((r) => (
  • {r.title}

    {format(new Date(r.due_date), "dd MMM yyyy", { locale: it })}

  • ))}
) : (
Nessun reminder impostato
)}
{/* Unified timeline */}

Storico delle Interazioni

{timeline.length > 0 ? (
{/* vertical connector line */}
{timeline.map((item) => { if (item.kind === "transcript") { const t = item.data; const isExpanded = expandedIds.has(t.id); const isLong = t.content.length > 140 || t.content.split("\n").length > 2; return (
Transcript Chiamata AI {t.title && (

{t.title}

)}
{format(new Date(t.call_date + "T00:00:00"), "d MMMM yyyy", { locale: it, })}

{t.content}

{isLong && ( )}
); } const a = item.data; const meta = ACTIVITY_META[a.type] ?? ACTIVITY_META.note; const Icon = meta.Icon; return (
{meta.label} {formatDistanceToNow(new Date(a.activity_date), { addSuffix: true, locale: it, })}
{a.notes && (

{a.notes}

)} {a.duration_minutes && (

Durata: {a.duration_minutes} min

)}
); })}
) : (

Nessuna interazione registrata

)}
); } function ProfileRow({ Icon, label, children, }: { Icon: LucideIcon; label: string; children: React.ReactNode; }) { return (

{label}

{children}
); }