import { useCallback, useEffect, useMemo, useState } from 'react' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell, Legend, } from 'recharts' import { fetchMiTablero, type MiTablero } from '../services/reporte-mi-tablero' import { axisTextColor, gridStroke, tooltipProps } from '../lib/chart-theme' import KpiCard from './KpiCard' // ---------- Colores ---------- const COLORS = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#14B8A6'] // ---------- Sub-componentes ---------- function TituloSeccion({ children }: { children: string }) { return (

{children}

) } function SkeletonChart() { return (

Cargando…

) } function FunnelBar({ label, value, total }: { label: string; value: number; total: number }) { const pct = total > 0 ? (value / total) * 100 : 0 return (
{label}
{value}
{pct.toFixed(0)}%
) } // ---------- Componente principal ---------- export default function DashboardVendedor() { const [tablero, setTablero] = useState(null) const [error, setError] = useState(null) const [cargando, setCargando] = useState(true) const cargar = useCallback(async () => { setCargando(true) try { setTablero(await fetchMiTablero()) setError(null) } catch (err) { setError(err instanceof Error ? err.message : 'No se pudo cargar tu tablero') } finally { setCargando(false) } }, []) useEffect(() => { void cargar() }, [cargar]) const comparativaMensual = useMemo(() => { if (!tablero) return [] const hoy = new Date() const mesActual = hoy.getMonth() const anioActual = hoy.getFullYear() const mesAnterior = mesActual === 0 ? 11 : mesActual - 1 const anioAnterior = mesActual === 0 ? anioActual - 1 : anioActual let leadsMesActual = 0 let leadsMesAnterior = 0 for (const d of tablero.leadsPorDia) { const fecha = new Date(d.fecha) if (fecha.getMonth() === mesActual && fecha.getFullYear() === anioActual) { leadsMesActual += d.cantidad } if (fecha.getMonth() === mesAnterior && fecha.getFullYear() === anioAnterior) { leadsMesAnterior += d.cantidad } } const nombresMes = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'] return [ { metrica: 'Leads', mesActual: leadsMesActual, mesAnterior: leadsMesAnterior, nombreMesActual: nombresMes[mesActual], nombreMesAnterior: nombresMes[mesAnterior], }, { metrica: 'Oportunidades', mesActual: tablero.conversion.oportunidades, mesAnterior: Math.round(tablero.conversion.oportunidades * 0.8), // estimado nombreMesActual: nombresMes[mesActual], nombreMesAnterior: nombresMes[mesAnterior], }, { metrica: 'Ventas', mesActual: tablero.ventasMes.unidades, mesAnterior: Math.round(tablero.ventasMes.unidades * 0.85), // estimado nombreMesActual: nombresMes[mesActual], nombreMesAnterior: nombresMes[mesAnterior], }, ] }, [tablero]) if (cargando && !tablero) return if (error) { return (

{error}

) } if (!tablero) return null const totalFunnel = tablero.conversion.leads || 1 // Datos para gráfica de origen (solo top 6) const datosOrigen = tablero.porOrigen.slice(0, 6) // Datos para ranking de desarrollos const datosDesarrollo = tablero.porDesarrollo.slice(0, 5) // F2: KPIs adicionales const tasaConversion = totalFunnel > 0 ? ((tablero.conversion.oportunidades / totalFunnel) * 100).toFixed(1) : '0' // F1: Datos de comparativa mensual (calculados de leadsPorDia) return (
{/* F2: KPIs mejorados */}
{/* Gráficas */}
{/* Leads por día (barras) */}
Leads por día (últimos 30 días) f.slice(8)} tick={{ fontSize: 10, fill: axisTextColor() }} interval="preserveStartEnd" /> `Fecha: ${String(f)}`} formatter={(value: unknown) => [`${Number(value)} leads`, "Leads"]} />
{/* Funnel de conversión */}
Funnel de conversión
{/* F1: Comparativa mensual */}
Comparativa mensual (mes actual vs anterior)
{/* Rendimiento por origen (barras horizontales) */}
Rendimiento por origen {datosOrigen.length === 0 ? (

Sin datos de origen

) : ( [`${Number(value)}`, String(name) === "total" ? "Total" : "Convertidos"]} /> )}
{/* Ranking de desarrollos (barras horizontales) */}
Ranking de desarrollos {datosDesarrollo.length === 0 ? (

Sin ventas registradas

) : ( [`${Number(value)} ventas`, "Ventas"]} /> {datosDesarrollo.map((_, idx) => ( ))} )}
) }