"use client"; import { useQuery } from "convex/react"; import type { FunctionReturnType } from "convex/server"; import { ArrowRight, Building2, CheckCircle2, Clock3, FileSearch, MapPin, ShieldAlert, type LucideIcon, } from "lucide-react"; import Link from "next/link"; import { api } from "@/convex/_generated/api"; import { groupLeadFunnelCards, type LeadFunnelCard, type LeadFunnelStageId, } from "@/lib/dashboard-model"; import { cn } from "@/lib/utils"; type LeadFunnelQueryResult = FunctionReturnType; const stageActionHref: Record = { missing_contact: "/dashboard/leads", audit_ready: "/dashboard/audits", review_open: "/dashboard/outreach", contacted: "/dashboard/outreach", follow_up: "/dashboard/outreach", deferred: "/dashboard/leads", }; const stageVisuals: Record< LeadFunnelStageId, { surface: string; label: string; icon: LucideIcon } > = { missing_contact: { surface: "review-surface", label: "Kontakt klären", icon: ShieldAlert, }, audit_ready: { surface: "evidence-surface", label: "Evidence sammeln", icon: FileSearch, }, review_open: { surface: "review-surface", label: "Freigabe prüfen", icon: Clock3, }, contacted: { surface: "safe-surface", label: "Kontakt läuft", icon: CheckCircle2, }, follow_up: { surface: "safe-surface", label: "Follow-up", icon: Clock3, }, deferred: { surface: "bg-[var(--danger-soft)] text-destructive", label: "Zurückgestellt", icon: ShieldAlert, }, }; export function LeadFunnelBoard() { const leads: LeadFunnelQueryResult | undefined = useQuery( api.leads.listFunnel, { limit: 100 }, ); if (leads === undefined) { return ; } const groups = groupLeadFunnelCards(leads); const totalCards = groups.reduce((total, group) => total + group.cards.length, 0); if (totalCards === 0) { return (

Lead-Funnel

Noch keine Leads im Arbeitsfluss

Sobald Kampagnen Leads erzeugen oder importieren, erscheinen sie hier nach Kontaktlage, Audit-Stand und Review-Bedarf sortiert.

); } return (

Lead Workflow

Evidence Pipeline

{totalCards} Leads nach nächster Entscheidung, Beleglage und Outreach-Sicherheit.

Human approval required

{groups.map((group) => ( ))}
); } function LeadFunnelStageView({ group, }: { group: ReturnType[number]; }) { const visual = stageVisuals[group.stage.id]; const Icon = visual.icon; return (

{visual.label}

{group.stage.title}

{group.stage.description}

{group.cards.length}
{group.cards.length > 0 ? ( group.cards.map((card) => ( )) ) : (

Keine Leads in diesem Entscheidungsschritt.

)}
); } function LeadFunnelCardView({ card }: { card: LeadFunnelCard }) { return (

{card.company}

{card.niche}

{card.priorityLabel}

{card.location}

{card.contactStatusLabel} {card.contactDetail}
{card.nextAction}
); } function LeadFunnelSkeleton() { return (
{Array.from({ length: 6 }, (_, index) => (
))}
); }