added new icons and new monitor
This commit is contained in:
@@ -25,7 +25,7 @@ export default function MachineTable() {
|
||||
const fetchMachines = async () => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/equipo`,
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/equipo/disable`,
|
||||
{ cache: "no-store" }
|
||||
);
|
||||
const data = await res.json();
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "./Page.module.css";
|
||||
|
||||
type Equipo = {
|
||||
id_equipo: number;
|
||||
nombre_equipo: string;
|
||||
ubicacion: string;
|
||||
activo: {
|
||||
data: number[];
|
||||
};
|
||||
plataforma: {
|
||||
nombre: string;
|
||||
};
|
||||
areaUbicacion: {
|
||||
area: string;
|
||||
};
|
||||
};
|
||||
|
||||
export default function MachineTableActive() {
|
||||
const [machines, setMachines] = useState<Equipo[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const fetchMachines = async () => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/equipo/active`,
|
||||
{ cache: "no-store" },
|
||||
);
|
||||
const data = await res.json();
|
||||
setMachines(data);
|
||||
} catch (error) {
|
||||
console.error("Error al cargar equipos", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchMachines();
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <p>Cargando equipos...</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr style={{ fontSize: "15px" }}>
|
||||
<th>Ubicación</th>
|
||||
<th>Nombre Equipo</th>
|
||||
<th>Plataforma</th>
|
||||
<th>Área</th>
|
||||
<th>Disponible</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{machines.map((machine) => {
|
||||
const disponible = machine.activo.data[0] === 1;
|
||||
|
||||
return (
|
||||
<tr key={machine.id_equipo}>
|
||||
<td>{machine.ubicacion}</td>
|
||||
<td>{machine.nombre_equipo}</td>
|
||||
<td className={styles[machine.plataforma.nombre]}>
|
||||
{machine.plataforma.nombre}
|
||||
</td>
|
||||
<td>{machine.areaUbicacion.area}</td>
|
||||
<td>{disponible ? "Sí" : "No"}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -39,3 +39,39 @@
|
||||
.resetButton:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
|
||||
.WINDOWS::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("/windows.png");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: 6px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.MACINTOSH::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("/apple.png");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: 6px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.PROFESORES::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("/teacher.png");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: 6px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -1,23 +1,46 @@
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import MachineTable from "./MachineTable";
|
||||
import styles from "./Page.module.css";
|
||||
import ToggleTable from "@/app/Components/Global/Toggle/ToggleTable";
|
||||
import MachineTableActive from "./MachineTableActive";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{ numAcount: string }>;
|
||||
searchParams?: Promise<{ numAcount: string; key: string }>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ?? null;
|
||||
const key = params?.key ?? "active";
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
<h2 className="title">MONITOR DE MÁQUINAS DISPONIBLES</h2>
|
||||
<h2 className="title">MONITOR DE MÁQUINAS</h2>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<button className={styles.resetButton}>
|
||||
Actualizar información
|
||||
</button>
|
||||
<button className={styles.resetButton}>Actualizar información</button>
|
||||
</div>
|
||||
|
||||
<MachineTable />
|
||||
<ToggleTable
|
||||
defaultView={key}
|
||||
options={[
|
||||
{
|
||||
key: "active",
|
||||
label: "Disponibles",
|
||||
content: (
|
||||
<>
|
||||
<MachineTableActive />
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "disable",
|
||||
label: "No Disponibles",
|
||||
content: (
|
||||
<>
|
||||
<MachineTable />
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.buttonInscription{
|
||||
background-color: #007a5b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.buttonSave:not(:disabled):hover {
|
||||
background-color: #001f5c;
|
||||
}
|
||||
|
||||
@@ -62,9 +62,19 @@ export default function RegisterAlta(props: urlProp) {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
await apiClient.post("/alumno", form);
|
||||
const payload = {
|
||||
id_cuenta: Number(form.cuenta),
|
||||
nombre: `${form.apellidoP} ${form.apellidoM} ${form.nombre}`.trim(),
|
||||
fecha_nacimiento: form.fecha.replaceAll("-", ""),
|
||||
correo: form.email || undefined,
|
||||
id_carrera: Number(form.carrera),
|
||||
genero: form.genero || undefined,
|
||||
};
|
||||
|
||||
await apiClient.post("/student", payload);
|
||||
|
||||
setSaved(true);
|
||||
toast.error("Alumno registrado correctamente");
|
||||
toast.success("Alumno registrado correctamente");
|
||||
} catch (error) {
|
||||
console.error("Error al guardar alumno:", error);
|
||||
toast.error("Error al guardar alumno");
|
||||
@@ -73,7 +83,7 @@ export default function RegisterAlta(props: urlProp) {
|
||||
|
||||
const handleInscripcion = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
router.push("/Inscripcion");
|
||||
router.push(`/Inscripcion?numAcount=${form.cuenta}`);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -150,7 +160,12 @@ export default function RegisterAlta(props: urlProp) {
|
||||
|
||||
<div className="containerForm">
|
||||
<label className="label">Género</label>
|
||||
<select name="genero" value={form.genero} onChange={handleChange} required>
|
||||
<select
|
||||
name="genero"
|
||||
value={form.genero}
|
||||
onChange={handleChange}
|
||||
required
|
||||
>
|
||||
<option value="">Selecciona género</option>
|
||||
<option value="Femenino">Femenino</option>
|
||||
<option value="Masculino">Masculino</option>
|
||||
@@ -160,7 +175,12 @@ export default function RegisterAlta(props: urlProp) {
|
||||
|
||||
<div className="containerForm">
|
||||
<label className="label">Carrera</label>
|
||||
<select name="carrera" value={form.carrera} onChange={handleChange} required>
|
||||
<select
|
||||
name="carrera"
|
||||
value={form.carrera}
|
||||
onChange={handleChange}
|
||||
required
|
||||
>
|
||||
<option value="">Selecciona la carrera</option>
|
||||
{listMajor.map((c) => (
|
||||
<option key={c.id_carrera} value={c.id_carrera}>
|
||||
@@ -180,7 +200,7 @@ export default function RegisterAlta(props: urlProp) {
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="button"
|
||||
className="button buttonInscription"
|
||||
disabled={!saved}
|
||||
onClick={handleInscripcion}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
"use client";
|
||||
|
||||
import { usePathname, useSearchParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState, ReactNode } from "react";
|
||||
|
||||
interface ToggleOption {
|
||||
key: string;
|
||||
label: string;
|
||||
content: ReactNode;
|
||||
}
|
||||
|
||||
interface ToggleProps {
|
||||
options: ToggleOption[];
|
||||
defaultView?: string;
|
||||
}
|
||||
|
||||
export default function ToggleTable({ options, defaultView }: ToggleProps) {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const pathname = usePathname();
|
||||
const [view, setView] = useState(defaultView || options[0].key);
|
||||
|
||||
const handleClick = (key: string) => {
|
||||
setView(key);
|
||||
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.set("key", key);
|
||||
|
||||
router.replace(`${pathname}?${params.toString()}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="toggleSection" style={{maxWidth:"none"}}>
|
||||
<div className="toggleGroup">
|
||||
{options.map((opt) => (
|
||||
<button
|
||||
key={opt.key}
|
||||
className={`toggleButton ${view === opt.key ? "active" : ""}`}
|
||||
onClick={() => handleClick(opt.key)}
|
||||
>
|
||||
{opt.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="padding toggleContent">
|
||||
{options.find((opt) => opt.key === view)?.content}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
@@ -20,15 +20,15 @@ function Selection({
|
||||
const options = [
|
||||
{
|
||||
name: "WINDOWS",
|
||||
img: "https://images.icon-icons.com/2235/PNG/512/windows_os_logo_icon_134678.png",
|
||||
img: "/windows.png",
|
||||
},
|
||||
{
|
||||
name: "MACINTOSH",
|
||||
img: "https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg",
|
||||
img: "apple.png",
|
||||
},
|
||||
{
|
||||
name: "PROFESORES",
|
||||
img: "https://cdn-icons-png.flaticon.com/512/3135/3135715.png",
|
||||
img: "teacher.png",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -15,19 +15,18 @@ function SelectionCo({
|
||||
const options = [
|
||||
{
|
||||
name: "WINDOWS",
|
||||
img: "https://images.icon-icons.com/2235/PNG/512/windows_os_logo_icon_134678.png",
|
||||
img: "/windows.png",
|
||||
},
|
||||
{
|
||||
name: "MACINTOSH",
|
||||
img: "https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg",
|
||||
img: "apple.png",
|
||||
},
|
||||
{
|
||||
name: "PROFESORES",
|
||||
img: "https://cdn-icons-png.flaticon.com/512/3135/3135715.png",
|
||||
img: "teacher.png",
|
||||
},
|
||||
];
|
||||
|
||||
// ✅ SOLO las inscritas
|
||||
const opcionesInscritas = options.filter((option) =>
|
||||
plataformasInscritas.includes(option.name),
|
||||
);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
Reference in New Issue
Block a user