"use client"; import { useEffect, useState } from "react"; import axios from "axios"; import Cookies from "js-cookie"; import { XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Line, LineChart, } from "recharts"; interface Periodo { id_periodo: number; semestre: string; fecha_inicio_servicio: string; fecha_fin_servicio: string; } interface Props { periodo1: Periodo | null; periodo2: Periodo | null; } export default function PorServicio({ periodo1, periodo2 }: Props) { const [data, setData] = useState([]); const [periodos, setPeriodos] = useState([]); const [loading, setLoading] = useState(false); const [serviciosSeleccionados, setServiciosSeleccionados] = useState([]); useEffect(() => { if (!periodo1 || !periodo2) return; const fetchServicios = async () => { setLoading(true); try { const token = Cookies.get("token"); const headers = { Authorization: `Bearer ${token}` }; // 🔥 1. traer TODOS los periodos en rango const resPeriodos = await axios.get( `${process.env.NEXT_PUBLIC_API_URL}/periodo/range?p1=${periodo1.id_periodo}&p2=${periodo2.id_periodo}`, { headers } ); const periodosRango = resPeriodos.data; setPeriodos(periodosRango); // 🔥 2. hacer requests por cada periodo const resultados = await Promise.all( periodosRango.map((p: Periodo) => axios.post( `${process.env.NEXT_PUBLIC_API_URL}/detalle-servicio/rango`, { desde: p.fecha_inicio_servicio, hasta: p.fecha_fin_servicio, }, { headers } ) ) ); // 🔥 3. merge dinámico const map = new Map(); periodosRango.forEach((p: Periodo, index: number) => { resultados[index].data.forEach((item: any) => { if (!map.has(item.servicio)) { map.set(item.servicio, { servicio: item.servicio, }); } map.get(item.servicio)[p.semestre] = Number(item.total); }); }); const finalData = Array.from(map.values()); setData(finalData); setServiciosSeleccionados(finalData.map((item: any) => item.servicio)); } catch (error) { console.error("Error comparando servicios", error); } finally { setLoading(false); } }; fetchServicios(); }, [periodo1, periodo2]); // 🔥 TRANSFORMAR DATA PARA GRAFICA const transformDataForChart = () => { if (!data.length || !periodos.length) return []; return periodos.map((p) => { const row: any = { periodo: p.semestre }; data.forEach((servicio) => { row[servicio.servicio] = servicio[p.semestre] || 0; }); return row; }); }; // FORMATO DE NUMEROS const formatNumber = (value: number) => { return value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2, }); }; // TOOLTIP ORDENADO const CustomTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { const sorted = [...payload] .filter((item) => item.value > 0) .sort((a, b) => b.value - a.value); return (

Periodo: {label}

{sorted.map((entry: any, index: number) => (
{entry.name}: ${formatNumber(entry.value)}
))}
); } return null; }; const chartData = transformDataForChart(); const colors = ["black", "red", "blue", "orange", "purple", "green"]; return (
{/* TABLA */}
{loading &&

Cargando...

} {periodos.map((p) => ( ))} {!loading && data.length === 0 && ( )} {data.map((row) => ( {periodos.map((p) => ( ))} ))}
Servicio{p.semestre}
No hay datos en este rango
{row.servicio} ${formatNumber(row[p.semestre] || 0)}
{data.map((servicio) => ( ))}
{/* GRAFICA */}
{chartData.length > 0 && ( value.toLocaleString()} /> } /> {data .filter((servicio) => serviciosSeleccionados.includes(servicio.servicio) ) .map((servicio, i) => ( ))} )}
); }