124 lines
3.1 KiB
TypeScript
124 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import axios from "axios";
|
|
import Cookies from "js-cookie";
|
|
|
|
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<any[]>([]);
|
|
const [periodos, setPeriodos] = useState<Periodo[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
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);
|
|
} catch (error) {
|
|
console.error("Error comparando servicios", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchServicios();
|
|
}, [periodo1, periodo2]);
|
|
|
|
return (
|
|
<div style={{ overflow: "auto", height: "300px" }}>
|
|
{loading && <p>Cargando...</p>}
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Servicio</th>
|
|
|
|
{periodos.map((p) => (
|
|
<th key={p.id_periodo}>{p.semestre}</th>
|
|
))}
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
{!loading && data.length === 0 && (
|
|
<tr>
|
|
<td colSpan={periodos.length + 1}>
|
|
No hay datos en este rango
|
|
</td>
|
|
</tr>
|
|
)}
|
|
|
|
{data.map((row) => (
|
|
<tr key={row.servicio}>
|
|
<td>{row.servicio}</td>
|
|
|
|
{periodos.map((p) => (
|
|
<td key={p.id_periodo}>
|
|
${(row[p.semestre] || 0).toFixed(2)}
|
|
</td>
|
|
))}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
} |