fixed %
This commit is contained in:
@@ -14,6 +14,7 @@ type PreguntaKey =
|
||||
| "pregunta2"
|
||||
| "pregunta3"
|
||||
| "pregunta7EP"
|
||||
| "pregunta8"
|
||||
| "pregunta9";
|
||||
|
||||
const LABELS: Record<PreguntaKey, string> = {
|
||||
@@ -21,6 +22,7 @@ const LABELS: Record<PreguntaKey, string> = {
|
||||
pregunta2: "Sistema Operativo",
|
||||
pregunta3: "Plataforma y tipo procesador",
|
||||
pregunta7EP: "Laboratorios",
|
||||
pregunta8:"Proyectos",
|
||||
pregunta9: "Generales",
|
||||
};
|
||||
|
||||
@@ -30,6 +32,7 @@ const TAB_BACKGROUNDS: Record<PreguntaKey, string> = {
|
||||
pregunta2: "bg-gray",
|
||||
pregunta3: "bg-gray",
|
||||
pregunta7EP: "bg-gray",
|
||||
pregunta8:"bg-gray",
|
||||
pregunta9: "bg-blue",
|
||||
};
|
||||
|
||||
@@ -45,12 +48,9 @@ export default function Page() {
|
||||
case "pregunta3":
|
||||
return <Pregunta3 />;
|
||||
case "pregunta7EP":
|
||||
return (
|
||||
<>
|
||||
<Pregunta7EP />
|
||||
<Pregunta8 />
|
||||
</>
|
||||
);
|
||||
return <Pregunta7EP />
|
||||
case "pregunta8":
|
||||
return <Pregunta8 />;
|
||||
case "pregunta9":
|
||||
return <Pregunta9 />;
|
||||
default:
|
||||
|
||||
@@ -110,6 +110,15 @@ tr:nth-child(even) {
|
||||
}
|
||||
}
|
||||
|
||||
.total-labs {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.controls {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -1,99 +1,113 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import axios from "axios";
|
||||
import "./pregunta7.css";
|
||||
|
||||
interface AntiguedadItem {
|
||||
antiguedad: string;
|
||||
total: number;
|
||||
porcentaje?: string;
|
||||
}
|
||||
type AntiguedadItem = {
|
||||
antiguedad: string | null;
|
||||
total: number | string;
|
||||
};
|
||||
|
||||
interface RespuestaAntiguedad {
|
||||
type RespuestaAntiguedad = {
|
||||
impresion: AntiguedadItem[];
|
||||
digitalizacion: AntiguedadItem[];
|
||||
}
|
||||
};
|
||||
|
||||
export default function Pregunta7() {
|
||||
const [datos, setDatos] = useState([
|
||||
{ nombre: "Impresión", valores: ["0.00", "0.00", "0.00", "0.00"] },
|
||||
{ nombre: "Digitalización", valores: ["0.00", "0.00", "0.00", "0.00"] },
|
||||
{ nombre: "Impresión", valores: ["0.00", "0.00", "0.00", "0.00", "0.00"] },
|
||||
{
|
||||
nombre: "Digitalización",
|
||||
valores: ["0.00", "0.00", "0.00", "0.00", "0.00"],
|
||||
},
|
||||
]);
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const api_url = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const calcularTotal = (valores: string[]) =>
|
||||
valores.reduce((acc, val) => acc + (Number(val) || 0), 0);
|
||||
// ------------------------------
|
||||
// TRANSFORMADOR (maneja null)
|
||||
// ------------------------------
|
||||
const transformarDatos = (items: AntiguedadItem[]): string[] => {
|
||||
let menores2 = 0;
|
||||
let entre2_3 = 0;
|
||||
let entre4_5 = 0;
|
||||
let mayores6 = 0;
|
||||
let notfound = 0;
|
||||
|
||||
for (const item of items) {
|
||||
const total = Number(item.total) || 0;
|
||||
const antig = item.antiguedad ? item.antiguedad.toUpperCase().trim() : null;
|
||||
|
||||
switch (antig) {
|
||||
case "MENORES DE 2":
|
||||
menores2 += total;
|
||||
break;
|
||||
case "ENTRE 2 Y 3":
|
||||
entre2_3 += total;
|
||||
break;
|
||||
case "ENTRE 4 Y 5":
|
||||
entre4_5 += total;
|
||||
break;
|
||||
case "ENTRE 6 Y MAYORES":
|
||||
mayores6 += total;
|
||||
break;
|
||||
default:
|
||||
notfound += total; // incluye null
|
||||
}
|
||||
}
|
||||
|
||||
const total = menores2 + entre2_3 + entre4_5 + mayores6 + notfound;
|
||||
|
||||
if (total === 0) return ["0.00", "0.00", "0.00", "0.00", "0.00"];
|
||||
|
||||
const pct = (v: number) => ((v / total) * 100).toFixed(2);
|
||||
|
||||
return [
|
||||
pct(menores2),
|
||||
pct(entre2_3),
|
||||
pct(entre4_5),
|
||||
pct(mayores6),
|
||||
pct(notfound),
|
||||
];
|
||||
};
|
||||
|
||||
// ------------------------------
|
||||
// CARGA DE DATOS
|
||||
// ------------------------------
|
||||
useEffect(() => {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
axios
|
||||
.get(`${api_url}/equipos/reporte/contar_perifericos_antiguedad`, {
|
||||
headers,
|
||||
})
|
||||
.get<RespuestaAntiguedad>(
|
||||
`${api_url}/equipos/reporte/contar_perifericos_antiguedad`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
const data: RespuestaAntiguedad = res.data;
|
||||
const { impresion, digitalizacion } = res.data;
|
||||
|
||||
const orden = [
|
||||
"MENORES DE 2",
|
||||
"ENTRE 2 Y 3",
|
||||
"ENTRE 4 Y 5",
|
||||
"MAYOR A 6",
|
||||
];
|
||||
|
||||
const nuevaTabla = [
|
||||
{ nombre: "Impresión", totales: [0, 0, 0, 0] },
|
||||
{ nombre: "Digitalización", totales: [0, 0, 0, 0] },
|
||||
];
|
||||
|
||||
if (Array.isArray(data.impresion)) {
|
||||
data.impresion.forEach((item) => {
|
||||
const antig = item.antiguedad.toUpperCase().trim();
|
||||
const i = orden.indexOf(antig);
|
||||
if (i !== -1) nuevaTabla[0].totales[i] = Number(item.total) || 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(data.digitalizacion)) {
|
||||
data.digitalizacion.forEach((item) => {
|
||||
const antig = item.antiguedad.toUpperCase().trim();
|
||||
const i = orden.indexOf(antig);
|
||||
if (i !== -1) nuevaTabla[1].totales[i] = Number(item.total) || 0;
|
||||
});
|
||||
}
|
||||
|
||||
const tablaConPorcentajes = nuevaTabla.map((fila) => {
|
||||
const totalFila = fila.totales.reduce((a, b) => a + b, 0);
|
||||
|
||||
let valores = ["0", "0", "0", "0"];
|
||||
|
||||
if (totalFila > 0) {
|
||||
valores = fila.totales.map((v) =>
|
||||
((v / totalFila) * 100).toFixed(2)
|
||||
);
|
||||
}
|
||||
|
||||
return { nombre: fila.nombre, valores };
|
||||
});
|
||||
|
||||
setDatos(tablaConPorcentajes);
|
||||
setDatos([
|
||||
{ nombre: "Impresión", valores: transformarDatos(impresion) },
|
||||
{ nombre: "Digitalización", valores: transformarDatos(digitalizacion) },
|
||||
]);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error cargando datos:", err);
|
||||
});
|
||||
.catch((err) => console.error("Error cargando datos:", err))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
const calcularTotalFila = (valores: string[]) =>
|
||||
valores.reduce((t, v) => t + Number(v), 0);
|
||||
|
||||
if (loading) return <div className="contenedor-pregunta">Cargando datos...</div>;
|
||||
|
||||
return (
|
||||
<div className="contenedor-pregunta">
|
||||
<div className="contenedor-censo">
|
||||
Censo de equipos periféricos - Estado del equipo periférico (impresión y
|
||||
digitalización.)
|
||||
</div>
|
||||
|
||||
<div className="pregunta-cuadro">
|
||||
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
|
||||
Antigüedad que tienen los equipos periféricos del área universitaria.
|
||||
</div>
|
||||
|
||||
@@ -101,36 +115,34 @@ export default function Pregunta7() {
|
||||
<table className="tabla">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="azul-marino">% Antiguedad de los equipos</th>
|
||||
<th className="azul-marino">% Antigüedad de los equipos</th>
|
||||
<th className="rosa-fuerte">Menor a 2 años</th>
|
||||
<th className="rosa-fuerte">Entre 2 y 3 años</th>
|
||||
<th className="rosa-fuerte">Entre 4 y 5 años</th>
|
||||
<th className="rosa-fuerte">Mayor a 6 años</th>
|
||||
<th className="rosa-fuerte">No registrados</th>
|
||||
<th className="azul-marino">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{datos.map((fila, filaIndex) => {
|
||||
const total = calcularTotal(fila.valores);
|
||||
{datos.map((fila, idx) => {
|
||||
const total = calcularTotalFila(fila.valores);
|
||||
|
||||
return (
|
||||
<tr key={filaIndex}>
|
||||
<tr key={idx}>
|
||||
<td>{fila.nombre}</td>
|
||||
|
||||
{fila.valores.map((valor, colIndex) => (
|
||||
<td key={colIndex}>
|
||||
{fila.valores.map((v, c) => (
|
||||
<td key={c}>
|
||||
<div className="input-contenedor">
|
||||
<input type="number" value={valor} disabled />
|
||||
<input type="number" value={v} readOnly />
|
||||
<span className="porcentaje">%</span>
|
||||
</div>
|
||||
</td>
|
||||
))}
|
||||
|
||||
<td
|
||||
className={`total-celda ${
|
||||
total > 100 ? "total-error" : ""
|
||||
}`}
|
||||
>
|
||||
<td className={`total-celda ${total > 100.1 ? "total-error" : ""}`}>
|
||||
{total.toFixed(2)}%
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import axios from "axios";
|
||||
import "./pregunta9.css";
|
||||
import Pregunta4 from "./Pregunta_4";
|
||||
import Pregunta10 from "./pregunta10";
|
||||
|
||||
type AntiguedadItem = {
|
||||
antiguedad: string | null;
|
||||
total: string;
|
||||
porcentaje: string; // lo ignoramos
|
||||
porcentaje: string;
|
||||
};
|
||||
|
||||
type ApiResponse = {
|
||||
@@ -26,12 +25,6 @@ export default function Pregunta9() {
|
||||
{ nombre: "Alto Rendimiento", valores: ["0.00", "0.00", "0.00", "0.00","0.00"] },
|
||||
]);
|
||||
|
||||
const [garantia, setGarantia] = useState({
|
||||
escritorio: "",
|
||||
portatil: "",
|
||||
altoRendimiento: "",
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Transforma los datos del backend al formato de 4 columnas con % calculados
|
||||
@@ -48,7 +41,7 @@ export default function Pregunta9() {
|
||||
const total = Number(item.total) || 0;
|
||||
|
||||
switch (item.antiguedad) {
|
||||
case "MENOR A 2":
|
||||
case "MENORES DE 2":
|
||||
menores2 += total;
|
||||
break;
|
||||
case "ENTRE 2 Y 3":
|
||||
@@ -57,7 +50,7 @@ export default function Pregunta9() {
|
||||
case "ENTRE 4 Y 5":
|
||||
entre4_6 += total;
|
||||
break;
|
||||
case "MAYORES DE 6":
|
||||
case "ENTRE 6 Y MAYORES":
|
||||
mayores6 += total;
|
||||
break;
|
||||
// Cualquier otro valor (aunque no debería haber) lo meteríamos en mayores6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
import "./pregunta10.css";
|
||||
@@ -37,7 +37,6 @@ export default function Pregunta10() {
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error al cargar datos de garantía", err);
|
||||
// Opcional: establecer valores por defecto en caso de error
|
||||
setGarantia({ escritorio: "0", portatil: "0", altoRendimiento: "0" });
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -75,7 +74,7 @@ export default function Pregunta10() {
|
||||
<input
|
||||
type="number"
|
||||
value={garantia.escritorio}
|
||||
readOnly // 👈 solo lectura, como en otros reportes
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -73,12 +73,11 @@ 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 + Number(item.cantidad), 0);
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="pregunta-cuadro">
|
||||
Numero de laboratorios.
|
||||
</div>
|
||||
<div className="pregunta-cuadro">Numero de laboratorios.</div>
|
||||
|
||||
<div className="controls">
|
||||
<div className="show-records">
|
||||
@@ -138,6 +137,10 @@ export default function Pregunta7EP() {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="total-labs">
|
||||
Total de laboratorios: <strong>{totalLaboratorios}</strong>
|
||||
</div>
|
||||
|
||||
<div className="pagination">
|
||||
<button
|
||||
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
|
||||
|
||||
@@ -73,6 +73,10 @@ 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 + Number(item.cantidad),
|
||||
0
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
@@ -135,6 +139,10 @@ export default function Pregunta8() {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="total-labs">
|
||||
Total de proyecto: <strong>{totalLaboratorios}</strong>
|
||||
</div>
|
||||
|
||||
<div className="pagination">
|
||||
<button
|
||||
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
|
||||
|
||||
Reference in New Issue
Block a user