'use client'; import { useQuery } from '@tanstack/react-query'; import { apiFetch } from '@/lib/api/client'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; interface SourceRow { source: string; total: number; won: number; lost: number; conversionRate: number; } interface SourceConversionResponse { data: SourceRow[]; } /** * Horizontal bar list of lead-source conversion rates. Complements the * existing Lead Source Attribution donut: that one shows where leads * COME from, this shows which sources actually CONVERT. Lets marketing * spend follow the buyers, not the tire-kickers. * * Renders only sources with at least one lead; uses a compact bar-in- * row layout so 5-8 sources fit comfortably without scrolling. */ export function SourceConversionChart() { const { data, isLoading } = useQuery({ queryKey: ['dashboard', 'source_conversion'], queryFn: () => apiFetch('/api/v1/dashboard/source-conversion'), staleTime: 60_000, }); const rows = data?.data ?? []; return ( Source conversion Won deals as a percentage of leads per source. {isLoading ? (
) : rows.length === 0 ? (

Once interests have a source assigned, conversion rates will appear here.

) : (
    {rows.map((r) => { const pct = Math.round(r.conversionRate * 100); const label = r.source .replace(/_/g, ' ') .replace(/\b\w/g, (c) => c.toUpperCase()); return (
  • {label} {pct}% ({r.won} won · {r.total} total)
    {/* Inline bar — keeps the widget compact and lets eight rows share the same vertical space a Recharts plot would use for two. */}
  • ); })}
)}
); }