"use client" import { useState, useMemo, useEffect } from "react" import { motion } from "framer-motion" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { ChevronLeft, ChevronRight } from "lucide-react" interface IntervalData { label: string leads: number closed: number } interface LeadsPerMonthChartProps { data: IntervalData[] } const NEW_LEADS = "#CC0000" const CLOSED = "#0033CC" export function LeadsPerMonthChart({ data: initialData }: LeadsPerMonthChartProps) { const [year, setYear] = useState(new Date().getFullYear()) const [chartData, setChartData] = useState(initialData) const [hovered, setHovered] = useState(null) useEffect(() => { setChartData(initialData) }, [initialData]) useEffect(() => { async function fetchYearData() { try { const res = await fetch(`/api/dashboard?year=${year}`) if (res.ok) { const data = await res.json() setChartData(data.leadsPerMonth || []) } } catch { console.warn("Failed to fetch year data in leads per month chart") } } const thisYear = new Date().getFullYear() if (year !== thisYear || initialData.length === 0) { fetchYearData() } else { setChartData(initialData) } }, [year, initialData]) const width = 880 const height = 620 const padding = { top: 128, right: 24, bottom: 48, left: 44 } const chartW = width - padding.left - padding.right const chartH = height - padding.top - padding.bottom const maxVal = useMemo(() => { if (chartData.length === 0) return 1 const max = Math.max(...chartData.map((d) => Math.max(d.leads, d.closed))) return Math.max(Math.ceil(max / 7) * 7, 1) }, [chartData]) const ticks = useMemo(() => { const steps = 4 return Array.from({ length: steps + 1 }, (_, i) => Math.round((maxVal / steps) * i)) }, [maxVal]) const groupW = chartW / Math.max(chartData.length, 1) const barW = groupW * 0.28 const gap = groupW * 0.06 const yScale = (v: number) => chartH - (v / maxVal) * chartH const active = hovered const activeDatum = active !== null ? chartData[active] : null const totalNew = chartData.reduce((s, d) => s + d.leads, 0) const totalClosed = chartData.reduce((s, d) => s + d.closed, 0) const closeRate = totalNew > 0 ? Math.round((totalClosed / totalNew) * 100) : 0 const currentYear = new Date().getFullYear() if (chartData.length === 0) { return (
Leads Per Month
{year}
No data for {year}
) } return (
Leads Per Month

{totalNew} new · {totalClosed} closed · {closeRate}% close rate

New Leads
Closed
{year}
{/* Grid lines */} {ticks.map((t, i) => ( {t} ))} {/* Bars */} {chartData.map((d, i) => { const groupX = i * groupW const isActive = active === i const newH = chartH - yScale(d.leads) const closedH = chartH - yScale(d.closed) return ( setHovered(i)} onMouseLeave={() => setHovered(null)} style={{ cursor: "pointer" }} > {d.label} ) })} {activeDatum && (
chartData.length - 2 ? "translate(-100%, 0)" : "translate(-12%, 0)", transition: "left 0.15s ease", }} >
{activeDatum.label}
New Leads {activeDatum.leads}
Closed {activeDatum.closed}
{activeDatum.leads > 0 ? `${Math.round((activeDatum.closed / activeDatum.leads) * 100)}% close rate` : "No leads"}
)}
) }