Merge branch 'Lino' of https://github.com/jls846/front-censo into Sarabia
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ import toast from "react-hot-toast";
|
||||
import "../../styles/layout/ForgotPasswordPage.scss"; // ajusta ruta si tu proyecto la tiene en otro sitio
|
||||
import Link from "next/link";
|
||||
|
||||
export default function ForgotPasswordPage() {
|
||||
export default function Page() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const router = useRouter();
|
||||
@@ -9,7 +9,7 @@ import axios from "axios";
|
||||
import { useRouter } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
function CrearCuenta() {
|
||||
export default function Page() {
|
||||
const [nombre, setNombre] = useState("");
|
||||
const [correo, setCorreo] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -116,4 +116,3 @@ function CrearCuenta() {
|
||||
</section>
|
||||
);
|
||||
}
|
||||
export default CrearCuenta;
|
||||
|
||||
@@ -1,379 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
import toast from "react-hot-toast";
|
||||
import "../../styles/layout/agregarEquipo.scss";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const AgregarEquipo = dynamic(() => import("@/components/AgregarEquipo"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
export default function Page() {
|
||||
const [formData, setFormData] = useState({
|
||||
serie: "",
|
||||
marca: "",
|
||||
modelo: "",
|
||||
tipoEquipo: "",
|
||||
estado: "",
|
||||
sistemaOperativo: "",
|
||||
procesador: "",
|
||||
tipoUso: "",
|
||||
observaciones: "",
|
||||
adscripcion: "",
|
||||
lugar: "",
|
||||
responsable: "",
|
||||
});
|
||||
|
||||
// Tipos de datos
|
||||
interface TipoUso {
|
||||
id_tipo_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;
|
||||
tipo_marca: string;
|
||||
}
|
||||
|
||||
interface Adscripcion {
|
||||
id_adscripcion: number;
|
||||
adscripcion: string;
|
||||
}
|
||||
|
||||
// Estados
|
||||
const [tiposUso, setTiposUso] = useState<TipoUso[]>([]);
|
||||
const [marcas, setMarcas] = useState<Marca[]>([]);
|
||||
const [estados, setEstados] = useState<Estado[]>([]);
|
||||
const [adscripciones, setAdscripciones] = useState<Adscripcion[]>([]);
|
||||
const [tiposEquipo, setTiposEquipo] = useState<TipoEquipo[]>([]);
|
||||
const [sistemasOperativos, setSistemasOperativos] = useState<
|
||||
SistemaOperativo[]
|
||||
>([]);
|
||||
const [procesadores, setProcesadores] = useState<Procesador[]>([]);
|
||||
|
||||
const [suggestions, setSuggestions] = useState({
|
||||
adscripcion: [] 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");
|
||||
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);
|
||||
console.log(adscripciones);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [api_url]);
|
||||
|
||||
const handleInputChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const handleSelectSuggestion = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
setSuggestions((prev) => ({ ...prev, [field]: [] }));
|
||||
};
|
||||
|
||||
const handleGuardar = async () => {
|
||||
try {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
await axios.post(`${api_url}/equipos/crear`, formData, { headers });
|
||||
toast.success("Equipo guardado correctamente");
|
||||
setFormData({
|
||||
serie: "",
|
||||
marca: "",
|
||||
modelo: "",
|
||||
tipoEquipo: "",
|
||||
estado: "",
|
||||
sistemaOperativo: "",
|
||||
procesador: "",
|
||||
tipoUso: "",
|
||||
observaciones: "",
|
||||
adscripcion: "",
|
||||
lugar: "",
|
||||
responsable: "",
|
||||
});
|
||||
} catch (err) {
|
||||
toast.error("Error al guardar el equipo");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelar = () => {
|
||||
toast.error("Acción cancelada");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="agregarEquipoContainer">
|
||||
<div className="innerContainer">
|
||||
<h2 className="information">Agregar Nuevo Equipo</h2>
|
||||
<form className="equipoForm">
|
||||
{/* Columna Izquierda */}
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Serie</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Ingresa serie"
|
||||
value={formData.serie}
|
||||
onChange={(e) => handleInputChange("serie", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Marca</label>
|
||||
<select
|
||||
required
|
||||
value={formData.marca}
|
||||
onChange={(e) => handleInputChange("marca", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona una marca</option>
|
||||
{marcas.map((m) => (
|
||||
<option key={m.id_marca} value={m.tipo_marca}>
|
||||
{m.tipo_marca}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Modelo</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Ingresa modelo"
|
||||
value={formData.modelo}
|
||||
onChange={(e) => handleInputChange("modelo", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Tipo de equipo</label>
|
||||
<select
|
||||
required
|
||||
value={formData.tipoEquipo}
|
||||
onChange={(e) =>
|
||||
handleInputChange("tipoEquipo", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona tipo de equipo</option>
|
||||
{tiposEquipo.map((t) => (
|
||||
<option key={t.id_tipo_de_equipo} value={t.tipo_equipo}>
|
||||
{t.tipo_equipo}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Estado</label>
|
||||
<select
|
||||
required
|
||||
value={formData.estado}
|
||||
onChange={(e) => handleInputChange("estado", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona estado</option>
|
||||
{estados.map((e) => (
|
||||
<option key={e.id_estado} value={e.estado}>
|
||||
{e.estado}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columna Centro */}
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Tipo de uso</label>
|
||||
<select
|
||||
required
|
||||
value={formData.tipoUso}
|
||||
onChange={(e) => handleInputChange("tipoUso", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona tipo de uso</option>
|
||||
{tiposUso.map((t) => (
|
||||
<option key={t.id_tipo_uso} value={t.tipo_uso}>
|
||||
{t.tipo_uso}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{mostrarCamposComputadora && (
|
||||
<>
|
||||
<div className="formGroup">
|
||||
<label>Procesador</label>
|
||||
<select
|
||||
value={formData.procesador}
|
||||
onChange={(e) =>
|
||||
handleInputChange("procesador", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona procesador</option>
|
||||
{procesadores.map((p) => (
|
||||
<option key={p.id_procesador} value={p.procesador}>
|
||||
{p.procesador}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Sistema operativo</label>
|
||||
<select
|
||||
value={formData.sistemaOperativo}
|
||||
onChange={(e) =>
|
||||
handleInputChange("sistemaOperativo", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona sistema operativo</option>
|
||||
{sistemasOperativos.map((so) => (
|
||||
<option
|
||||
key={so.id_sistema_operativo}
|
||||
value={so.sistema_operativo}
|
||||
>
|
||||
{so.sistema_operativo}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Adscripción</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Selecciona adscripción"
|
||||
value={formData.adscripcion}
|
||||
onChange={(e) =>
|
||||
handleInputChange("adscripcion", e.target.value)
|
||||
}
|
||||
/>
|
||||
{suggestions.adscripcion.length > 0 && (
|
||||
<ul className="suggestions">
|
||||
{suggestions.adscripcion.map((s) => (
|
||||
<li
|
||||
key={s}
|
||||
onClick={() => handleSelectSuggestion("adscripcion", s)}
|
||||
>
|
||||
{s}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Lugar</label>
|
||||
<textarea
|
||||
placeholder="Ingresa lugar"
|
||||
value={formData.lugar}
|
||||
onChange={(e) => handleInputChange("lugar", e.target.value)}
|
||||
rows={5}
|
||||
className="textAreaLarge"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Observaciones</label>
|
||||
<textarea
|
||||
placeholder="Ingresa observaciones"
|
||||
value={formData.observaciones}
|
||||
onChange={(e) =>
|
||||
handleInputChange("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>
|
||||
);
|
||||
return <AgregarEquipo />;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ export default function Dashboard() {
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("Error No se encontro el equipo");
|
||||
router.push(`/AgregarEquipo?equipoId=${code}`);
|
||||
}
|
||||
toast(`${code}`);
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import Header from "../components/header";
|
||||
import { Inter, Montserrat } from "next/font/google";
|
||||
import "../app/styles/base/globales.scss";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import "../app/styles/base/globales.scss";
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
@@ -21,7 +21,7 @@ export default function RootLayout({
|
||||
}) {
|
||||
return (
|
||||
<html lang="es" className={`${inter.variable} ${montserrat.variable}`}>
|
||||
<body suppressHydrationWarning>
|
||||
<body>
|
||||
<Header />
|
||||
<Toaster position="top-left" reverseOrder={false} />
|
||||
{children}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
.pestaña {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 62%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* Contenedor principal del reporte */
|
||||
.reporte-layout {
|
||||
display: flex;
|
||||
@@ -28,7 +35,61 @@
|
||||
color: #0056b3;
|
||||
}
|
||||
|
||||
/* Buscador */
|
||||
.pestaña span:hover {
|
||||
color: #b8870b; /* cambia de color al pasar el cursor */
|
||||
}
|
||||
|
||||
.titulo-reporte {
|
||||
font-weight: bold; /* negrita */
|
||||
font-size: 24px; /* tamaño de texto */
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
/*BUSCADOR*/
|
||||
|
||||
input[type="text"] {
|
||||
width: 500px; /* más ancho, más largo */
|
||||
padding: 7px; /* mantiene espacio cómodo dentro */
|
||||
font-size: 18px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 8px 12px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.contenedor {
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
.filtro-rec {
|
||||
border: 2px solid #003366; /* Color del borde */
|
||||
border-radius: 10px; /* Bordes redondeados */
|
||||
padding: 10px; /* Espacio interno */
|
||||
margin: 80px 550px; /* Separación del resto del contenido */
|
||||
background-color: #f9f9f9;
|
||||
position: relative;
|
||||
left: 380px;
|
||||
font-family: Arial, sans-serif;
|
||||
top: -570px; /* sube 50px respecto a su posición original */
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-color: #003366;
|
||||
box-shadow: 0 0 4px rgba(0, 51, 102, 0.3);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
form[action="/buscar"] {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
@@ -108,8 +169,9 @@ form[action="/buscar"] button:hover {
|
||||
/* Botones del filtro */
|
||||
.botones-filtro {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
justify-content: flex-end; /* botones a la derecha */
|
||||
gap: 10px; /* espacio entre botones */
|
||||
margin-top: 15px; /* separación del resto del formulario */
|
||||
}
|
||||
|
||||
.botones-filtro .aplicar,
|
||||
@@ -123,6 +185,19 @@ form[action="/buscar"] button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tabla-rec {
|
||||
border: 2px solid #003366; /* Color del borde */
|
||||
border-radius: 10px; /* Bordes redondeados */
|
||||
padding: 10px; /* Espacio interno */
|
||||
margin: 50px 700px 0 80px; /* superior, derecha, inferior, izquierda */
|
||||
background-color: #f9f9f9;
|
||||
font-family: Arial, sans-serif;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.boton-descargar {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.botones-filtro .aplicar {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
@@ -143,6 +218,8 @@ form[action="/buscar"] button:hover {
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
right: 30px;
|
||||
margin-left: 700px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -166,4 +243,4 @@ form[action="/buscar"] button:hover {
|
||||
.boton-descargar {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,16 +69,28 @@ label {
|
||||
display: block;
|
||||
text-align: start;
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
select {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
background-position: right 10px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
.barNavigation li {
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
width: auto;
|
||||
transition: background-color 0.3s ease;
|
||||
font-size: 1.5rem;
|
||||
@@ -96,7 +95,6 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 1.5rem;
|
||||
@@ -111,7 +109,7 @@
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -140,7 +138,7 @@
|
||||
|
||||
.barNavigation ul {
|
||||
position: absolute;
|
||||
background-color: #003e79;
|
||||
background-color: #f4f5f7;
|
||||
flex-direction: column;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
@@ -158,7 +156,7 @@
|
||||
|
||||
.barNavigation li:hover {
|
||||
background-color: #d59f0f;
|
||||
color: white;
|
||||
color: black;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
@@ -172,7 +170,7 @@
|
||||
|
||||
.logout-button {
|
||||
margin-top: 10px;
|
||||
font-size: 1rem;
|
||||
font-size: 1.75rem;
|
||||
padding: 6px 12px;
|
||||
max-width: 180px;
|
||||
}
|
||||
@@ -183,6 +181,6 @@
|
||||
}
|
||||
|
||||
.subMenu a span {
|
||||
color: #fff;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
|
||||
.innerContainer {
|
||||
max-width: 1000px;
|
||||
width: 1000px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
padding: 1rem 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
color: #0056b3;
|
||||
margin-bottom: 20px;
|
||||
@@ -25,7 +24,7 @@
|
||||
|
||||
.equipoForm {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
gap: 1.5rem;
|
||||
|
||||
.column {
|
||||
flex: 1;
|
||||
@@ -88,7 +87,7 @@ textarea {
|
||||
height: 100%;
|
||||
.btnGuardar {
|
||||
background-color: #ffb700;
|
||||
color: #0056b3;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 6px;
|
||||
@@ -117,8 +116,58 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.suggestions {
|
||||
position: absolute; // mantiene fuera del flujo
|
||||
top: 100%; // justo debajo del input
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
list-style: none;
|
||||
margin: 4px 0 0 0;
|
||||
padding: 0;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.suggestions li {
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1075px) {
|
||||
.equipoForm {
|
||||
flex-wrap: wrap;
|
||||
max-width: 100%;
|
||||
|
||||
.column {
|
||||
flex: 1 1 calc(50% - 15px);
|
||||
min-width: 250px;
|
||||
|
||||
.formGroup {
|
||||
input,
|
||||
select {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive: en móvil, una columna */
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 600px) {
|
||||
.agregarEquipoContainer .innerContainer {
|
||||
padding: 15px;
|
||||
max-width: 90vw;
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import "../app/styles/layout/agregarEquipo.scss";
|
||||
import { AREAS } from "@/data/areas";
|
||||
import { SO_POR_EQUIPO } from "@/data/so_por_equipo";
|
||||
import { PROCESADORES_POR_EQUIPO } from "@/data/procesadores";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function Page() {
|
||||
const searchParams = useSearchParams();
|
||||
const inventario = searchParams.get("equipoId");
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
inventario: "",
|
||||
serie: "",
|
||||
marca: "",
|
||||
modelo: "",
|
||||
tipoEquipo: "",
|
||||
estado: "",
|
||||
sistemaOperativo: "",
|
||||
procesador: "",
|
||||
tipoUso: "",
|
||||
observaciones: "",
|
||||
adscripcion: "",
|
||||
lugar: "",
|
||||
responsable: "",
|
||||
tipoPeriferico: "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (inventario) {
|
||||
setFormData((prev) => ({ ...prev, inventario }));
|
||||
}
|
||||
}, [inventario]);
|
||||
|
||||
// Tipos de datos
|
||||
interface TipoUso {
|
||||
id_tipo_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;
|
||||
}
|
||||
|
||||
// Estados
|
||||
const [tiposUso, setTiposUso] = useState<TipoUso[]>([]);
|
||||
const [marcas, setMarcas] = useState<Marca[]>([]);
|
||||
const [estados, setEstados] = useState<Estado[]>([]);
|
||||
const [adscripciones, setAdscripciones] = useState<Adscripcion[]>([]);
|
||||
const [tiposEquipo, setTiposEquipo] = useState<TipoEquipo[]>([]);
|
||||
const [sistemasOperativos, setSistemasOperativos] = useState<
|
||||
SistemaOperativo[]
|
||||
>([]);
|
||||
const [procesadores, setProcesadores] = useState<Procesador[]>([]);
|
||||
const [perifericos, setPerifericos] = useState([]);
|
||||
|
||||
const [suggestions, setSuggestions] = useState({
|
||||
adscripcion: [] as string[],
|
||||
});
|
||||
|
||||
const mostrarCamposComputadora = formData.tipoEquipo !== "PERIFÉRICO";
|
||||
const api_url = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
try {
|
||||
const [
|
||||
usosRes,
|
||||
marcasRes,
|
||||
estadosRes,
|
||||
adscripcionesRes,
|
||||
tiposEquipoRes,
|
||||
sistemasOperativosRes,
|
||||
] = 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 }),
|
||||
]);
|
||||
|
||||
setTiposUso(usosRes.data);
|
||||
setMarcas(marcasRes.data);
|
||||
setEstados(estadosRes.data);
|
||||
setAdscripciones(adscripcionesRes.data);
|
||||
setTiposEquipo(tiposEquipoRes.data);
|
||||
setSistemasOperativos(sistemasOperativosRes.data);
|
||||
console.log(adscripciones);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [api_url]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchProcesador = async () => {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
const response = await axios.get(
|
||||
`${api_url}/equipos/procesador-tipo-equipos/${formData.tipoEquipo}`,
|
||||
{
|
||||
headers,
|
||||
}
|
||||
);
|
||||
|
||||
setProcesadores(response.data);
|
||||
};
|
||||
fetchProcesador();
|
||||
}, [tiposEquipo]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPerifericos = async () => {
|
||||
if (formData.tipoEquipo !== "PERIFÉRICO") return;
|
||||
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
try {
|
||||
const response = await axios.get(`${api_url}/equipos/perifericos`, {
|
||||
headers,
|
||||
});
|
||||
setPerifericos(response.data);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
toast.error("No se pudieron cargar los periféricos");
|
||||
}
|
||||
};
|
||||
|
||||
fetchPerifericos();
|
||||
}, [formData.tipoEquipo]);
|
||||
|
||||
const handleInputChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
|
||||
if (field === "adscripcion") {
|
||||
if (value.length < 3) {
|
||||
// Si no hay al menos 3 letras, no mostrar sugerencias
|
||||
setSuggestions((prev) => ({ ...prev, adscripcion: [] }));
|
||||
return;
|
||||
}
|
||||
|
||||
// Función para normalizar: minúsculas y quitar acentos
|
||||
const normalize = (str: string) =>
|
||||
str
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
|
||||
const searchValue = normalize(value);
|
||||
|
||||
const matches = AREAS.map((a) => a.label)
|
||||
.filter((label) => normalize(label).includes(searchValue))
|
||||
.slice(0, 5); // máximo 10 sugerencias
|
||||
|
||||
setSuggestions((prev) => ({ ...prev, adscripcion: matches }));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectSuggestion = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
setSuggestions((prev) => ({ ...prev, [field]: [] }));
|
||||
};
|
||||
|
||||
const handleGuardar = async () => {
|
||||
const adscripcionesValidas = AREAS.map((a) => a.label);
|
||||
if (!adscripcionesValidas.includes(formData.adscripcion)) {
|
||||
toast.error("Debes seleccionar una adscripción válida.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
await axios.post(`${api_url}/equipos/crear`, formData, { headers });
|
||||
toast.success("Equipo guardado correctamente");
|
||||
setFormData({
|
||||
inventario: "",
|
||||
serie: "",
|
||||
marca: "",
|
||||
modelo: "",
|
||||
tipoEquipo: "",
|
||||
estado: "",
|
||||
sistemaOperativo: "",
|
||||
procesador: "",
|
||||
tipoUso: "",
|
||||
observaciones: "",
|
||||
adscripcion: "",
|
||||
lugar: "",
|
||||
responsable: "",
|
||||
tipoPeriferico: "",
|
||||
});
|
||||
} catch (err) {
|
||||
toast.error("Error al guardar el equipo");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelar = () => {
|
||||
router.push("/Escaner");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="agregarEquipoContainer">
|
||||
<div className="innerContainer">
|
||||
<h2 className="information">Agregar Nuevo Equipo</h2>
|
||||
<form className="equipoForm">
|
||||
{/* Columna Izquierda */}
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Numero de Inventario</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Ingresa Inventario"
|
||||
value={formData.inventario}
|
||||
onChange={(e) =>
|
||||
handleInputChange("inventario", e.target.value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="formGroup">
|
||||
<label>Serie</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Ingresa serie"
|
||||
value={formData.serie}
|
||||
onChange={(e) => handleInputChange("serie", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Marca</label>
|
||||
<select
|
||||
required
|
||||
value={formData.marca}
|
||||
onChange={(e) => handleInputChange("marca", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona una marca</option>
|
||||
{marcas.map((m) => (
|
||||
<option key={m.id_marca} value={m.marca}>
|
||||
{m.marca}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Modelo</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Ingresa modelo"
|
||||
value={formData.modelo}
|
||||
onChange={(e) => handleInputChange("modelo", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Tipo de equipo</label>
|
||||
<select
|
||||
required
|
||||
value={formData.tipoEquipo}
|
||||
onChange={(e) =>
|
||||
handleInputChange("tipoEquipo", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona tipo de equipo</option>
|
||||
{tiposEquipo.map((t) => (
|
||||
<option key={t.id_tipo_de_equipo} value={t.tipo_equipo}>
|
||||
{t.tipo_equipo}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Estado</label>
|
||||
<select
|
||||
required
|
||||
value={formData.estado}
|
||||
onChange={(e) => handleInputChange("estado", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona estado</option>
|
||||
{estados.map((e) => (
|
||||
<option key={e.id_estado} value={e.estado}>
|
||||
{e.estado}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Tipo de uso</label>
|
||||
<select
|
||||
required
|
||||
value={formData.tipoUso}
|
||||
onChange={(e) => handleInputChange("tipoUso", e.target.value)}
|
||||
>
|
||||
<option value="">Selecciona tipo de uso</option>
|
||||
{tiposUso.map((t) => (
|
||||
<option key={t.id_tipo_uso} value={t.tipo_uso}>
|
||||
{t.tipo_uso}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{mostrarCamposComputadora && (
|
||||
<>
|
||||
<div className="formGroup">
|
||||
<label>Procesador</label>
|
||||
<select
|
||||
value={formData.procesador}
|
||||
onChange={(e) =>
|
||||
handleInputChange("procesador", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona procesador</option>
|
||||
{PROCESADORES_POR_EQUIPO[formData.tipoEquipo]?.map((p) => (
|
||||
<option key={p} value={p}>
|
||||
{p}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Sistema operativo</label>
|
||||
<select
|
||||
value={formData.sistemaOperativo}
|
||||
onChange={(e) =>
|
||||
handleInputChange("sistemaOperativo", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona sistema operativo</option>
|
||||
{SO_POR_EQUIPO[formData.tipoEquipo]?.map((so) => (
|
||||
<option key={so} value={so}>
|
||||
{so}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!mostrarCamposComputadora && (
|
||||
<div className="formGroup">
|
||||
<label>Tipos de Periféricos</label>
|
||||
<select
|
||||
value={formData.tipoPeriferico || ""}
|
||||
onChange={(e) =>
|
||||
handleInputChange("tipoPeriferico", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona periférico</option>
|
||||
{perifericos.map((p: any) => (
|
||||
<option key={p.id_periferico} value={p.nombre}>
|
||||
{p.nombre}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="formGroup" style={{ position: "relative" }}>
|
||||
<label>Adscripción</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Ingresa adscripcion"
|
||||
value={formData.adscripcion}
|
||||
onChange={(e) =>
|
||||
handleInputChange("adscripcion", e.target.value)
|
||||
}
|
||||
/>
|
||||
{suggestions.adscripcion.length > 0 && (
|
||||
<ul className="suggestions">
|
||||
{suggestions.adscripcion.map((s) => (
|
||||
<li
|
||||
key={s}
|
||||
onClick={() => handleSelectSuggestion("adscripcion", s)}
|
||||
>
|
||||
{s}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Lugar</label>
|
||||
<textarea
|
||||
placeholder="Ingresa lugar"
|
||||
value={formData.lugar}
|
||||
onChange={(e) => handleInputChange("lugar", e.target.value)}
|
||||
rows={5}
|
||||
className="textAreaLarge"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Observaciones</label>
|
||||
<textarea
|
||||
placeholder="Ingresa observaciones"
|
||||
value={formData.observaciones}
|
||||
onChange={(e) =>
|
||||
handleInputChange("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>
|
||||
);
|
||||
}
|
||||
@@ -33,8 +33,8 @@ export default function BarcodeScanner({ onScan }: BarcodeScannerProps) {
|
||||
type: "LiveStream",
|
||||
target: scannerRef.current,
|
||||
constraints: {
|
||||
width: 640,
|
||||
height: 370,
|
||||
width: 300,
|
||||
height: 500,
|
||||
facingMode: "environment",
|
||||
},
|
||||
},
|
||||
|
||||
+97
-34
@@ -1,17 +1,24 @@
|
||||
"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";
|
||||
import Cookies from "js-cookie";
|
||||
import toast from "react-hot-toast";
|
||||
import { SO_POR_EQUIPO } from "@/data/so_por_equipo";
|
||||
import { AREAS } from "@/data/areas";
|
||||
|
||||
import "../app/styles/layout/agregarEquipo.scss";
|
||||
import "./editar.css";
|
||||
import { PROCESADORES_POR_EQUIPO } from "@/data/procesadores";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function Editar() {
|
||||
const searchParams = useSearchParams();
|
||||
const inventario = searchParams.get("equipoId");
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
inventario: "",
|
||||
serie: "",
|
||||
@@ -55,7 +62,7 @@ export default function Editar() {
|
||||
|
||||
interface Marca {
|
||||
id_marca: number;
|
||||
tipo_marca: string;
|
||||
marca: string;
|
||||
}
|
||||
|
||||
interface Adscripcion {
|
||||
@@ -73,8 +80,12 @@ export default function Editar() {
|
||||
>([]);
|
||||
const [procesadores, setProcesadores] = useState<Procesador[]>([]);
|
||||
|
||||
const [suggestions, setSuggestions] = useState({
|
||||
adscripcion: [] as string[],
|
||||
});
|
||||
|
||||
const api_url = process.env.NEXT_PUBLIC_API_URL;
|
||||
const mostrarCamposComputadora = formData.tipoEquipo !== "Impresora";
|
||||
const mostrarCamposComputadora = formData.tipoEquipo !== "PERIFÉRICO";
|
||||
|
||||
// 🔹 Cargar catálogos
|
||||
useEffect(() => {
|
||||
@@ -175,30 +186,62 @@ export default function Editar() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
|
||||
if (field === "adscripcion") {
|
||||
if (value.length < 3) {
|
||||
// Si no hay al menos 3 letras, no mostrar sugerencias
|
||||
setSuggestions((prev) => ({ ...prev, adscripcion: [] }));
|
||||
return;
|
||||
}
|
||||
|
||||
// Normaliza para quitar acentos y poner en minúsculas
|
||||
const normalize = (str: string) =>
|
||||
str
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
|
||||
const searchValue = normalize(value);
|
||||
|
||||
// Busca coincidencias
|
||||
const matches = AREAS.map((a) => a.label)
|
||||
.filter((label) => normalize(label).includes(searchValue))
|
||||
.slice(0, 10); // máximo 10 sugerencias
|
||||
|
||||
setSuggestions((prev) => ({ ...prev, adscripcion: matches }));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectSuggestion = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
setSuggestions((prev) => ({ ...prev, [field]: [] }));
|
||||
};
|
||||
|
||||
const handleCancelar = () => {
|
||||
toast("Acción cancelada");
|
||||
router.push("/Escaner");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="agregarEquipoContainer">
|
||||
<div className="innerContainer">
|
||||
<h2 className="information">
|
||||
{inventario ? `Editar Equipo (${inventario})` : "Agregar Equipo"}
|
||||
<span>{formData.tipoEquipo}</span>
|
||||
<span>Inventario:{formData.inventario}</span>
|
||||
<span>Fecha de censo:</span>
|
||||
</h2>
|
||||
|
||||
<form className="equipoForm">
|
||||
{/* Columna 1 */}
|
||||
<div className="column">
|
||||
<div className="formGroup">
|
||||
<label>Inventario</label>
|
||||
<input type="text" value={formData.inventario} disabled />
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Serie</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.serie}
|
||||
placeholder="Ingresa serie"
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, serie: e.target.value })
|
||||
}
|
||||
@@ -215,8 +258,8 @@ export default function Editar() {
|
||||
>
|
||||
<option value="">Selecciona marca</option>
|
||||
{marcas.map((m) => (
|
||||
<option key={m.id_marca} value={m.tipo_marca}>
|
||||
{m.tipo_marca}
|
||||
<option key={m.id_marca} value={m.marca}>
|
||||
{m.marca}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -227,6 +270,7 @@ export default function Editar() {
|
||||
<input
|
||||
type="text"
|
||||
value={formData.modelo}
|
||||
placeholder="Ingresa modelo"
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, modelo: e.target.value })
|
||||
}
|
||||
@@ -298,9 +342,9 @@ export default function Editar() {
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona procesador</option>
|
||||
{procesadores.map((p) => (
|
||||
<option key={p.id_procesador} value={p.procesador}>
|
||||
{p.procesador}
|
||||
{PROCESADORES_POR_EQUIPO[formData.tipoEquipo]?.map((p) => (
|
||||
<option key={p} value={p}>
|
||||
{p}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -318,12 +362,9 @@ export default function Editar() {
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona sistema operativo</option>
|
||||
{sistemasOperativos.map((so) => (
|
||||
<option
|
||||
key={so.id_sistema_operativo}
|
||||
value={so.sistema_operativo}
|
||||
>
|
||||
{so.sistema_operativo}
|
||||
{SO_POR_EQUIPO[formData.tipoEquipo]?.map((so) => (
|
||||
<option key={so} value={so}>
|
||||
{so}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -331,26 +372,48 @@ export default function Editar() {
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="formGroup">
|
||||
{!mostrarCamposComputadora && (
|
||||
<div className="formGroup">
|
||||
<label>Tipos de Perifericos</label>
|
||||
<select>
|
||||
<option value="">Selecciona periferico</option>
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="formGroup" style={{ position: "relative" }}>
|
||||
<label>Adscripción</label>
|
||||
<select
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
placeholder="Ingresa adscripción"
|
||||
value={formData.adscripcion}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, adscripcion: e.target.value })
|
||||
handleInputChange("adscripcion", e.target.value)
|
||||
}
|
||||
>
|
||||
<option value="">Selecciona adscripción</option>
|
||||
{adscripciones.map((a) => (
|
||||
<option key={a.id_adscripcion} value={a.adscripcion}>
|
||||
{a.adscripcion}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
/>
|
||||
{suggestions.adscripcion.length > 0 && (
|
||||
<ul className="suggestions">
|
||||
{suggestions.adscripcion.map((s) => (
|
||||
<li
|
||||
key={s}
|
||||
onClick={() => handleSelectSuggestion("adscripcion", s)}
|
||||
>
|
||||
{s}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label>Responsable</label>
|
||||
<input type="text" value={formData.responsable} disabled />
|
||||
<input
|
||||
type="text"
|
||||
value={formData.responsable}
|
||||
disabled
|
||||
placeholder="Selecciona una Adscripcion"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import { usePathname } from "next/navigation";
|
||||
function Header() {
|
||||
const pathname = usePathname();
|
||||
|
||||
const rutasConBar = ["/Escaner", "/AgregarEquipo","/reporte"];
|
||||
const publicNav = ["/Escaner", "/AgregarEquipo", "/Editar"];
|
||||
const privateNav = ["/Reporte", "/CrearCuenta", "/CambiarPass"];
|
||||
|
||||
return (
|
||||
<header className={header.header}>
|
||||
@@ -40,7 +41,8 @@ function Header() {
|
||||
alignItems: "end",
|
||||
}}
|
||||
>
|
||||
{rutasConBar.includes(pathname) && <BarNavigation />}
|
||||
{publicNav.includes(pathname) && <BarNavigation />}
|
||||
{privateNav.includes(pathname) && <BarNavigation />}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
//Esto es culpa de los webservices y de santi(wizard) attentamente IO
|
||||
|
||||
export const AREAS: Array<{ id: number; label: string }> = [
|
||||
{ id: 128, label: "Coordinación de Actividades Deportivas y Recreativas" },
|
||||
{ id: 122, label: "Coordinación de Comunicación Social" },
|
||||
{ id: 9, label: "Coordinación de Cuerpos Colegiados" },
|
||||
{
|
||||
id: 126,
|
||||
label:
|
||||
"Coordinación de Derecho del Sistema de Universidad Abierta y Educación a Distancia",
|
||||
},
|
||||
{ id: 206, label: "Coordinación de Especializaciones" },
|
||||
{ id: 120, label: "Coordinación de Estudios de Posgrado" },
|
||||
{
|
||||
id: 182,
|
||||
label:
|
||||
"Coordinación de la Unidad de Investigación Multidisciplinaria Aplicada",
|
||||
},
|
||||
{
|
||||
id: 174,
|
||||
label:
|
||||
"Coordinación de LICEL Sistema de Universidad Abierta y Educación a Distancia",
|
||||
},
|
||||
{ id: 221, label: "Coordinación de Maestrías y Doctorados" },
|
||||
{
|
||||
id: 152,
|
||||
label:
|
||||
"Coordinación de Relaciones Internacionales del Sistema de Universidad Abierta y Educación a Distancia",
|
||||
},
|
||||
{ id: 121, label: "Coordinación de Servicios Académicos" },
|
||||
{ id: 125, label: "Coordinación del Centro de Difusión Cultural" },
|
||||
{ id: 124, label: "Coordinación del Centro de Educación Continua" },
|
||||
{ id: 129, label: "Coordinación del Centro de Enseñanza de Idiomas" },
|
||||
{
|
||||
id: 214,
|
||||
label: "Coordinación del Centro de Estudios Municipales y Metropolitanos",
|
||||
},
|
||||
{
|
||||
id: 176,
|
||||
label: "Coordinación del Centro Tecnológico para la Educación a Distancia",
|
||||
},
|
||||
{ id: 58, label: "Coordinación del Programa de Actuaría" },
|
||||
{ id: 57, label: "Coordinación del Programa de Arquitectura" },
|
||||
{ id: 46, label: "Coordinación del Programa de Comunicación" },
|
||||
{ id: 56, label: "Coordinación del Programa de Derecho" },
|
||||
{ id: 55, label: "Coordinación del Programa de Diseño Gráfico" },
|
||||
{ id: 54, label: "Coordinación del Programa de Economía" },
|
||||
{ id: 49, label: "Coordinación del Programa de Enseñanza de Inglés" },
|
||||
{ id: 51, label: "Coordinación del Programa de Ingeniería Civil" },
|
||||
{
|
||||
id: 48,
|
||||
label: "Coordinación del Programa de Matemáticas Aplicadas y Computación",
|
||||
},
|
||||
{ id: 47, label: "Coordinación del Programa de Pedagogía" },
|
||||
{ id: 44, label: "Coordinación del Programa de Sociología" },
|
||||
{ id: 43, label: "Coordinación del Programa Político" },
|
||||
{ id: 194, label: "Departamento de Intendencia" },
|
||||
{
|
||||
id: 193,
|
||||
label:
|
||||
"Departamento de Investigación en Comunicación y Estudios Culturales",
|
||||
},
|
||||
{
|
||||
id: 222,
|
||||
label:
|
||||
"Departamento de Orientación Académica del Sistema de Universidad Abierta y Educación a Distancia",
|
||||
},
|
||||
{ id: 204, label: "Departamento de Proyectos Administrativos" },
|
||||
{ id: 86, label: "Departamento de Talleres y Laboratorios" },
|
||||
{ id: 72, label: "Dirección" },
|
||||
{ id: 80, label: "División de Ciencias Jurídicas" },
|
||||
{ id: 79, label: "División de Ciencias Socioeconómicas" },
|
||||
{ id: 78, label: "División de Diseño y Edificación" },
|
||||
{ id: 77, label: "División de Humanidades" },
|
||||
{ id: 76, label: "División de Matemáticas e Ingeniería" },
|
||||
{
|
||||
id: 74,
|
||||
label:
|
||||
"División del Sistema de Universidad Abierta y Educación a Distancia",
|
||||
},
|
||||
{ id: 70, label: "Especialización en Costos en la Construcción" },
|
||||
{ id: 69, label: "Especialización en Finanzas Públicas" },
|
||||
{ id: 68, label: "Especialización en Geotecnia" },
|
||||
{ id: 71, label: "Especialización en Sistemas de Calidad" },
|
||||
{
|
||||
id: 220,
|
||||
label:
|
||||
"Especialización en Tecnología Digital para la Enseñanza de Matemáticas",
|
||||
},
|
||||
{ id: 207, label: "Grupo de Trabajo de Educación para Adultos (GTEA)" },
|
||||
{ id: 173, label: "Maestría en Docencia para la Educación Media Superior" },
|
||||
{ id: 224, label: "Posgrado en Ciencias Políticas y Sociales" },
|
||||
{ id: 62, label: "Posgrado en Derecho" },
|
||||
{ id: 164, label: "Posgrado en Economía" },
|
||||
{ id: 197, label: "Posgrado en Pedagogía" },
|
||||
{ id: 63, label: "Posgrado en Urbanismo" },
|
||||
{ id: 226, label: "Programa Único de Especializaciones en Derecho" },
|
||||
{ id: 127, label: "Secretaría Administrativa" },
|
||||
{ id: 181, label: "Secretaría de Asuntos Académicos Estudiantiles" },
|
||||
{
|
||||
id: 177,
|
||||
label: "Secretaría de Extensión Universitaria y Vinculación Institucional",
|
||||
},
|
||||
{ id: 119, label: "Secretaría de Posgrado e Investigación" },
|
||||
{ id: 8, label: "Secretaría General" },
|
||||
{ id: 6, label: "Unidad de Administración Escolar" },
|
||||
{ id: 5, label: "Unidad de Administración y Recursos" },
|
||||
{ id: 4, label: "Unidad de Planeación" },
|
||||
{ id: 3, label: "Unidad de Servicios a la Comunidad" },
|
||||
{ id: 2, label: "Unidad de Servicios Editoriales" },
|
||||
{ id: 1, label: "Unidad de Talleres, Laboratorios y Audiovisuales" },
|
||||
{ id: 130, label: "Unidad del Centro de Desarrollo Tecnológico" },
|
||||
{ id: 123, label: "Unidad del Centro de Información y Documentación" },
|
||||
];
|
||||
@@ -0,0 +1,97 @@
|
||||
export const PROCESADORES_POR_EQUIPO: Record<string, string[]> = {
|
||||
"ESCRITORIO PC": [
|
||||
"i7 o equivalentes (13a generación en adelante)",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (5a - 8a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (13a generación en adelante)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (13a generación en adelante)",
|
||||
"i3 o equivalentes (9a - 12a generación)",
|
||||
"i3 o equivalentes (5a - 8a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
"Pentium Silver O Gold",
|
||||
"Pentium Dual Core o anteriores",
|
||||
"Celeron (adquirido en 2018 hasta la fecha)",
|
||||
"Celeron Dual Core o anteriores",
|
||||
"Core2 Duo, Quad Core, Pentium Dual Core o anteriores",
|
||||
"Pentium Series J, G",
|
||||
"Celeron Serie J, G",
|
||||
],
|
||||
"ESCRITORIO LINUX": [
|
||||
"i7 o equivalentes (13a generación en adelante)",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (5a - 8a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (13a generación en adelante)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (13a generación en adelante)",
|
||||
"i3 o equivalentes (9a - 12a generación)",
|
||||
"i3 o equivalentes (5a - 8a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
"Pentium Silver O Gold",
|
||||
"Pentium Dual Core o anteriores",
|
||||
],
|
||||
"PORTÁTILES WINDOWS": [
|
||||
"i7 o equivalentes (13a generación en adelante)",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (5a - 8a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (13a generación en adelante)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (13a generación en adelante)",
|
||||
"i3 o equivalentes (9a - 12a generación)",
|
||||
"i3 o equivalentes (5a - 8a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
"Pentium Silver O Gold",
|
||||
"Pentium Dual Core o anteriores",
|
||||
],
|
||||
"PORTÁTILES CHROMEBOOK": [
|
||||
"i7 o equivalentes (13a generación en adelante)",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (5a - 8a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (13a generación en adelante)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (13a generación en adelante)",
|
||||
"i3 o equivalentes (9a - 12a generación)",
|
||||
"i3 o equivalentes (5a - 8a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
],
|
||||
"ESCRITORIO MAC OS": [
|
||||
"Familia M2",
|
||||
"Familia M1",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
"Core2 Mac, Quad Core o anteriores",
|
||||
],
|
||||
"PORTÁTILES MAC OS": [
|
||||
"Familia M2",
|
||||
"Familia M1",
|
||||
"i7 o equivalentes (9a - 12a generación)",
|
||||
"i7 o equivalentes (1a - 4a generación)",
|
||||
"i5 o equivalentes (9a - 12a generación)",
|
||||
"i5 o equivalentes (5a - 8a generación)",
|
||||
"i5 o equivalentes (1a - 4a generación)",
|
||||
"i3 o equivalentes (1a - 4a generación)",
|
||||
"Core2 Mac, Quad Core o anteriores",
|
||||
],
|
||||
SERVIDOR: [
|
||||
"Xeon Bronce, Plata, Oro 1a generación",
|
||||
"Xeon E3, E5, E7",
|
||||
"Xeon Phi",
|
||||
"Xeon o anteriores",
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
export const SO_POR_EQUIPO: Record<string, string[]> = {
|
||||
"ESCRITORIO PC": [
|
||||
"Windows 11",
|
||||
"Windows 10",
|
||||
"Windows 7/8",
|
||||
"Windows XP/Vista",
|
||||
"Linux",
|
||||
],
|
||||
"ESCRITORIO APPLE": [
|
||||
"Mac OS (13 - Ventura, 14 - Sonoma)",
|
||||
"Mac OS X (Mojave, Catalina, 11 - Big Sur, 12 - Monterrey)",
|
||||
"Mac OS X (Yosemite, El Capitan, Sierra, High Sierra)",
|
||||
"Mac OS X (Snow Leopard, Lion, Mountain Lion, Mavericks)",
|
||||
],
|
||||
"TABLETA ANDROID": [
|
||||
"Windows 11",
|
||||
"Windows 10",
|
||||
"Windows 7/8",
|
||||
"Windows XP/Vista",
|
||||
"Chrome OS",
|
||||
],
|
||||
"TABLETA iPAD OS": [
|
||||
"Mac OS (13 - Ventura, 14 - Sonoma)",
|
||||
"Mac OS X (Mojave, Catalina, 11 - Big Sur, 12 - Monterrey)",
|
||||
"Mac OS X (Yosemite, El Capitan, Sierra, High Sierra)",
|
||||
"Mac OS X (Snow Leopard, Lion, Mountain Lion, Mavericks)",
|
||||
],
|
||||
SERVIDOR: [
|
||||
"Linux (CentOS, Fedora, Ubuntu, Red Hat Enterprise, entre otros)",
|
||||
"Unix (AIX, MAC OS Server, Solaris, entre otros)",
|
||||
"Windows Server 2022/2023",
|
||||
"Windows Server 2016/2019",
|
||||
"Windows Server 2008/2012",
|
||||
"Windows Server 2000/2003",
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user