This commit is contained in:
jls846
2025-11-26 16:22:10 -06:00
69 changed files with 1064 additions and 5604 deletions
+26 -1
View File
@@ -13,6 +13,7 @@
"@zxing/library": "^0.21.3",
"axios": "^1.13.2",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"next": "16.0.2",
"react": "19.2.0",
"react-dom": "19.2.0",
@@ -61,6 +62,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -1632,6 +1634,7 @@
"integrity": "sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -1692,6 +1695,7 @@
"integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.4",
"@typescript-eslint/types": "8.46.4",
@@ -2233,6 +2237,7 @@
"resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.21.3.tgz",
"integrity": "sha512-hZHqFe2JyH/ZxviJZosZjV+2s6EDSY0O24R+FQmlWZBZXP9IqMo7S3nb3+2LBWxodJQkSurdQGnqE7KXqrYgow==",
"license": "MIT",
"peer": true,
"dependencies": {
"ts-custom-error": "^3.2.1"
},
@@ -2256,6 +2261,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2655,6 +2661,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754",
@@ -2872,7 +2879,8 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/cwise-compiler": {
"version": "1.1.3",
@@ -3299,6 +3307,7 @@
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3484,6 +3493,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -4969,6 +4979,15 @@
"node": ">=4.0"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -5702,6 +5721,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -5711,6 +5731,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -6015,6 +6036,7 @@
"integrity": "sha512-Dqh7SiYcaFtdv5Wvku6QgS5IGPm281L+ZtVD1U2FJa7Q0EFRlq8Z3sjYtz6gYObsYThUOz9ArwFqPZx+1azILQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -6549,6 +6571,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -6751,6 +6774,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -7055,6 +7079,7 @@
"integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
+1
View File
@@ -14,6 +14,7 @@
"@zxing/library": "^0.21.3",
"axios": "^1.13.2",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"next": "16.0.2",
"react": "19.2.0",
"react-dom": "19.2.0",
+13 -28
View File
@@ -4,33 +4,16 @@ import { useState } from "react";
import "../../styles/layout/login.scss";
import "../../styles/base/globales.scss";
import Link from "next/link";
import axios from "axios";
import { useRouter } from "next/navigation";
import toast from "react-hot-toast";
import Cookies from "js-cookie";
export default function Page() {
const [nombre, setNombre] = useState("");
const [correo, setCorreo] = useState("");
const [password, setPassword] = useState("");
const [confirmarPassword, setConfirmarPassword] = useState("");
const [loading, setLoading] = useState(false);
const router = useRouter();
const [crearCuenta,setCrearCuenta]=useState();
async function CrearCuenta() {
const res=await axios.post("https",{
nombre,
contraseña:password,
tipoUsuario:2
});
setCrearCuenta(res.data);
}
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
@@ -42,17 +25,20 @@ export default function Page() {
setLoading(true);
try {
const response = await axios.post(
`${process.env.NEXT_PUBLIC_API_URL}/auth/registro`,
{
nombre,
contraseña: password,
tipoUsuario: 2,
}
);
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
const response = await axios.post(
`${process.env.NEXT_PUBLIC_API_URL}/auth/registro`,
{
nombre,
contraseña: password,
tipoUsuario: 2,
},
{ headers }
);
toast.success("Cuenta creada correctamente");
router.push("/"); // redirige al login
} catch (err: unknown) {
if (axios.isAxiosError(err)) {
if (err.response) {
@@ -111,7 +97,6 @@ export default function Page() {
<button type="submit" disabled={loading}>
{loading ? "Creando cuenta..." : "Registrarse"}
</button>
</form>
</div>
</section>
+8 -10
View File
@@ -3,29 +3,27 @@
import { useState } from "react";
import Pregunta1 from "@/components/Equipo_Computo/Pregunta1";
import Pregutna2 from "@/components/Equipo_Computo/Pregunta2";
import Pregunta2_1 from "@/components/Equipo_Computo/Pregunta2_1";
import Pregunta3 from "@/components/Equipo_Computo/Pregunta3";
import Pregunta7EP from "@/components/Perifericos/Pregunta7EP";
import Pregunta9 from "@/components/Equipo_Computo/Pregunta9";
import Pregunta10 from "@/components/Equipo_Computo/pregunta10";
import "../../styles/layout/reporte.scss";
import Pregunta_4 from "@/components/Equipo_Computo/Pregunta_4";
import Pregunta8 from "@/components/Perifericos/Pregunta8";
type PreguntaKey =
| "pregunta1"
| "pregunta2"
| "pregunta3"
| "pregunta7EP"
| "pregunta9"
| "pregunta10";
| "pregunta8"
| "pregunta9";
const LABELS: Record<PreguntaKey, string> = {
pregunta1: "Perfil de Usuario",
pregunta2: "Sistema Operativo",
pregunta3: "Plataforma y tipo procesador",
pregunta7EP: "Laboratorios",
pregunta8:"Proyectos",
pregunta9: "Generales",
pregunta10: "Garantía de Proveedor",
};
// Mapeo de fondo por pregunta (puedes personalizarlo)
@@ -34,8 +32,8 @@ const TAB_BACKGROUNDS: Record<PreguntaKey, string> = {
pregunta2: "bg-gray",
pregunta3: "bg-gray",
pregunta7EP: "bg-gray",
pregunta8:"bg-gray",
pregunta9: "bg-blue",
pregunta10: "bg-blue",
};
export default function Page() {
@@ -50,11 +48,11 @@ export default function Page() {
case "pregunta3":
return <Pregunta3 />;
case "pregunta7EP":
return <Pregunta7EP />;
return <Pregunta7EP />
case "pregunta8":
return <Pregunta8 />;
case "pregunta9":
return <Pregunta9 />;
case "pregunta10":
return <Pregunta10 />;
default:
return (
<div className="p-6 text-center text-gray-500">
+24 -21
View File
@@ -7,20 +7,14 @@ import Pregunta2EP from "@/components/Perifericos/Pregunta2EP";
import Pregunta4EP from "@/components/Perifericos/Pregunta4EP";
import Pregunta5EP from "@/components/Perifericos/Pregunta5EP";
import "../../styles/layout/reporte.scss";
import DownloadReporteXLSX from "@/components/Dowload/Reporte";
type PreguntaKey =
| "pregunta1"
| "pregunta2"
| "pregunta4"
| "pregunta5"
| "pregunta7";
type PreguntaKey = "pregunta1" | "pregunta4" | "pregunta7";
const LABELS: Record<PreguntaKey, string> = {
pregunta1: "Pregunta 1",
pregunta2: "Pregunta 2",
pregunta4: "Pregunta 4",
pregunta5: "Pregunta 5",
pregunta7: "Pregunta 7",
pregunta1: "Impresoras",
pregunta4: "Digitales",
pregunta7: "Antiguedad",
};
export default function Page() {
@@ -29,15 +23,26 @@ export default function Page() {
const renderPregunta = () => {
switch (activeTab) {
case "pregunta1":
return <Pregunta1EP />;
case "pregunta2":
return <Pregunta2EP />;
return (
<>
<Pregunta1EP />
<Pregunta2EP />
</>
);
case "pregunta4":
return <Pregunta4EP />;
case "pregunta5":
return <Pregunta5EP />;
return (
<>
<Pregunta4EP />
<Pregunta5EP />
</>
);
case "pregunta7":
return <Pregunta7 />;
return (
<>
<Pregunta7 />
<DownloadReporteXLSX/>
</>
);
default:
return (
<div className="p-6 text-center text-gray-500">
@@ -64,9 +69,7 @@ export default function Page() {
</button>
))}
</div>
<div className={`data-table_reporte`}>
{renderPregunta()}
</div>
<div className={`data-table_reporte`}>{renderPregunta()}</div>
</div>
</div>
</div>
-124
View File
@@ -1,124 +0,0 @@
"use client";
import { useState } from "react";
type OsEntry = {
os: string;
count: number;
isTotal?: boolean;
};
type PlatformKey =
| "pc-desktop"
| "apple-desktop"
| "pc-laptop"
| "apple-laptop"
| "servers";
type PlatformData = Record<PlatformKey, OsEntry[]>;
const MOCK_DATA: PlatformData = {
"pc-desktop": [
{ os: "Windows 11", count: 408 },
{ os: "Windows 10", count: 1171 },
{ os: "Windows 7/8", count: 177 },
{ os: "Windows XP/Vista", count: 43 },
{ os: "Linux", count: 45 },
{ os: "Total", count: 1844, isTotal: true },
],
"apple-desktop": [
{ os: "Mac OS X (13 - Ventura, 14 - Sonoma)", count: 205 },
{
os: "Mac OS X (Mojave, Catalina, 11 - Big Sur, 12 - Monterrey)",
count: 180,
},
{ os: "Mac OS X (Yosemite, El Capitan, Sierra, High Sierra)", count: 95 },
{ os: "Mac OS X (Snow Leopard, Mountain Lion, Mavericks)", count: 6 },
{ os: "Total", count: 480, isTotal: true },
],
"pc-laptop": [
{ os: "Windows 11", count: 40 },
{ os: "Windows 10", count: 171 },
{ os: "Windows 7/8", count: 17 },
{ os: "Windows XP/Vista", count: 3 },
{ os: "Linux", count: 5 },
{ os: "Total", count: 236, isTotal: true },
],
"apple-laptop": [
{ os: "Mac OS X (13 - Ventura, 14 - Sonoma)", count: 205 },
{
os: "Mac OS X (Mojave, Catalina, 11 - Big Sur, 12 - Monterrey)",
count: 180,
},
{ os: "Mac OS X (Yosemite, El Capitan, Sierra, High Sierra)", count: 95 },
{ os: "Mac OS X (Snow Leopard, Mountain Lion, Mavericks)", count: 6 },
{ os: "Total", count: 480, isTotal: true },
],
servers: [
{
os: "Linux (CentOS, Fedora, Ubuntu, Red Hat Enterprise, entre otros)",
count: 120,
},
{ os: "Unix (AIX, Mac OS Server, Solaris, etc.)", count: 80 },
{ os: "Windows Server 2022/2023", count: 50 },
{ os: "Windows Server 2016/2019", count: 80 },
{ os: "Windows Server 2008/2012", count: 50 },
{ os: "Windows Server 2000/2003", count: 12 },
{ os: "Total", count: 392, isTotal: true },
],
};
const PLATFORM_LABELS: Record<PlatformKey, string> = {
"pc-desktop": "Computadoras de escritorio Plataforma PC",
"apple-desktop": "Computadoras de escritorio Plataforma Apple",
"pc-laptop": "Computadoras portátiles Plataforma PC",
"apple-laptop": "Computadoras portátiles Plataforma Apple",
servers: "Servidores de alto rendimiento",
};
export default function Pregunta1() {
const [activeTab, setActiveTab] = useState<PlatformKey>("pc-desktop");
const currentData = MOCK_DATA[activeTab];
return (
<div className="scanView">
<div className="container">
<div className="header">
Presione cada pestaña para ver la información de las plataformas.
</div>
<div className="main-content">
{/* Tabs */}
<div className="tabs">
{Object.entries(PLATFORM_LABELS).map(([key, label]) => (
<button
key={key}
className={`tab ${activeTab === key ? "active" : ""}`}
onClick={() => setActiveTab(key as PlatformKey)}
aria-selected={activeTab === key}
>
{label}
</button>
))}
</div>
{/* Data Table */}
<div className="data-table-wrapper">
<div className="data-table">
{currentData.map((item, index) => (
<div
key={index}
className={`data-row ${item.isTotal ? "total-row" : ""}`}
>
<div className="os-name">{item.os}</div>
<div className="count-box">{item.count}</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
}
@@ -1,162 +0,0 @@
"use client";
import React, { useState, useEffect } from "react";
import "../../styles/layout/pregunta1EP.scss";
interface EquiposImpresion {
inyeccionTinta: string;
laserPequenaBN: string;
matrizPuntos: string;
laserAltoVolumenBN: string;
laserPequenaColor: string;
multifuncionales: string;
laserAltoVolumenColor: string;
impresora3D: string;
plotter: string;
}
export default function Pregunta1EPPage() {
const [equipos, setEquipos] = useState<EquiposImpresion>({
inyeccionTinta: "7",
laserPequenaBN: "186",
matrizPuntos: "",
laserAltoVolumenBN: "28",
laserPequenaColor: "20",
multifuncionales: "108",
laserAltoVolumenColor: "18",
impresora3D: "2",
plotter: "11",
});
// 🔹 Preparado para conectar con API del backend
useEffect(() => {
// Cuando te den la API, descomenta y edita la URL 👇
/*
fetch("https://tu-api-backend.com/api/equipos-impresion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEquipos({
...equipos,
[e.target.name]: e.target.value,
});
};
return (
<div className="container">
<div className="header">
1. Desglose el número de equipos de impresión con que cuenta el área
universitaria.
</div>
<div className="grid">
{/* Columna 1 */}
<div className="item">
<label htmlFor="inyeccionTinta">Inyección de tinta</label>
<input
type="text"
id="inyeccionTinta"
name="inyeccionTinta"
value={equipos.inyeccionTinta}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="laserPequenaBN">Láser pequeña B/N</label>
<input
type="text"
id="laserPequenaBN"
name="laserPequenaBN"
value={equipos.laserPequenaBN}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="matrizPuntos">Matriz de puntos</label>
<input
type="text"
id="matrizPuntos"
name="matrizPuntos"
value={equipos.matrizPuntos}
onChange={handleChange}
/>
</div>
{/* Columna 2 */}
<div className="item">
<label htmlFor="laserAltoVolumenBN">Láser de alto volumen B/N</label>
<input
type="text"
id="laserAltoVolumenBN"
name="laserAltoVolumenBN"
value={equipos.laserAltoVolumenBN}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="laserPequenaColor">Láser pequeña Color</label>
<input
type="text"
id="laserPequenaColor"
name="laserPequenaColor"
value={equipos.laserPequenaColor}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="multifuncionales">Multifuncionales</label>
<input
type="text"
id="multifuncionales"
name="multifuncionales"
value={equipos.multifuncionales}
onChange={handleChange}
/>
</div>
{/* Columna 3 */}
<div className="item">
<label htmlFor="laserAltoVolumenColor">
Láser de alto volumen Color
</label>
<input
type="text"
id="laserAltoVolumenColor"
name="laserAltoVolumenColor"
value={equipos.laserAltoVolumenColor}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="impresora3D">3D</label>
<input
type="text"
id="impresora3D"
name="impresora3D"
value={equipos.impresora3D}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="plotter">Plotter</label>
<input
type="text"
id="plotter"
name="plotter"
value={equipos.plotter}
onChange={handleChange}
/>
</div>
</div>
</div>
);
}
@@ -1,129 +0,0 @@
"use client";
import React, { useState } from "react";
import "./pregunta1.1.css";
export default function Pregunta1() {
const [datos, setDatos] = useState([
{ nombre: "Windows", valores: ["", "", "", "", ""] },
{ nombre: "Linux", valores: ["", "", "", "", ""] },
{ nombre: "Mac OS", valores: ["", "", "", "", ""] },
{ nombre: "Total", valores: ["", "", "", "", ""] },
]);
const handleChange = (filaIndex: number, colIndex: number, value: string) => {
const nuevosDatos = [...datos];
nuevosDatos[filaIndex].valores[colIndex] = value;
setDatos(nuevosDatos);
};
const calcularTotalFila = (valores: string[]) =>
valores.reduce((acc, val) => acc + (Number(val) || 0), 0);
const calcularTotalesColumnas = () => {
const numColumnas = datos[0].valores.length;
const totales = Array(numColumnas).fill(0);
datos.slice(0, -1).forEach((fila) => {
fila.valores.forEach((valor, colIndex) => {
totales[colIndex] += Number(valor) || 0;
});
});
return totales;
};
const totalesColumnas = calcularTotalesColumnas();
// Títulos de las tablas
const tablas = [
"Computadoras de escritorio",
"Tabletas",
"Computadoras portátiles",
"Alto rendimiento",
];
// Función para renderizar una tabla
const renderTabla = (titulo: string) => (
<div className="tabla-contenedor">
<table className="tabla">
<thead>
<tr>
<th className="azul-marino">{titulo}</th>
<th className="rosa-fuerte">Alumnos</th>
<th className="rosa-fuerte">Profesores</th>
<th className="rosa-fuerte">Técnicos Académicos</th>
<th className="rosa-fuerte">Investigadores</th>
<th className="rosa-fuerte">Administrativos</th>
<th className="azul-marino">Total</th>
</tr>
</thead>
<tbody>
{datos.map((fila, filaIndex) => {
if (fila.nombre === "Total") {
const totalGeneral = calcularTotalFila(
totalesColumnas.map(String)
);
return (
<tr key={filaIndex} className="fila-total">
<td className="negrita">{fila.nombre}</td>
{totalesColumnas.map((colTotal, i) => (
<td key={i}>{colTotal}</td>
))}
<td className="negrita">{totalGeneral}</td>
</tr>
);
}
const totalFila = calcularTotalFila(fila.valores);
return (
<tr key={filaIndex}>
<td>{fila.nombre}</td>
{fila.valores.map((valor, colIndex) => (
<td key={colIndex}>
<div className="input-contenedor">
<input
type="number"
value={valor}
onChange={(e) =>
handleChange(filaIndex, colIndex, e.target.value)
}
/>
</div>
</td>
))}
<td
className={`total-celda ${
totalFila > 100 ? "total-error" : ""
}`}
>
{totalFila}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
return (
<div className="contenedor-pregunta">
<div className="contenedor-censo">Censo de equipos de cómputo</div>
<div className="pregunta-cuadro">
1. Desglose en cada renglón, el número de equipos de cómputo dedicado por cada categoría
enlistada, de acuerdo con el perfil de usuario al que se destina su uso primordialmente. *
</div>
{/* FILA SUPERIOR */}
<div className="contenedor-tablas">
{renderTabla(tablas[0])}
{renderTabla(tablas[1])}
</div>
{/* FILA INFERIOR */}
<div className="contenedor-tablas">
{renderTabla(tablas[2])}
{renderTabla(tablas[3])}
</div>
</div>
);
}
@@ -1,148 +0,0 @@
.contenedor-pregunta {
padding: 20px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
background-color: #f9fafc;
}
.contenedor-censo{
background-color: #002855;
color: white;
padding: 15px;
font-size: 20px;
margin-bottom: 25px;
}
.pregunta-cuadro {
background-color: #f5f5f5;
border-left: 6px solid #001f3f;
padding: 15px;
border-radius: 8px;
font-size: 16px;
margin-bottom: 25px;
}
.tabla-contenedor {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
overflow-x: auto;
min-width: 700px;
}
/* Tabla */
.tabla {
width: 100%;
border-collapse: collapse;
text-align: center;
color: black;
width: 100%; /* ocupa todo el ancho del contenedor */
table-layout: fixed;
}
.tabla th,
.tabla td {
border: 1px solid #ddd;
padding: 12px;
}
.tabla th {
color: white;
font-weight: 600;
font-size: 15px;
}
.tabla td {
font-size: 14px;
}
/* Colores personalizados */
.azul-marino {
background-color: #002855;
color: white;
}
.rosa-fuerte {
background-color: #dc1557;
color: white;
}
/* Contenedor input */
.input-contenedor {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
/* Input */
.input-contenedor input {
width: 100%;
padding: 6px 25px 6px 6px;
border: 2px solid #002855;
border-radius: 6px;
font-size: 14px;
color: #333;
text-align: center;
outline: none;
background-color: rgb(232, 226, 226);
box-sizing: border-box;
}
.input-contenedor input::-webkit-inner-spin-button,
.input-contenedor input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Focus del input */
.input-contenedor input:focus {
border-color: #001f3f;
box-shadow: 0 0 6px rgba(0, 47, 95, 0.3);
}
/* Placeholder gris claro */
.input-contenedor input::placeholder {
color: #bbb;
opacity: 1;
}
.input-contenedor .porcentaje {
position: absolute;
right: 8px;
color: #555;
font-weight: bold;
pointer-events: none;
font-size: 14px;
top: 50%;
transform: translateY(-50%);
}
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
background-color: #eef2f6;
}
/* Total > 100% */
.total-error {
background-color: #ffcccc;
color: #a80000;
}
.contenedor-tablas {
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.tabla-contenedor {
flex: 1;
}
@@ -1,65 +0,0 @@
import React from "react";
import Link from "next/link";
import "./page1.css"; // Importamos los estilos
export default function Pregunta1() {
return (
<main className="pregunta-page pregunta1">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 1</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
1. Desglose el número de equipos de impresión con que cuenta el área
universitaria.
</p>
<div className="pregunta-grid">
<div>
<label>Inyección de tinta</label>
<input value="7" readOnly />
</div>
<div>
<label>Láser pequeña B/N</label>
<input value="186" readOnly />
</div>
<div>
<label>Láser de alto volumen B/N</label>
<input value="28" readOnly />
</div>
<div>
<label>Láser de alto volumen Color</label>
<input value="18" readOnly />
</div>
<div>
<label>Láser pequeña Color</label>
<input value="20" readOnly />
</div>
<div>
<label>Multifuncionales</label>
<input value="108" readOnly />
</div>
<div>
<label>Matriz de puntos</label>
<input value="" readOnly />
</div>
<div>
<label>3D</label>
<input value="2" readOnly />
</div>
<div>
<label>Plotter</label>
<input value="11" readOnly />
</div>
</div>
</section>
<div className="boton-contenedor">
<Link href="/pregunta2" className="boton siguiente">
Ir a Pregunta 2
</Link>
</div>
</div>
</main>
);
}
@@ -1,94 +0,0 @@
/* === ESTILOS GENERALES === */
.pregunta-page {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(to bottom, #ebf4ff, #ffffff);
font-family: "Inter", sans-serif;
}
/* === CONTENEDOR === */
.pregunta-container {
background: white;
border: 1px solid #e5e7eb;
border-radius: 20px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.05);
width: 90%;
max-width: 900px;
padding: 3rem;
}
/* === TÍTULO === */
.pregunta-titulo {
font-size: 2rem;
font-weight: 700;
text-align: center;
color: #1e40af;
margin-bottom: 2rem;
}
/* === TEXTO === */
.pregunta-texto {
font-weight: 600;
color: #374151;
margin-bottom: 1.5rem;
}
/* === GRID DE INPUTS === */
.pregunta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.5rem;
}
.pregunta-grid label {
display: block;
font-size: 0.9rem;
color: #4b5563;
margin-bottom: 0.4rem;
}
.pregunta-grid input {
width: 100%;
padding: 0.6rem 0.8rem;
border: 1px solid #d1d5db;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
background-color: #f9fafb;
transition: all 0.2s ease;
}
.pregunta-grid input:focus {
border-color: #2563eb;
outline: none;
background-color: #ffffff;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.3);
}
/* === BOTONES === */
.boton-contenedor {
display: flex;
justify-content: center;
margin-top: 2.5rem;
}
.boton {
display: inline-block;
padding: 0.8rem 1.6rem;
border-radius: 10px;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
box-shadow: 0 3px 8px rgba(37, 99, 235, 0.25);
}
.boton.siguiente {
background-color: #2563eb;
color: white;
}
.boton.siguiente:hover {
background-color: #1e3a8a;
transform: scale(1.05);
}
-161
View File
@@ -1,161 +0,0 @@
"use client";
import { useState, useEffect } from "react";
import "./pregunta2.scss";
// Tipos
type OsEntry = {
os: string;
count: string; // o number si la API devuelve números
isTotal?: boolean;
};
type PlatformData = {
[key: string]: OsEntry[];
};
// === DATOS TEMPORALES (mock) ===
const MOCK_DATA: PlatformData = {
"pc-desktop": [
{ os: "Windows 11", count: "408" },
{ os: "Windows 10", count: "1171" },
{ os: "Windows 7/8", count: "177" },
{ os: "Windows XP/Vista", count: "43" },
{ os: "Linux", count: "45" },
{ os: "Total", count: "1844", isTotal: true },
],
"apple-desktop": [
{ os: "Mac OS X(13 - Ventura, 14 - Sonoma)", count: "205" },
{
os: "Mac OS X(Mojave,Catalina,11 - Big Sur, 12 - Monterrey)",
count: "180",
},
{ os: "Mac OS X(Yosemite,El Capitan,Sierra,High Sierra)", count: "95" },
{ os: "Mac OS X(Snow Leopard,Mountain Lion,Mavericks)", count: "6" },
{ os: "Total", count: "480", isTotal: true },
],
"pc-laptop": [
{ os: "Windows 11", count: "40" },
{ os: "Windows 10", count: "171" },
{ os: "Windows 7/8", count: "17" },
{ os: "Windows XP/Vista", count: "3" },
{ os: "Linux", count: "5" },
{ os: "Total", count: "144", isTotal: true },
],
"apple-laptop": [
{ os: "Mac OS X(13 - Ventura, 14 - Sonoma)", count: "39" },
{
os: "Mac OS X(Mojave,Catalina,11 - Big Sur, 12 - Monterrey)",
count: "23",
},
{ os: "Mac OS X(Yosemite,El Capitan,Sierra,High Sierra)", count: "0" },
{ os: "Mac OS X(Snow Leopard,Mountain Lion,Mavericks)", count: "9" },
{ os: "Total", count: "71", isTotal: true },
],
servers: [
{
os: "Linux (CentOs,Fedora,Ubuntu,Red Hat Enterprise,entre otros)",
count: "21",
},
{ os: "Unix (AIX,MAC OS Server,Solaris,entre otros)", count: "2" },
{ os: "Windows Server 2022/2023", count: "6" },
{ os: "Windows Server 2016/2019", count: "3" },
{ os: "Windows Server 2008/2012", count: "3" },
{ os: "Windows Server 2000/2003", count: "2" },
{ os: "Total", count: "37", isTotal: true },
],
};
const API_ENDPOINT = "/api/platform-stats"; // ← ¡Reemplaza esto cuando sepas la URL real!
const Page = () => {
const [activeTab, setActiveTab] = useState<string>("pc-desktop");
const [data, setData] = useState<PlatformData>(MOCK_DATA);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
// === DESCOMENTA ESTO CUANDO TENGAS LA API ===
// const response = await fetch(API_ENDPOINT);
// if (!response.ok) throw new Error('Error al cargar estadísticas');
// const apiData: PlatformData = await response.json();
// setData(apiData);
// setLoading(false);
// === POR AHORA: usa datos simulados (y simula un retraso si quieres) ===
// await new Promise(resolve => setTimeout(resolve, 300));
setData(MOCK_DATA);
setLoading(false);
} catch (err) {
console.error("Error al cargar datos:", err);
setError(
"No se pudieron cargar las estadísticas. Usando datos temporales."
);
setData(MOCK_DATA); // fallback en caso de error
setLoading(false);
}
};
fetchData();
}, []);
const currentData = data[activeTab] || [];
// Si quisieras mostrar un estado de carga (opcional)
// if (loading) return <div className="dashboardContainer"><p>Cargando...</p></div>;
// if (error) console.warn(error); // o muestra un toast, etc.
return (
<div className="dashboardContainer">
<div className="header">
<h2>Estadísticas de Plataformas</h2>
</div>
<div className="scanView">
<div className="container">
<div className="header">
Presione cada pestaña para ver la información de las plataformas.
</div>
<div className="main-content">
<div className="tabs">
{Object.entries({
"pc-desktop": "Computadoras de escritorio Plataforma PC",
"apple-desktop": "Computadoras de escritorio Plataforma Apple",
"pc-laptop": "Computadoras portátiles Plataforma PC",
"apple-laptop": "Computadoras portátiles Plataforma Apple",
servers: "Servidores de alto rendimiento",
}).map(([key, label]) => (
<div
key={key}
className={`tab ${activeTab === key ? "active" : ""}`}
onClick={() => setActiveTab(key)}
>
{label}
</div>
))}
</div>
<div className="data-table-wrapper">
<div className="data-table">
{currentData.map((item, index) => (
<div
key={index}
className={`data-row ${item.isTotal ? "total-row" : ""}`}
>
<div className="os-name">{item.os}</div>
<div className="count-box">{item.count}</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Page;
@@ -1,164 +0,0 @@
.dashboardContainer {
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
min-height: 100vh;
background-color: #f4f4f4;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background-color: #ffffff;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 10;
h2 {
margin: 0;
font-size: 1.5rem;
color: #0056b3;
}
}
.scanView {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 20px;
width: 100%;
height: 100%;
.container {
width: 100%;
max-width: 900px;
border-radius: 12px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
border: 1px solid #ddd;
}
.header {
padding: 16px 20px;
background: #f7f7f7;
border-bottom: 1px solid #e0e0e0;
font-size: 15px;
color: #0056b3;
text-align: center;
font-weight: 500;
display: block;
box-shadow: none;
position: static;
}
.main-content {
display: flex;
min-height: 420px;
}
.tabs {
width: 230px;
background-color: #fafafa;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.tab {
padding: 18px 16px;
cursor: pointer;
border-right: 1px solid #e0e0e0;
color: #555;
transition: all 0.3s ease;
border-left: 4px solid transparent;
font-size: 15px;
font-weight: 500;
}
.tab:hover {
background-color: #f0f0f0;
color: #000;
}
.tab.active {
background-color: #fff;
border-left: 4px solid #0056b3;
border-right: none;
border-bottom: 1px solid #0056b3;
color: #0056b3;
font-weight: 600;
}
.data-table-wrapper {
flex: 1;
padding: 20px;
}
.data-table {
width: 100%;
}
.data-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: #f9f9f9;
transition: background 0.2s ease;
}
.data-row:hover {
background: #f1f1f1;
}
.os-name {
flex: 1;
font-size: 15px;
color: #333;
}
.count-box {
background: #ffffff;
border: 1px solid #0056b3;
padding: 6px 14px;
font-weight: 600;
font-size: 15px;
text-align: center;
min-width: 70px;
}
.total-row {
background: #eaf4ff;
font-weight: bold;
.count-box {
color:#0056b3;
}
}
}
/* ======== RESPONSIVE ======== */
@media (max-width: 700px) {
.scanView .main-content {
flex-direction: column;
}
.scanView .tabs {
flex-direction: row;
width: 100%;
}
.scanView .tab {
flex: 1;
text-align: center;
font-size: 13px;
}
}
@@ -1,125 +0,0 @@
"use client";
import React, { useState, useEffect } from "react";
import "../../styles/layout/pregunta2EP.scss";
interface EquiposPoblacion {
alumnos: string;
profesores: string;
tecnicosAcademicos: string;
investigadores: string;
administrativos: string;
total: string;
}
export default function Pregunta2EPPage() {
const [equipos, setEquipos] = useState<EquiposPoblacion>({
alumnos: "35",
profesores: "43",
tecnicosAcademicos: "",
investigadores: "",
administrativos: "302",
total: "380",
});
// 🔹 Preparado para conectarse al backend
useEffect(() => {
// Cuando tengas la API, descomenta esta parte 👇 y reemplaza la URL:
/*
fetch("https://tu-api-backend.com/api/equipos-poblacion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setEquipos({
...equipos,
[name]: value,
});
};
return (
<div className="container">
<div className="header">
<span style={{ color: "#d9534f", fontWeight: "normal" }}>*</span>{" "}
<small>(Requerido en el caso de contar con Equipo de impresión)</small>
</div>
<div className="row">
<div className="item">
<label htmlFor="alumnos">Alumnos</label>
<input
type="text"
id="alumnos"
name="alumnos"
value={equipos.alumnos}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="profesores">
Profesores <span className="help-icon">?</span>
</label>
<input
type="text"
id="profesores"
name="profesores"
value={equipos.profesores}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="tecnicosAcademicos">Técnicos Académicos</label>
<input
type="text"
id="tecnicosAcademicos"
name="tecnicosAcademicos"
value={equipos.tecnicosAcademicos}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="investigadores">
Investigadores <span className="help-icon">?</span>
</label>
<input
type="text"
id="investigadores"
name="investigadores"
value={equipos.investigadores}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="administrativos">
Administrativos <span className="help-icon">?</span>
</label>
<input
type="text"
id="administrativos"
name="administrativos"
value={equipos.administrativos}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="total">Total</label>
<input
type="text"
id="total"
name="total"
value={equipos.total}
onChange={handleChange}
/>
</div>
</div>
</div>
);
}
@@ -1,59 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page2.css"; // 👈 Importamos los estilos
export default function Pregunta2() {
return (
<main className="pregunta-page pregunta2">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 2</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
Indique el número de equipos de impresión de acuerdo con la
población universitaria al que se destina su uso primordialmente.
</p>
<div className="pregunta-grid">
<div>
<label>Alumnos</label>
<input value="35" readOnly />
</div>
<div>
<label>Profesores</label>
<input value="43" readOnly />
</div>
<div>
<label>Técnicos Académicos</label>
<input value="" readOnly />
</div>
<div>
<label>Investigadores</label>
<input value="" readOnly />
</div>
<div>
<label>Administrativos</label>
<input value="302" readOnly />
</div>
<div>
<label>Total</label>
<input value="380" readOnly />
</div>
</div>
</section>
<div className="boton-grupo">
<Link href="/pregunta1" className="boton anterior">
Volver a Pregunta 1
</Link>
<Link href="#" className="boton siguiente">
Ir a Pregunta 3
</Link>
</div>
</div>
</main>
);
}
@@ -1,96 +0,0 @@
.pregunta-page {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(to bottom, #eef2ff, #ffffff);
font-family: "Inter", sans-serif;
}
.pregunta-container {
background: white;
border: 1px solid #e5e7eb;
border-radius: 20px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.05);
width: 90%;
max-width: 900px;
padding: 3rem;
}
.pregunta-titulo {
font-size: 2rem;
font-weight: 700;
text-align: center;
color: #4338ca;
margin-bottom: 2rem;
}
.pregunta-texto {
font-weight: 500;
color: #374151;
margin-bottom: 1.5rem;
text-align: justify;
}
.pregunta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}
.pregunta-grid label {
display: block;
color: #4b5563;
margin-bottom: 0.4rem;
}
.pregunta-grid input {
width: 100%;
padding: 0.6rem 0.8rem;
border: 1px solid #d1d5db;
border-radius: 8px;
background-color: #f9fafb;
transition: all 0.2s ease;
}
.pregunta-grid input:focus {
border-color: #6366f1;
outline: none;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3);
}
.boton-grupo {
display: flex;
justify-content: space-between;
margin-top: 2.5rem;
}
.boton {
display: inline-block;
padding: 0.8rem 1.6rem;
border-radius: 10px;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
box-shadow: 0 3px 8px rgba(99, 102, 241, 0.25);
}
.boton.anterior {
background-color: #6b7280;
color: white;
}
.boton.anterior:hover {
background-color: #374151;
transform: scale(1.05);
}
.boton.siguiente {
background-color: #4f46e5;
color: white;
}
.boton.siguiente:hover {
background-color: #312e81;
transform: scale(1.05);
}
-366
View File
@@ -1,366 +0,0 @@
"use client";
import React, { useState } from "react";
import Link from "next/link";
import "./page3.css";
export default function Pregunta3() {
const [activeTab, setActiveTab] = useState(0);
const tabs = [
"Computadoras de escritorio Plataforma PC",
"Computadoras de escritorio Plataforma Apple",
"Computadoras portátiles Plataforma PC",
"Computadoras portátiles Plataforma Apple",
"Alto rendimiento Servidores",
];
// === DATOS DE CADA TABLA ===
const data = [
// === 1. PC Escritorio ===
{
color: "#16a34a",
headerColor: "#15803d",
rows: [
{
tipo: "Core i9 / Ryzen 9",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core i7 / Ryzen 7",
alumnos: "15",
profesores: "8",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "23",
},
{
tipo: "Core i5 / Ryzen 5",
alumnos: "10",
profesores: "5",
tecnicos: "",
investigadores: "",
administrativos: "2",
total: "17",
},
],
total: {
alumnos: "25",
profesores: "13",
tecnicos: "0",
investigadores: "0",
administrativos: "2",
total: "40",
},
},
// === 2. Apple Escritorio ===
{
color: "#a855f7",
headerColor: "#7e22ce",
rows: [
{
tipo: "Familia M3",
alumnos: "10",
profesores: "2",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "12",
},
{
tipo: "Familia M2",
alumnos: "5",
profesores: "3",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "8",
},
],
total: {
alumnos: "15",
profesores: "5",
tecnicos: "0",
investigadores: "0",
administrativos: "0",
total: "20",
},
},
// === 3. PC Portátiles ===
{
color: "#22c55e",
headerColor: "#15803d",
rows: [
{
tipo: "Core i5 (12a generación)",
alumnos: "12",
profesores: "5",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "17",
},
{
tipo: "Core i7 (13a generación)",
alumnos: "6",
profesores: "4",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "11",
},
],
total: {
alumnos: "18",
profesores: "9",
tecnicos: "0",
investigadores: "0",
administrativos: "1",
total: "28",
},
},
// === 4. Apple Portátiles ===
{
color: "#9333ea",
headerColor: "#7e22ce",
rows: [
{
tipo: "Familia M2",
alumnos: "35",
profesores: "3",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "38",
},
{
tipo: "Familia M1",
alumnos: "",
profesores: "5",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "6",
},
{
tipo: "i5 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "14",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "14",
},
],
total: {
alumnos: "35",
profesores: "31",
tecnicos: "0",
investigadores: "0",
administrativos: "5",
total: "71",
},
},
// === 5. Servidores ===
{
color: "#2563eb",
headerColor: "#1e40af",
rows: [
{
tipo: "Xeon E3, E5, E7",
alumnos: "19",
profesores: "",
tecnicos: "",
investigadores: "16",
administrativos: "",
total: "35",
},
{
tipo: "Xeon Bronce, Plata, Oro 6a generación",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "Xeon Phi",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
],
total: {
alumnos: "19",
profesores: "0",
tecnicos: "0",
investigadores: "16",
administrativos: "2",
total: "37",
},
},
];
return (
<main className="pregunta-page">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 3 (1/5 - 5/5)</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
3. Desglose la cantidad de población beneficiada por plataforma y
tipo de procesador: *
</p>
<p className="pregunta-subtexto">
Presione cada pestaña para ingresar la información.
</p>
{/* === PESTAÑAS === */}
<div className="tab-container">
{tabs.map((tab, index) => (
<div
key={index}
className={`tab ${activeTab === index ? "active" : "inactive"}`}
style={
activeTab === index
? {
borderBottomColor: data[index].color,
color: data[index].color,
}
: {}
}
onClick={() => setActiveTab(index)}
>
{tab}
</div>
))}
</div>
{/* === TABLA === */}
<div className="tabla-container">
<table className="tabla">
<thead>
<tr>
<th
rowSpan={2}
className="header-procesador"
style={{ backgroundColor: data[activeTab].color }}
>
Tipo de procesador
</th>
<th
colSpan={5}
className="header-poblacion"
style={{ backgroundColor: data[activeTab].headerColor }}
>
Población Beneficiada
</th>
<th
rowSpan={2}
className="header-total"
style={{ backgroundColor: data[activeTab].color }}
>
Total
</th>
</tr>
<tr>
<th className="sub-header">Alumnos</th>
<th className="sub-header">Profesores</th>
<th className="sub-header">Técnicos</th>
<th className="sub-header">Investigadores</th>
<th className="sub-header">Administrativos</th>
</tr>
</thead>
<tbody>
{data[activeTab].rows.map((item, i) => (
<tr key={i}>
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input type="text" value={item.alumnos} readOnly />
</td>
<td>
<input type="text" value={item.profesores} readOnly />
</td>
<td>
<input type="text" value={item.tecnicos} readOnly />
</td>
<td>
<input type="text" value={item.investigadores} readOnly />
</td>
<td>
<input
type="text"
value={item.administrativos}
readOnly
/>
</td>
<td className="total-celda">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td className="tipo-procesador">Total</td>
<td>
<input
type="text"
value={data[activeTab].total.alumnos}
readOnly
/>
</td>
<td>
<input
type="text"
value={data[activeTab].total.profesores}
readOnly
/>
</td>
<td>
<input
type="text"
value={data[activeTab].total.tecnicos}
readOnly
/>
</td>
<td>
<input
type="text"
value={data[activeTab].total.investigadores}
readOnly
/>
</td>
<td>
<input
type="text"
value={data[activeTab].total.administrativos}
readOnly
/>
</td>
<td className="total-celda">{data[activeTab].total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
</section>
<div className="boton-contenedor">
<Link href="/" className="boton volver">
Volver al inicio
</Link>
</div>
</div>
</main>
);
}
-167
View File
@@ -1,167 +0,0 @@
/* === CONTENEDOR GENERAL === */
.pregunta-page {
display: flex;
justify-content: center;
padding: 2rem;
}
.pregunta-container {
width: 100%;
max-width: 1100px;
}
.pregunta-titulo {
text-align: center;
color: #1e3a8a;
margin-bottom: 1.2rem;
font-size: 1.6rem;
font-weight: 700;
}
.pregunta-texto {
font-size: 1rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.pregunta-subtexto {
font-size: 0.9rem;
color: #6b7280;
margin-bottom: 1rem;
}
/* === PESTAÑAS === */
.tab-container {
display: flex;
overflow-x: auto;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 1.5rem;
}
.tab {
padding: 0.8rem 1.2rem;
cursor: pointer;
white-space: nowrap;
font-weight: 500;
border-radius: 8px 8px 0 0;
transition: all 0.2s ease;
margin-right: 0.25rem;
}
.tab.active {
font-weight: 600;
background-color: #f3f4f6;
}
.tab.inactive {
color: #6b7280;
background-color: #ffffff;
}
.tab.inactive:hover {
background-color: #f9fafb;
}
/* === TABLA === */
.tabla-container {
overflow-x: auto;
position: relative;
}
.tabla {
width: 100%;
border-collapse: collapse;
min-width: 950px;
font-size: 0.85rem;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}
.tabla th {
padding: 0.7rem 0.5rem;
text-align: center;
color: white;
font-weight: 600;
border: 1px solid #d1d5db;
}
.tabla .sub-header {
background-color: #9ca3af;
}
.tabla td {
border: 1px solid #e5e7eb;
text-align: center;
vertical-align: middle;
}
.tabla tr:hover td {
background-color: #f9fafb;
}
.tipo-procesador {
text-align: left;
font-weight: 500;
padding: 0.6rem 0.5rem;
background-color: #f9fafb;
color: #374151;
}
.tabla input[type="text"] {
width: 100%;
padding: 0.45rem 0.3rem;
border: none;
background-color: #f3f4f6;
text-align: center;
box-sizing: border-box;
color: #374151;
}
.total-celda {
font-weight: 600;
color: #111827;
background-color: #eef2ff;
}
.fila-total td {
background-color: #e0e7ff;
font-weight: 700;
}
/* === BOTONES === */
.boton-consultar {
margin-top: 1rem;
background-color: #10b981;
color: white;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
box-shadow: 0 2px 5px rgba(16, 185, 129, 0.3);
transition: background-color 0.2s;
float: right;
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-contenedor {
margin-top: 4rem;
text-align: right;
}
.boton.volver {
background-color: #2563eb;
color: white;
padding: 0.7rem 1.4rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
box-shadow: 0 2px 5px rgba(37, 99, 235, 0.3);
transition: background-color 0.2s;
}
.boton.volver:hover {
background-color: #1d4ed8;
}
@@ -1,248 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page3.1.css";
export default function Pregunta3() {
const data = [
{
tipo: "Core Ultra (i3, i5, i7) Serie 2",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core Ultra (i3, i5, i7) Serie 1",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i9 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (13a generación en adelante)",
alumnos: "15",
profesores: "16",
tecnicos: "",
investigadores: "",
administrativos: "52",
total: "97",
},
{
tipo: "i7 o equivalentes (12a generación en adelante)",
alumnos: "29",
profesores: "16",
tecnicos: "",
investigadores: "",
administrativos: "52",
total: "97",
},
{
tipo: "i5 o equivalentes (13a generación en adelante)",
alumnos: "107",
profesores: "3",
tecnicos: "",
investigadores: "",
administrativos: "8",
total: "118",
},
{
tipo: "i5 o equivalentes (12a generación en adelante)",
alumnos: "250",
profesores: "59",
tecnicos: "3",
investigadores: "",
administrativos: "904",
total: "1216",
},
{
tipo: "i3 o equivalentes (13a generación en adelante)",
alumnos: "3",
profesores: "1",
tecnicos: "",
investigadores: "",
administrativos: "12",
total: "16",
},
{
tipo: "i3 o equivalentes (12a generación en adelante)",
alumnos: "36",
profesores: "19",
tecnicos: "2",
investigadores: "",
administrativos: "78",
total: "137",
},
{
tipo: "i3 o equivalentes (11a generación en adelante)",
alumnos: "264",
profesores: "66",
tecnicos: "",
investigadores: "",
administrativos: "410",
total: "740",
},
{
tipo: "Pentium Gold",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "Pentium Serie J, G",
alumnos: "2",
profesores: "3",
tecnicos: "",
investigadores: "",
administrativos: "3",
total: "8",
},
{
tipo: "Celeron Dual Core, Pentium Dual Core o anteriores",
alumnos: "25",
profesores: "40",
tecnicos: "",
investigadores: "",
administrativos: "56",
total: "121",
},
];
const total = {
alumnos: "774",
profesores: "227",
tecnicos: "5",
investigadores: "0",
administrativos: "838",
total: "1844",
};
return (
<main className="pregunta-page pregunta3">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 3 (1/5)</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
3. Desglose la cantidad de población beneficiada por plataforma y
tipo de procesador: *
</p>
<p className="pregunta-subtexto">
Presione cada pestaña para ingresar la información.
</p>
{/* Pestañas */}
<div className="tab-container">
<div className="tab active">
Computadoras de escritorio Plataforma PC
</div>
<div className="tab inactive">
Computadoras de escritorio Plataforma Apple
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma PC
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma Apple
</div>
<div className="tab inactive">Alto rendimiento Servidores</div>
</div>
{/* Tabla */}
<div className="tabla-wrapper">
<table className="tabla-pc">
<thead>
<tr>
<th rowSpan={2} className="header-procesador">
Plataforma PC <br /> Tipo de procesador
</th>
<th colSpan={5} className="header-poblacion">
Población Beneficiada
</th>
<th rowSpan={2} className="header-total">
Total
</th>
</tr>
<tr>
<th>Alumnos</th>
<th>Profesores</th>
<th>Técnicos Académicos</th>
<th>Investigadores</th>
<th>Administrativos</th>
</tr>
</thead>
<tbody>
{data.map((item, i) => (
<tr key={i}>
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input value={item.alumnos} readOnly />
</td>
<td>
<input value={item.profesores} readOnly />
</td>
<td>
<input value={item.tecnicos} readOnly />
</td>
<td>
<input value={item.investigadores} readOnly />
</td>
<td>
<input value={item.administrativos} readOnly />
</td>
<td className="total-celda">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td className="tipo-procesador">Total</td>
<td>
<input value={total.alumnos} readOnly />
</td>
<td>
<input value={total.profesores} readOnly />
</td>
<td>
<input value={total.tecnicos} readOnly />
</td>
<td>
<input value={total.investigadores} readOnly />
</td>
<td>
<input value={total.administrativos} readOnly />
</td>
<td className="total-celda final-total">{total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
</section>
<div className="boton-contenedor">
<Link href="/pregunta3.2" className="boton siguiente">
Pregunta 3 (2/5)
</Link>
</div>
</div>
</main>
);
}
@@ -1,171 +0,0 @@
/* === CONTENEDOR GENERAL === */
.pregunta-page {
display: flex;
justify-content: center;
padding: 2rem 0;
}
.pregunta-container {
width: 90%;
max-width: 1100px;
background-color: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
/* === TITULOS === */
.pregunta-titulo {
text-align: center;
color: #0a2d6e;
margin-bottom: 1rem;
font-size: 1.6rem;
font-weight: 700;
}
.pregunta-texto {
font-size: 1rem;
font-weight: 600;
margin-bottom: 0.2rem;
color: #1f2937;
}
.pregunta-subtexto {
font-size: 0.9rem;
color: #6b7280;
margin-bottom: 1rem;
}
/* === PESTAÑAS === */
.tab-container {
display: flex;
border-bottom: 3px solid #d1d5db;
margin-bottom: 1rem;
}
.tab {
padding: 0.6rem 1rem;
cursor: pointer;
font-weight: 600;
border-radius: 8px 8px 0 0;
margin-right: 0.25rem;
font-size: 0.9rem;
}
.tab.active {
color: #1e40af;
border: 2px solid #1e40af;
border-bottom: none;
background-color: #f3f4f6;
}
.tab.inactive {
color: #6b7280;
background-color: #fff;
}
/* === TABLA === */
.tabla-wrapper {
overflow-x: auto;
display: flex;
justify-content: center;
}
.tabla-pc {
border-collapse: collapse;
width: 95%;
text-align: center;
font-size: 0.83rem;
}
.tabla-pc th,
.tabla-pc td {
border: 1px solid #d1d5db;
padding: 0.4rem;
}
.header-procesador,
.header-total {
background-color: #3b82f6;
color: white;
font-weight: 700;
}
.header-poblacion {
background-color: #9333ea;
color: white;
font-weight: 700;
}
.tabla-pc th {
text-align: center;
}
.tipo-procesador {
text-align: left;
background-color: #f9fafb;
font-weight: 600;
padding-left: 0.5rem;
}
.tabla-pc input {
width: 60px;
text-align: center;
border: none;
background-color: #f3f4f6;
border-radius: 4px;
padding: 0.2rem;
font-size: 0.8rem;
color: #111827;
}
.total-celda {
background-color: #e0f2fe;
font-weight: 600;
color: #1e3a8a;
}
.fila-total td {
background-color: #bfdbfe;
font-weight: 700;
}
.fila-total .total-celda {
background-color: #93c5fd;
}
/* === BOTONES === */
.boton-consultar {
margin-top: 1rem;
background-color: #10b981;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
float: right;
box-shadow: 0 2px 6px rgba(16, 185, 129, 0.3);
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-contenedor {
text-align: right;
margin-top: 4rem;
}
.boton.siguiente {
background-color: #2563eb;
color: white;
padding: 0.6rem 1.2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
}
.boton.siguiente:hover {
background-color: #1e3a8a;
}
@@ -1,270 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page3.2.css";
export default function Pregunta3_2() {
const data = [
{
tipo: "Core Ultra (i3, i5, i7) Serie 2",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core Ultra (i3, i5, i7) Serie 1",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Familia M4",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "2",
total: "2",
},
{
tipo: "Familia M3",
alumnos: "",
profesores: "1",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "2",
},
{
tipo: "Familia M2",
alumnos: "",
profesores: "2",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "2",
},
{
tipo: "Familia M1",
alumnos: "51",
profesores: "1",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "52",
},
{
tipo: "i9 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "i5 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "i5 o equivalentes (12a generación en adelante)",
alumnos: "11",
profesores: "1",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "12",
},
{
tipo: "i3 o equivalentes (13a generación en adelante)",
alumnos: "175",
profesores: "5",
tecnicos: "",
investigadores: "",
administrativos: "26",
total: "206",
},
{
tipo: "i3 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "i3 o equivalentes (11a generación en adelante)",
alumnos: "",
profesores: "2",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "2",
},
{
tipo: "Core2 Mac, Quad Core o anteriores",
alumnos: "12",
profesores: "3",
tecnicos: "3",
investigadores: "",
administrativos: "3",
total: "21",
},
];
const total = {
alumnos: "249",
profesores: "14",
tecnicos: "3",
investigadores: "0",
administrativos: "37",
total: "303",
};
return (
<main className="pregunta-page pregunta3">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 3 (2/5)</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
3. Desglose la cantidad de población beneficiada por plataforma y
tipo de procesador: *
</p>
<p className="pregunta-subtexto">
Presione cada pestaña para ingresar la información.
</p>
{/* === PESTAÑAS === */}
<div className="tab-container">
<div className="tab inactive">
Computadoras de escritorio Plataforma PC
</div>
<div className="tab active">
Computadoras de escritorio Plataforma Apple
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma PC
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma Apple
</div>
<div className="tab inactive">Alto rendimiento Servidores</div>
</div>
{/* === TABLA === */}
<div className="tabla-apple-container">
<table className="tabla-apple">
<thead>
<tr>
<th rowSpan={2} className="header-procesador">
Plataforma Apple <br /> Tipo de procesador
</th>
<th colSpan={5} className="header-poblacion">
Población Beneficiada
</th>
<th rowSpan={2} className="header-total">
Total
</th>
</tr>
<tr>
<th className="sub-header">Alumnos</th>
<th className="sub-header">Profesores</th>
<th className="sub-header">Técnicos Académicos</th>
<th className="sub-header">Investigadores</th>
<th className="sub-header">Administrativos</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={index}>
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input type="text" value={item.alumnos} readOnly />
</td>
<td>
<input type="text" value={item.profesores} readOnly />
</td>
<td>
<input type="text" value={item.tecnicos} readOnly />
</td>
<td>
<input type="text" value={item.investigadores} readOnly />
</td>
<td>
<input
type="text"
value={item.administrativos}
readOnly
/>
</td>
<td className="total-celda">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td className="tipo-procesador">Total</td>
<td>
<input type="text" value={total.alumnos} readOnly />
</td>
<td>
<input type="text" value={total.profesores} readOnly />
</td>
<td>
<input type="text" value={total.tecnicos} readOnly />
</td>
<td>
<input type="text" value={total.investigadores} readOnly />
</td>
<td>
<input type="text" value={total.administrativos} readOnly />
</td>
<td className="total-celda final-total">{total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
</section>
<div className="boton-contenedor">
<Link href="/pregunta3.3" className="boton siguiente">
Pregunta 3 (3/5)
</Link>
</div>
</div>
</main>
);
}
@@ -1,170 +0,0 @@
/* === ESTILOS PREGUNTA 3 (2/5) - Plataforma Apple === */
.pregunta-titulo {
text-align: center;
color: #7e22ce;
margin-bottom: 1.2rem;
font-size: 1.5rem;
font-weight: 700;
}
.pregunta-texto {
font-size: 1rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.pregunta-subtexto {
font-size: 0.9rem;
color: #6b7280;
margin-bottom: 1rem;
}
/* === PESTAÑAS === */
.tab-container {
display: flex;
overflow-x: auto;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 1.5rem;
}
.tab {
padding: 0.8rem 1.2rem;
cursor: pointer;
white-space: nowrap;
font-weight: 500;
border-radius: 8px 8px 0 0;
transition: all 0.2s ease;
margin-right: 0.25rem;
}
.tab.active {
color: #7e22ce;
border-bottom: 3px solid #7e22ce;
background-color: #f3f4f6;
}
.tab.inactive {
color: #6b7280;
background-color: #ffffff;
}
.tab.inactive:hover {
color: #7e22ce;
background-color: #f9fafb;
}
/* === TABLA === */
.tabla-apple-container {
overflow-x: auto;
margin-bottom: 2rem;
position: relative;
}
.tabla-apple {
width: 100%;
border-collapse: collapse;
min-width: 950px;
font-size: 0.85rem;
}
.tabla-apple th {
padding: 0.7rem 0.5rem;
text-align: center;
color: white;
font-weight: 600;
border: 1px solid #d1d5db;
}
.tabla-apple .header-procesador,
.tabla-apple .header-total {
background-color: #9333ea;
}
.tabla-apple .header-poblacion {
background-color: #7e22ce;
}
.tabla-apple .sub-header {
background-color: #a855f7;
color: white;
}
.tabla-apple td {
border: 1px solid #e5e7eb;
text-align: center;
vertical-align: middle;
}
.tabla-apple .tipo-procesador {
text-align: left;
font-weight: 500;
padding: 0.6rem 0.5rem;
background-color: #faf5ff;
color: #4b5563;
}
.tabla-apple input[type="text"] {
width: 100%;
padding: 0.45rem 0.3rem;
border: none;
background-color: #f3f4f6;
text-align: center;
box-sizing: border-box;
color: #374151;
}
.tabla-apple .total-celda {
background-color: #f3e8ff;
font-weight: 600;
color: #7e22ce;
}
.tabla-apple .fila-total td {
background-color: #e9d5ff;
font-weight: 700;
}
.tabla-apple .fila-total .total-celda {
background-color: #d8b4fe;
}
/* === BOTONES === */
.boton-consultar {
position: absolute;
bottom: -3.5rem;
right: 0;
background-color: #10b981;
color: white;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
box-shadow: 0 2px 5px rgba(16, 185, 129, 0.3);
transition: background-color 0.2s;
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-contenedor {
margin-top: 5rem;
text-align: right;
}
.boton.siguiente {
background-color: #9333ea;
color: white;
padding: 0.7rem 1.4rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
box-shadow: 0 2px 5px rgba(147, 51, 234, 0.3);
transition: background-color 0.2s;
}
.boton.siguiente:hover {
background-color: #7e22ce;
}
@@ -1,271 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page3.3.css";
export default function Pregunta3_3() {
const data = [
{
tipo: "Core Ultra (i3, i5, i7) Serie 2",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core Ultra (i3, i5, i7) Serie 1",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i9 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (12a generación en adelante)",
alumnos: "16",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "27",
total: "43",
},
{
tipo: "i7 o equivalentes (11a generación)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "i5 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "1",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "2",
},
{
tipo: "i5 o equivalentes (12a generación en adelante)",
alumnos: "146",
profesores: "34",
tecnicos: "",
investigadores: "",
administrativos: "42",
total: "222",
},
{
tipo: "i5 o equivalentes (11a generación en adelante)",
alumnos: "",
profesores: "2",
tecnicos: "",
investigadores: "",
administrativos: "15",
total: "19",
},
{
tipo: "i3 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "12",
total: "12",
},
{
tipo: "i3 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "8",
tecnicos: "",
investigadores: "",
administrativos: "23",
total: "31",
},
{
tipo: "i3 o equivalentes (11a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Pentium Dual Core o anteriores",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Celeron (equivalente 2018 hasta la fecha)",
alumnos: "299",
profesores: "8",
tecnicos: "",
investigadores: "",
administrativos: "4",
total: "311",
},
{
tipo: "Celeron anteriores",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core2 Duo, Quad Core, Pentium Dual Core o anteriores",
alumnos: "4",
profesores: "4",
tecnicos: "",
investigadores: "",
administrativos: "3",
total: "11",
},
];
const total = {
alumnos: "445",
profesores: "132",
tecnicos: "0",
investigadores: "0",
administrativos: "139",
total: "716",
};
return (
<main className="pregunta-page pregunta3">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 3 (3/5)</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
3. Desglose la cantidad de población beneficiada por plataforma y
tipo de procesador: *
</p>
<p className="pregunta-subtexto">
Presione cada pestaña para ingresar la información.
</p>
{/* === PESTAÑAS === */}
<div className="tab-container">
<div className="tab inactive">
Computadoras de escritorio Plataforma PC
</div>
<div className="tab inactive">
Computadoras de escritorio Plataforma Apple
</div>
<div className="tab active">
Computadoras portátiles Plataforma PC
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma Apple
</div>
<div className="tab inactive">Alto rendimiento Servidores</div>
</div>
{/* === TABLA === */}
<div className="tabla-pc-container">
<table className="tabla-pc">
<thead>
<tr>
<th rowSpan={2} className="header-procesador">
Plataforma PC <br /> Tipo de procesador
</th>
<th colSpan={5} className="header-poblacion">
Población Beneficiada
</th>
<th rowSpan={2} className="header-total">
Total
</th>
</tr>
<tr>
<th className="sub-header">Alumnos</th>
<th className="sub-header">Profesores</th>
<th className="sub-header">Técnicos Académicos</th>
<th className="sub-header">Investigadores</th>
<th className="sub-header">Administrativos</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={index}>
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input type="text" value={item.alumnos} readOnly />
</td>
<td>
<input type="text" value={item.profesores} readOnly />
</td>
<td>
<input type="text" value={item.tecnicos} readOnly />
</td>
<td>
<input type="text" value={item.investigadores} readOnly />
</td>
<td>
<input
type="text"
value={item.administrativos}
readOnly
/>
</td>
<td className="total-celda">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td className="tipo-procesador">Total</td>
<td>
<input type="text" value={total.alumnos} readOnly />
</td>
<td>
<input type="text" value={total.profesores} readOnly />
</td>
<td>
<input type="text" value={total.tecnicos} readOnly />
</td>
<td>
<input type="text" value={total.investigadores} readOnly />
</td>
<td>
<input type="text" value={total.administrativos} readOnly />
</td>
<td className="total-celda final-total">{total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
</section>
<div className="boton-contenedor">
<Link href="/pregunta3.4" className="boton siguiente">
Pregunta 3 (4/5)
</Link>
</div>
</div>
</main>
);
}
@@ -1,170 +0,0 @@
/* === ESTILOS PREGUNTA 3 (3/5) - Portátiles Plataforma PC === */
.pregunta-titulo {
text-align: center;
color: #dc2626;
margin-bottom: 1.2rem;
font-size: 1.5rem;
font-weight: 700;
}
.pregunta-texto {
font-size: 1rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.pregunta-subtexto {
font-size: 0.9rem;
color: #6b7280;
margin-bottom: 1rem;
}
/* === PESTAÑAS === */
.tab-container {
display: flex;
overflow-x: auto;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 1.5rem;
}
.tab {
padding: 0.8rem 1.2rem;
cursor: pointer;
white-space: nowrap;
font-weight: 500;
border-radius: 8px 8px 0 0;
transition: all 0.2s ease;
margin-right: 0.25rem;
}
.tab.active {
color: #dc2626;
border-bottom: 3px solid #dc2626;
background-color: #fef2f2;
}
.tab.inactive {
color: #6b7280;
background-color: #ffffff;
}
.tab.inactive:hover {
color: #dc2626;
background-color: #f9fafb;
}
/* === TABLA === */
.tabla-pc-container {
overflow-x: auto;
margin-bottom: 2rem;
position: relative;
}
.tabla-pc {
width: 100%;
border-collapse: collapse;
min-width: 950px;
font-size: 0.85rem;
}
.tabla-pc th {
padding: 0.7rem 0.5rem;
text-align: center;
color: white;
font-weight: 600;
border: 1px solid #d1d5db;
}
.tabla-pc .header-procesador,
.tabla-pc .header-total {
background-color: #b91c1c;
}
.tabla-pc .header-poblacion {
background-color: #dc2626;
}
.tabla-pc .sub-header {
background-color: #ef4444;
color: white;
}
.tabla-pc td {
border: 1px solid #e5e7eb;
text-align: center;
vertical-align: middle;
}
.tabla-pc .tipo-procesador {
text-align: left;
font-weight: 500;
padding: 0.6rem 0.5rem;
background-color: #fef2f2;
color: #4b5563;
}
.tabla-pc input[type="text"] {
width: 100%;
padding: 0.45rem 0.3rem;
border: none;
background-color: #f3f4f6;
text-align: center;
box-sizing: border-box;
color: #374151;
}
.tabla-pc .total-celda {
background-color: #fee2e2;
font-weight: 600;
color: #b91c1c;
}
.tabla-pc .fila-total td {
background-color: #fecaca;
font-weight: 700;
}
.tabla-pc .fila-total .total-celda {
background-color: #fca5a5;
}
/* === BOTONES === */
.boton-consultar {
position: absolute;
bottom: -3.5rem;
right: 0;
background-color: #10b981;
color: white;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
box-shadow: 0 2px 5px rgba(16, 185, 129, 0.3);
transition: background-color 0.2s;
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-contenedor {
margin-top: 5rem;
text-align: right;
}
.boton.siguiente {
background-color: #b91c1c;
color: white;
padding: 0.7rem 1.4rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
box-shadow: 0 2px 5px rgba(220, 38, 38, 0.3);
transition: background-color 0.2s;
}
.boton.siguiente:hover {
background-color: #dc2626;
}
@@ -1,257 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page3.4.css";
export default function Pregunta3_4() {
const data = [
{
tipo: "Core Ultra (i3, i5, i7) Serie 2",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Core Ultra (i3, i5, i7) Serie 1",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Familia M4",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Familia M3",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Familia M2",
alumnos: "35",
profesores: "3",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "38",
},
{
tipo: "Familia M1",
alumnos: "",
profesores: "5",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "6",
},
{
tipo: "i9 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i7 o equivalentes (11a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i5 o equivalentes (13a generación en adelante)",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "i5 o equivalentes (12a generación en adelante)",
alumnos: "",
profesores: "14",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "14",
},
{
tipo: "i5 o equivalentes (11a generación en adelante)",
alumnos: "",
profesores: "9",
tecnicos: "",
investigadores: "",
administrativos: "4",
total: "13",
},
{
tipo: "Core2 Mac, Quad Core o anteriores",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
];
const total = {
alumnos: "35",
profesores: "31",
tecnicos: "0",
investigadores: "0",
administrativos: "5",
total: "71",
};
return (
<main className="pregunta3-container">
<h1 className="pregunta3-titulo">PREGUNTA 3 (4/5)</h1>
<div className="pregunta3-descripcion">
<p>
<strong>3.</strong> Desglose la cantidad de población beneficiada por
plataforma y tipo de procesador:
</p>
<span className="subtexto">
Presione cada pestaña para ingresar la información.
</span>
</div>
{/* === PESTAÑAS === */}
<div className="tabs">
<button className="tab inactive">
Computadoras de escritorio Plataforma PC
</button>
<button className="tab inactive">
Computadoras de escritorio Plataforma Apple
</button>
<button className="tab inactive">
Computadoras portátiles Plataforma PC
</button>
<button className="tab active">
Computadoras portátiles Plataforma Apple
</button>
<button className="tab inactive">Alto rendimiento Servidores</button>
</div>
{/* === TABLA === */}
<div className="tabla-wrapper">
<table className="tabla-pregunta3">
<thead>
<tr>
<th rowSpan={2} className="header-procesador">
Plataforma Apple <br /> Tipo de procesador
</th>
<th colSpan={5} className="header-poblacion">
Población Beneficiada
</th>
<th rowSpan={2} className="header-total">
Total
</th>
</tr>
<tr>
<th>Alumnos</th>
<th>Profesores</th>
<th>Técnicos Académicos</th>
<th>Investigadores</th>
<th>Administrativos</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={index}>
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input type="text" value={item.alumnos} readOnly />
</td>
<td>
<input type="text" value={item.profesores} readOnly />
</td>
<td>
<input type="text" value={item.tecnicos} readOnly />
</td>
<td>
<input type="text" value={item.investigadores} readOnly />
</td>
<td>
<input type="text" value={item.administrativos} readOnly />
</td>
<td className="celda-total">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td>Total</td>
<td>
<input type="text" value={total.alumnos} readOnly />
</td>
<td>
<input type="text" value={total.profesores} readOnly />
</td>
<td>
<input type="text" value={total.tecnicos} readOnly />
</td>
<td>
<input type="text" value={total.investigadores} readOnly />
</td>
<td>
<input type="text" value={total.administrativos} readOnly />
</td>
<td className="celda-total final">{total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
<div className="boton-siguiente">
<Link href="/pregunta3.5" className="next">
Pregunta 3 (5/5)
</Link>
</div>
</main>
);
}
@@ -1,166 +0,0 @@
/* === CONTENEDOR GENERAL === */
.pregunta3-container {
max-width: 1100px;
margin: 2rem auto;
padding: 2rem;
background: #fff;
border-radius: 16px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
font-family: "Inter", sans-serif;
}
.pregunta3-titulo {
text-align: left;
font-size: 1.3rem;
font-weight: 700;
color: #6d28d9;
margin-bottom: 1rem;
}
.pregunta3-descripcion p {
font-size: 1rem;
margin-bottom: 0.3rem;
}
.subtexto {
font-size: 0.9rem;
color: #6b7280;
}
/* === TABS === */
.tabs {
display: flex;
flex-wrap: wrap;
margin: 1rem 0 1.5rem;
border-bottom: 2px solid #e5e7eb;
}
.tab {
padding: 0.8rem 1.1rem;
font-size: 0.9rem;
border: none;
cursor: pointer;
background: #fff;
color: #6b7280;
transition: all 0.2s ease;
border-radius: 8px 8px 0 0;
margin-right: 0.25rem;
}
.tab.active {
background: #f3f4f6;
color: #7e22ce;
border-bottom: 3px solid #9333ea;
}
.tab.inactive:hover {
background: #f9fafb;
color: #9333ea;
}
/* === TABLA === */
.tabla-wrapper {
overflow-x: auto;
position: relative;
margin-bottom: 2.5rem;
}
.tabla-pregunta3 {
width: 100%;
border-collapse: collapse;
min-width: 950px;
font-size: 0.85rem;
}
.tabla-pregunta3 th,
.tabla-pregunta3 td {
border: 1px solid #e5e7eb;
text-align: center;
padding: 0.5rem;
}
.header-procesador,
.header-total {
background-color: #9333ea;
color: #fff;
font-weight: 600;
}
.header-poblacion {
background-color: #7e22ce;
color: #fff;
font-weight: 600;
}
.tabla-pregunta3 th {
padding: 0.7rem;
}
.tabla-pregunta3 input {
width: 100%;
padding: 0.4rem;
border: none;
background-color: #f3f4f6;
text-align: center;
font-size: 0.85rem;
}
.tipo-procesador {
text-align: left;
background-color: #faf5ff;
font-weight: 500;
color: #4b5563;
}
.celda-total {
background-color: #f3e8ff;
font-weight: 600;
color: #6b21a8;
}
.fila-total td {
background-color: #e9d5ff;
font-weight: 700;
}
.fila-total .celda-total.final {
background-color: #d8b4fe;
}
/* === BOTONES === */
.boton-consultar {
position: absolute;
bottom: -3rem;
right: 0;
background-color: #10b981;
color: white;
padding: 0.6rem 1.1rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s;
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-siguiente {
text-align: right;
margin-top: 4rem;
}
.next {
background-color: #9333ea;
color: white;
padding: 0.7rem 1.4rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
transition: 0.2s;
}
.next:hover {
background-color: #7e22ce;
}
@@ -1,209 +0,0 @@
"use client";
import React from "react";
import Link from "next/link";
import "./page3.5.css";
export default function Pregunta3_5() {
const data = [
{
tipo: "Xeon 6",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Xeon Bronce, Plata, Oro 3a generación",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Xeon Bronce, Plata, Oro 4a generación",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Xeon Bronce, Plata, Oro 5a generación",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
{
tipo: "Xeon Bronce, Plata, Oro 6a generación",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "Xeon E3, E5, E7",
alumnos: "19",
profesores: "",
tecnicos: "",
investigadores: "16",
administrativos: "",
total: "35",
},
{
tipo: "Xeon Phi",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "1",
total: "1",
},
{
tipo: "Xeon o anteriores",
alumnos: "",
profesores: "",
tecnicos: "",
investigadores: "",
administrativos: "",
total: "0",
},
];
const total = {
alumnos: "19",
profesores: "0",
tecnicos: "0",
investigadores: "16",
administrativos: "2",
total: "37",
};
return (
<main className="pregunta-page pregunta3">
<div className="pregunta-container">
<h1 className="pregunta-titulo">PREGUNTA 3 (5/5)</h1>
<section className="pregunta-seccion">
<p className="pregunta-texto">
3. Desglose la cantidad de población beneficiada por plataforma y
tipo de procesador: *
</p>
<p className="pregunta-subtexto">
Presione cada pestaña para ingresar la información.
</p>
{/* === PESTAÑAS === */}
<div className="tab-container">
<div className="tab inactive">
Computadoras de escritorio Plataforma PC
</div>
<div className="tab inactive">
Computadoras de escritorio Plataforma Apple
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma PC
</div>
<div className="tab inactive">
Computadoras portátiles Plataforma Apple
</div>
<div className="tab active">Alto rendimiento Servidores</div>
</div>
{/* === TABLA === */}
<div className="tabla-servidores-container">
<table className="tabla-servidores">
<thead>
<tr>
<th rowSpan={2} className="header-procesador">
Servidores <br /> Tipo de procesador
</th>
<th colSpan={5} className="header-poblacion">
Población Beneficiada
</th>
<th rowSpan={2} className="header-total">
Total
</th>
</tr>
<tr>
<th className="sub-header">Alumnos</th>
<th className="sub-header">Profesores</th>
<th className="sub-header">Técnicos Académicos</th>
<th className="sub-header">Investigadores</th>
<th className="sub-header">Administrativos</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={index} className="tabla-fila">
<td className="tipo-procesador">{item.tipo}</td>
<td>
<input type="text" value={item.alumnos} readOnly />
</td>
<td>
<input type="text" value={item.profesores} readOnly />
</td>
<td>
<input type="text" value={item.tecnicos} readOnly />
</td>
<td>
<input type="text" value={item.investigadores} readOnly />
</td>
<td>
<input
type="text"
value={item.administrativos}
readOnly
/>
</td>
<td className="total-celda">{item.total}</td>
</tr>
))}
<tr className="fila-total">
<td className="tipo-procesador">Total</td>
<td>
<input type="text" value={total.alumnos} readOnly />
</td>
<td>
<input type="text" value={total.profesores} readOnly />
</td>
<td>
<input type="text" value={total.tecnicos} readOnly />
</td>
<td>
<input type="text" value={total.investigadores} readOnly />
</td>
<td>
<input type="text" value={total.administrativos} readOnly />
</td>
<td className="total-celda final-total">{total.total}</td>
</tr>
</tbody>
</table>
<button className="boton-consultar">
Consultar las equivalencias de procesadores
</button>
</div>
</section>
<div className="boton-contenedor">
<Link href="/" className="boton volver">
Volver al inicio
</Link>
</div>
</div>
</main>
);
}
@@ -1,201 +0,0 @@
/* === ESTILOS PREGUNTA 3 (5/5) - Alto Rendimiento Servidores === */
.pregunta-page {
display: flex;
justify-content: center;
padding: 2rem 1rem;
background-color: #f9fafb;
}
.pregunta-container {
width: 100%;
max-width: 1100px;
background-color: #ffffff;
border-radius: 12px;
padding: 2rem 2.5rem;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
.pregunta-titulo {
text-align: center;
color: #2563eb;
margin-bottom: 1.5rem;
font-size: 1.6rem;
font-weight: 700;
border-bottom: 3px solid #2563eb;
display: inline-block;
padding-bottom: 0.3rem;
}
.pregunta-texto {
font-size: 1rem;
font-weight: 500;
margin-bottom: 0.5rem;
color: #1f2937;
}
.pregunta-subtexto {
font-size: 0.9rem;
color: #6b7280;
margin-bottom: 1.2rem;
}
/* === PESTAÑAS === */
.tab-container {
display: flex;
overflow-x: auto;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 1.5rem;
}
.tab {
padding: 0.8rem 1.2rem;
cursor: pointer;
white-space: nowrap;
font-weight: 500;
border-radius: 8px 8px 0 0;
transition: all 0.2s ease;
margin-right: 0.25rem;
}
.tab.active {
color: #2563eb;
border-bottom: 3px solid #2563eb;
background-color: #f3f4f6;
box-shadow: inset 0 -2px 4px rgba(37, 99, 235, 0.1);
}
.tab.inactive {
color: #6b7280;
background-color: #ffffff;
}
.tab.inactive:hover {
color: #2563eb;
background-color: #f9fafb;
}
/* === TABLA === */
.tabla-servidores-container {
overflow-x: auto;
margin-bottom: 3rem;
position: relative;
}
.tabla-servidores {
width: 100%;
border-collapse: collapse;
min-width: 950px;
font-size: 0.85rem;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.08);
}
.tabla-servidores th {
padding: 0.7rem 0.5rem;
text-align: center;
color: white;
font-weight: 600;
border: 1px solid #d1d5db;
}
.tabla-servidores .header-procesador,
.tabla-servidores .header-total {
background-color: #2563eb;
}
.tabla-servidores .header-poblacion {
background-color: #1e40af;
}
.tabla-servidores .sub-header {
background-color: #3b82f6;
color: white;
}
.tabla-servidores td {
border: 1px solid #e5e7eb;
text-align: center;
vertical-align: middle;
background-color: #ffffff;
transition: background-color 0.2s;
}
.tabla-fila:hover td {
background-color: #f3f4f6;
}
.tabla-servidores .tipo-procesador {
text-align: left;
font-weight: 500;
padding: 0.6rem 0.7rem;
background-color: #eff6ff;
color: #374151;
}
.tabla-servidores input[type="text"] {
width: 100%;
padding: 0.45rem 0.3rem;
border: none;
background-color: #f9fafb;
text-align: center;
color: #374151;
border-radius: 4px;
font-weight: 500;
}
.tabla-servidores .total-celda {
background-color: #dbeafe;
font-weight: 600;
color: #1d4ed8;
}
.tabla-servidores .fila-total td {
background-color: #bfdbfe;
font-weight: 700;
}
.tabla-servidores .fila-total .total-celda {
background-color: #93c5fd;
}
/* === BOTONES === */
.boton-consultar {
position: absolute;
bottom: -3.5rem;
right: 0;
background-color: #10b981;
color: white;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
box-shadow: 0 2px 5px rgba(16, 185, 129, 0.3);
transition: background-color 0.2s;
}
.boton-consultar:hover {
background-color: #059669;
}
.boton-contenedor {
margin-top: 5rem;
text-align: right;
}
.boton.volver {
background-color: #2563eb;
color: white;
padding: 0.7rem 1.4rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
box-shadow: 0 2px 5px rgba(37, 99, 235, 0.3);
transition: background-color 0.2s;
}
.boton.volver:hover {
background-color: #1d4ed8;
}
@@ -1,105 +0,0 @@
"use client";
import React, { useState, useEffect } from "react";
import "../../styles/layout/pregunta4EP.scss";
interface EquiposDigitalizacion {
digitalizadorCamaPlana: string;
digitalizador3d: string;
digitalizadorAlimentador: string;
digitalizadorGranVolumen: string;
}
export default function Pregunta4EPPage() {
const [equipos, setEquipos] = useState<EquiposDigitalizacion>({
digitalizadorCamaPlana: "27",
digitalizador3d: "",
digitalizadorAlimentador: "108",
digitalizadorGranVolumen: "1",
});
// 🔹 Preparado para conectar con el backend
useEffect(() => {
// Cuando tengas la API, descomenta y reemplaza la URL:
/*
fetch("https://tu-api-backend.com/api/equipos-digitalizacion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setEquipos({
...equipos,
[name]: value,
});
};
return (
<div className="container">
<div className="contenedor-censo">
Censo de equipos periféricos - Equipo de digitalización
</div>
<div className="pregunta-cuadro">
7. Calcule porcentualmente (%) la antiguedad que tienen los equipos
periféricos del área universitaria. * (Requerido en el caso de contar
con Equipo de impresión o digitalización.)
</div>
<div className="grid">
<div className="item">
<label htmlFor="digitalizadorCamaPlana">
Digitalizador de cama plana para oficina
</label>
<input
type="text"
id="digitalizadorCamaPlana"
name="digitalizadorCamaPlana"
value={equipos.digitalizadorCamaPlana}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="digitalizador3d">3D</label>
<input
type="text"
id="digitalizador3d"
name="digitalizador3d"
value={equipos.digitalizador3d}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="digitalizadorAlimentador">
Digitalizador con alimentador de hojas para oficina
</label>
<input
type="text"
id="digitalizadorAlimentador"
name="digitalizadorAlimentador"
value={equipos.digitalizadorAlimentador}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="digitalizadorGranVolumen">
Digitalizador de gran volumen
</label>
<input
type="text"
id="digitalizadorGranVolumen"
name="digitalizadorGranVolumen"
value={equipos.digitalizadorGranVolumen}
onChange={handleChange}
/>
</div>
</div>
</div>
);
}
@@ -1,55 +0,0 @@
"use client";
import "../../styles/layout/pregunta5EP.scss";
export default function Pregunta5EP() {
return (
<div className="container">
<div className="header">
Indique el número de equipos de digitalización de acuerdo con la
población universitaria al que se destina su uso primordialmente.
<span>*</span>
<small> (Requerido en el caso de contar con Equipo de digitalización)</small>
</div>
<div className="row">
<div className="item">
<label htmlFor="alumnos-digital">Alumnos</label>
<input type="text" id="alumnos-digital" defaultValue="11" />
</div>
<div className="item">
<label htmlFor="profesores-digital">
Profesores
</label>
<input type="text" id="profesores-digital" defaultValue="24" />
</div>
<div className="item">
<label htmlFor="tecnicos-academicos-digital">
Técnicos Académicos
</label>
<input type="text" id="tecnicos-academicos-digital" defaultValue="" />
</div>
<div className="item">
<label htmlFor="investigadores-digital">
Investigadores
</label>
<input type="text" id="investigadores-digital" defaultValue="" />
</div>
<div className="item">
<label htmlFor="administrativos-digital">
Administrativos
</label>
<input type="text" id="administrativos-digital" defaultValue="101" />
</div>
<div className="item">
<label htmlFor="total-digital">Total</label>
<input type="text" id="total-digital" defaultValue="136" />
</div>
</div>
</div>
);
}
@@ -1,89 +0,0 @@
"use client";
import React, { useState } from "react";
import "./pregunta7.css";
export default function Pregunta7() {
const [datos, setDatos] = useState([
{ nombre: "Impresión", valores: ["", "", "", ""] },
{ nombre: "Digitalización", valores: ["", "", "", ""] },
]);
const [garantia, setGarantia] = useState({
escritorio: "",
portatil: "",
altoRendimiento: "",
});
// Función para actualizar datos de Pregunta 7
const handleChange = (filaIndex: number, colIndex: number, value: string) => {
const nuevosDatos = [...datos];
nuevosDatos[filaIndex].valores[colIndex] = value;
setDatos(nuevosDatos);
};
// Función para calcular total de cada fila en Pregunta 7
const calcularTotal = (valores: string[]) =>
valores.reduce((acc, val) => acc + (Number(val) || 0), 0);
return (
<div className="contenedor-pregunta">
{/* Pregunta 7 */}
<div className="contenedor-censo">
Censo de equipos periféricos - Estado del equipo periférico (impresión y
digitalización.)
</div>
<div className="pregunta-cuadro">
7. Calcule porcentualmente (%) la antiguedad que tienen los equipos
periféricos del área universitaria. * (Requerido en el caso de contar
con Equipo de impresión o digitalización.)
</div>
<div className="tabla-contenedor">
<table className="tabla">
<thead>
<tr>
<th className="azul-marino">% Antiguedad 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="azul-marino">Total</th>
</tr>
</thead>
<tbody>
{datos.map((fila, filaIndex) => {
const total = calcularTotal(fila.valores);
return (
<tr key={filaIndex}>
<td>{fila.nombre}</td>
{fila.valores.map((valor, colIndex) => (
<td key={colIndex}>
<div className="input-contenedor">
<input
type="number"
value={valor}
onChange={(e) =>
handleChange(filaIndex, colIndex, e.target.value)
}
/>
<span className="porcentaje">%</span>
</div>
</td>
))}
<td
className={`total-celda ${
total > 100 ? "total-error" : ""
}`}
>
{total.toFixed(2)}%
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}
@@ -1,134 +0,0 @@
.contenedor-pregunta {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.contenedor-censo{
background-color: #002855;
color: white;
padding: 15px;
font-size: 16px;
margin-bottom: 25px;
}
.pregunta-cuadro {
border-left: 6px solid #001f3f;
padding: 15px;
border-radius: 8px;
font-size: 16px;
margin-bottom: 25px;
}
.tabla-contenedor {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
overflow-x: auto;
}
/* Tabla */
.tabla {
width: 100%;
border-collapse: collapse;
text-align: center;
color: black;
}
.tabla th,
.tabla td {
border: 1px solid #ddd;
padding: 12px;
}
.tabla th {
color: white;
font-weight: 600;
font-size: 15px;
}
.tabla td {
font-size: 14px;
}
/* Colores personalizados */
.azul-marino {
background-color: #002855;
color: white;
}
.rosa-fuerte {
background-color: #dc1557;
color: white;
}
/* Contenedor input */
.input-contenedor {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
/* Input */
.input-contenedor input {
width: 40%;
padding: 6px 6px 6px 6px;
border: 2px solid #002855;
border-radius: 6px;
font-size: 14px;
color: #333;
text-align: center;
outline: none;
background-color: rgb(232, 226, 226);
box-sizing: border-box;
}
.input-contenedor input::-webkit-inner-spin-button,
.input-contenedor input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Focus del input */
.input-contenedor input:focus {
border-color: #001f3f;
box-shadow: 0 0 6px rgba(0, 47, 95, 0.3);
}
/* Placeholder gris claro */
.input-contenedor input::placeholder {
color: #bbb;
opacity: 1;
}
.input-contenedor .porcentaje {
position: absolute;
right: 8px;
color: #555;
font-weight: bold;
pointer-events: none;
font-size: 14px;
top: 50%;
transform: translateY(-50%);
}
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
background-color: #eef2f6;
}
/* Total > 100% */
.total-error {
background-color: #ffcccc;
color: #a80000;
}
@@ -1,131 +0,0 @@
.contenedor-pregunta {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.contenedor-censo{
background-color: #001f3f;
color: white;
}
.pregunta-cuadro {
border-left: 6px solid #001f3f;
padding: 15px;
border-radius: 8px;
font-size: 16px;
margin-bottom: 25px;
}
.tabla-contenedor {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
overflow-x: auto;
}
/* Tabla */
.tabla {
width: 100%;
border-collapse: collapse;
text-align: center;
color: black;
}
.tabla th,
.tabla td {
border: 1px solid #ddd;
padding: 12px;
}
.tabla th {
color: white;
font-weight: 600;
font-size: 15px;
}
.tabla td {
font-size: 14px;
}
/* Colores personalizados */
.azul-marino {
background-color: #002855;
color: white;
}
.rosa-fuerte {
background-color: #dc1557;
color: white;
}
/* Contenedor input */
.input-contenedor {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
/* Input */
.input-contenedor input {
width: 40%;
padding: 6px 6px 6px 6px;
border: 2px solid #002855;
border-radius: 6px;
font-size: 14px;
color: #333;
text-align: center;
outline: none;
background-color: rgb(232, 226, 226);
box-sizing: border-box;
}
.input-contenedor input::-webkit-inner-spin-button,
.input-contenedor input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Focus del input */
.input-contenedor input:focus {
border-color: #001f3f;
box-shadow: 0 0 6px rgba(0, 47, 95, 0.3);
}
/* Placeholder gris claro */
.input-contenedor input::placeholder {
color: #bbb;
opacity: 1;
}
.input-contenedor .porcentaje {
position: absolute;
right: 8px;
color: #555;
font-weight: bold;
pointer-events: none;
font-size: 14px;
top: 50%;
transform: translateY(-50%);
}
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
background-color: #eef2f6;
}
/* Total > 100% */
.total-error {
background-color: #ffcccc;
color: #a80000;
}
-142
View File
@@ -1,142 +0,0 @@
"use client";
import React, { useState } from "react";
import "./pregunta9.css";
export default function Pregunta9() {
const [datos, setDatos] = useState([
{ nombre: "Computadoras de Escritorio", valores: ["", "", "", ""] },
{ nombre: "Computadoras Portátiles", valores: ["", "", "", ""] },
{ nombre: "Alto Rendimiento", valores: ["", "", "", ""] },
]);
const [garantia, setGarantia] = useState({
escritorio: "",
portatil: "",
altoRendimiento: "",
});
// Función para actualizar datos de Pregunta 9
const handleChange = (filaIndex: number, colIndex: number, value: string) => {
const nuevosDatos = [...datos];
nuevosDatos[filaIndex].valores[colIndex] = value;
setDatos(nuevosDatos);
};
// Función para calcular total de cada fila en Pregunta 9
const calcularTotal = (valores: string[]) =>
valores.reduce((acc, val) => acc + (Number(val) || 0), 0);
return (
<div className="contenedor-pregunta">
{/* Pregunta 9 */}
<div className="pregunta-cuadro">
9. Calcule porcentualmente (%) la antigüedad que tienen los equipos de
cómputo del área universitaria. *
</div>
<div className="tabla-contenedor">
<table className="tabla">
<thead>
<tr>
<th className="azul-marino">% Antiguedad 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="azul-marino">Total</th>
</tr>
</thead>
<tbody>
{datos.map((fila, filaIndex) => {
const total = calcularTotal(fila.valores);
return (
<tr key={filaIndex}>
<td>{fila.nombre}</td>
{fila.valores.map((valor, colIndex) => (
<td key={colIndex}>
<div className="input-contenedor">
<input
type="number"
value={valor}
onChange={(e) =>
handleChange(filaIndex, colIndex, e.target.value)
}
/>
<span className="porcentaje">%</span>
</div>
</td>
))}
<td
className={`total-celda ${
total > 100 ? "total-error" : ""
}`}
>
{total.toFixed(2)}%
</td>
</tr>
);
})}
</tbody>
</table>
</div>
{/* Pregunta 10 */}
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
10. ¿Cuántos equipos de cómputo tienen garantía de proveedor?. *
</div>
<div className="tabla-contenedor">
<table className="tabla">
<thead>
<tr>
<th className="azul-marino">Computadoras de Escritorio (247)</th>
<th className="azul-marino">Computadoras Portátiles (767)</th>
<th className="azul-marino">Alto Rendimiento (17)</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div className="input-contenedor input-sp">
<input
type="number"
value={garantia.escritorio}
onChange={(e) =>
setGarantia({ ...garantia, escritorio: e.target.value })
}
/>
</div>
</td>
<td>
<div className="input-contenedor input-sp">
<input
type="number"
value={garantia.portatil}
onChange={(e) =>
setGarantia({ ...garantia, portatil: e.target.value })
}
/>
</div>
</td>
<td>
<div className="input-contenedor input-sp">
<input
type="number"
value={garantia.altoRendimiento}
onChange={(e) =>
setGarantia({ ...garantia, altoRendimiento: e.target.value })
}
/>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
@@ -1,131 +0,0 @@
.contenedor-pregunta {
background-color: #f9fafc;
}
.pregunta-cuadro {
border-left: 6px solid #001f3f;
padding: 15px;
border-radius: 8px;
font-size: 16px;
margin-bottom: 25px;
}
.tabla-contenedor {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
overflow-x: auto;
}
/* Tabla */
.tabla {
width: 100%;
border-collapse: collapse;
text-align: center;
color: black;
}
.tabla th,
.tabla td {
border: 1px solid #ddd;
padding: 12px;
}
.tabla th {
color: white;
font-weight: 600;
font-size: 15px;
}
.tabla td {
font-size: 14px;
}
/* Colores personalizados */
.azul-marino {
background-color: #002855;
color: white;
}
.rosa-fuerte {
background-color: #dc1557;
color: white;
}
/* Contenedor input */
.input-contenedor {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
/* Input */
.input-contenedor input {
width: 40%;
padding: 6px 6px 6px 6px;
border: 2px solid #002855;
border-radius: 6px;
font-size: 14px;
color: #333;
text-align: center;
outline: none;
background-color: rgb(232, 226, 226);
box-sizing: border-box;
}
.input-contenedor input::-webkit-inner-spin-button,
.input-contenedor input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Focus del input */
.input-contenedor input:focus {
border-color: #001f3f;
box-shadow: 0 0 6px rgba(0, 47, 95, 0.3);
}
/* Placeholder gris claro */
.input-contenedor input::placeholder {
color: #bbb;
opacity: 1;
}
.input-contenedor .porcentaje {
position: absolute;
right: 8px;
color: #555;
font-weight: bold;
pointer-events: none;
font-size: 14px;
top: 50%;
transform: translateY(-50%);
}
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
background-color: #eef2f6;
}
/* Total > 100% */
.total-error {
background-color: #ffcccc;
color: #a80000;
}
.input-sp input {
width: 38%;
padding: 6px 6px 6px 6px;
}
@@ -1,93 +0,0 @@
"use client";
import { useState } from "react";
import "./reporte.css";
import axios from "axios";
import Pregunta9 from "../pregunta9/page";
export default function Page() {
const [report, setReport] = useState();
async function Report() {
const res = await axios.get("https");
setReport(res.data);
}
return (
<div className="reporte-layout">
{/* Panel izquierdo: título, buscador y tabla */}
<div className="panel-izquierdo">
<div className="titulo-reporte">
<p>REPORTE</p>
</div>
<form action="/buscar" method="get">
<input type="text" name="q" placeholder="Buscar equipo" />
<button type="submit">Buscar</button>
</form>
<div className="tabla-rec">
{/* Aquí irá tu tabla real */}
<p>Tabla de equipos...</p>
</div>
</div>
{/* Panel derecho: filtros + botón descargar */}
<div className="panel-derecho">
<div className="filtro-rec">
<form className="editar">
<p className="titulo-rec">Filtro</p>
<div className="linea"></div>
<label htmlFor="adscripcion">Adscripción</label>
<select id="adscripcion">
<option value="">Seleccione la adscripción</option>
<option value="informatica">CEDETEC</option>
<option value="administracion">Administración</option>
<option value="biblioteca">Biblioteca</option>
<option value="direccion">Dirección</option>
</select>
<label htmlFor="estado">Estado</label>
<select id="estado">
<option value="">Seleccione el estado del equipo</option>
<option value="activo">Activo</option>
<option value="mantenimiento">En Mantenimiento</option>
<option value="baja">Dado de Baja</option>
<option value="reparacion">En Reparación</option>
</select>
<label htmlFor="tipo">Tipo de Equipo</label>
<select id="tipo">
<option value="">Seleccione el tipo de equipo</option>
<option value="cpu">CPU</option>
<option value="laptop">Laptop</option>
<option value="monitor">Monitor</option>
<option value="impresora">Impresora</option>
<option value="servidor">Servidor</option>
</select>
<label htmlFor="antiguedad">Antigüedad</label>
<select id="antiguedad">
<option value="">Seleccione la antigüedad del equipo</option>
<option value="menos1">Menos de 1 año</option>
<option value="1-3">1 a 3 años</option>
<option value="3-5">3 a 5 años</option>
<option value="mas5">Más de 5 años</option>
</select>
<Pregunta9/>
<div className="botones-filtro">
<button type="reset" className="limpiar">
Limpiar filtros
</button>
<button type="submit" className="aplicar">
Aplicar filtros
</button>
</div>
</form>
</div>
<button className="boton-descargar">Descargar</button>
</div>
</div>
);
}
@@ -1,169 +0,0 @@
/* Contenedor principal del reporte */
.reporte-layout {
display: flex;
flex-wrap: wrap;
gap: 50px;
padding: 20px;
max-width: 1400px;
margin: 0 20px;
}
/* Panel izquierdo: contenedor + tabla */
.panel-izquierdo {
flex: 1;
min-width: 300px; /* evita que se colapse demasiado en móviles */
}
/* Panel derecho: filtro */
.panel-derecho {
width: 320px; /* ancho fijo razonable para filtros */
min-width: 280px;
}
.titulo-reporte {
font-weight: bold;
font-size: 24px;
text-align: center;
margin-bottom: 15px;
color: #0056b3;
}
/* Buscador */
form[action="/buscar"] {
display: flex;
gap: 10px;
margin-bottom: 20px;
align-items: center;
flex-wrap: wrap;
}
form[action="/buscar"] input {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
flex: 1;
min-width: 200px;
}
form[action="/buscar"] button {
background-color: #0056b3;
color: white;
border: none;
padding: 8px 16px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
form[action="/buscar"] button:hover {
background-color: #0056b3;
}
/* Tabla de reporte */
.tabla-rec {
border: 2px solid #0056b3;
border-radius: 10px;
padding: 15px;
background-color: #f9f9f9;
min-height: 400px;
width: 100%;
box-sizing: border-box;
}
/* Filtro */
.filtro-rec {
border: 2px solid #0056b3;
border-radius: 10px;
padding: 15px;
background-color: #f9f9f9;
font-family: Arial, sans-serif;
width: 100%;
box-sizing: border-box;
}
.filtro-rec .titulo-rec {
font-weight: bold;
margin-top: 0;
margin-bottom: 10px;
color: #0056b3;
}
.filtro-rec label {
display: block;
margin-top: 12px;
font-weight: bold;
font-size: 14px;
}
.filtro-rec select {
width: 100%;
padding: 8px;
margin-top: 4px;
border: 1px solid #0056b3;
border-radius: 5px;
font-size: 14px;
}
/* Botones del filtro */
.botones-filtro {
display: flex;
gap: 10px;
margin-top: 20px;
}
.botones-filtro .aplicar,
.botones-filtro .limpiar {
flex: 1;
padding: 8px;
border: none;
border-radius: 4px;
color: white;
font-size: 14px;
cursor: pointer;
}
.botones-filtro .aplicar {
background-color: #0056b3;
}
.botones-filtro .limpiar {
background-color: #ffb700;
color: #0056b3;
font-weight: bold;
}
/* Botón descargar */
.boton-descargar {
margin-top: 25px;
padding: 10px 20px;
font-size: 16px;
border: none;
background-color: #0056b3;
color: white;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
/* Responsive: en pantallas pequeñas (iPad portrait, etc.) */
@media (max-width: 768px) {
.reporte-layout {
flex-direction: column;
align-items: center;
}
.panel-derecho {
width: 100%;
max-width: 500px;
}
.panel-izquierdo {
width: 100%;
max-width: 500px;
}
.boton-descargar {
max-width: 500px;
}
}
-1
View File
@@ -1,5 +1,4 @@
.notfound {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
+13 -4
View File
@@ -7,6 +7,7 @@ import Image from "next/image";
import axios from "axios";
import { useRouter } from "next/navigation";
import toast from "react-hot-toast";
import { jwtDecode } from "jwt-decode";
export default function Login() {
const [nombre, setNombre] = useState("");
@@ -31,7 +32,18 @@ export default function Login() {
const { token } = response.data;
document.cookie = `token=${token}; path=/; SameSite=Strict`;
router.push("/escaner");
const decoded: any = jwtDecode(token);
const tipo = decoded?.tipoUsuario;
if (tipo === 2) {
router.push("/escaner");
} else if (tipo === 1) {
router.push("/equipoComputo");
} else {
toast.error("Tipo de usuario no válido");
}
} catch (err) {
if (axios.isAxiosError(err)) {
if (err.response) {
@@ -79,9 +91,6 @@ export default function Login() {
<button type="submit" disabled={loading}>
{loading ? "Buscando..." : "Iniciar sesión"}
</button>
{/* <Link href={"/forgotPassword"}>Olvidaste Contraseña?</Link> */}
{/* <Link href={"/crearCuenta"}>Crear Cuenta</Link> */}
</form>
</div>
+1 -1
View File
@@ -14,7 +14,7 @@ export default function NotFound() {
Lo sentimos, la página que buscas no existe o ha sido movida. Verifica
la URL o regresa a la página principal.
</p>
<button onClick={() => router.push("/front-Censo")}>
<button onClick={() => router.push("/")}>
Regresar al inicio
</button>
</section>
+3 -2
View File
@@ -21,7 +21,7 @@
cursor: pointer;
width: auto;
transition: background-color 0.3s ease;
font-size: 1.5rem;
font-size: 1rem;
}
.menuToggle {
@@ -88,7 +88,7 @@
align-items: center;
justify-content: center;
color: #383838;
font-size: 2rem;
font-size: 1.5rem;
}
.links {
@@ -152,6 +152,7 @@
left: 0;
display: flex;
width: 100vw;
z-index: 3;
}
.barNavigation li:hover {
@@ -21,7 +21,7 @@
cursor: pointer;
width: auto;
transition: background-color 0.3s ease;
font-size: 1.5rem;
font-size: 1rem;
}
.menuToggle {
@@ -88,7 +88,7 @@
align-items: center;
justify-content: center;
color: #383838;
font-size: 2rem;
font-size: 1.5rem;
}
.links {
+10 -1
View File
@@ -47,7 +47,7 @@ table {
}
thead th {
background-color: #0056b3;
background-color: #003e79;
color: #fff;
text-align: left;
padding: 14px;
@@ -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;
+4 -1
View File
@@ -77,7 +77,7 @@
box-shadow:
0 -2px 6px rgba(0,0,0,0.05),
inset 0 -3px 0 #fff; /* simula borde inferior */
z-index: 5;
z-index: 0;
}
}
@@ -87,10 +87,13 @@
.data-table_reporte {
display: flex;
flex-direction: column;
gap: 20px;
justify-content: center;
padding: 20px;
background-color: #f5f5f7;
text-align: center;
border: none;
min-height: 300px;
animation: fadein 0.2s ease;
+75 -56
View File
@@ -10,7 +10,7 @@ import { SO_POR_EQUIPO } from "@/data/so_por_equipo";
import { PROCESADORES_POR_EQUIPO } from "@/data/procesadores";
import { useRouter } from "next/navigation";
import "../app/styles/layout/agregarEquipo.scss";
interface FormData {
interface FormData {
inventario: string;
serie: string;
lugar: string;
@@ -25,8 +25,8 @@ import "../app/styles/layout/agregarEquipo.scss";
id_uso: number;
id_marca: number;
id_periferico: number;
id_laboratorio: number | null; // ✅ ahora acepta null
id_proyecto: number | null; // ✅ ahora acepta null
id_laboratorio: number | null;
id_proyecto: number | null;
isImpresora: boolean;
}
export default function Page() {
@@ -70,7 +70,6 @@ export default function Page() {
}
}, [inventario]);
// Interfaces
interface TipoUso {
id_uso: number;
@@ -156,8 +155,13 @@ export default function Page() {
axios.get(`${api_url}/equipos/laboratorios`, { headers }),
axios.get(`${api_url}/equipos/proyectos`, { headers }),
]);
const ordenados = marcasRes.data.sort((a: Marca, b: Marca) =>
a.marca.localeCompare(b.marca)
);
setTiposUso(usosRes.data);
setMarcas(marcasRes.data);
setMarcas(ordenados);
setEstados(estadosRes.data);
setAdscripciones(adscripcionesRes.data);
setTiposEquipo(tiposEquipoRes.data);
@@ -190,7 +194,7 @@ export default function Page() {
}
};
fetchProcesador();
}, []); // Ya no depende de tiposEquipo (si la API los da todos juntos)
}, []);
useEffect(() => {
const fetchPerifericos = async () => {
@@ -203,7 +207,12 @@ export default function Page() {
const response = await axios.get(`${api_url}/equipos/perifericos`, {
headers,
});
setPerifericos(response.data);
const ordenados = response.data.sort((a: any, b: any) =>
a.periferico.localeCompare(b.periferico)
);
setPerifericos(ordenados);
} catch (err) {
console.error(err);
toast.error("No se pudieron cargar los periféricos");
@@ -265,18 +274,18 @@ export default function Page() {
setFormData((prev) => {
let newValue: string | number | null | boolean = value;
if (field.startsWith("id_")) {
if (value === "" || value === 0) {
// Para campos opcionales, usamos null en lugar de 0
if (field === "id_laboratorio" || field === "id_proyecto") {
newValue = null;
} else {
newValue = 0;
}
} else {
newValue = Number(value);
}
}
if (field.startsWith("id_")) {
if (value === "" || value === 0) {
// Para campos opcionales, usamos null en lugar de 0
if (field === "id_laboratorio" || field === "id_proyecto") {
newValue = null;
} else {
newValue = 0;
}
} else {
newValue = Number(value);
}
}
if (field === "id_tipo_equipo") {
const idTipoEquipo = Number(value);
const tipoSeleccionado = tiposEquipo.find(
@@ -380,8 +389,13 @@ if (field.startsWith("id_")) {
await axios.post(`${api_url}/equipos/crear`, dataToSend, { headers });
toast.success("Equipo guardado correctamente");
router.push("/escaner");
} catch (err) {
console.error(err);
} catch (err: any) {
if (err.response && err.response.status === 400) {
const mensaje = err.response.data?.message || "El equipo ya existe";
toast.error(mensaje);
return;
}
toast.error("Error al guardar el equipo");
}
};
@@ -601,42 +615,46 @@ if (field.startsWith("id_")) {
{/* Columna Derecha */}
<div className="column">
{/* Laboratorio */}
<div className="formGroup">
<label>Laboratorio</label>
<select
value={formData.id_laboratorio ?? ""}
onChange={(e) =>
handleInputChange("id_laboratorio", e.target.value)
}
>
<option value="">Selecciona un laboratorio</option>
{laboratorios.map((lab) => (
<option key={lab.id_laboratorio} value={lab.id_laboratorio}>
{lab.laboratorio}
</option>
))}
</select>
</div>
{mostrarCamposComputadora && (
<>
<div className="formGroup">
<label>Laboratorio</label>
<select
value={formData.id_laboratorio ?? ""}
onChange={(e) =>
handleInputChange("id_laboratorio", e.target.value)
}
>
<option value="">Selecciona un laboratorio</option>
{laboratorios.map((lab) => (
<option
key={lab.id_laboratorio}
value={lab.id_laboratorio}
>
{lab.laboratorio}
</option>
))}
</select>
</div>
{/* Proyecto */}
<div className="formGroup">
<label>Proyecto</label>
<select
value={formData.id_proyecto ?? ""}
onChange={(e) =>
handleInputChange("id_proyecto", e.target.value)
}
>
<option value="">Selecciona un proyecto</option>
{proyectos.map((proy) => (
<option key={proy.id_proyecto} value={proy.id_proyecto}>
{proy.proyecto}
</option>
))}
</select>
</div>
<div className="formGroup">
<label>Proyecto</label>
<select
value={formData.id_proyecto ?? ""}
onChange={(e) =>
handleInputChange("id_proyecto", e.target.value)
}
>
<option value="">Selecciona un proyecto</option>
{proyectos.map((proy) => (
<option key={proy.id_proyecto} value={proy.id_proyecto}>
{proy.proyecto}
</option>
))}
</select>
</div>
</>
)}
{/* Lugar */}
<div className="formGroup">
@@ -673,3 +691,4 @@ if (field.startsWith("id_")) {
</div>
);
}
//IO
+2 -1
View File
@@ -13,7 +13,8 @@ function BarNavigation() {
const cerrarSesion = () => {
if (typeof window !== "undefined") {
localStorage.removeItem("loggedIn");
document.cookie =
"token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict";
router.push("/");
}
setOpenMenu(false);
+3 -2
View File
@@ -13,7 +13,8 @@ function BarNavigation() {
const cerrarSesion = () => {
if (typeof window !== "undefined") {
localStorage.removeItem("loggedIn");
document.cookie =
"token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict";
router.push("/");
}
setOpenMenu(false);
@@ -43,7 +44,7 @@ function BarNavigation() {
<span>Equipo de Computo</span>
</Link>
</li>
<li className="subMenu" onClick={toggleMenu}>
<li className="subMenu" onClick={toggleMenu}>
<Link href="/perifericos" className="links">
<span>Perifericos</span>
</Link>
+43
View File
@@ -0,0 +1,43 @@
"use client";
import styles from "./style.module.css";
import Cookies from "js-cookie";
export default function DownloadReporteXLSX() {
const handleDownload = async () => {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
try {
const response = await fetch(
"https://venus.acatlan.unam.mx/censo_test/equipos/reporteXLSX",{headers}
);
if (!response.ok) {
throw new Error("Error al descargar el archivo");
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "reporte.xlsx";
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error(error);
alert("Hubo un problema al descargar el archivo.");
}
};
return (
<button className={styles.downloadBtn} onClick={handleDownload}>
<span className={styles.icon}></span>
Descargar XLSX
</button>
);
}
+47
View File
@@ -0,0 +1,47 @@
.downloadBtn {
display: flex;
align-items: center;
gap: 8px;
background: #1a73e8;
color: white;
border: none;
padding: 10px 16px;
cursor: pointer;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
transition: background 0.2s ease;
}
.downloadBtn:hover {
background: #1459b3;
}
/* Icono con css puro */
.icon {
width: 18px;
height: 18px;
position: relative;
}
.icon::before {
content: "";
width: 3px;
height: 10px;
background: white;
position: absolute;
left: 7px;
top: 0;
}
.icon::after {
content: "";
width: 10px;
height: 10px;
border-left: 3px solid white;
border-bottom: 3px solid white;
transform: rotate(-45deg);
position: absolute;
left: 4px;
top: 8px;
}
+72 -45
View File
@@ -95,7 +95,9 @@ export default function Editar() {
const [tiposEquipo, setTiposEquipo] = useState<TipoEquipo[]>([]);
const [laboratorios, setLaboratorios] = useState<Laboratorio[]>([]);
const [proyectos, setProyectos] = useState<Proyecto[]>([]);
const [sistemasOperativos, setSistemasOperativos] = useState<SistemaOperativo[]>([]);
const [sistemasOperativos, setSistemasOperativos] = useState<
SistemaOperativo[]
>([]);
const [procesadores, setProcesadores] = useState<Procesador[]>([]);
const [perifericos, setPerifericos] = useState<Perifericos[]>([]);
const [adscripcionLabel, setAdscripcionLabel] = useState("");
@@ -108,7 +110,6 @@ export default function Editar() {
const api_url = process.env.NEXT_PUBLIC_API_URL;
const mostrarCamposComputadora = Number(formData.id_tipo_equipo) !== 9;
// 🔹 Cargar catálogos
useEffect(() => {
const fetchCatalogos = async () => {
const token = Cookies.get("token");
@@ -194,8 +195,12 @@ export default function Editar() {
marca: { id_marca: number; marca: string };
periferico: { id_periferico: number; periferico: string };
observaciones?: string;
id_laboratorio?: number;
id_proyecto?: number;
laboratorio: {
id_laboratorio?: number;
};
proyecto: {
id_proyecto?: number;
};
}
const fetchEquipo = async () => {
@@ -245,16 +250,28 @@ export default function Editar() {
id_adscripcion: equipo.adscripcion?.id_adscripcion || 0,
lugar: equipo.lugar || "",
id_periferico: equipo.periferico?.id_periferico || 0,
id_laboratorio: equipo.id_laboratorio || 0,
id_proyecto: equipo.id_proyecto || 0,
id_laboratorio: equipo.laboratorio?.id_laboratorio || 0,
id_proyecto: equipo.proyecto?.id_proyecto || 0,
fechaMovimiento: equipo.fechaMovimiento || "",
responsable,
});
setAdscripcionLabel(equipo.adscripcion?.adscripcion);
setId(equipo.id_equipo);
} catch (error) {
console.error("Error al obtener el equipo:", error);
} catch (err) {
if (axios.isAxiosError(err)) {
if (err.response) {
toast.error(
err.response.data?.message || "Error al crear la cuenta"
);
} else if (err.request) {
toast.error("No se pudo conectar con el servidor");
} else {
toast.error("Ocurrió un error inesperado");
}
} else {
toast.error("Ocurrió un error inesperado");
}
toast.error("No se pudo cargar la información del equipo.");
}
};
@@ -331,7 +348,8 @@ export default function Editar() {
return;
}
{/*if (!formData.id_laboratorio) {
{
/*if (!formData.id_laboratorio) {
toast.error("Laboratorio no seleccionado");
return;
}
@@ -339,7 +357,8 @@ export default function Editar() {
if (!formData.id_proyecto) {
toast.error("Proyecto no seleccionado");
return;
}*/}
}*/
}
if (formData.id_tipo_equipo == 9) {
if (!formData.id_periferico) {
@@ -378,6 +397,7 @@ export default function Editar() {
lugar: formData.lugar,
id_sistema_operativo: formData.id_sistema_operativo,
id_tipo_uso: formData.id_uso,
id_periferico: formData.id_periferico,
serie: formData.serie,
modelo: formData.modelo,
id_marca: formData.id_marca,
@@ -462,7 +482,9 @@ export default function Editar() {
const first = data[0];
setFormData((prev) => ({
...prev,
responsable: `${first.nombre ?? ""} ${first.apellidos ?? ""}`.trim(),
responsable: `${first.nombre ?? ""} ${
first.apellidos ?? ""
}`.trim(),
}));
} else {
toast.error(
@@ -549,7 +571,7 @@ export default function Editar() {
/>
</div>
<div className="formGroup">
{/* <div className="formGroup">
<label>Tipo de equipo</label>
<select
style={{ background: "#f6f7f9" }}
@@ -567,7 +589,7 @@ export default function Editar() {
</option>
))}
</select>
</div>
</div> */}
<div className="formGroup">
<label>Estado</label>
@@ -588,9 +610,7 @@ export default function Editar() {
))}
</select>
</div>
</div>
{/* Columna 2 */}
<div className="column">
@@ -727,39 +747,46 @@ export default function Editar() {
placeholder="Selecciona una Adscripción"
/>
</div>
<div className="formGroup">
<label>Laboratorio</label>
<select
value={formData.id_laboratorio}
onChange={(e) => handleInputChange("id_laboratorio", e.target.value)}
>
<option value="">Selecciona laboratorio</option>
{laboratorios.map((lab) => (
<option key={lab.id_laboratorio} value={lab.id_laboratorio}>
{lab.laboratorio}
</option>
))}
</select>
</div>
{mostrarCamposComputadora && (
<div className="formGroup">
<label>Laboratorio</label>
<select
value={formData.id_laboratorio}
onChange={(e) =>
handleInputChange("id_laboratorio", e.target.value)
}
>
<option value="">Selecciona laboratorio</option>
{laboratorios.map((lab) => (
<option key={lab.id_laboratorio} value={lab.id_laboratorio}>
{lab.laboratorio}
</option>
))}
</select>
</div>
)}
</div>
{/* Columna 3 */}
<div className="column">
<div className="formGroup">
<label>Proyecto</label>
<select
value={formData.id_proyecto}
onChange={(e) => handleInputChange("id_proyecto", e.target.value)}
>
<option value="">Selecciona proyecto</option>
{proyectos.map((proy) => (
<option key={proy.id_proyecto} value={proy.id_proyecto}>
{proy.proyecto}
</option>
))}
</select>
</div>
{mostrarCamposComputadora && (
<div className="formGroup">
<label>Proyecto</label>
<select
value={formData.id_proyecto}
onChange={(e) =>
handleInputChange("id_proyecto", e.target.value)
}
>
<option value="">Selecciona proyecto</option>
{proyectos.map((proy) => (
<option key={proy.id_proyecto} value={proy.id_proyecto}>
{proy.proyecto}
</option>
))}
</select>
</div>
)}
<div className="formGroup">
<label>Lugar</label>
<textarea
@@ -807,4 +834,4 @@ export default function Editar() {
</div>
</div>
);
}
}
+4 -5
View File
@@ -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 "./pregunta1.1.css";
@@ -71,7 +71,7 @@ export default function Pregunta1() {
);
for (const item of res.data) {
const categoria = item.categoria.trim(); // ⚠️ elimina espacios basura
const categoria = item.categoria.trim();
const mapping = CATEGORIA_MAP[categoria];
if (!mapping) continue;
@@ -170,9 +170,8 @@ export default function Pregunta1() {
<div className="contenedor-censo">Censo de equipos de cómputo</div>
<div className="pregunta-cuadro">
1. Desglose en cada renglón, el número de equipos de cómputo dedicado
por cada categoría enlistada, de acuerdo con el perfil de usuario al que
se destina su uso primordialmente. *
Número de equipos de cómputo
por cada categoría enlistada, de acuerdo con el perfil de usuario.
</div>
<div className="contenedor-tablas">
+2 -6
View File
@@ -57,9 +57,9 @@ export default function Pregunta2() {
const token = Cookies.get("token");
const headers = {Authorization: `Bearer ${token}`};
axios
.get("https://venus.acatlan.unam.mx/censo_test/equipos/reporte/tipoEquipos_sistemasOperativos",{headers}) // ← TU API AQUI
.get("https://venus.acatlan.unam.mx/censo_test/equipos/reporte/tipoEquipos_sistemasOperativos",{headers})
.then((res) => {
const json = res.data; // Tu JSON con 5 arreglos
const json = res.data;
const formatted: PlatformData = {
"pc-desktop": transformPlatform(json[0]),
@@ -85,10 +85,6 @@ export default function Pregunta2() {
Censo de equipos Sistemas Operativos
</div>
<div className={styles.header_P1}>
Presione cada pestaña para ver la información de las plataformas.
</div>
<div className={styles["main-content_P1"]}>
{/* Tabs */}
<div className={styles.tabs_P1}>
+1 -6
View File
@@ -143,11 +143,9 @@ export default function Pregunta3_2() {
<div className={styles.scanView_P3}>
<div className={styles.container_P3}>
<div className={styles.header_P3}>
<h1 className={styles.titulo}>PREGUNTA 3 (2/5)</h1>
<p className={styles.texto}>
3. Desglose la cantidad de población beneficiada por plataforma y tipo de procesador: *
Cantidad de población beneficiada por plataforma y tipo de procesador:
</p>
<p className={styles.subtexto}>Presione cada pestaña para ingresar la información.</p>
</div>
<div className={styles.mainContent_P3}>
@@ -245,9 +243,6 @@ export default function Pregunta3_2() {
</tbody>
</table>
</div>
<button className={styles.consultarBtn_P3}>
Consultar las equivalencias de procesadores
</button>
</>
) : (
<div className={styles.emptyState_P3}>
+114 -31
View File
@@ -1,65 +1,148 @@
"use client";
import React, { useState } from "react";
import { useState, useEffect } from "react";
import Cookies from "js-cookie";
import axios from "axios";
import "./pregunta7.css";
type AntiguedadItem = {
antiguedad: string | null;
total: number | string;
};
type RespuestaAntiguedad = {
impresion: AntiguedadItem[];
digitalizacion: AntiguedadItem[];
};
export default function Pregunta7() {
const [datos, setDatos] = useState([
{ nombre: "Impresión", valores: ["", "", "", ""] },
{ nombre: "Digitalización", valores: ["", "", "", ""] },
{ 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"],
},
]);
// Función para calcular total de cada fila en Pregunta 7
const calcularTotal = (valores: string[]) =>
valores.reduce((acc, val) => acc + (Number(val) || 0), 0);
const [loading, setLoading] = useState(true);
const api_url = process.env.NEXT_PUBLIC_API_URL;
// ------------------------------
// 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");
axios
.get<RespuestaAntiguedad>(
`${api_url}/equipos/reporte/contar_perifericos_antiguedad`,
{
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => {
const { impresion, digitalizacion } = res.data;
setDatos([
{ nombre: "Impresión", valores: transformarDatos(impresion) },
{ nombre: "Digitalización", valores: transformarDatos(digitalizacion) },
]);
})
.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">
{/* Pregunta 7 */}
<div className="contenedor-censo">
Censo de equipos periféricos - Estado del equipo periférico (impresión y
digitalización.)
</div>
<div className="pregunta-cuadro">
7. Calcule porcentualmente (%) la antiguedad que tienen los equipos
periféricos del área universitaria.
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
Antigüedad que tienen los equipos periféricos del área universitaria.
</div>
<div className="tabla-contenedor">
<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>
+10 -16
View File
@@ -1,15 +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 = {
@@ -25,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
@@ -47,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":
@@ -56,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
@@ -72,7 +66,6 @@ export default function Pregunta9() {
const pct = (valor: number) => ((valor / totalEquipo) * 100).toFixed(2);
// [Menor a 2, Entre 2-3, Entre 4-5, Mayor a 6]
return [pct(menores2), pct(entre2_3), pct(entre4_6), pct(mayores6),pct(notfound)];
};
@@ -124,15 +117,15 @@ export default function Pregunta9() {
return (
<div className="contenedor-pregunta">
{/* Pregunta intro (servidores) */}
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
{/* <div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
Indique cuantos servidores son utilizados en ambientes productivos y si en ellos se almacenan datos personales.
</div>
<Pregunta4/>
<Pregunta4/> */}
{/* Pregunta 9: Antigüedad */}
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
Calcule porcentualmente (%) la antigüedad que tienen los equipos de cómputo del área universitaria.
Antigüedad que tienen los equipos de cómputo del área universitaria.
</div>
<div className="tabla-contenedor">
@@ -177,7 +170,8 @@ export default function Pregunta9() {
</table>
</div>
<Pregunta10/>
</div>
);
}
@@ -1,6 +1,6 @@
.contenedor-censo{
background-color: #002855;
background-color: #003e79;
color: white;
padding: 15px;
font-size: 20px;
@@ -10,7 +10,7 @@
.pregunta-cuadro {
background-color: #f5f5f5;
border-left: 6px solid #001f3f;
border-left: 6px solid #003e79;
padding: 15px;
border-radius: 8px;
font-size: 16px;
@@ -56,7 +56,7 @@
/* Colores personalizados */
.azul-marino {
background-color: #002855;
background-color: #003e79;
color: white;
}
@@ -78,7 +78,7 @@
.input-contenedor input {
width: 100%;
padding: 6px 25px 6px 6px;
border: 2px solid #002855;
border: 2px solid #003e79;
border-radius: 6px;
font-size: 14px;
color: #333;
@@ -122,7 +122,7 @@
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
color: #003e79;
background-color: #eef2f6;
}
+7 -6
View File
@@ -1,6 +1,7 @@
/* === Cuadro de la pregunta === */
.pregunta-cuadro {
border-left: 6px solid #001f3f;
background-color: #fff;
border-left: 6px solid #003e79;
padding: 15px;
border-radius: 8px;
font-size: 16px;
@@ -31,7 +32,7 @@
}
.tabla th {
background-color: #002855;
background-color: #003e79;
color: white;
font-weight: 600;
font-size: 15px;
@@ -43,7 +44,7 @@
/* === Colores personalizados === */
.azul-marino {
background-color: #002855 !important;
background-color: #003e79 !important;
color: white !important;
}
@@ -61,9 +62,9 @@
}
.input-contenedor input {
width: 40%;
width: 60%;
padding: 6px;
border: 2px solid #002855;
border: 2px solid #003e79;
border-radius: 6px;
font-size: 14px;
color: #333;
@@ -93,7 +94,7 @@
/* Para celdas del total */
.total-celda {
font-weight: bold;
color: #002855;
color: #003e79;
background-color: #eef2f6;
}
+6 -7
View File
@@ -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(() => {
@@ -56,16 +55,16 @@ export default function Pregunta10() {
return (
<>
<div className="pregunta-cuadro" style={{ marginTop: "30px" }}>
¿Cuántos equipos de cómputo tienen garantía de proveedor?
Equipos de cómputo que tienen garantía de proveedor
</div>
<div className="tabla-contenedor">
<table className="tabla">
<thead>
<tr>
<th className="azul-marino">Computadoras de Escritorio (247)</th>
<th className="azul-marino">Computadoras Portátiles (767)</th>
<th className="azul-marino">Alto Rendimiento (17)</th>
<th className="azul-marino">Computadoras de Escritorio</th>
<th className="azul-marino">Computadoras Portátiles</th>
<th className="azul-marino">Alto Rendimiento</th>
</tr>
</thead>
<tbody>
@@ -75,7 +74,7 @@ export default function Pregunta10() {
<input
type="number"
value={garantia.escritorio}
readOnly // 👈 solo lectura, como en otros reportes
readOnly
/>
</div>
</td>
+6 -7
View File
@@ -3,24 +3,23 @@
}
.contenedor-censo{
background-color: #002855;
background-color: #003e79;
color: white;
padding: 15px;
font-size: 16px;
margin-bottom: 25px;
border-radius: 4px;
}
.pregunta-cuadro {
background-color: #fff;
border-left: 6px solid #001f3f;
border-left: 10px solid #003e79;
padding: 15px;
border-radius: 8px;
font-size: 16px;
margin-bottom: 25px;
}
.tabla-contenedor {
background: white;
padding: 20px;
@@ -56,7 +55,7 @@
/* Colores personalizados */
.azul-marino {
background-color: #002855;
background-color: #003e79;
color: white;
}
@@ -78,7 +77,7 @@
.input-contenedor input {
width: 40%;
padding: 6px 6px 6px 6px;
border: 2px solid #002855;
border: 2px solid #003e79;
border-radius: 6px;
font-size: 14px;
color: #333;
@@ -123,7 +122,7 @@
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
color: #003e79;
background-color: #eef2f6;
}
+4 -4
View File
@@ -1,6 +1,6 @@
.pregunta-cuadro {
border-left: 6px solid #001f3f;
border-left: 6px solid #003e79;
padding: 15px;
border-radius: 8px;
font-size: 16px;
@@ -43,7 +43,7 @@
/* Colores personalizados */
.azul-marino {
background-color: #002855;
background-color: #003e79;
color: white;
}
@@ -65,7 +65,7 @@
.input-contenedor input {
width: 40%;
padding: 6px 6px 6px 6px;
border: 2px solid #002855;
border: 2px solid #003e79;
border-radius: 6px;
font-size: 14px;
color: #333;
@@ -110,7 +110,7 @@
/* Celda del total */
.total-celda {
font-weight: bold;
color: #002855;
color: #003e79;
background-color: #eef2f6;
}
+171 -84
View File
@@ -1,6 +1,8 @@
"use client";
import React, { useState, useEffect } from "react";
import "./pregunta1EP.module.scss";
import style from "./pregunta1EP.module.scss";
import axios from "axios";
import Cookies from "js-cookie";
interface EquiposImpresion {
inyeccionTinta: string;
@@ -12,51 +14,115 @@ interface EquiposImpresion {
laserAltoVolumenColor: string;
impresora3D: string;
plotter: string;
credencial: string;
termica: string;
}
export default function Pregunta1EP() {
const [equipos, setEquipos] = useState<EquiposImpresion>({
inyeccionTinta: "7",
laserPequenaBN: "186",
matrizPuntos: "",
laserAltoVolumenBN: "28",
laserPequenaColor: "20",
multifuncionales: "108",
laserAltoVolumenColor: "18",
impresora3D: "2",
plotter: "11",
inyeccionTinta: "0",
laserPequenaBN: "0",
matrizPuntos: "0",
laserAltoVolumenBN: "0",
laserPequenaColor: "0",
multifuncionales: "0",
laserAltoVolumenColor: "0",
impresora3D: "0",
plotter: "0",
credencial: "0",
termica: "0",
});
// 🔹 Preparado para conectar con API del backend
useEffect(() => {
// Cuando te den la API, descomenta y edita la URL 👇
/*
fetch("https://tu-api-backend.com/api/equipos-impresion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const api_url = process.env.NEXT_PUBLIC_API_URL;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEquipos({
...equipos,
[e.target.name]: e.target.value,
});
};
useEffect(() => {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/equipos_impesion_group/impresoras`, {
headers,
})
.then((res) => {
const data = res.data;
const valores = {
inyeccionTinta: "0",
laserPequenaBN: "0",
matrizPuntos: "0",
laserAltoVolumenBN: "0",
laserPequenaColor: "0",
multifuncionales: "0",
laserAltoVolumenColor: "0",
impresora3D: "0",
plotter: "0",
credencial: "0",
termica: "0",
};
data.forEach((item: any) => {
const uso = item.periferico.toUpperCase().trim();
const total = item.total ?? "0";
switch (uso) {
case "INYECCIÓN TINTA":
valores.inyeccionTinta = total;
break;
case "LÁSER PEQUEÑA B/N":
valores.laserPequenaBN = total;
break;
case "MATRIZ DE PUNTOS":
valores.matrizPuntos = total;
break;
case "LÁSER DE ALTO VOLUMEN B/N":
valores.laserAltoVolumenBN = total;
break;
case "LÁSER PEQUEÑA COLOR":
valores.laserPequenaColor = total;
break;
case "MULTIFUNCIONALES":
valores.multifuncionales = total;
break;
case "LÁSER DE ALTO VOLUMEN COLOR":
valores.laserAltoVolumenColor = total;
break;
case "3D":
valores.impresora3D = total;
break;
case "IMPRESORA CREDENCIALES":
valores.credencial = total;
break;
case "IMPRESORA TÉRMICA":
valores.termica = total;
break;
case "PLOTTER":
valores.plotter = total;
break;
}
});
setEquipos(valores);
})
.catch((err) => {
console.error("Error:", err);
});
}, []);
return (
<div className="container">
<div className="contenedor-censo">
Censo de equipos periféricos - Equipo de digitalización
Censo de equipos periféricos - Equipo de Impresion
</div>
<div className="pregunta-cuadro">
1. Desglose el número de equipos de impresión con que cuenta el área
universitaria.
</div>
<div className="pregunta-cuadro">Equipos de impresión.</div>
<div className="grid">
<div className={style.grid}>
{/* Columna 1 */}
<div className="item">
<label htmlFor="inyeccionTinta">Inyección de tinta</label>
@@ -65,29 +131,7 @@ export default function Pregunta1EP() {
id="inyeccionTinta"
name="inyeccionTinta"
value={equipos.inyeccionTinta}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="laserPequenaBN">Láser pequeña B/N</label>
<input
type="text"
id="laserPequenaBN"
name="laserPequenaBN"
value={equipos.laserPequenaBN}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="matrizPuntos">Matriz de puntos</label>
<input
type="text"
id="matrizPuntos"
name="matrizPuntos"
value={equipos.matrizPuntos}
onChange={handleChange}
disabled
/>
</div>
@@ -99,7 +143,42 @@ export default function Pregunta1EP() {
id="laserAltoVolumenBN"
name="laserAltoVolumenBN"
value={equipos.laserAltoVolumenBN}
onChange={handleChange}
disabled
/>
</div>
<div className="item">
<label htmlFor="laserAltoVolumenColor">
Láser de alto volumen Color
</label>
<input
type="text"
id="laserAltoVolumenColor"
name="laserAltoVolumenColor"
value={equipos.laserAltoVolumenColor}
disabled
/>
</div>
<div className="item">
<label htmlFor="laserAltoVolumenColor">Impresora credenciales</label>
<input
type="text"
id="laserAltoVolumenColor"
name="laserAltoVolumenColor"
value={equipos.credencial}
disabled
/>
</div>
<div className="item">
<label htmlFor="laserPequenaBN">Láser pequeña B/N</label>
<input
type="text"
id="laserPequenaBN"
name="laserPequenaBN"
value={equipos.laserPequenaBN}
disabled
/>
</div>
@@ -110,32 +189,7 @@ export default function Pregunta1EP() {
id="laserPequenaColor"
name="laserPequenaColor"
value={equipos.laserPequenaColor}
onChange={handleChange}
/>
</div>
<div className="item">
<label htmlFor="multifuncionales">Multifuncionales</label>
<input
type="text"
id="multifuncionales"
name="multifuncionales"
value={equipos.multifuncionales}
onChange={handleChange}
/>
</div>
{/* Columna 3 */}
<div className="item">
<label htmlFor="laserAltoVolumenColor">
Láser de alto volumen Color
</label>
<input
type="text"
id="laserAltoVolumenColor"
name="laserAltoVolumenColor"
value={equipos.laserAltoVolumenColor}
onChange={handleChange}
disabled
/>
</div>
@@ -146,7 +200,40 @@ export default function Pregunta1EP() {
id="impresora3D"
name="impresora3D"
value={equipos.impresora3D}
onChange={handleChange}
disabled
/>
</div>
<div className="item">
<label htmlFor="matrizPuntos">Impresora termica</label>
<input
type="text"
id="matrizPuntos"
name="matrizPuntos"
value={equipos.termica}
disabled
/>
</div>
<div className="item">
<label htmlFor="matrizPuntos">Matriz de puntos</label>
<input
type="text"
id="matrizPuntos"
name="matrizPuntos"
value={equipos.matrizPuntos}
disabled
/>
</div>
<div className="item">
<label htmlFor="multifuncionales">Multifuncionales</label>
<input
type="text"
id="multifuncionales"
name="multifuncionales"
value={equipos.multifuncionales}
disabled
/>
</div>
@@ -157,7 +244,7 @@ export default function Pregunta1EP() {
id="plotter"
name="plotter"
value={equipos.plotter}
onChange={handleChange}
disabled
/>
</div>
</div>
+87 -41
View File
@@ -1,6 +1,8 @@
"use client";
import React, { useState, useEffect } from "react";
import { useState, useEffect } from "react";
import styles from "./pregunta2EP.module.scss";
import axios from "axios";
import Cookies from "js-cookie";
interface EquiposPoblacion {
alumnos: string;
@@ -13,40 +15,89 @@ interface EquiposPoblacion {
export default function Pregunta2EP() {
const [equipos, setEquipos] = useState<EquiposPoblacion>({
alumnos: "35",
profesores: "43",
alumnos: "0",
profesores: "0",
tecnicosAcademicos: "",
investigadores: "",
administrativos: "302",
total: "380",
administrativos: "0",
total: "0",
});
// Listo para conectar al backend
useEffect(() => {
/*
fetch("https://tu-api-backend.com/api/equipos-poblacion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const api_url = process.env.NEXT_PUBLIC_API_URL;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setEquipos((prev) => ({
...prev,
[name]: value,
}));
};
useEffect(() => {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_periferico_tipoUso/impresoras`, {
headers,
})
.then((res) => {
const data = res.data;
// Valores por defecto
const valores = {
alumnos: "0",
profesores: "0",
tecnicosAcademicos: "0",
investigadores: "0",
administrativos: "0",
total: "0",
};
data.forEach((item: any) => {
const uso = item.uso.toUpperCase().trim();
const total = item.total ?? "0";
switch (uso) {
case "ALUMNO":
case "ALUMNOS":
valores.alumnos = total;
break;
case "PROFESOR":
case "PROFESORES":
valores.profesores = total;
break;
case "TÉCNICO ACADEMICO":
case "TÉCNICO ACADÉMICO":
valores.tecnicosAcademicos = total;
break;
case "INVESTIGADOR":
case "INVESTIGADORES":
valores.investigadores = total;
break;
case "ADMINISTRATIVO":
case "ADMINISTRATIVOS":
valores.administrativos = total;
break;
}
});
// Calcular total general
valores.total = String(
Number(valores.alumnos) +
Number(valores.profesores) +
Number(valores.tecnicosAcademicos) +
Number(valores.investigadores) +
Number(valores.administrativos)
);
setEquipos(valores);
})
.catch((err) => {
console.error("Error:", err);
});
}, []);
return (
<div className={styles.container_P2}>
<div className="contenedor-censo">
Censo de equipos periféricos - Equipo de digitalización
</div>
<div className="pregunta-cuadro">
2. Indique el número de equipos de impresión de acuerdo con la población universitaria al que se destina su uso primordialmente.
Equipos de impresión de acuerdo con la población universitaria.
</div>
<div className={styles.row_P2}>
@@ -57,20 +108,18 @@ export default function Pregunta2EP() {
id="alumnos"
name="alumnos"
value={equipos.alumnos}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="profesores">
Profesores
</label>
<label htmlFor="profesores">Profesores</label>
<input
type="text"
id="profesores"
name="profesores"
value={equipos.profesores}
onChange={handleChange}
disabled
/>
</div>
@@ -81,33 +130,29 @@ export default function Pregunta2EP() {
id="tecnicosAcademicos"
name="tecnicosAcademicos"
value={equipos.tecnicosAcademicos}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="investigadores">
Investigadores
</label>
<label htmlFor="investigadores">Investigadores</label>
<input
type="text"
id="investigadores"
name="investigadores"
value={equipos.investigadores}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="administrativos">
Administrativos
</label>
<label htmlFor="administrativos">Administrativos</label>
<input
type="text"
id="administrativos"
name="administrativos"
value={equipos.administrativos}
onChange={handleChange}
disabled
/>
</div>
@@ -118,10 +163,11 @@ export default function Pregunta2EP() {
id="total"
name="total"
value={equipos.total}
onChange={handleChange}
disabled
/>
</div>
</div>
</div>
);
}
//IO
+62 -30
View File
@@ -1,40 +1,73 @@
"use client";
import React, { useState, useEffect } from "react";
import { useState, useEffect } from "react";
import "@/app/styles/layout/pregunta4EP.scss";
import Cookies from "js-cookie";
import axios from "axios";
interface EquiposDigitalizacion {
digitalizadorCamaPlana: string;
digitalizador3d: string;
d3D: string;
digitalizadorAlimentador: string;
digitalizadorGranVolumen: string;
}
export default function Pregunta4EP() {
const [equipos, setEquipos] = useState<EquiposDigitalizacion>({
digitalizadorCamaPlana: "27",
digitalizador3d: "",
digitalizadorAlimentador: "108",
digitalizadorGranVolumen: "1",
digitalizadorCamaPlana: "0",
d3D: "0",
digitalizadorAlimentador: "0",
digitalizadorGranVolumen: "0",
});
// 🔹 Preparado para conectar con el backend
useEffect(() => {
// Cuando tengas la API, descomenta y reemplaza la URL:
/*
fetch("https://tu-api-backend.com/api/equipos-digitalizacion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const api_url = process.env.NEXT_PUBLIC_API_URL;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setEquipos({
...equipos,
[name]: value,
});
};
useEffect(() => {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/equipos_impesion_group/dijitales`, {
headers,
})
.then((res) => {
const data = res.data;
const valores = {
digitalizadorCamaPlana: "0",
d3D: "0",
digitalizadorAlimentador: "0",
digitalizadorGranVolumen: "0",
};
data.forEach((item: any) => {
const periferico = item.periferico.toUpperCase().trim();
const total = item.total ?? "0";
switch (periferico) {
case "DIGITALIZADOR DE CAMA PLANA PARA OFICINA":
valores.digitalizadorCamaPlana = total;
break;
case "3D":
valores.d3D = total;
break;
case "DIGITALIZADOR CON ALIMENTADOR DE HOJAS PARA OFICINA":
valores.digitalizadorAlimentador = total;
break;
case "DIGITALIZADOR DE GRAN VOLUMEN":
valores.digitalizadorGranVolumen = total;
break;
}
});
setEquipos(valores);
})
.catch((err) => {
console.error("Error:", err);
});
}, []);
return (
<div className="container">
@@ -43,8 +76,7 @@ export default function Pregunta4EP() {
</div>
<div className="pregunta-cuadro">
4. Desglose el número de equipos de digitalización con que cuenta el
área universitaria.
Número de equipos de digitalización.
</div>
<div className="grid">
@@ -57,7 +89,7 @@ export default function Pregunta4EP() {
id="digitalizadorCamaPlana"
name="digitalizadorCamaPlana"
value={equipos.digitalizadorCamaPlana}
onChange={handleChange}
disabled
/>
</div>
@@ -67,8 +99,8 @@ export default function Pregunta4EP() {
type="text"
id="digitalizador3d"
name="digitalizador3d"
value={equipos.digitalizador3d}
onChange={handleChange}
value={equipos.d3D}
disabled
/>
</div>
@@ -81,7 +113,7 @@ export default function Pregunta4EP() {
id="digitalizadorAlimentador"
name="digitalizadorAlimentador"
value={equipos.digitalizadorAlimentador}
onChange={handleChange}
disabled
/>
</div>
@@ -94,7 +126,7 @@ export default function Pregunta4EP() {
id="digitalizadorGranVolumen"
name="digitalizadorGranVolumen"
value={equipos.digitalizadorGranVolumen}
onChange={handleChange}
disabled
/>
</div>
</div>
+93 -48
View File
@@ -2,6 +2,8 @@
import "./pregunta5EP.scss";
import styles from "./pregunta2EP.module.scss";
import { useEffect, useState } from "react";
import Cookies from "js-cookie";
import axios from "axios";
interface EquiposPoblacion {
alumnos: string;
@@ -13,44 +15,93 @@ interface EquiposPoblacion {
}
export default function Pregunta5EP() {
const [equipos, setEquipos] = useState<EquiposPoblacion>({
alumnos: "35",
profesores: "43",
tecnicosAcademicos: "",
investigadores: "",
administrativos: "302",
total: "380",
});
// Listo para conectar al backend
useEffect(() => {
/*
fetch("https://tu-api-backend.com/api/equipos-poblacion")
.then((res) => res.json())
.then((data) => setEquipos(data))
.catch((err) => console.error("Error al obtener datos:", err));
*/
}, []);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setEquipos((prev) => ({
...prev,
[name]: value,
}));
};
const [equipos, setEquipos] = useState<EquiposPoblacion>({
alumnos: "0",
profesores: "0",
tecnicosAcademicos: "0",
investigadores: "0",
administrativos: "0",
total: "0",
});
const api_url = process.env.NEXT_PUBLIC_API_URL;
useEffect(() => {
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_periferico_tipoUso/dijtales`, {
headers,
})
.then((res) => {
const data = res.data;
const valores = {
alumnos: "0",
profesores: "0",
tecnicosAcademicos: "0",
investigadores: "0",
administrativos: "0",
total: "0",
};
data.forEach((item: any) => {
const uso = item.uso.toUpperCase().trim();
const total = item.total ?? "0";
switch (uso) {
case "ALUMNO":
case "ALUMNOS":
valores.alumnos = total;
break;
case "PROFESOR":
case "PROFESORES":
valores.profesores = total;
break;
case "TÉCNICO ACADEMICO":
case "TÉCNICO ACADÉMICO":
valores.tecnicosAcademicos = total;
break;
case "INVESTIGADOR":
case "INVESTIGADORES":
valores.investigadores = total;
break;
case "ADMINISTRATIVO":
case "ADMINISTRATIVOS":
valores.administrativos = total;
break;
}
});
// Calcular total general
valores.total = String(
Number(valores.alumnos) +
Number(valores.profesores) +
Number(valores.tecnicosAcademicos) +
Number(valores.investigadores) +
Number(valores.administrativos)
);
setEquipos(valores);
})
.catch((err) => {
console.error("Error:", err);
});
}, []);
return (
<div className="container">
<div className="contenedor-censo">
Censo de equipos periféricos - Equipo de digitalización
</div>
<div className="pregunta-cuadro">
5. Indique el número de equipos de digitalización de acuerdo con la
población universitaria al que se destina su uso primordialmente.
Número de equipos de digitalización de acuerdo con la población
universitaria.
</div>
<div className={styles.row_P2}>
<div className={styles.row_P2}>
<div className={styles.item_P2}>
<label htmlFor="alumnos">Alumnos</label>
<input
@@ -58,20 +109,18 @@ export default function Pregunta5EP() {
id="alumnos"
name="alumnos"
value={equipos.alumnos}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="profesores">
Profesores
</label>
<label htmlFor="profesores">Profesores</label>
<input
type="text"
id="profesores"
name="profesores"
value={equipos.profesores}
onChange={handleChange}
disabled
/>
</div>
@@ -82,33 +131,29 @@ export default function Pregunta5EP() {
id="tecnicosAcademicos"
name="tecnicosAcademicos"
value={equipos.tecnicosAcademicos}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="investigadores">
Investigadores
</label>
<label htmlFor="investigadores">Investigadores</label>
<input
type="text"
id="investigadores"
name="investigadores"
value={equipos.investigadores}
onChange={handleChange}
disabled
/>
</div>
<div className={styles.item_P2}>
<label htmlFor="administrativos">
Administrativos
</label>
<label htmlFor="administrativos">Administrativos</label>
<input
type="text"
id="administrativos"
name="administrativos"
value={equipos.administrativos}
onChange={handleChange}
disabled
/>
</div>
@@ -119,7 +164,7 @@ export default function Pregunta5EP() {
id="total"
name="total"
value={equipos.total}
onChange={handleChange}
disabled
/>
</div>
</div>
+39 -27
View File
@@ -1,6 +1,8 @@
"use client";
import React, { useState, useEffect } from "react";
import axios from "axios";
import Cookies from "js-cookie";
import "../../app/styles/layout/pregunta7.scss";
interface Dato {
@@ -8,29 +10,6 @@ interface Dato {
cantidad: number;
}
const datosSimulados: Dato[] = [
{ nombre: "AULA DE ROBÓTICA 101", cantidad: 18 },
{ nombre: "LAB DE QUÍMICA 201", cantidad: 25 },
{ nombre: "LAB DE FÍSICA 202", cantidad: 30 },
{ nombre: "LAB DE PROGRAMACIÓN 301", cantidad: 40 },
{ nombre: "AULA DE DISEÑO 102", cantidad: 22 },
{ nombre: "LAB ELECTRÓNICA 204", cantidad: 35 },
{ nombre: "LAB COMPUTACIÓN 305", cantidad: 28 },
{ nombre: "AULA INTERACTIVA 106", cantidad: 15 },
{ nombre: "LAB DE INNOVACIÓN 307", cantidad: 33 },
{ nombre: "SALA DE CONFERENCIAS A", cantidad: 12 },
{ nombre: "LAB DE MECATRÓNICA 308", cantidad: 45 },
{ nombre: "LAB DE INTELIGENCIA ARTIFICIAL 309", cantidad: 38 },
{ nombre: "LAB DE REDES 310", cantidad: 27 },
{ nombre: "SALA MULTIMEDIA B", cantidad: 20 },
{ nombre: "LAB DE BIOLOGÍA 205", cantidad: 26 },
{ nombre: "LAB DE MECÁNICA 210", cantidad: 32 },
{ nombre: "AULA DE INGLÉS 110", cantidad: 19 },
{ nombre: "SALA DE DOCENTES", cantidad: 14 },
{ nombre: "LAB DE BIG DATA 311", cantidad: 36 },
{ nombre: "LAB DE CIBERSEGURIDAD 312", cantidad: 29 },
];
export default function Pregunta7EP() {
const [data, setData] = useState<Dato[]>([]);
const [currentPage, setCurrentPage] = useState<number>(1);
@@ -38,8 +17,25 @@ export default function Pregunta7EP() {
const [sortColumn, setSortColumn] = useState<keyof Dato | null>(null);
const [sortAsc, setSortAsc] = useState<boolean>(true);
const api_url = process.env.NEXT_PUBLIC_API_URL;
useEffect(() => {
setData(datosSimulados);
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_laboratorio`, { headers })
.then((res) => {
const formato: Dato[] = res.data.map((item: any) => ({
nombre: item.laboratorio || "SIN NOMBRE",
cantidad: item.total || 0,
}));
setData(formato);
})
.catch((err) => {
console.error("Error cargando datos:", err);
});
}, []);
const sortedData = React.useMemo(() => {
@@ -77,9 +73,15 @@ 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),
0
);
return (
<div className="container">
<div className="pregunta-cuadro">Numero de laboratorios.</div>
<div className="controls">
<div className="show-records">
Mostrar
@@ -99,7 +101,10 @@ export default function Pregunta7EP() {
<table>
<thead>
<tr>
<th onClick={() => handleSort("nombre")}>
<th
onClick={() => handleSort("nombre")}
style={{ textAlign: "center" }}
>
Nombre del laboratorio o aula
{sortColumn === "nombre" && (
<img
@@ -109,7 +114,10 @@ export default function Pregunta7EP() {
)}
</th>
<th onClick={() => handleSort("cantidad")}>
<th
onClick={() => handleSort("cantidad")}
style={{ textAlign: "center" }}
>
Cantidad
{sortColumn === "cantidad" && (
<img
@@ -132,6 +140,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))}
@@ -1,45 +1,41 @@
"use client";
import React, { useState, useEffect } from "react";
import "../../styles/layout/pregunta7.scss";
import axios from "axios";
import Cookies from "js-cookie";
import "../../app/styles/layout/pregunta7.scss";
interface Dato {
nombre: string;
cantidad: number;
}
const datosSimulados: Dato[] = [
{ nombre: "AULA DE ROBÓTICA 101", cantidad: 18 },
{ nombre: "LAB DE QUÍMICA 201", cantidad: 25 },
{ nombre: "LAB DE FÍSICA 202", cantidad: 30 },
{ nombre: "LAB DE PROGRAMACIÓN 301", cantidad: 40 },
{ nombre: "AULA DE DISEÑO 102", cantidad: 22 },
{ nombre: "LAB ELECTRÓNICA 204", cantidad: 35 },
{ nombre: "LAB COMPUTACIÓN 305", cantidad: 28 },
{ nombre: "AULA INTERACTIVA 106", cantidad: 15 },
{ nombre: "LAB DE INNOVACIÓN 307", cantidad: 33 },
{ nombre: "SALA DE CONFERENCIAS A", cantidad: 12 },
{ nombre: "LAB DE MECATRÓNICA 308", cantidad: 45 },
{ nombre: "LAB DE INTELIGENCIA ARTIFICIAL 309", cantidad: 38 },
{ nombre: "LAB DE REDES 310", cantidad: 27 },
{ nombre: "SALA MULTIMEDIA B", cantidad: 20 },
{ nombre: "LAB DE BIOLOGÍA 205", cantidad: 26 },
{ nombre: "LAB DE MECÁNICA 210", cantidad: 32 },
{ nombre: "AULA DE INGLÉS 110", cantidad: 19 },
{ nombre: "SALA DE DOCENTES", cantidad: 14 },
{ nombre: "LAB DE BIG DATA 311", cantidad: 36 },
{ nombre: "LAB DE CIBERSEGURIDAD 312", cantidad: 29 },
];
const Page: React.FC = () => {
export default function Pregunta8() {
const [data, setData] = useState<Dato[]>([]);
const [currentPage, setCurrentPage] = useState<number>(1);
const [recordsPerPage, setRecordsPerPage] = useState<number>(10);
const [sortColumn, setSortColumn] = useState<keyof Dato | null>(null);
const [sortAsc, setSortAsc] = useState<boolean>(true);
const api_url = process.env.NEXT_PUBLIC_API_URL;
useEffect(() => {
setData(datosSimulados);
const token = Cookies.get("token");
const headers = { Authorization: `Bearer ${token}` };
axios
.get(`${api_url}/equipos/reporte/contar_proyecto`, { headers })
.then((res) => {
const formato: Dato[] = res.data.map((item: any) => ({
nombre: item.proyecto || "SIN PROYECTO",
cantidad: Number(item.total) || 0,
}));
setData(formato);
})
.catch((err) => {
console.error("Error cargando datos:", err);
});
}, []);
const sortedData = React.useMemo(() => {
@@ -77,9 +73,14 @@ const Page: React.FC = () => {
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),
0
);
return (
<div className="container">
<div className="pregunta-cuadro">Numero de proyectos.</div>
<div className="controls">
<div className="show-records">
Mostrar
@@ -101,32 +102,32 @@ const Page: React.FC = () => {
<tr>
<th
onClick={() => handleSort("nombre")}
style={{ cursor: "pointer" }}
style={{ textAlign: "center" }}
>
Nombre del laboratorio o aula
{sortColumn === "nombre" && sortAsc && (
<img src="/arrow_up.svg" alt="ascendente" />
Proyecto
{sortColumn === "nombre" && (
<img
src={sortAsc ? "/arrow_up.svg" : "/arrow_down.svg"}
alt="orden"
/>
)}
{sortColumn === "nombre" && !sortAsc && (
<img src="/arrow_down.svg" alt="descendente" />
)}
{sortColumn !== "nombre" && <></>}
</th>
<th
onClick={() => handleSort("cantidad")}
style={{ cursor: "pointer" }}
style={{ textAlign: "center" }}
>
Cantidad
{sortColumn === "cantidad" && sortAsc && (
<img src="/arrow_up.svg" alt="ascendente" />
{sortColumn === "cantidad" && (
<img
src={sortAsc ? "/arrow_up.svg" : "/arrow_down.svg"}
alt="orden"
/>
)}
{sortColumn === "cantidad" && !sortAsc && (
<img src="/arrow_down.svg" alt="descendente" />
)}
{sortColumn !== "cantidad" && <></>}
</th>
</tr>
</thead>
<tbody>
{paginatedData.map((item, index) => (
<tr key={index}>
@@ -138,6 +139,10 @@ const Page: React.FC = () => {
</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))}
@@ -167,6 +172,4 @@ const Page: React.FC = () => {
</div>
</div>
);
};
export default Page;
}
@@ -122,6 +122,18 @@
}
}
.grid {
background-color: #fff;
border-radius: 10px;
grid-template-columns: repeat(4, 1fr);
align-items: end;
gap: 20px;
padding: 20px;
display: grid;
overflow-x: auto;
box-shadow: 0 4px 10px #0000001a;
}
@media (max-width: 700px) {
.scanView_P1 .tabs_P1 {
width: 160px;
@@ -132,4 +144,4 @@
padding: 10px 12px;
text-align: left;
}
}
}
-18
View File
@@ -1,18 +0,0 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
const token = request.cookies.get("token")?.value;
if (!token) {
console.log("No hay token, redirigiendo a la página de inicio de sesión");
return NextResponse.redirect(new URL("/", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/escaner","/agregarEquipo","/editar"],
};
//IO
+46
View File
@@ -0,0 +1,46 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { jwtDecode } from "jwt-decode";
const permisos: Record<number, string[]> = {
1: ["/crearCuenta", "/equipoComputo", "/perifericos","/escaner", "/agregarEquipo", "/editar"],
2: ["/escaner", "/agregarEquipo", "/editar"],
};
export function proxy(request: NextRequest) {
const token = request.cookies.get("token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/", request.url));
}
const decoded: any = jwtDecode(token);
const tipoUsuario = decoded.tipoUsuario
if (!tipoUsuario) {
return NextResponse.redirect(new URL("/", request.url));
}
const pathname = new URL(request.url).pathname;
const rutasPermitidas = permisos[tipoUsuario] ?? [];
if (!rutasPermitidas.includes(pathname)) {
console.log(`Usuario tipo ${tipoUsuario} NO autorizado para: ${pathname}`);
return NextResponse.redirect(new URL("/", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
"/escaner",
"/agregarEquipo",
"/editar",
"/crearCuenta",
"/equipoComputo",
"/perifericos",
],
};
//IO