Merge branch 'Axel' of repositorio.acatlan.unam.mx:IO/front-AT
This commit is contained in:
@@ -0,0 +1,150 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { envConfig } from "@/app/lib/config";
|
||||||
|
import axios from "axios";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
|
interface TotalServicioPeriodo {
|
||||||
|
nombre_servicio: string;
|
||||||
|
periodo: string;
|
||||||
|
monto_total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Servicio {
|
||||||
|
id_servicio: number;
|
||||||
|
servicio: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Periodo {
|
||||||
|
id_periodo: number;
|
||||||
|
semestre: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ReporteTotalesPage() {
|
||||||
|
const [totales, setTotales] = useState<TotalServicioPeriodo[]>([]);
|
||||||
|
const [servicios, setServicios] = useState<Servicio[]>([]);
|
||||||
|
const [periodos, setPeriodos] = useState<Periodo[]>([]);
|
||||||
|
const [cargando, setCargando] = useState(true);
|
||||||
|
|
||||||
|
// Estados para los filtros
|
||||||
|
const [periodoInicio, setPeriodoInicio] = useState<string>("");
|
||||||
|
const [periodoFin, setPeriodoFin] = useState<string>("");
|
||||||
|
const [servicioId, setServicioId] = useState<string>("");
|
||||||
|
|
||||||
|
const token = Cookies.get("token");
|
||||||
|
const headers = { Authorization: `Bearer ${token}` };
|
||||||
|
|
||||||
|
// Obtener lista de servicios y periodos para los selects
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
const [serviciosRes, periodosRes] = await Promise.all([
|
||||||
|
axios.get(`${envConfig.apiUrl}/servicio`, { headers }),
|
||||||
|
axios.get(`${envConfig.apiUrl}/periodo`, { headers }),
|
||||||
|
]);
|
||||||
|
setServicios(serviciosRes.data);
|
||||||
|
setPeriodos(periodosRes.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error al cargar servicios o periodos", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const obtenerTotales = async () => {
|
||||||
|
setCargando(true);
|
||||||
|
try {
|
||||||
|
// Construir query params
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (periodoInicio) params.append("periodoInicio", periodoInicio);
|
||||||
|
if (periodoFin) params.append("periodoFin", periodoFin);
|
||||||
|
if (servicioId) params.append("servicioId", servicioId);
|
||||||
|
|
||||||
|
const url = `${envConfig.apiUrl}/detalle-servicio/totales-por-periodo?${params.toString()}`;
|
||||||
|
const res = await axios.get(url, { headers });
|
||||||
|
setTotales(res.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error al obtener totales", error);
|
||||||
|
} finally {
|
||||||
|
setCargando(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Llamar cuando cambien los filtros (podría ser con un botón o automático con debounce)
|
||||||
|
const aplicarFiltros = () => {
|
||||||
|
obtenerTotales();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 style={{ color: "rgb(3, 1, 72)" }}>REPORTE DE TOTALES POR SERVICIO Y PERIODO</h1>
|
||||||
|
|
||||||
|
{/* Filtros */}
|
||||||
|
<div style={{ marginBottom: "20px", display: "flex", gap: "10px", flexWrap: "wrap" }}>
|
||||||
|
<select
|
||||||
|
value={periodoInicio}
|
||||||
|
onChange={(e) => setPeriodoInicio(e.target.value)}
|
||||||
|
>
|
||||||
|
<option value="">Periodo inicio (todos)</option>
|
||||||
|
{periodos.map((p) => (
|
||||||
|
<option key={p.id_periodo} value={p.id_periodo}>
|
||||||
|
{p.semestre}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select
|
||||||
|
value={periodoFin}
|
||||||
|
onChange={(e) => setPeriodoFin(e.target.value)}
|
||||||
|
>
|
||||||
|
<option value="">Periodo fin (todos)</option>
|
||||||
|
{periodos.map((p) => (
|
||||||
|
<option key={p.id_periodo} value={p.id_periodo}>
|
||||||
|
{p.semestre}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select
|
||||||
|
value={servicioId}
|
||||||
|
onChange={(e) => setServicioId(e.target.value)}
|
||||||
|
>
|
||||||
|
<option value="">Todos los servicios</option>
|
||||||
|
{servicios.map((s) => (
|
||||||
|
<option key={s.id_servicio} value={s.id_servicio}>
|
||||||
|
{s.servicio}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button onClick={aplicarFiltros}>Filtrar</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{cargando ? (
|
||||||
|
<p>Cargando...</p>
|
||||||
|
) : (
|
||||||
|
<div style={{ overflow: "auto", maxHeight: "500px" }}>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Servicio</th>
|
||||||
|
<th>Periodo</th>
|
||||||
|
<th>Monto Total</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{totales.map((item, index) => (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>{item.nombre_servicio}</td>
|
||||||
|
<td>{item.periodo}</td>
|
||||||
|
<td>${item.monto_total.toFixed(2)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user