4 Commits

Author SHA1 Message Date
IO b4eb945b40 merge axel 2026-03-03 17:40:44 -06:00
IO 59f8fa673d Merge branch 'Axel' of repositorio.acatlan.unam.mx:IO/front-AT 2026-03-03 17:36:15 -06:00
IO c69aa009b7 fixed size 2026-03-03 17:36:06 -06:00
Tyrannuss 6c80ecf3db se agrego la vista para el monto total por periodo y tipo de servicio 2026-03-03 17:26:16 -06:00
9 changed files with 209 additions and 40 deletions
+6 -1
View File
@@ -63,10 +63,15 @@
background-repeat: no-repeat;
}
@media(max-height:550px) {
@media(max-height:800px) {
.addTime {
margin-top: 0.5rem;
padding: 0.5rem;
max-width: 320px;
}
.firstPartInformationTime {
max-width: 320px;
}
}
+7 -2
View File
@@ -3,7 +3,7 @@
top: 0;
background-color: #ffffff;
width: 100%;
max-width: 700px;
max-width: 600px;
border-radius: 4px;
padding: 1rem;
margin-top: 1rem;
@@ -28,8 +28,13 @@
height: fit-content;
}
@media(max-height:550px) {
@media(max-height:800px) {
.firstPartInformation {
max-width: 320px;
}
.inscripcion {
max-width: 400px;
padding: 0.5rem;
margin-top: 0.5rem;
}
+146
View File
@@ -0,0 +1,146 @@
"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);
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}` };
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);
}
};
const aplicarFiltros = () => {
obtenerTotales();
};
return (
<div>
<h1 style={{ color: "rgb(3, 1, 72)" }}>REPORTE DE TOTALES POR SERVICIO Y PERIODO</h1>
<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>
);
}
@@ -15,7 +15,7 @@ export default function Information(props: InformationProps) {
{entries.map(([key, value]) => (
<li key={key} className="informationItem">
<span className="informationKey">{key}</span>
<span className="informationValue">{value}</span>
<span className={`informationValue ${key}`}>{value}</span>
</li>
))}
</ul>
+3 -1
View File
@@ -44,9 +44,11 @@
margin-right: 6px;
vertical-align: middle;
}
@media(max-height:550px) {
@media(max-height:800px) {
.tableContainer {
margin-top: 1.5rem;
max-width: 320px;
}
}
@@ -172,6 +172,7 @@ tbody {
position: absolute;
top: 76px;
left: 0;
top: 100%;
width: 100%;
background-color: #fff;
flex-direction: column;
+31 -6
View File
@@ -362,8 +362,13 @@ a {
}
.informationValue {
color: #555;
font-size: 1.25rem;
color: #000000;
font-size: 1.5rem;
}
.Credito {
font-weight: bold;
font-size: 2rem;
}
.title {
@@ -399,7 +404,7 @@ form {
.toggleSection {
width: 100%;
max-width: fit-content;
min-width: 750px;
min-width: 600px;
border-radius: 4px;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
@@ -496,7 +501,7 @@ thead tr {
background-color: #2563eb;
position: relative;
z-index: 1;
}
}
tbody tr {
transition: transform 0.3s ease, opacity 0.3s ease;
@@ -677,7 +682,7 @@ table td:last-child {
}
.informationValue {
font-size: 1rem;
font-size: 1.01rem;
}
.informationItem {
@@ -687,7 +692,6 @@ table td:last-child {
input,
select {
padding: 0.5rem;
font-size: 1.3rem;
height: 3rem;
}
@@ -727,6 +731,27 @@ table td:last-child {
height: 30px;
}
.information {
max-width: 320px;
}
.containerForm {
max-width: 320px;
}
.Credito {
font-size: 1.5rem;
}
table th,
table td {
padding: 0.65rem 1rem;
}
.toggleSection {
min-width: 570px;
}
}
@media (max-height: 960px) {
+8 -5
View File
@@ -9,11 +9,14 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"], weight: ["400", "700"] });
export const metadata: Metadata = {
title: "Servicio AT",
title: {
default: "Servicio AT",
template: "Servicio AT | %s",
},
description: "Servicio de administracion de la FES Acatlan",
authors: [{ name: "FES Acatlán" }],
creator: "Lino,Carlos,Axel",
icons: {
icons: {
icon: "/icon.svg",
},
};
@@ -26,9 +29,9 @@ export default function RootLayout({
return (
<html lang="es">
<body className={inter.className} suppressHydrationWarning>
<Header />
<main>{children}</main>
<Footer />
<Header />
<main>{children}</main>
<Footer />
</body>
</html>
);
+6 -24
View File
@@ -693,7 +693,6 @@
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -733,7 +732,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -754,7 +752,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -775,7 +772,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -796,7 +792,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -817,7 +812,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -838,7 +832,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -859,7 +852,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -880,7 +872,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -901,7 +892,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -922,7 +912,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -943,7 +932,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -964,7 +952,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -985,7 +972,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1855,7 +1841,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
@@ -1866,7 +1851,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2109,9 +2093,9 @@
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -2216,7 +2200,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
"license": "MIT",
"optional": true
},
@@ -2263,7 +2246,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
@@ -2389,9 +2371,9 @@
}
},
"node_modules/readdir-glob/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"