From 909530f858ca2088cd216ae335aae97ae726a6f4 Mon Sep 17 00:00:00 2001 From: jls846 Date: Thu, 20 Nov 2025 17:31:32 -0600 Subject: [PATCH] add crated input in agreguarEquipo and editar --- src/components/AgregarEquipo.tsx | 354 ++++++++++++-------- src/components/Editar.tsx | 92 ++++- src/components/Equipo_Computo/Pregunta1.tsx | 2 +- 3 files changed, 297 insertions(+), 151 deletions(-) diff --git a/src/components/AgregarEquipo.tsx b/src/components/AgregarEquipo.tsx index fcf3c28..fbbb6d2 100644 --- a/src/components/AgregarEquipo.tsx +++ b/src/components/AgregarEquipo.tsx @@ -10,14 +10,31 @@ 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 { + inventario: string; + serie: string; + lugar: string; + fechaFactura: Date; + antiguedad: string; + modelo: string; + id_estado: number; + id_adscripcion: number; + id_tipo_equipo: number; + id_sistema_operativo: number; + id_procesador: number; + id_uso: number; + id_marca: number; + id_periferico: number; + id_laboratorio: number | null; // ✅ ahora acepta null + id_proyecto: number | null; // ✅ ahora acepta null + isImpresora: boolean; +} export default function Page() { const searchParams = useSearchParams(); const inventario = searchParams.get("equipoId"); - const router = useRouter(); - const [formData, setFormData] = useState({ + const [formData, setFormData] = useState({ inventario: "", serie: "", lugar: "", @@ -32,50 +49,65 @@ export default function Page() { id_uso: 0, id_marca: 0, id_periferico: 0, + id_laboratorio: null, + id_proyecto: null, isImpresora: false, }); + const [adscripcionLabel, setAdscripcionLabel] = useState(""); + const [laboratorioLabel, setLaboratorioLabel] = useState(""); + const [proyectoLabel, setProyectoLabel] = useState(""); + + const [suggestions, setSuggestions] = useState({ + adscripcion: [] as string[], + laboratorio: [] as string[], + proyecto: [] as string[], + }); + useEffect(() => { if (inventario) { setFormData((prev) => ({ ...prev, inventario })); } }, [inventario]); + + // Interfaces interface TipoUso { id_uso: number; tipo_uso: string; } - interface Estado { id_estado: number; estado: string; } - interface TipoEquipo { id_tipo_de_equipo: number; tipo_equipo: string; } - interface SistemaOperativo { id_sistema_operativo: number; sistema_operativo: string; } - interface Procesador { id_procesador: number; procesador: string; } - interface Marca { id_marca: number; marca: string; } - interface Adscripcion { id_adscripcion: number; adscripcion: string; } - + interface Laboratorio { + id_laboratorio: number; + laboratorio: string; + } + interface Proyecto { + id_proyecto: number; + proyecto: string; + } interface Perifericos { id_periferico: number; periferico: string; @@ -92,16 +124,11 @@ export default function Page() { >([]); const [procesadores, setProcesadores] = useState([]); const [perifericos, setPerifericos] = useState([]); - const [adscripcionLabel, setAdscripcionLabel] = useState(""); - - const [suggestions, setSuggestions] = useState({ - adscripcion: [] as string[], - }); + const [laboratorios, setLaboratorios] = useState([]); + const [proyectos, setProyectos] = useState([]); const mostrarCamposComputadora = Number(formData.id_tipo_equipo) !== 9; - const tableta = - Number(formData.id_tipo_equipo) !== 7 && - Number(formData.id_tipo_equipo) !== 8; + const esTablet = [7, 8].includes(Number(formData.id_tipo_equipo)); const api_url = process.env.NEXT_PUBLIC_API_URL; useEffect(() => { @@ -117,6 +144,8 @@ export default function Page() { adscripcionesRes, tiposEquipoRes, sistemasOperativosRes, + laboratoriosRes, + proyectosRes, ] = await Promise.all([ axios.get(`${api_url}/equipos/usos`, { headers }), axios.get(`${api_url}/equipos/marcas`, { headers }), @@ -124,28 +153,20 @@ export default function Page() { 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/laboratorios`, { headers }), + axios.get(`${api_url}/equipos/proyectos`, { headers }), ]); - setTiposUso(usosRes.data); setMarcas(marcasRes.data); setEstados(estadosRes.data); setAdscripciones(adscripcionesRes.data); setTiposEquipo(tiposEquipoRes.data); setSistemasOperativos(sistemasOperativosRes.data); + setLaboratorios(laboratoriosRes.data); + setProyectos(proyectosRes.data); } catch (err) { - if (axios.isAxiosError(err)) { - if (err.response) { - toast.error( - err.response.data?.message || "No se pudo conectar con el API" - ); - } 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"); - } + console.error(err); + toast.error("Error al cargar los datos"); } }; @@ -157,21 +178,23 @@ export default function Page() { const token = Cookies.get("token"); const headers = { Authorization: `Bearer ${token}` }; - const response = await axios.get( - `${api_url}/equipos/procesador-tipo-equipos`, - { - headers, - } - ); - - setProcesadores(response.data); + try { + const response = await axios.get( + `${api_url}/equipos/procesador-tipo-equipos`, + { headers } + ); + setProcesadores(response.data); + } catch (err) { + console.error(err); + toast.error("No se pudieron cargar los procesadores"); + } }; fetchProcesador(); - }, [tiposEquipo]); + }, []); // Ya no depende de tiposEquipo (si la API los da todos juntos) useEffect(() => { const fetchPerifericos = async () => { - if (Number(formData.id_tipo_equipo) != 9) return; + if (Number(formData.id_tipo_equipo) !== 9) return; const token = Cookies.get("token"); const headers = { Authorization: `Bearer ${token}` }; @@ -190,6 +213,12 @@ export default function Page() { fetchPerifericos(); }, [formData.id_tipo_equipo]); + const normalize = (str: string) => + str + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .toLowerCase(); + const handleInputChange = ( field: string, value: string | number | boolean @@ -197,17 +226,9 @@ export default function Page() { if (field === "adscripcionLabel") { const textValue = value as string; setAdscripcionLabel(textValue); - - const normalize = (str: string) => - str - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .toLowerCase(); - const matches = adscripciones .filter((a) => normalize(a.adscripcion).includes(normalize(textValue))) .map((a) => a.adscripcion); - setSuggestions((prev) => ({ ...prev, adscripcion: matches.slice(0, 5), @@ -215,10 +236,47 @@ export default function Page() { return; } - setFormData((prev) => { - const newValue = - field.startsWith("id_") && value !== "" ? Number(value) : value; + if (field === "laboratorioLabel") { + const textValue = value as string; + setLaboratorioLabel(textValue); + const matches = laboratorios + .filter((l) => normalize(l.laboratorio).includes(normalize(textValue))) + .map((l) => l.laboratorio); + setSuggestions((prev) => ({ + ...prev, + laboratorio: matches.slice(0, 5), + })); + return; + } + if (field === "proyectoLabel") { + const textValue = value as string; + setProyectoLabel(textValue); + const matches = proyectos + .filter((p) => normalize(p.proyecto).includes(normalize(textValue))) + .map((p) => p.proyecto); + setSuggestions((prev) => ({ + ...prev, + proyecto: matches.slice(0, 5), + })); + return; + } + + 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 === "id_tipo_equipo") { const idTipoEquipo = Number(value); const tipoSeleccionado = tiposEquipo.find( @@ -230,6 +288,8 @@ export default function Page() { ...prev, id_tipo_equipo: idTipoEquipo, isImpresora: esPeriferico, + id_procesador: 0, + id_sistema_operativo: 0, }; } @@ -237,60 +297,72 @@ export default function Page() { }); }; + const handleSuggestionSelect = ( + type: "adscripcion" | "laboratorio" | "proyecto", + label: string + ) => { + if (type === "adscripcion") { + const selected = adscripciones.find((a) => a.adscripcion === label); + if (selected) { + setFormData((prev) => ({ + ...prev, + id_adscripcion: selected.id_adscripcion, + })); + setAdscripcionLabel(selected.adscripcion); + } + } else if (type === "laboratorio") { + const selected = laboratorios.find((l) => l.laboratorio === label); + if (selected) { + setFormData((prev) => ({ + ...prev, + id_laboratorio: selected.id_laboratorio, + })); + setLaboratorioLabel(selected.laboratorio); + } + } else if (type === "proyecto") { + const selected = proyectos.find((p) => p.proyecto === label); + if (selected) { + setFormData((prev) => ({ ...prev, id_proyecto: selected.id_proyecto })); + setProyectoLabel(selected.proyecto); + } + } + + setSuggestions((prev) => ({ ...prev, [type]: [] })); + }; + const handleGuardar = async () => { - if (!formData.inventario) { - toast.error("Inventario no encontrado"); - return; - } + const requiredFields = [ + { field: formData.inventario, name: "Inventario" }, + { field: formData.id_marca, name: "Marca" }, + { field: formData.id_tipo_equipo, name: "Tipo de equipo" }, + { field: formData.id_estado, name: "Estado" }, + { field: formData.id_uso, name: "Tipo de uso" }, + { field: formData.id_adscripcion, name: "Adscripción" }, + ]; - if (!formData.id_marca) { - toast.error("marca no encontrada"); - return; - } - - if (!formData.id_tipo_equipo) { - toast.error("Tipo de equipo no encontrado"); - return; - } - - if (!formData.id_estado) { - toast.error("estado no encontrado"); - return; - } - - if (!formData.id_uso) { - toast.error("tipo de uso no encontrado"); - return; - } - - if (!formData.id_adscripcion) { - toast.error("adscripcion no encontrado"); - return; - } - - if (formData.id_tipo_equipo == 9) { - if (!formData.id_periferico) { - toast.error("Periferico no encontrado"); + for (const { field, name } of requiredFields) { + if (!field) { + toast.error(`${name} es obligatorio`); return; } } + if (formData.id_tipo_equipo === 9 && !formData.id_periferico) { + toast.error("Periférico es obligatorio"); + return; + } + if ( - formData.id_tipo_equipo != 8 && - formData.id_tipo_equipo != 7 && - formData.id_tipo_equipo != 9 + ![7, 8, 9].includes(formData.id_tipo_equipo) && + !formData.id_sistema_operativo ) { - if (!formData.id_sistema_operativo) { - toast.error("Sistema operativo no encontrado "); - return; - } + toast.error("Sistema operativo es obligatorio"); + return; } - if (formData.id_tipo_equipo != 9) { - if (!formData.id_procesador) { - toast.error("Procesador no encontrado"); - return; - } + if (formData.id_tipo_equipo !== 9 && !formData.id_procesador) { + toast.error("Procesador es obligatorio"); + return; } try { @@ -301,13 +373,15 @@ export default function Page() { ...formData, fechaFactura: new Date(formData.fechaFactura) .toISOString() - .split("T")[0], // "YYYY-MM-DD" + .split("T")[0], antiguedad: formData.antiguedad || "0 años", }; await axios.post(`${api_url}/equipos/crear`, dataToSend, { headers }); toast.success("Equipo guardado correctamente"); + router.push("/escaner"); } catch (err) { + console.error(err); toast.error("Error al guardar el equipo"); } }; @@ -324,7 +398,7 @@ export default function Page() { {/* Columna Izquierda */}
- + handleInputChange("serie", e.target.value)} />
-
handleInputChange("modelo", e.target.value)} />
-
handleInputChange("id_procesador", e.target.value) @@ -449,11 +521,11 @@ export default function Page() { )}
- {tableta && ( + {!esTablet && (
(
  • { - const selected = adscripciones.find( - (a) => a.adscripcion === s - ); - if (selected) { - setFormData((prev) => ({ - ...prev, - id_adscripcion: selected.id_adscripcion, - })); - setAdscripcionLabel(selected.adscripcion); - setSuggestions((prev) => ({ - ...prev, - adscripcion: [], - })); - } - }} + onClick={() => handleSuggestionSelect("adscripcion", s)} > {s}
  • @@ -541,31 +599,58 @@ export default function Page() {
    + {/* Columna Derecha */}
    + {/* Laboratorio */} +
    + + +
    + + {/* Proyecto */} +
    + + +
    + + {/* Lugar */}