From 0725467d9a965984671f7cca76308a56a0fe2962 Mon Sep 17 00:00:00 2001 From: IO420 Date: Tue, 28 Oct 2025 23:10:32 -0600 Subject: [PATCH] responsive in login and added request in agregarEquipo --- package-lock.json | 48 ++- package.json | 5 +- src/app/(Operador)/AgregarEquipo/page.tsx | 339 ++++++++++++++-------- src/app/layout.tsx | 7 +- src/app/styles/layout/login.scss | 9 + src/components/Login.tsx | 36 ++- 6 files changed, 312 insertions(+), 132 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd3f18e..c8fee99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,15 @@ "@ericblade/quagga2": "^1.8.4", "@zxing/library": "^0.21.3", "axios": "^1.13.1", + "js-cookie": "^3.0.5", "next": "15.5.6", "react": "19.1.0", - "react-dom": "19.1.0" + "react-dom": "19.1.0", + "react-hot-toast": "^2.6.0" }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/js-cookie": "^3.0.6", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -1284,6 +1287,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2492,7 +2502,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/cwise-compiler": { @@ -3723,6 +3732,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4394,6 +4412,15 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "license": "BSD-3-Clause" }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5227,6 +5254,23 @@ "react": "^19.1.0" } }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 26b69e6..392fc83 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,15 @@ "@ericblade/quagga2": "^1.8.4", "@zxing/library": "^0.21.3", "axios": "^1.13.1", + "js-cookie": "^3.0.5", "next": "15.5.6", "react": "19.1.0", - "react-dom": "19.1.0" + "react-dom": "19.1.0", + "react-hot-toast": "^2.6.0" }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/js-cookie": "^3.0.6", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", diff --git a/src/app/(Operador)/AgregarEquipo/page.tsx b/src/app/(Operador)/AgregarEquipo/page.tsx index df3c474..1c0dc81 100644 --- a/src/app/(Operador)/AgregarEquipo/page.tsx +++ b/src/app/(Operador)/AgregarEquipo/page.tsx @@ -1,14 +1,17 @@ "use client"; -import { useState } from "react"; -import "../../styles/layout/agregarEquipo.scss"; // Asegúrate de crear este archivo +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"; export default function page() { const [formData, setFormData] = useState({ serie: "", marca: "", modelo: "", - tipoEquipo: "", // Nuevo campo + tipoEquipo: "", estado: "", sistemaOperativo: "", procesador: "", @@ -19,9 +22,96 @@ export default function page() { responsable: "", }); - // Estado para saber si mostramos los campos de SO y Procesador + const [tiposUso, setTiposUso] = useState([]); + const [marcas, setMarcas] = useState([]); + const [estados, setEstados] = useState([]); + const [adscripciones, setAdscripciones] = useState([]); + const [tiposEquipo, setTiposEquipo] = useState([]); + const [sistemasOperativos, setSistemasOperativos] = useState([]); + const [procesadores, setProcesadores] = useState([]); + + const [suggestions, setSuggestions] = useState({ + marca: [] as string[], + modelo: [] as string[], + estado: [] as string[], + adscripcion: [] as string[], + tipoEquipo: [] as string[], + sistemaOperativo: [] as string[], + procesador: [] as string[], + tipoUso: [] as string[], + }); + const mostrarCamposComputadora = formData.tipoEquipo !== "Impresora"; + const api_url = process.env.NEXT_PUBLIC_API_URL; + + useEffect(() => { + const fetchData = async () => { + const token = Cookies.get("token"); // Token desde cookies + const headers = { Authorization: `Bearer ${token}` }; + + try { + const [ + usosRes, + marcasRes, + estadosRes, + adscripcionesRes, + tiposEquipoRes, + sistemasOperativosRes, + procesadoresRes, + ] = await Promise.all([ + axios.get(`${api_url}/equipos/usos`, { headers }), + axios.get(`${api_url}/equipos/marcas`, { headers }), + axios.get(`${api_url}/equipos/estados`, { headers }), + axios.get(`${api_url}/equipos/adscripciones`, { headers }), + axios.get(`${api_url}/equipos/tipos-equipo`, { headers }), + axios.get(`${api_url}/equipos/sistemas-operativos`, { headers }), + axios.get(`${api_url}/equipos/procesadores`, { headers }), + ]); + + setTiposUso(usosRes.data); + setMarcas(marcasRes.data); + setEstados(estadosRes.data); + setAdscripciones(adscripcionesRes.data); + setTiposEquipo(tiposEquipoRes.data); + setSistemasOperativos(sistemasOperativosRes.data); + setProcesadores(procesadoresRes.data); + } catch (err: any) { + if (axios.isAxiosError(err)) { + if (err.response) { + toast.error(err.response.data?.message || "Usuario o contraseña incorrectos") + } 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") + } + } + }; + + fetchData(); + }, []); + + const handleInputChange = (field: string, value: string, options: string[]) => { + setFormData((prev) => ({ ...prev, [field]: value })); + + if (value.length >= 3) { + const filtered = options.filter((opt) => + opt.toLowerCase().includes(value.toLowerCase()) + ); + setSuggestions((prev) => ({ ...prev, [field]: filtered })); + } else { + setSuggestions((prev) => ({ ...prev, [field]: [] })); + } + }; + + const handleSelectSuggestion = (field: string, value: string) => { + setFormData((prev) => ({ ...prev, [field]: value })); + setSuggestions((prev) => ({ ...prev, [field]: [] })); + }; + const handleGuardar = () => { console.log("Formulario enviado:", formData); alert("Equipo guardado (vista solo)"); @@ -31,18 +121,14 @@ export default function page() { alert("Acción cancelada"); }; - // Función para actualizar el estado y limpiar campos si es impresora const handleChange = (e: any) => { const { name, value } = e.target; setFormData((prev) => { let updated = { ...prev, [name]: value }; - - // Si es impresora, limpiamos SO y Procesador if (value === "Impresora") { updated.sistemaOperativo = ""; updated.procesador = ""; } - return updated; }); }; @@ -60,65 +146,77 @@ export default function page() { type="text" placeholder="Ingresa serie" value={formData.serie} - onChange={(e) => - setFormData({ ...formData, serie: e.target.value }) - } + onChange={(e) => setFormData({ ...formData, serie: e.target.value })} /> +
- + onChange={(e) => handleInputChange("marca", e.target.value, marcas)} + /> + {suggestions.marca.length > 0 && ( +
    + {suggestions.marca.map((s) => ( +
  • handleSelectSuggestion("marca", s)}> + {s} +
  • + ))} +
+ )}
+
- + onChange={(e) => handleInputChange("modelo", e.target.value, [])} + />
+
- + onChange={(e) => + handleInputChange("tipoEquipo", e.target.value, tiposEquipo) + } + /> + {suggestions.tipoEquipo.length > 0 && ( +
    + {suggestions.tipoEquipo.map((s) => ( +
  • handleSelectSuggestion("tipoEquipo", s)}> + {s} +
  • + ))} +
+ )}
+
- + onChange={(e) => handleInputChange("estado", e.target.value, estados)} + /> + {suggestions.estado.length > 0 && ( +
    + {suggestions.estado.map((s) => ( +
  • handleSelectSuggestion("estado", s)}> + {s} +
  • + ))} +
+ )}
@@ -126,83 +224,106 @@ export default function page() {
- + onChange={(e) => handleInputChange("tipoUso", e.target.value, tiposUso)} + /> + {suggestions.tipoUso.length > 0 && ( +
    + {suggestions.tipoUso.map((s) => ( +
  • handleSelectSuggestion("tipoUso", s)}> + {s} +
  • + ))} +
+ )}
- {/* Mostrar SO y Procesador solo si NO es impresora */} + {mostrarCamposComputadora && ( <>
- + /> + {suggestions.procesador.length > 0 && ( +
    + {suggestions.procesador.map((s) => ( +
  • handleSelectSuggestion("procesador", s)} + > + {s} +
  • + ))} +
+ )}
+
- + /> + {suggestions.sistemaOperativo.length > 0 && ( +
    + {suggestions.sistemaOperativo.map((s) => ( +
  • + handleSelectSuggestion("sistemaOperativo", s) + } + > + {s} +
  • + ))} +
+ )}
)}
- + /> + {suggestions.adscripcion.length > 0 && ( +
    + {suggestions.adscripcion.map((s) => ( +
  • handleSelectSuggestion("adscripcion", s)}> + {s} +
  • + ))} +
+ )}
+
- + onChange={(e) => setFormData({ ...formData, responsable: e.target.value })} + />
@@ -213,9 +334,7 @@ export default function page() {