This commit is contained in:
2025-10-29 13:41:03 -06:00
parent c2168d4366
commit 210aa2f3db
10 changed files with 305 additions and 411 deletions
+17 -14
View File
@@ -3,10 +3,10 @@
import { useState, useEffect } from "react";
import axios from "axios";
import Cookies from "js-cookie"; // Para leer cookies en el cliente
import "../../styles/layout/agregarEquipo.scss";
import toast from "react-hot-toast";
import "../../styles/layout/agregarEquipo.scss";
export default function page() {
export default function Page() {
const [formData, setFormData] = useState({
serie: "",
marca: "",
@@ -76,7 +76,7 @@ export default function page() {
setTiposEquipo(tiposEquipoRes.data);
setSistemasOperativos(sistemasOperativosRes.data);
setProcesadores(procesadoresRes.data);
} catch (err: any) {
} catch (err) {
if (axios.isAxiosError(err)) {
if (err.response) {
toast.error(
@@ -127,17 +127,17 @@ export default function page() {
alert("Acción cancelada");
};
const handleChange = (e: any) => {
const { name, value } = e.target;
setFormData((prev) => {
let updated = { ...prev, [name]: value };
if (value === "Impresora") {
updated.sistemaOperativo = "";
updated.procesador = "";
}
return updated;
});
};
// const handleChange = (e: any) => {
// const { name, value } = e.target;
// setFormData((prev) => {
// let updated = { ...prev, [name]: value };
// if (value === "Impresora") {
// updated.sistemaOperativo = "";
// updated.procesador = "";
// }
// return updated;
// });
// };
return (
<div className="agregarEquipoContainer">
@@ -303,6 +303,9 @@ export default function page() {
<div className="formGroup">
<label>Sistema operativo</label>
<select>
<option value=""></option>
</select>
<input
type="text"
placeholder="Selecciona sistema operativo"
+6 -262
View File
@@ -1,267 +1,11 @@
"use client";
import { useEffect, useState } from "react";
import "../../styles/layout/agregarEquipo.scss";
import "./editar.css";
import { useSearchParams } from "next/navigation";
import axios from "axios";
export default function Home() {
const searchParams = useSearchParams();
const equipoId = searchParams.get("equipoId");
import dynamic from "next/dynamic";
const [formData, setFormData] = useState({
serie: "",
marca: "",
modelo: "",
tipoEquipo: "",
estado: "",
sistemaOperativo: "",
procesador: "",
tipoUso: "",
observaciones: "",
adscripcion: "",
lugar: "",
responsable: "",
});
const Editar = dynamic(() => import("@/components/Editar"), {
ssr: false,
});
useEffect(() => {
const fetchEquipo = async () => {
try {
const response = await axios.get(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/${equipoId}`
);
setFormData(response.data);
} catch (error) {
console.error("Error al obtener el equipo:", error);
alert("No se pudo cargar la información del equipo.");
}
};
if (equipoId) {
fetchEquipo();
}
}, [equipoId]);
const mostrarCamposComputadora = formData.tipoEquipo !== "Impresora";
const handleGuardar = async () => {
try {
await axios.patch(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/update/${equipoId}`,
formData
);
alert("Equipo actualizado correctamente");
} catch (error) {
console.error("Error al guardar:", error);
alert("Hubo un error al guardar el equipo.");
}
};
const handleCancelar = () => {
alert("Acción cancelada");
};
return (
<div className="agregarEquipoContainer">
<div className="innerContainer">
<h2 className="information">
{equipoId ? `Editar Equipo (${equipoId})` : "Agregar Equipo"}
<span>Inventario:</span>
<span>Fecha de censo:</span>
</h2>
<form className="equipoForm">
{/* Columna 1 */}
<div className="column">
<div className="formGroup">
<label>Serie</label>
<input
type="text"
placeholder="Ingresa serie"
value={formData.serie}
onChange={(e) =>
setFormData({ ...formData, serie: e.target.value })
}
/>
</div>
<div className="formGroup">
<label>Marca</label>
<select
value={formData.marca}
onChange={(e) =>
setFormData({ ...formData, marca: e.target.value })
}
>
<option value="">Ingresa marca</option>
<option value="Dell">Dell</option>
<option value="HP">HP</option>
<option value="Lenovo">Lenovo</option>
</select>
</div>
<div className="formGroup">
<label>Modelo</label>
<select
value={formData.modelo}
onChange={(e) =>
setFormData({ ...formData, modelo: e.target.value })
}
>
<option value="">Ingresa modelo</option>
<option value="XPS 15">XPS 15</option>
<option value="EliteBook">EliteBook</option>
<option value="ThinkPad">ThinkPad</option>
</select>
</div>
<div className="formGroup">
<label>Estado</label>
<select
value={formData.estado}
onChange={(e) =>
setFormData({ ...formData, estado: e.target.value })
}
>
<option value="">Selecciona estado</option>
<option value="Activado">Activado</option>
<option value="Desactivado">Desactivado</option>
<option value="En reparación">En reparación</option>
</select>
</div>
<div className="formGroup">
<label>Tipo uso</label>
<select
value={formData.tipoUso}
onChange={(e) =>
setFormData({ ...formData, tipoUso: e.target.value })
}
>
<option value="">Ingresa tipo de uso</option>
<option value="administrativo">administrativo</option>
<option value="educacional">educacional</option>
<option value="laboratorio">laboratorio</option>
</select>
</div>
</div>
{/* Columna 2 */}
<div className="column">
{mostrarCamposComputadora && (
<>
<div className="formGroup">
<label>Procesador</label>
<select
value={formData.procesador}
onChange={(e) =>
setFormData({ ...formData, procesador: e.target.value })
}
>
<option value="">Selecciona procesador</option>
<option value="Ryzen 3">Ryzen 3</option>
<option value="Intel i5">Intel i5</option>
<option value="AMD Ryzen 5">AMD Ryzen 5</option>
</select>
</div>
<div className="formGroup">
<label>Sistema operativo</label>
<select
value={formData.sistemaOperativo}
onChange={(e) =>
setFormData({
...formData,
sistemaOperativo: e.target.value,
})
}
>
<option value="">Selecciona sistema operativo</option>
<option value="Windows 10">Windows 10</option>
<option value="Windows 11">Windows 11</option>
<option value="Linux">Linux</option>
<option value="macOS">macOS</option>
</select>
</div>
</>
)}
<div className="formGroup">
<label>Adscripción</label>
<select
value={formData.adscripcion}
onChange={(e) =>
setFormData({ ...formData, adscripcion: e.target.value })
}
>
<option value="">Selecciona adscripción</option>
<option value="Cedetec">Cedetec</option>
<option value="Laboratorio">Laboratorio</option>
<option value="Administración">Administración</option>
</select>
</div>
<div className="formGroup">
<label>Responsable</label>
<select
value={formData.responsable}
onChange={(e) =>
setFormData({ ...formData, responsable: e.target.value })
}
>
<option value="">Selecciona responsable</option>
<option value="Lino">Lino</option>
<option value="Ana">Ana</option>
<option value="Carlos">Carlos</option>
</select>
</div>
</div>
{/* Columna 3 */}
<div className="column">
<div className="formGroup">
<label>Lugar</label>
<textarea
placeholder="Ingresa lugar"
value={formData.lugar}
onChange={(e) =>
setFormData({ ...formData, lugar: e.target.value })
}
rows={5}
className="textAreaLarge"
/>
</div>
<div className="formGroup">
<label>Observaciones</label>
<textarea
placeholder="Ingresa observaciones"
value={formData.observaciones}
onChange={(e) =>
setFormData({ ...formData, observaciones: e.target.value })
}
rows={5}
className="textAreaLarge"
/>
</div>
<div className="formActions">
<button
type="button"
className="btnGuardar"
onClick={handleGuardar}
>
Guardar
</button>
<button
type="button"
className="btnCancelar"
onClick={handleCancelar}
>
Cancelar
</button>
</div>
</div>
</form>
</div>
</div>
);
export default function Page() {
return <Editar />;
}
+7 -10
View File
@@ -5,13 +5,12 @@ import { useRouter } from "next/navigation";
import "../../styles/layout/escaner.scss"; // Importación global
import BarcodeScanner from "@/components/BarcodeScanner";
import axios from "axios";
import Image from "next/image";
export default function Dashboard() {
const router = useRouter();
const [isScanning, setIsScanning] = useState(false);
const [equipos, setEquipos] = useState();
const [search, setSearch] = useState("");
const [lastScan, setLastScan] = useState<string | null>(null);
interface equipo {
id: number;
@@ -29,7 +28,6 @@ export default function Dashboard() {
};
const handleScan = async (code: string) => {
setLastScan(code);
setIsScanning(false);
const encontrado: equipo = await axios.get("");
@@ -41,12 +39,6 @@ export default function Dashboard() {
}
};
// 🔒 Cerrar sesión
const cerrarSesion = () => {
localStorage.removeItem("loggedIn");
router.push("/");
};
return (
<div className="dashboardContainer">
<main className="scanView">
@@ -56,7 +48,12 @@ export default function Dashboard() {
<BarcodeScanner onScan={handleScan} />
) : (
<div className="scannerFrame">
<img src="/barcode_scanner.png" alt="Marco de escaneo" />
<Image
src="/barcode_scanner.png"
alt="Marco de escaneo"
width={200}
height={200}
/>
</div>
)}
-91
View File
@@ -1,91 +0,0 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import BarcodeScanner from "../../components/BarcodeScanner";
import "../styles/components/dashboard.scss";
type Equipo = {
id: string;
nombre: string;
estado: string;
};
const initialEquipos: Equipo[] = [
{ id: "001", nombre: "PC Aula 1", estado: "Disponible" },
{ id: "002", nombre: "PC Aula 2", estado: "En reparación" },
];
export default function Dashboard() {
const router = useRouter();
const [equipos, setEquipos] = useState<Equipo[]>(initialEquipos);
const [search, setSearch] = useState("");
const [lastScan, setLastScan] = useState("");
useEffect(() => {
const loggedIn = localStorage.getItem("loggedIn");
if (!loggedIn) router.push("/");
}, [router]);
const buscarEquipo = () => {
const resultado = equipos.filter(
e => e.id.includes(search) || e.nombre.toLowerCase().includes(search.toLowerCase())
);
setEquipos(resultado);
};
const cerrarSesion = () => {
localStorage.removeItem("loggedIn");
router.push("/");
};
const handleScan = (code: string) => {
setLastScan(code);
const encontrado = equipos.find(e => e.id === code);
if (encontrado) {
alert(`Equipo encontrado: ${encontrado.nombre} (${encontrado.estado})`);
} else {
const nombre = prompt("Equipo no registrado. Ingresa el nombre:");
if (nombre) {
setEquipos([...equipos, { id: code, nombre, estado: "Disponible" }]);
alert("Equipo agregado al inventario");
}
}
};
return (
<div className="dashboard-container">
<div className="header">
<h2>Dashboard Inventario Escolar</h2>
<button onClick={cerrarSesion}>Cerrar sesión</button>
</div>
<div className="search-section">
<h3>Buscar equipo</h3>
<div style={{ display: "flex", marginTop: "10px" }}>
<input type="text" placeholder="ID o nombre" value={search} onChange={(e) => setSearch(e.target.value)} />
<button onClick={buscarEquipo}>Buscar</button>
</div>
</div>
<div className="scanner-section">
<h3>Escanear código de barras</h3>
<BarcodeScanner onDetected={handleScan} />
{lastScan && <p>Último código escaneado: <strong>{lastScan}</strong></p>}
</div>
<div className="equipos-section">
<h3>Equipos</h3>
<ul>
{equipos.map((e) => (
<li key={e.id}>
<span>{e.id} - {e.nombre}</span>
<span className={e.estado === "Disponible" ? "estado-disponible" : "estado-reparacion"}>{e.estado}</span>
</li>
))}
</ul>
</div>
</div>
);
}
+1 -5
View File
@@ -12,13 +12,11 @@ import toast from "react-hot-toast";
export default function Login() {
const [nombre, setNombre] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const router = useRouter();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setLoading(true);
try {
const response = await axios.post(
@@ -32,7 +30,7 @@ export default function Login() {
document.cookie = `token=${token}; path=/; SameSite=Strict`;
router.push("/Escaner");
} catch (err: any) {
} catch (err) {
if (axios.isAxiosError(err)) {
if (err.response) {
toast.error(
@@ -46,8 +44,6 @@ export default function Login() {
} else {
toast.error("Ocurrió un error inesperado");
}
} finally {
setLoading(false);
}
};
+14 -13
View File
@@ -1,13 +1,10 @@
import './reporte.css';
import "./reporte.css";
export default function Reporte() {
return (
<div>
<header className="encabezado">
<div className="encabezado-sup"></div>
<div className="logo">
<img src="fes-logo.jpg" alt="" className="logo-img" />
</div>
<div className="pestaña">
<span>Escanear código</span>
@@ -20,8 +17,8 @@ export default function Reporte() {
</nav>
</header>
<div className='contenedor'>
<div className='titulo-reporte'>
<div className="contenedor">
<div className="titulo-reporte">
<p>REPORTE</p>
</div>
@@ -30,10 +27,10 @@ export default function Reporte() {
<button type="submit">Buscar</button>
</form>
</div>
<div className='tabla-rec'></div>
<button className='boton-descargar'>Descargar</button>
<div className="tabla-rec"></div>
<button className="boton-descargar">Descargar</button>
<div className='filtro-rec'>
<div className="filtro-rec">
<form className="editar">
{/* Columna 1 */}
<div className="columna">
@@ -78,11 +75,15 @@ export default function Reporte() {
</select>
</div>
<div className="botones-filtro">
<button type="reset" className="limpiar">Limpiar filtros</button>
<button type="submit" className="aplicar">Aplicar filtros</button>
</div>
<button type="reset" className="limpiar">
Limpiar filtros
</button>
<button type="submit" className="aplicar">
Aplicar filtros
</button>
</div>
</form>
</div>
</div>
);
}
}
-6
View File
@@ -8,14 +8,8 @@ import Link from "next/link";
function BarNavigation() {
const router = useRouter(); // ✅ Para redirigir
const [openMenu, setOpenMenu] = useState(false);
const [openSubMenu, setOpenSubMenu] = useState<number | null>(null);
const toggleMenu = () => setOpenMenu(!openMenu);
const toggleSubMenu = (index: number) => {
if (typeof window !== "undefined" && window.innerWidth <= 800) {
setOpenSubMenu(openSubMenu === index ? null : index);
}
};
const cerrarSesion = () => {
if (typeof window !== "undefined") {
-10
View File
@@ -4,16 +4,6 @@
import React, { useEffect, useRef } from "react";
import Quagga from "@ericblade/quagga2";
// Tipos mínimos para el resultado de Quagga
interface CodeResult {
code: string;
format: string;
}
interface QuaggaResult {
codeResult: CodeResult | null;
}
// Tipos para la configuración (opcional, pero mejora legibilidad)
interface QuaggaConfig {
inputStream: {
+260
View File
@@ -0,0 +1,260 @@
"use client";
import { useSearchParams } from "next/navigation";
import "../app/styles/layout/agregarEquipo.scss";
import "./editar.css";
import { useEffect, useState } from "react";
import axios from "axios";
export default function Editar() {
const searchParams = useSearchParams();
const equipoId = searchParams.get("equipoId");
const [formData, setFormData] = useState({
serie: "",
marca: "",
modelo: "",
tipoEquipo: "",
estado: "",
sistemaOperativo: "",
procesador: "",
tipoUso: "",
observaciones: "",
adscripcion: "",
lugar: "",
responsable: "",
});
useEffect(() => {
const fetchEquipo = async () => {
try {
const response = await axios.get(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/${equipoId}`
);
setFormData(response.data);
} catch (error) {
console.error("Error al obtener el equipo:", error);
alert("No se pudo cargar la información del equipo.");
}
};
if (equipoId) {
fetchEquipo();
}
}, [equipoId]);
const mostrarCamposComputadora = formData.tipoEquipo !== "Impresora";
const handleGuardar = async () => {
try {
await axios.patch(
`${process.env.NEXT_PUBLIC_API_URL}/equipos/update/${equipoId}`,
formData
);
alert("Equipo actualizado correctamente");
} catch (error) {
console.error("Error al guardar:", error);
alert("Hubo un error al guardar el equipo.");
}
};
const handleCancelar = () => {
alert("Acción cancelada");
};
return (
<div className="agregarEquipoContainer">
<div className="innerContainer">
<h2 className="information">
{equipoId ? `Editar Equipo (${equipoId})` : "Agregar Equipo"}
<span>Inventario:</span>
<span>Fecha de censo:</span>
</h2>
<form className="equipoForm">
{/* Columna 1 */}
<div className="column">
<div className="formGroup">
<label>Serie</label>
<input
type="text"
placeholder="Ingresa serie"
value={formData.serie}
onChange={(e) =>
setFormData({ ...formData, serie: e.target.value })
}
/>
</div>
<div className="formGroup">
<label>Marca</label>
<select
value={formData.marca}
onChange={(e) =>
setFormData({ ...formData, marca: e.target.value })
}
>
<option value="">Ingresa marca</option>
<option value="Dell">Dell</option>
<option value="HP">HP</option>
<option value="Lenovo">Lenovo</option>
</select>
</div>
<div className="formGroup">
<label>Modelo</label>
<select
value={formData.modelo}
onChange={(e) =>
setFormData({ ...formData, modelo: e.target.value })
}
>
<option value="">Ingresa modelo</option>
<option value="XPS 15">XPS 15</option>
<option value="EliteBook">EliteBook</option>
<option value="ThinkPad">ThinkPad</option>
</select>
</div>
<div className="formGroup">
<label>Estado</label>
<select
value={formData.estado}
onChange={(e) =>
setFormData({ ...formData, estado: e.target.value })
}
>
<option value="">Selecciona estado</option>
<option value="Activado">Activado</option>
<option value="Desactivado">Desactivado</option>
<option value="En reparación">En reparación</option>
</select>
</div>
<div className="formGroup">
<label>Tipo uso</label>
<select
value={formData.tipoUso}
onChange={(e) =>
setFormData({ ...formData, tipoUso: e.target.value })
}
>
<option value="">Ingresa tipo de uso</option>
<option value="administrativo">administrativo</option>
<option value="educacional">educacional</option>
<option value="laboratorio">laboratorio</option>
</select>
</div>
</div>
{/* Columna 2 */}
<div className="column">
{mostrarCamposComputadora && (
<>
<div className="formGroup">
<label>Procesador</label>
<select
value={formData.procesador}
onChange={(e) =>
setFormData({ ...formData, procesador: e.target.value })
}
>
<option value="">Selecciona procesador</option>
<option value="Ryzen 3">Ryzen 3</option>
<option value="Intel i5">Intel i5</option>
<option value="AMD Ryzen 5">AMD Ryzen 5</option>
</select>
</div>
<div className="formGroup">
<label>Sistema operativo</label>
<select
value={formData.sistemaOperativo}
onChange={(e) =>
setFormData({
...formData,
sistemaOperativo: e.target.value,
})
}
>
<option value="">Selecciona sistema operativo</option>
<option value="Windows 10">Windows 10</option>
<option value="Windows 11">Windows 11</option>
<option value="Linux">Linux</option>
<option value="macOS">macOS</option>
</select>
</div>
</>
)}
<div className="formGroup">
<label>Adscripción</label>
<select
value={formData.adscripcion}
onChange={(e) =>
setFormData({ ...formData, adscripcion: e.target.value })
}
>
<option value="">Selecciona adscripción</option>
<option value="Cedetec">Cedetec</option>
<option value="Laboratorio">Laboratorio</option>
<option value="Administración">Administración</option>
</select>
</div>
<div className="formGroup">
<label>Responsable</label>
<select value={formData.responsable} disabled={true}>
<option value="">Responsable</option>
</select>
</div>
</div>
{/* Columna 3 */}
<div className="column">
<div className="formGroup">
<label>Lugar</label>
<textarea
placeholder="Ingresa lugar"
value={formData.lugar}
onChange={(e) =>
setFormData({ ...formData, lugar: e.target.value })
}
rows={5}
className="textAreaLarge"
/>
</div>
<div className="formGroup">
<label>Observaciones</label>
<textarea
placeholder="Ingresa observaciones"
value={formData.observaciones}
onChange={(e) =>
setFormData({ ...formData, observaciones: e.target.value })
}
rows={5}
className="textAreaLarge"
/>
</div>
<div className="formActions">
<button
type="button"
className="btnGuardar"
onClick={handleGuardar}
>
Guardar
</button>
<button
type="button"
className="btnCancelar"
onClick={handleCancelar}
>
Cancelar
</button>
</div>
</div>
</form>
</div>
</div>
);
}