new format to reporte

This commit is contained in:
2025-11-28 16:19:36 -06:00
parent c887f67ed2
commit b26b45355f
12 changed files with 206 additions and 106 deletions
+7 -3
View File
@@ -57,8 +57,9 @@ export default function Pregunta1() {
}
axios
.get<RawEntry[]>(
.post<RawEntry[]>(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_tipoUso`,
["EN DESUSO", "EN USO"],
{ headers: { Authorization: `Bearer ${token}` } }
)
.then((res) => {
@@ -161,10 +162,13 @@ export default function Pregunta1() {
return (
<div className={style["contenedor-pregunta"]}>
<div className={style["contenedor-censo"]}>Censo de equipos de cómputo</div>
<div className={style["contenedor-censo"]}>
Censo de equipos de cómputo
</div>
<div className={style["pregunta-cuadro"]}>
Número de equipos de cómputo por cada categoría y perfil de usuario.<ToggleButton/>
Número de equipos de cómputo por cada categoría y perfil de usuario.
<ToggleButton />
</div>
<div className={style["contenedor-tablas"]}>
+12 -7
View File
@@ -4,7 +4,6 @@ import { useState, useEffect } from "react";
import axios from "axios";
import styles from "./pregunta2.module.scss";
import Cookies from "js-cookie";
import style from "styled-jsx/style";
import ToggleButton from "../Toggle/ToggleButton";
type OsEntry = {
os: string;
@@ -60,11 +59,15 @@ export default function Pregunta2() {
// ✔ GET AXIOS PROFESIONAL
useEffect(() => {
const token = Cookies.get("token");
const headers = {Authorization: `Bearer ${token}`};
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_sistemasOperativos`,{headers})
.post(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_sistemasOperativos`,
["EN DESUSO", "EN USO"],
{ headers }
)
.then((res) => {
const json = res.data;
const json = res.data;
const formatted: PlatformData = {
"pc-desktop": transformPlatform(json[0]),
@@ -85,13 +88,15 @@ export default function Pregunta2() {
return (
<div className={styles.container_P1}>
<div className={styles["contenedor-censo_p1"]}>Censo de equipos de cómputo - Sitema Operativo</div>
<div className={styles["contenedor-censo_p1"]}>
Censo de equipos de cómputo - Sitema Operativo
</div>
<div className={styles["pregunta-cuadro_p1"]}>
Número de equipos de cómputo por cada categoría y perfil de usuario.<ToggleButton/>
Número de equipos de cómputo por cada categoría y perfil de usuario.
<ToggleButton />
</div>
<div className={styles.scanView_P1}>
<div className={styles["main-content_P1"]}>
{/* Tabs */}
<div className={styles.tabs_P1}>
+56 -20
View File
@@ -35,7 +35,10 @@ const PLATFORM_LABELS: Record<PlatformKey, string> = {
};
// Mapeo de "uso" del JSON a campos en ProcessorEntry
const USO_TO_FIELD: Record<string, keyof Omit<ProcessorEntry, "tipo" | "total" | "isTotal">> = {
const USO_TO_FIELD: Record<
string,
keyof Omit<ProcessorEntry, "tipo" | "total" | "isTotal">
> = {
ALUMNO: "alumnos",
PROFESOR: "profesores",
"TÉCNICO ACADEMICO": "tecnicos",
@@ -44,7 +47,9 @@ const USO_TO_FIELD: Record<string, keyof Omit<ProcessorEntry, "tipo" | "total" |
};
// Transforma un array plano del tipo [{procesador, uso, total}] en ProcessorEntry[]
function transformProcessorData(rawArray: { procesador: string; uso: string; total: string }[]): ProcessorEntry[] {
function transformProcessorData(
rawArray: { procesador: string; uso: string; total: string }[]
): ProcessorEntry[] {
const map = new Map<string, ProcessorEntry>();
for (const item of rawArray) {
@@ -85,12 +90,24 @@ function transformProcessorData(rawArray: { procesador: string; uso: string; tot
// Calculamos los totales generales
const grandTotal: ProcessorEntry = {
tipo: "Total",
alumnos: rows.reduce((sum, r) => sum + parseInt(r.alumnos || "0"), 0).toString(),
profesores: rows.reduce((sum, r) => sum + parseInt(r.profesores || "0"), 0).toString(),
tecnicos: rows.reduce((sum, r) => sum + parseInt(r.tecnicos || "0"), 0).toString(),
investigadores: rows.reduce((sum, r) => sum + parseInt(r.investigadores || "0"), 0).toString(),
administrativos: rows.reduce((sum, r) => sum + parseInt(r.administrativos || "0"), 0).toString(),
total: rows.reduce((sum, r) => sum + parseInt(r.total || "0"), 0).toString(),
alumnos: rows
.reduce((sum, r) => sum + parseInt(r.alumnos || "0"), 0)
.toString(),
profesores: rows
.reduce((sum, r) => sum + parseInt(r.profesores || "0"), 0)
.toString(),
tecnicos: rows
.reduce((sum, r) => sum + parseInt(r.tecnicos || "0"), 0)
.toString(),
investigadores: rows
.reduce((sum, r) => sum + parseInt(r.investigadores || "0"), 0)
.toString(),
administrativos: rows
.reduce((sum, r) => sum + parseInt(r.administrativos || "0"), 0)
.toString(),
total: rows
.reduce((sum, r) => sum + parseInt(r.total || "0"), 0)
.toString(),
isTotal: true,
};
@@ -112,7 +129,11 @@ export default function Pregunta3_2() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_procesador`, { headers })
.post(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_procesador`,
["EN DESUSO", "EN USO"],
{ headers }
)
.then((res) => {
const json = res.data; // array de 5 arreglos
@@ -134,28 +155,34 @@ export default function Pregunta3_2() {
});
}, []);
if (loading) return <div className={styles.scanView_P3}>Cargando datos...</div>;
if (loading)
return <div className={styles.scanView_P3}>Cargando datos...</div>;
if (!data) return <div className={styles.scanView_P3}>Error al cargar los datos.</div>;
if (!data)
return <div className={styles.scanView_P3}>Error al cargar los datos.</div>;
const currentData = data[activeTab];
return (
<div className={styles.container_P3}>
<div className={styles["contenedor-censo_P3"]}>Censo de equipos de cómputo - Plataforma y tipo procesador</div>
<div className={styles["contenedor-censo_P3"]}>
Censo de equipos de cómputo - Plataforma y tipo procesador
</div>
<div className={styles["pregunta-cuadro_P3"]}>
Cantidad de población beneficiada por plataforma y tipo de procesador.<ToggleButton/>
Cantidad de población beneficiada por plataforma y tipo de procesador.
<ToggleButton />
</div>
<div className={styles.scanView_P3}>
<div className={styles.scanView_P3}>
<div className={styles.mainContent_P3}>
{/* Pestañas verticales */}
<div className={styles.tabs_P3}>
{Object.entries(PLATFORM_LABELS).map(([key, label]) => (
<button
key={key}
className={`${styles.tab_P3} ${activeTab === key ? styles.active_P3 : ""}`}
className={`${styles.tab_P3} ${
activeTab === key ? styles.active_P3 : ""
}`}
onClick={() => setActiveTab(key as PlatformKey)}
aria-selected={activeTab === key}
>
@@ -173,7 +200,10 @@ export default function Pregunta3_2() {
<thead>
<tr>
<th rowSpan={2} className={styles.headerProcesador}>
{activeTab.includes("apple") ? "Plataforma Apple" : "Plataforma PC"} <br />
{activeTab.includes("apple")
? "Plataforma Apple"
: "Plataforma PC"}{" "}
<br />
Tipo de procesador
</th>
<th colSpan={5} className={styles.headerPoblacion}>
@@ -186,7 +216,9 @@ export default function Pregunta3_2() {
<tr>
<th className={styles.subHeader}>Alumnos</th>
<th className={styles.subHeader}>Profesores</th>
<th className={styles.subHeader}>Técnicos Académicos</th>
<th className={styles.subHeader}>
Técnicos Académicos
</th>
<th className={styles.subHeader}>Investigadores</th>
<th className={styles.subHeader}>Administrativos</th>
</tr>
@@ -195,7 +227,11 @@ export default function Pregunta3_2() {
{currentData.map((item, index) => (
<tr
key={index}
className={item.isTotal ? styles.totalRow_P3 : styles.dataRow_P3}
className={
item.isTotal
? styles.totalRow_P3
: styles.dataRow_P3
}
>
<td className={styles.processor_P3}>{item.tipo}</td>
<td>
@@ -255,4 +291,4 @@ export default function Pregunta3_2() {
</div>
</div>
);
}
}
+6 -10
View File
@@ -21,8 +21,7 @@ export default function Pregunta7() {
{ nombre: "Impresión", valores: ["0.00", "0.00", "0.00", "0.00"] },
{
nombre: "Digitalización",
valores: ["0.00", "0.00", "0.00", "0.00"
],
valores: ["0.00", "0.00", "0.00", "0.00"],
},
]);
@@ -70,12 +69,7 @@ export default function Pregunta7() {
const pct = (v: number) => ((v / total) * 100).toFixed(2);
return [
pct(menores2),
pct(entre2_3),
pct(entre4_5),
pct(mayores6),
];
return [pct(menores2), pct(entre2_3), pct(entre4_5), pct(mayores6)];
};
// ------------------------------
@@ -85,8 +79,9 @@ export default function Pregunta7() {
const token = Cookies.get("token");
axios
.get<RespuestaAntiguedad>(
.post<RespuestaAntiguedad>(
`${api_url}/equipos/reporte/contar_perifericos_antiguedad`,
["EN DESUSO", "EN USO"],
{
headers: { Authorization: `Bearer ${token}` },
}
@@ -116,7 +111,8 @@ export default function Pregunta7() {
</div>
<div className="pregunta-cuadro">
Antigüedad que tienen los equipos periféricos del área universitaria.<ToggleButton/>
Antigüedad que tienen los equipos periféricos del área universitaria.
<ToggleButton />
</div>
<div className="tabla-contenedor">
+45 -19
View File
@@ -10,7 +10,7 @@ import ToggleButton from "../Toggle/ToggleButton";
type AntiguedadItem = {
antiguedad: string | null;
total: string;
porcentaje: string;
porcentaje: string;
};
type ApiResponse = {
@@ -21,16 +21,24 @@ type ApiResponse = {
export default function Pregunta9() {
const [datos, setDatos] = useState([
{ nombre: "Computadoras de Escritorio", valores: ["0.00", "0.00", "0.00", "0.00","0.00"] },
{ nombre: "Computadoras Portátiles", valores: ["0.00", "0.00", "0.00", "0.00","0.00"] },
{ nombre: "Alto Rendimiento", valores: ["0.00", "0.00", "0.00", "0.00","0.00"] },
{
nombre: "Computadoras de Escritorio",
valores: ["0.00", "0.00", "0.00", "0.00", "0.00"],
},
{
nombre: "Computadoras Portátiles",
valores: ["0.00", "0.00", "0.00", "0.00", "0.00"],
},
{
nombre: "Alto Rendimiento",
valores: ["0.00", "0.00", "0.00", "0.00", "0.00"],
},
]);
const [loading, setLoading] = useState(true);
// Transforma los datos del backend al formato de 4 columnas con % calculados
const transformarDatos = (items: AntiguedadItem[]): string[] => {
let menores2 = 0;
let entre2_3 = 0;
let entre4_6 = 0;
@@ -54,20 +62,28 @@ export default function Pregunta9() {
case "ENTRE 6 Y MAYORES":
mayores6 += total;
break;
// Cualquier otro valor (aunque no debería haber) lo meteríamos en mayores6
default:notfound += total; break;
// Cualquier otro valor (aunque no debería haber) lo meteríamos en mayores6
default:
notfound += total;
break;
}
}
const totalEquipo = menores2 + mayores6+ entre2_3 + entre4_6 + notfound;
const totalEquipo = menores2 + mayores6 + entre2_3 + entre4_6 + notfound;
if (totalEquipo === 0) {
return ["0.00", "0.00", "0.00", "0.00","0.00"];
return ["0.00", "0.00", "0.00", "0.00", "0.00"];
}
const pct = (valor: number) => ((valor / totalEquipo) * 100).toFixed(2);
return [pct(menores2), pct(entre2_3), pct(entre4_6), pct(mayores6),pct(notfound)];
return [
pct(menores2),
pct(entre2_3),
pct(entre4_6),
pct(mayores6),
pct(notfound),
];
};
useEffect(() => {
@@ -79,9 +95,13 @@ export default function Pregunta9() {
}
axios
.get<ApiResponse>(`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_antiguedad`, {
headers: { Authorization: `Bearer ${token}` },
})
.post<ApiResponse>(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/tipoEquipos_antiguedad`,
["EN DESUSO", "EN USO"],
{
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => {
const { escritorios, portatiles, altoRendimiento } = res.data;
@@ -117,7 +137,9 @@ export default function Pregunta9() {
return (
<div className="contenedor-pregunta">
<div className="contenedor-censo">Censo de equipos de cómputo - Generales</div>
<div className="contenedor-censo">
Censo de equipos de cómputo - Generales
</div>
{/* Pregunta intro (servidores) */}
{/* <div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
Indique cuantos servidores son utilizados en ambientes productivos y si en ellos se almacenan datos personales.
@@ -127,7 +149,8 @@ export default function Pregunta9() {
{/* Pregunta 9: Antigüedad */}
<div className="pregunta-cuadro">
Antigüedad que tienen los equipos de cómputo del área universitaria.<ToggleButton/>
Antigüedad que tienen los equipos de cómputo del área universitaria.
<ToggleButton />
</div>
<div className="tabla-contenedor">
@@ -162,7 +185,11 @@ export default function Pregunta9() {
</div>
</td>
))}
<td className={`total-celda ${total > 100.1 ? "total-error" : ""}`}>
<td
className={`total-celda ${
total > 100.1 ? "total-error" : ""
}`}
>
{total.toFixed(2)}%
</td>
</tr>
@@ -172,8 +199,7 @@ export default function Pregunta9() {
</table>
</div>
<Pregunta10/>
<Pregunta10 />
</div>
);
}
}
+13 -20
View File
@@ -24,9 +24,13 @@ export default function Pregunta10() {
}
axios
.get<number[]>(`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/garantia`, {
headers: { Authorization: `Bearer ${token}` },
})
.post<number[]>(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/reporte/garantia`,
["EN DESUSO", "EN USO"],
{
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => {
const [escritorio, portatil, altoRendimiento] = res.data;
@@ -46,17 +50,14 @@ export default function Pregunta10() {
}, []);
if (loading) {
return (
<div className="pregunta-cuadro">
Cargando datos de garantía...
</div>
);
return <div className="pregunta-cuadro">Cargando datos de garantía...</div>;
}
return (
<>
<div className="pregunta-cuadro">
Equipos de cómputo que tienen garantía de proveedoro.<ToggleButton/>
Equipos de cómputo que tienen garantía de proveedoro.
<ToggleButton />
</div>
<div className="tabla-contenedor">
@@ -72,20 +73,12 @@ export default function Pregunta10() {
<tr>
<td>
<div className="input-contenedor input-sp">
<input
type="number"
value={garantia.escritorio}
readOnly
/>
<input type="number" value={garantia.escritorio} readOnly />
</div>
</td>
<td>
<div className="input-contenedor input-sp">
<input
type="number"
value={garantia.portatil}
readOnly
/>
<input type="number" value={garantia.portatil} readOnly />
</div>
</td>
<td>
@@ -103,4 +96,4 @@ export default function Pregunta10() {
</div>
</>
);
}
}
+11 -4
View File
@@ -41,9 +41,13 @@ export default function Pregunta1EP() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/equipos_impesion_group/impresoras`, {
headers,
})
.post(
`${api_url}/equipos/reporte/equipos_impesion_group/impresoras`,
["EN DESUSO", "EN USO"],
{
headers,
}
)
.then((res) => {
const data = res.data;
@@ -121,7 +125,10 @@ export default function Pregunta1EP() {
Censo de equipos periféricos - Equipo de Impresion
</div>
<div className="pregunta-cuadro">Equipos de impresión.<ToggleButton/></div>
<div className="pregunta-cuadro">
Equipos de impresión.
<ToggleButton />
</div>
<div className={style.grid}>
{/* Columna 1 */}
+9 -4
View File
@@ -31,9 +31,13 @@ export default function Pregunta2EP() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_periferico_tipoUso/impresoras`, {
headers,
})
.post(
`${api_url}/equipos/reporte/contar_periferico_tipoUso/impresoras`,
["EN DESUSO", "EN USO"],
{
headers,
}
)
.then((res) => {
const data = res.data;
@@ -98,7 +102,8 @@ export default function Pregunta2EP() {
return (
<div className={styles.container_P2}>
<div className="pregunta-cuadro">
Equipos de impresión de acuerdo con la población universitaria.<ToggleButton/>
Equipos de impresión de acuerdo con la población universitaria.
<ToggleButton />
</div>
<div className={styles.row_P2}>
+9 -4
View File
@@ -26,9 +26,13 @@ export default function Pregunta4EP() {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/equipos_impesion_group/dijitales`, {
headers,
})
.post(
`${api_url}/equipos/reporte/equipos_impesion_group/dijitales`,
["EN DESUSO", "EN USO"],
{
headers,
}
)
.then((res) => {
const data = res.data;
@@ -77,7 +81,8 @@ export default function Pregunta4EP() {
</div>
<div className="pregunta-cuadro">
Número de equipos de digitalización.<ToggleButton/>
Número de equipos de digitalización.
<ToggleButton />
</div>
<div className="grid">
+9 -4
View File
@@ -32,9 +32,13 @@ export default function Pregunta5EP() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_periferico_tipoUso/dijtales`, {
headers,
})
.post(
`${api_url}/equipos/reporte/contar_periferico_tipoUso/dijtales`,
["EN DESUSO", "EN USO"],
{
headers,
}
)
.then((res) => {
const data = res.data;
@@ -99,7 +103,8 @@ export default function Pregunta5EP() {
<div className="container">
<div className="pregunta-cuadro">
Número de equipos de digitalización de acuerdo con la población
universitaria.<ToggleButton/>
universitaria.
<ToggleButton />
</div>
<div className={styles.row_P2}>
+15 -6
View File
@@ -25,7 +25,11 @@ export default function Pregunta7EP() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_laboratorio`, { headers })
.post(
`${api_url}/equipos/reporte/contar_laboratorio`,
["EN DESUSO", "EN USO"],
{ headers }
)
.then((res) => {
const formato: Dato[] = res.data.map((item: any) => ({
nombre: item.laboratorio || "SIN NOMBRE",
@@ -75,15 +79,20 @@ export default function Pregunta7EP() {
const startItem = (currentPage - 1) * recordsPerPage + 1;
const endItem = Math.min(startItem + recordsPerPage - 1, sortedData.length);
const totalLaboratorios = data.reduce(
(sum, item) => sum + (item.nombre != "NO_APLICA" ? Number(item.cantidad):0),
(sum, item) =>
sum + (item.nombre != "NO_APLICA" ? Number(item.cantidad) : 0),
0
);
return (
<div className="container">
<div className="contenedor-censo">Censo de equipos de cómputo - Laboratorio</div>
<div className="pregunta-cuadro">Numero de laboratorios.<ToggleButton/></div>
<div className="contenedor-censo">
Censo de equipos de cómputo - Laboratorio
</div>
<div className="pregunta-cuadro">
Numero de laboratorios.
<ToggleButton />
</div>
<div className="controls">
<div className="show-records">
+14 -5
View File
@@ -25,7 +25,11 @@ export default function Pregunta8() {
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_proyecto`, { headers })
.post(
`${api_url}/equipos/reporte/contar_proyecto`,
["EN DESUSO", "EN USO"],
{ headers }
)
.then((res) => {
const formato: Dato[] = res.data.map((item: any) => ({
nombre: item.proyecto || "SIN PROYECTO",
@@ -75,15 +79,20 @@ export default function Pregunta8() {
const startItem = (currentPage - 1) * recordsPerPage + 1;
const endItem = Math.min(startItem + recordsPerPage - 1, sortedData.length);
const totalLaboratorios = data.reduce(
(sum, item) => sum + (item.nombre != "NO_APLICA" ? Number(item.cantidad):0),
(sum, item) =>
sum + (item.nombre != "NO_APLICA" ? Number(item.cantidad) : 0),
0
);
return (
<div className="container">
<div className="contenedor-censo">Censo de equipos de cómputo - Proyectos</div>
<div className="pregunta-cuadro">Numero de proyectos.<ToggleButton/></div>
<div className="contenedor-censo">
Censo de equipos de cómputo - Proyectos
</div>
<div className="pregunta-cuadro">
Numero de proyectos.
<ToggleButton />
</div>
<div className="controls">
<div className="show-records">
Mostrar