added fetch perifericos and change name

This commit is contained in:
2025-11-03 19:07:01 -06:00
parent afe6410bfb
commit 50dae88430
7 changed files with 121 additions and 28 deletions
@@ -7,7 +7,7 @@ import toast from "react-hot-toast";
import "../../styles/base/globales.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();
+1 -2
View File
@@ -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;
+2 -2
View File
@@ -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}
+49 -7
View File
@@ -19,6 +19,7 @@ export default function Page() {
const router = useRouter();
const [formData, setFormData] = useState({
inventario: "",
serie: "",
marca: "",
modelo: "",
@@ -31,9 +32,14 @@ export default function Page() {
adscripcion: "",
lugar: "",
responsable: "",
tipoPeriferico: "",
});
formData.serie = inventario ? inventario : "";
useEffect(() => {
if (inventario) {
setFormData((prev) => ({ ...prev, inventario }));
}
}, [inventario]);
// Tipos de datos
interface TipoUso {
@@ -81,6 +87,7 @@ export default function Page() {
SistemaOperativo[]
>([]);
const [procesadores, setProcesadores] = useState<Procesador[]>([]);
const [perifericos, setPerifericos] = useState([]);
const [suggestions, setSuggestions] = useState({
adscripcion: [] as string[],
@@ -155,6 +162,27 @@ export default function Page() {
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 }));
@@ -201,6 +229,7 @@ export default function Page() {
await axios.post(`${api_url}/equipos/crear`, formData, { headers });
toast.success("Equipo guardado correctamente");
setFormData({
inventario: "",
serie: "",
marca: "",
modelo: "",
@@ -213,6 +242,7 @@ export default function Page() {
adscripcion: "",
lugar: "",
responsable: "",
tipoPeriferico: "",
});
} catch (err) {
toast.error("Error al guardar el equipo");
@@ -236,8 +266,10 @@ export default function Page() {
required
type="text"
placeholder="Ingresa Inventario"
value={formData.serie}
onChange={(e) => handleInputChange("serie", e.target.value)}
value={formData.inventario}
onChange={(e) =>
handleInputChange("inventario", e.target.value)
}
/>
</div>
<div className="formGroup">
@@ -246,7 +278,7 @@ export default function Page() {
required
type="text"
placeholder="Ingresa serie"
value={""}
value={formData.serie}
onChange={(e) => handleInputChange("serie", e.target.value)}
/>
</div>
@@ -369,9 +401,19 @@ export default function Page() {
{!mostrarCamposComputadora && (
<div className="formGroup">
<label>Tipos de Perifericos</label>
<select>
<option value="">Selecciona periferico</option>
<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>
)}
+63 -13
View File
@@ -5,16 +5,20 @@ 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 { SO_POR_EQUIPO } from "@/data/so_por_equipo";
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: "",
@@ -76,6 +80,10 @@ 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 !== "PERIFÉRICO";
@@ -178,8 +186,42 @@ 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 (
@@ -339,21 +381,29 @@ export default function Editar() {
</div>
)}
<div className="formGroup">
<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">
+4 -2
View File
@@ -8,7 +8,8 @@ import { usePathname } from "next/navigation";
function Header() {
const pathname = usePathname();
const rutasConBar = ["/Escaner", "/AgregarEquipo"];
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>
);
+1 -1
View File
@@ -1,4 +1,4 @@
//Esto es culpa de los webservices
//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" },