Merge branch 'Lino' of https://github.com/IO420/Nexus into Carlos
This commit is contained in:
@@ -1,52 +1,32 @@
|
||||
import Areas from "@/app/Components/ActivosMantenimiento/Areas";
|
||||
import Mesas from "@/app/Components/ActivosMantenimiento/Mesas";
|
||||
import Equipos from "@/app/Components/Equipos/equipos";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import MesasDisponibles from "@/app/Components/ActivosMantenimiento/MesasDisponibles";
|
||||
import TableEquipos from "@/app/Components/Equipos/tableequipos";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key?: string;
|
||||
numAcount?: string;
|
||||
machine?: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title">EQUIPOS ACTIVOS Y EN MANTENIMIENTO</h2>
|
||||
|
||||
<Toggle
|
||||
defaultView="Equipos"
|
||||
defaultView={key}
|
||||
options={[
|
||||
{
|
||||
key: "Equipos",
|
||||
label: "Equipos",
|
||||
content: (
|
||||
<>
|
||||
<SearchUser value={numAcount} />
|
||||
<Equipos />
|
||||
<TableEquipos />
|
||||
</>
|
||||
),
|
||||
},
|
||||
@@ -61,10 +41,10 @@ export default async function Page(props: {
|
||||
},
|
||||
{
|
||||
key: "Mesas",
|
||||
label: "Liberar mesa",
|
||||
label: "Mesas",
|
||||
content: (
|
||||
<>
|
||||
<Mesas />
|
||||
<MesasDisponibles />
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
.addTime {
|
||||
position: relative;
|
||||
max-width: 600px;
|
||||
margin-top: 1rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 4px;
|
||||
background-color: #f9fafb;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
position: relative;
|
||||
max-width: 600px;
|
||||
margin-top: 1rem;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,27 @@
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import Information from "@/app/Components/Global/Information/information";
|
||||
import Receipt from "@/app/Components/Receipt/Receipt";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
|
||||
import "./addTime.css";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
numAcount: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
let showError = params?.error ? params.error : null;
|
||||
|
||||
let student: any = null;
|
||||
if (numAcount) {
|
||||
const result = await GetStudent(parseInt(numAcount));
|
||||
|
||||
if (result.error) {
|
||||
showError = "Alumno no encontrado";
|
||||
toast.error("Alumno no encontrado");
|
||||
return;
|
||||
} else {
|
||||
student = result;
|
||||
}
|
||||
@@ -33,34 +29,19 @@ export default async function Page(props: {
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox message="Recibo guardado correctamente" type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title"> AGREGAR TIEMPO </h2>
|
||||
|
||||
<SearchUser value={numAcount} />
|
||||
|
||||
{student ? (
|
||||
{student && (
|
||||
<>
|
||||
<Information NoCuenta={student.id_cuenta} Nombre={student.nombre} />
|
||||
|
||||
<div className="addTime">
|
||||
<div className="groupInput" style={{ marginBottom: "1rem" }}></div>
|
||||
<Receipt numAcount={student.id_cuenta} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import RegisterAlta from "@/app/Components/Alta/registerAlta";
|
||||
|
||||
import "./style.css";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h1 className="title">ALTA</h1>
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.containerAlta {
|
||||
background-color: #f9f9f9;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
padding: 1rem;
|
||||
|
||||
@@ -1,60 +1,46 @@
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
|
||||
import "@/app/globals.css";
|
||||
import SearchBoxEquipo from "@/app/Components/SearchEquipo";
|
||||
import CheckBox from "@/app/Components/CheckBox";
|
||||
import CheckBoxEquipo from "@/app/Components/CheckBoxEquipo";
|
||||
import Information from "@/app/Components/Global/Information/information";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
|
||||
import "@/app/globals.css";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key?:string
|
||||
numAcount?: string;
|
||||
machine?: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const machine = params?.machine ? params.machine : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
let student: any = null;
|
||||
let errorMessage = "";
|
||||
|
||||
if (numAcount) {
|
||||
const result = await GetStudent(parseInt(numAcount));
|
||||
|
||||
if (result.error) {
|
||||
errorMessage = `${result.error}`;
|
||||
} else {
|
||||
student = result;
|
||||
student = result as Student;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
{errorMessage && <ShowError key={Date.now()} message={errorMessage} />}
|
||||
|
||||
<h2 className="title"> ASIGNACION DE EQUIPOS </h2>
|
||||
|
||||
<Toggle
|
||||
defaultView="Asignar"
|
||||
defaultView={key}
|
||||
options={[
|
||||
{
|
||||
key: "Asignar",
|
||||
@@ -63,18 +49,34 @@ export default async function Page(props: {
|
||||
<>
|
||||
<SearchUser value={numAcount} />
|
||||
|
||||
<Information
|
||||
numerocuenta={"12345"}
|
||||
nombre={"Carlos"}
|
||||
inscrito={"WINDOWS"}
|
||||
tiempo={"9minutos"}
|
||||
confirmo={"si/no"}
|
||||
/>
|
||||
<label>Seleccionar tiempo</label>
|
||||
<select name="" id=""></select>
|
||||
<label>Seleccione un equipo</label>
|
||||
<select name="" id=""></select>
|
||||
<button className="button buttonSearch">Asignar Equipo</button>
|
||||
{student && (
|
||||
<>
|
||||
<Information
|
||||
numerocuenta={student.id_cuenta}
|
||||
nombre={student.nombre}
|
||||
/>
|
||||
<Information
|
||||
inscrito={"WINDOWS"}
|
||||
tiempo={"9minutos"}
|
||||
confirmo={"si/no"}
|
||||
/>
|
||||
{/* <div className="containerForm">
|
||||
<label style={{ marginTop: "1rem" }}>
|
||||
Seleccionar tiempo
|
||||
</label>
|
||||
<select></select>
|
||||
<label style={{ marginTop: "1rem" }}>
|
||||
Seleccione un equipo
|
||||
</label>
|
||||
<div className="groupInput">
|
||||
<select></select>
|
||||
<button className="button buttonSearch">
|
||||
Asignar Equipo
|
||||
</button>
|
||||
</div>
|
||||
</div> */}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -2,35 +2,74 @@ import AsignacionMesas from "@/app/Components/AsignacionMesas";
|
||||
import CheckBox from "@/app/Components/CheckBox";
|
||||
import Information from "@/app/Components/Global/Information/information";
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key: string;
|
||||
numAcount: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
|
||||
let student: any = null;
|
||||
let errorMessage = "";
|
||||
|
||||
if (numAcount) {
|
||||
const result = await GetStudent(parseInt(numAcount));
|
||||
|
||||
if (result.error) {
|
||||
errorMessage = `${result.error}`;
|
||||
} else {
|
||||
student = result as Student;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{errorMessage && <ShowError key={Date.now()} message={errorMessage} />}
|
||||
<h2 className="title"> ASIGNACION DE MESAS </h2>
|
||||
|
||||
<Toggle
|
||||
defaultView="Asignar"
|
||||
defaultView={key}
|
||||
options={[
|
||||
{
|
||||
key: "Asignar",
|
||||
label: "Asignar mesa",
|
||||
content: (
|
||||
<>
|
||||
<SearchUser value={"3"} />
|
||||
<AsignacionMesas />
|
||||
<Information cuenta={"12345"} nombre={"Alberto"} />
|
||||
<label>Tiempo</label>
|
||||
<select name="" id="">
|
||||
<option value="1">Seleciona el tiempo </option>{" "}
|
||||
</select>
|
||||
<button className="button buttonSearch">Asignar</button>
|
||||
<SearchUser value={numAcount} />
|
||||
{student && (
|
||||
<>
|
||||
<Information
|
||||
cuenta={student.id_cuenta}
|
||||
nombre={student.nombre}
|
||||
/>
|
||||
{/* <div
|
||||
className="containerForm"
|
||||
style={{ margin: "1rem 0" }}
|
||||
>
|
||||
<label>Tiempo</label>
|
||||
<div className="groupInput">
|
||||
<select name="" id="">
|
||||
<option value="1">Seleciona el tiempo </option>{" "}
|
||||
</select>
|
||||
<button className="button buttonSearch">Asignar</button>
|
||||
</div>
|
||||
</div> */}
|
||||
<AsignacionMesas />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "Liberar",
|
||||
label: "Liberar mesa",
|
||||
key: "Tiempo",
|
||||
label: "Cancelar Tiempo",
|
||||
content: (
|
||||
<>
|
||||
<CheckBox />
|
||||
|
||||
@@ -2,24 +2,19 @@ import BitacoraAlumno from "@/app/Components/BitacoraSanciones/BitacoraAlumno";
|
||||
import BitacoraEquipo from "@/app/Components/BitacoraSanciones/BitacoraEquipo";
|
||||
import BitacoraMesas from "@/app/Components/BitacoraSanciones/BitacoraMesas";
|
||||
import Sanciones from "@/app/Components/BitacoraSanciones/Sanciones";
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key?: string;
|
||||
numAcount?: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key ;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
let student: any = null;
|
||||
|
||||
@@ -34,19 +29,6 @@ export default async function Page(props: {
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title"> BITACORA Y SANCIONES </h2>
|
||||
|
||||
@@ -67,6 +49,7 @@ export default async function Page(props: {
|
||||
label: "Bitacora alumno",
|
||||
content: (
|
||||
<>
|
||||
<SearchUser value={numAcount}/>
|
||||
<BitacoraAlumno />
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -1,32 +1,13 @@
|
||||
import ChangePassword from "@/app/Components/auth/ChangePassword/changePassword";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title"> Cambiar contraseña </h2>
|
||||
|
||||
|
||||
@@ -2,53 +2,40 @@ import SearchUser from "../../Components/Global/SearchUser/searchUser";
|
||||
import Receipt from "../../Components/Receipt/Receipt";
|
||||
import Toggle from "../../Components/Global/Toggle/Toggle";
|
||||
import Information from "../../Components/Global/Information/information";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import Impressions from "@/app/Components/Impressions/impressions";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
|
||||
import "@/app/globals.css";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key: string;
|
||||
numAcount: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
let student: any = null;
|
||||
let errorMessage = "";
|
||||
|
||||
if (numAcount) {
|
||||
const result = await GetStudent(parseInt(numAcount));
|
||||
|
||||
if (result.error) {
|
||||
errorMessage = `${result.error}`;
|
||||
} else {
|
||||
student = result;
|
||||
student = result as Student;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
{errorMessage && <ShowError key={Date.now()} message={errorMessage} />}
|
||||
|
||||
<h2 className="title">IMPRESIONES Y PLOTEO</h2>
|
||||
<SearchUser value={numAcount} />
|
||||
|
||||
@@ -1,40 +1,21 @@
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import Equipos from "@/app/Components/Equipos/equipos";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ProgramSelector from "@/app/Components/InformacionEquipos/ProgramSelector";
|
||||
|
||||
import "./informacionequipo.css";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key?: string;
|
||||
machine?: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
const machine = params?.machine ? params.machine : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title"> INFORMACION DE EQUIPOS </h2>
|
||||
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
.inscripcion{
|
||||
background-color: #f9f9f9;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
border-radius: 4px;
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
outline: 1px solid #cfcfcf;
|
||||
}
|
||||
.inscripcion {
|
||||
position: relative;
|
||||
top: 0;
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
border-radius: 4px;
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.containeInformation {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.firstPartInformation {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.containeInformation {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.containeInformation {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,65 +2,90 @@ import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import Information from "@/app/Components/Global/Information/information";
|
||||
import Receipt from "@/app/Components/Receipt/Receipt";
|
||||
import Selection from "@/app/Components/Selection/Selection";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
import { GetStudent } from "@/app/lib/getStudent";
|
||||
|
||||
import "./inscripcion.css";
|
||||
import Table from "@/app/Components/Global/table";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
numAcount: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
let showError = params?.error ? params.error : null;
|
||||
|
||||
let student: any = null;
|
||||
let errorMessage = "";
|
||||
if (numAcount) {
|
||||
const result = await GetStudent(parseInt(numAcount));
|
||||
|
||||
if (result.error) {
|
||||
showError = "Alumno no encontrado";
|
||||
errorMessage = `${result.error}`;
|
||||
} else {
|
||||
student = result;
|
||||
}
|
||||
}
|
||||
|
||||
const headers = ["Inscrito", "Tiempo", "Confirmó"];
|
||||
const data = [
|
||||
{
|
||||
Inscrito: "WINDOWS",
|
||||
Tiempo: "9 minutos",
|
||||
Confirmó: "si",
|
||||
},
|
||||
{
|
||||
Inscrito: "WINDOWS",
|
||||
Tiempo: "9 minutos",
|
||||
Confirmó: "si/no",
|
||||
},
|
||||
{
|
||||
Inscrito: "WINDOWS",
|
||||
Tiempo: "9 minutos",
|
||||
Confirmó: "si/no",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
{errorMessage && <ShowError key={Date.now()} message={errorMessage} />}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
<h2 className="title"> INSCRIPCIÓN </h2>
|
||||
|
||||
<h2 className="title"> INSCRIPCION </h2>
|
||||
<div className="containeInformation">
|
||||
<div className="firstPartInformation">
|
||||
<SearchUser value={numAcount} />
|
||||
|
||||
<SearchUser value={numAcount} />
|
||||
{student && (
|
||||
<Information
|
||||
NoCuenta={student.id_cuenta}
|
||||
Nombre={student.nombre}
|
||||
Carrera={student.carrera.carrera}
|
||||
Credito={student.credito}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{student && <Table headers={headers} data={data} />}
|
||||
</div>
|
||||
|
||||
{student && (
|
||||
<>
|
||||
<Information
|
||||
NoCuenta={student.id_cuenta}
|
||||
Nombre={student.nombre}
|
||||
Carrera={student.carrera.carrera}
|
||||
Credito={student.credito}
|
||||
/>
|
||||
<section className="inscripcion">
|
||||
<Selection />
|
||||
|
||||
<select
|
||||
style={{
|
||||
marginBottom: "1rem",
|
||||
maxWidth: "100px",
|
||||
minWidth: "100px",
|
||||
}}
|
||||
>
|
||||
<option value="0">con pago</option>
|
||||
<option value="1">sin pago</option>
|
||||
</select>
|
||||
|
||||
<Receipt numAcount={student.id_cuenta} />
|
||||
</section>
|
||||
</>
|
||||
|
||||
@@ -1,33 +1,15 @@
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
period: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const period = params?.period ? params.period : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
<h2 className="title"> INSCRITOS </h2>
|
||||
|
||||
<form className="containerForm">
|
||||
@@ -53,15 +35,38 @@ export default async function Page(props: {
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Carrera</th>
|
||||
<th>Windows</th>
|
||||
<th>Macintosh</th>
|
||||
<th>Linux</th>
|
||||
<th>Genero</th>
|
||||
<th>Profesores</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="tableContainer" style={{ marginTop: "100px" }}>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Impresione B/N</th>
|
||||
<th>Impresiones Color</th>
|
||||
<th>Plotteo</th>
|
||||
<th>Escaner</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>5,000</td>
|
||||
<td>10,000</td>
|
||||
<td>10,000</td>
|
||||
<td>20,000</td>
|
||||
<td>45,000</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,16 @@
|
||||
import EnviarMensaje from "@/app/Components/EviarMensaje/EnviarMensaje";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key:string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key ;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
<ClearParams paramsToClear={["error"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
<ClearParams paramsToClear={["success"]} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="title">Enviar mensaje</h2>
|
||||
|
||||
@@ -41,6 +22,7 @@ export default async function Page(props: {
|
||||
label: "Equipo",
|
||||
content: (
|
||||
<EnviarMensaje
|
||||
key={1}
|
||||
titulo="Seleccione un equipo"
|
||||
opciones={["1", "2", "3", "4", "5", "6"]}
|
||||
/>
|
||||
@@ -51,6 +33,7 @@ export default async function Page(props: {
|
||||
label: "Sala",
|
||||
content: (
|
||||
<EnviarMensaje
|
||||
key={2}
|
||||
titulo="Seleccione una sala"
|
||||
opciones={["PECERA", "PCNET1", "PCNET2", "PCNET3"]}
|
||||
/>
|
||||
|
||||
@@ -1,70 +1,41 @@
|
||||
.tableContainer {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #cfcfcf;
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
background-color: #f9f9f9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.machineTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.machineTable th,
|
||||
.machineTable td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.machineTable th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: rgb(1, 92, 184);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.machineTable tr {
|
||||
min-width: 400px;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.disponible {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: green;
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: green;
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ocupado {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.actions {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.resetButton {
|
||||
padding: 8px 16px;
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
padding: 8px 16px;
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.resetButton:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
background-color: #cc0000;
|
||||
}
|
||||
|
||||
@@ -3,35 +3,56 @@ import styles from "./Page.module.css";
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
numAcount: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<section className='containerSection'>
|
||||
<h2 className='title'> MONITOR DE MÁQUINAS DISPONIBLES </h2>
|
||||
<section className="containerSection">
|
||||
<h2 className="title"> MONITOR DE MÁQUINAS DISPONIBLES </h2>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<button className={styles.resetButton}>
|
||||
Actualizar informacion
|
||||
</button>
|
||||
<button className={styles.resetButton}>Actualizar informacion</button>
|
||||
</div>
|
||||
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<tr style={{fontSize:"15px"}}>
|
||||
<th>Ubicación</th>
|
||||
<th>Nombre Equipo</th>
|
||||
<th>Plataforma</th>
|
||||
<th>Área</th>
|
||||
<th>Disponible</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>pcnet1</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>mostrar todos</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>windows</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>mostrar Todo</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>si</option>
|
||||
</select>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* {machines.map((machine, index) => (
|
||||
@@ -51,4 +72,4 @@ export default async function Page(props: {
|
||||
</section>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
//IO
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function Page() {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="containerSection">
|
||||
{modo === "ver" && (
|
||||
<section className="containersection">
|
||||
<h3 className="title">PROGRAMAS</h3>
|
||||
@@ -86,6 +86,6 @@ export default function Page() {
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,22 +4,19 @@ import QuitarSancion from "@/app/Components/QuitarSancion/QuitarSancion";
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
numAcount: string;
|
||||
success?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const showSuccess = params?.success ? params.success : null;
|
||||
const showError = params?.error ? params.error : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="title"> Quitar Sanciones </h2>
|
||||
<div style={{ display: "flex", gap: "1rem", flexDirection: "column" }}>
|
||||
<SearchUser value={numAcount} />
|
||||
<QuitarSancion />
|
||||
</div>
|
||||
<h2 className="title"> Quitar Sanciones </h2>
|
||||
<div className="containerSection"
|
||||
>
|
||||
<SearchUser value={numAcount} />
|
||||
<QuitarSancion />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,94 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import styles from "./Page.module.css";
|
||||
import Toggle from "@/app/Components/Global/Toggle/Toggle";
|
||||
import SearchDateBetween from "@/app/Components/SearchDateBetween/SearchDateBetween";
|
||||
import PorServicios from "@/app/Components/Reportes/porServicio";
|
||||
import PorRecibos from "@/app/Components/Reportes/porRecibo";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
export default function Page() {
|
||||
const [reportes] = useState([
|
||||
{
|
||||
Servicio: "Plotter",
|
||||
Total: "$1440.00",
|
||||
},
|
||||
]);
|
||||
|
||||
const [recibos] = useState([
|
||||
{
|
||||
folio_recibo: "100255",
|
||||
monto: "40.00",
|
||||
fecha_recibo: "10/10/2025",
|
||||
fecha_registro: "10/10/2025 05:32:20 pm",
|
||||
usuario: "modulo1",
|
||||
},
|
||||
]);
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
key: string;
|
||||
numAcount: string;
|
||||
}>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const key = params?.key && params.key;
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
<h2 className="title"> REPORTES </h2>
|
||||
|
||||
<Toggle
|
||||
defaultView="1"
|
||||
defaultView={key}
|
||||
options={[
|
||||
{
|
||||
key: "1",
|
||||
key: "Por recibo",
|
||||
label: "Por recibo",
|
||||
content: (
|
||||
<>
|
||||
<SearchDateBetween />
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Folio Recibo</th>
|
||||
<th>Monto</th>
|
||||
<th>Fecha Recibo</th>
|
||||
<th>Fecha Registro</th>
|
||||
<th>Usuario</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{recibos.map((recibo, index) => (
|
||||
<tr key={index}>
|
||||
<td>{recibo.folio_recibo}</td>
|
||||
<td>{recibo.monto}</td>
|
||||
<td>{recibo.fecha_recibo}</td>
|
||||
<td>{recibo.fecha_registro}</td>
|
||||
<td>{recibo.usuario}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<PorServicios />
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
key: "2",
|
||||
key: "Por Servicio",
|
||||
label: "Por Servicio",
|
||||
content: (
|
||||
<>
|
||||
<SearchDateBetween />
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Servicio</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{reportes.map((reporte, index) => (
|
||||
<tr key={index}>
|
||||
<td>{reporte.Servicio}</td>
|
||||
<td>{reporte.Total}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<PorRecibos />
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
|
||||
import "@/app/globals.css"
|
||||
|
||||
export default function Areas() {
|
||||
const [area, setArea] = useState(""); // Área seleccionada
|
||||
const [activo, setActivo] = useState(false); // Checkbox Activo
|
||||
const [mantenimiento, setMantenimiento] = useState(false); // Checkbox Mantenimiento
|
||||
const [mensaje, setMensaje] = useState(""); // Mensaje dinámico
|
||||
|
||||
const handleActualizar = (e: React.FormEvent) => {
|
||||
const handleActualizar = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!area) {
|
||||
@@ -35,11 +37,10 @@ export default function Areas() {
|
||||
|
||||
return (
|
||||
<form className="containerForm" onSubmit={handleActualizar}>
|
||||
<label className="label">Áreas disponibles:</label>
|
||||
<label className="label">Áreas</label>
|
||||
<div className="groupInput">
|
||||
{/* Select de áreas */}
|
||||
<select value={area} onChange={(e) => setArea(e.target.value)}>
|
||||
<option value="">-- Áreas disponibles --</option>
|
||||
<option value="">-- Áreas --</option>
|
||||
<option value="PECERA">PECERA</option>
|
||||
<option value="JAULA">JAULA</option>
|
||||
<option value="HUACAL">HUACAL</option>
|
||||
@@ -48,13 +49,15 @@ export default function Areas() {
|
||||
</select>
|
||||
|
||||
{/* Checkboxes */}
|
||||
<div className="checkbox-grid">
|
||||
|
||||
<div className="checkbox" style={{ marginTop: "10px" }}>
|
||||
<label style={{ marginRight: "10px" }}>
|
||||
<label style={{ marginRight: "10px"}}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={activo}
|
||||
onChange={(e) => setActivo(e.target.checked)}
|
||||
/>
|
||||
/>
|
||||
Activo
|
||||
</label>
|
||||
<label>
|
||||
@@ -62,10 +65,11 @@ export default function Areas() {
|
||||
type="checkbox"
|
||||
checked={mantenimiento}
|
||||
onChange={(e) => setMantenimiento(e.target.checked)}
|
||||
/>
|
||||
/>
|
||||
Mantenimiento
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Botón Actualizar */}
|
||||
<button
|
||||
|
||||
@@ -6,7 +6,7 @@ function Equipos() {
|
||||
const [tiempo, setTiempo] = useState("");
|
||||
const [mensaje, setMensaje] = useState("");
|
||||
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
const handleBuscar = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
if (!cuenta) {
|
||||
setMensaje("Ingresa un número de cuenta antes de buscar");
|
||||
@@ -15,7 +15,7 @@ function Equipos() {
|
||||
setMensaje(`Buscando información del No. de cuenta: ${cuenta}`);
|
||||
};
|
||||
|
||||
const handleAsignar = (e: React.FormEvent) => {
|
||||
const handleAsignar = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
if (!tiempo) {
|
||||
setMensaje("Selecciona un equipo antes de asignar");
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
|
||||
import "@/app/globals.css"
|
||||
|
||||
function Mesas() {
|
||||
const [mesa, setMesa] = useState(""); // Mesa seleccionada
|
||||
const [mantenimiento, setMantenimiento] = useState(false); // Checkbox Mantenimiento
|
||||
const [mensaje, setMensaje] = useState(""); // Mensaje dinámico
|
||||
|
||||
const handleConfirmar = (e: React.FormEvent) => {
|
||||
const handleConfirmar = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!mesa) {
|
||||
@@ -26,7 +28,7 @@ function Mesas() {
|
||||
return (
|
||||
<form className="containerForm" onSubmit={handleConfirmar}>
|
||||
<label className="label">Mesas disponibles:</label>
|
||||
<div className="groupInput">
|
||||
<div className="groupInput" style={{display:"flex", flexDirection:"column"}}>
|
||||
{/* Select de mesas */}
|
||||
<select value={mesa} onChange={(e) => setMesa(e.target.value)}>
|
||||
<option value="">-- Mesas disponibles --</option>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import styles from "./Page.module.css";
|
||||
|
||||
export default async function MesasDisponibles() {
|
||||
return (
|
||||
<section className="containerSection">
|
||||
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr style={{fontSize:"15px"}}>
|
||||
<th>Mesa</th>
|
||||
<th>Activo</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* {machines.map((machine, index) => (
|
||||
<tr key={index}>
|
||||
<td>{machine.ubicacion}</td>
|
||||
<td>{machine.nombre}</td>
|
||||
<td>{machine.plataforma}</td>
|
||||
<td>{machine.area}</td>
|
||||
<td className={machine.disponible ? "disponible" : ""}>
|
||||
{machine.disponible ? "si" : "no"}
|
||||
</td>
|
||||
</tr>
|
||||
))} */}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
@@ -0,0 +1,70 @@
|
||||
.tableContainer {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #cfcfcf;
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
background-color: #f9f9f9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.machineTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.machineTable th,
|
||||
.machineTable td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.machineTable th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: rgb(1, 92, 184);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.machineTable tr {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.disponible {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: green;
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ocupado {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.actions {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.resetButton {
|
||||
padding: 8px 16px;
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.resetButton:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
@@ -1,8 +1,29 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import apiClient from "@/app/lib/apiClient";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function RegisterAlta() {
|
||||
const [listMajor, setListMajor] = useState([]);
|
||||
const [major, setMajor] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCarreras = async () => {
|
||||
try {
|
||||
const response = await apiClient.get("/carrera");
|
||||
|
||||
const sortedCarreras = response.data.sort((a: any, b: any) =>
|
||||
a.carrera.localeCompare(b.carrera)
|
||||
);
|
||||
|
||||
setListMajor(sortedCarreras);
|
||||
} catch (error) {
|
||||
console.error("Error al obtener carreras:", error);
|
||||
}
|
||||
};
|
||||
fetchCarreras();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form className="containerAlta gap gridAlta">
|
||||
<div className="containerForm">
|
||||
@@ -59,6 +80,11 @@ export default function RegisterAlta() {
|
||||
<label className="label">Carrera</label>
|
||||
<select value={major} onChange={(e) => setMajor(e.target.value)}>
|
||||
<option value="">Selecciona la carrera</option>
|
||||
{listMajor.map((carrera: any, index) => (
|
||||
<option key={index} value={carrera.id_carrera}>
|
||||
{carrera.carrera}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function BitacoraAlumno() {
|
||||
return (
|
||||
<>
|
||||
<SearchDate />
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableContainer} style={{marginTop:"1rem"}}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -33,7 +33,7 @@ function BitacoraEquipo() {
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableContainer} style={{marginTop:"1rem"}}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -18,7 +18,7 @@ function BitacoraMesas() {
|
||||
return (
|
||||
<>
|
||||
<SearchDate />
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableContainer} style={{marginTop:"1rem"}}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -20,7 +20,7 @@ export default async function Sanciones(props: { student?: Student }) {
|
||||
Nombre={props.student.nombre}
|
||||
/>
|
||||
|
||||
<TableSancion />
|
||||
<TableSancion />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -27,30 +27,28 @@ export default function TableSancion() {
|
||||
const [sanciones, setSanciones] = useState<any>();
|
||||
const [button, setButton] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const getSanciones = async () => {
|
||||
const response = await axios.get(
|
||||
""
|
||||
);
|
||||
setSanciones(response);
|
||||
};
|
||||
getSanciones();
|
||||
}, [button]);
|
||||
// useEffect(() => {
|
||||
// const getSanciones = async () => {
|
||||
// const response = await axios.get("");
|
||||
// setSanciones(response);
|
||||
// };
|
||||
// getSanciones();
|
||||
// }, [button]);
|
||||
|
||||
const handlebutton = () => {
|
||||
setButton(!button);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{sanciones}</h1>
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableContainer} style={{margin:"1rem 0"}}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Cuenta</th>
|
||||
<th>Motivo de la sancion</th>
|
||||
<th>Motivo de la sanción</th>
|
||||
<th>Duracion (Semanas) </th>
|
||||
<th>Fecha Sancion</th>
|
||||
<th>Fecha Sanción</th>
|
||||
<th>Podra utilizar el servicio hasta</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -61,15 +59,14 @@ export default function TableSancion() {
|
||||
<form className="containerForm">
|
||||
<div className="groupInput">
|
||||
<select>
|
||||
<option value="">-- Selecciona una sancion --</option>
|
||||
<option value="">-- Selecciona una sanción --</option>
|
||||
<option value="sancion 1">No cerrar sesion (Una semana)</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
<button className="button buttonSearch" onClick={handlebutton}>
|
||||
Aplicar sancion
|
||||
</button>
|
||||
<h1>{button ? <p>desactivado</p> : <p>activado</p>}</h1>
|
||||
<button className="button buttonSearch" style={{margin:"1rem 0"}} onClick={handlebutton}>
|
||||
Aplicar sanción
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
.tableContainer {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #cfcfcf;
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
background-color: #f9f9f9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.machineTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.machineTable th,
|
||||
.machineTable td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.machineTable th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: rgb(1, 92, 184);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.machineTable tr {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.disponible {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: green;
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ocupado {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.actions {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.resetButton {
|
||||
padding: 8px 16px;
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.resetButton:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
@@ -14,16 +14,17 @@ export default function Equipos() {
|
||||
const [Equipo, setEquipo] = useState("");
|
||||
const [Data, setData] = useState<Data | any>();
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const response = await axios.get(
|
||||
`${envConfig.apiUrl}/InformacionEquipo/${Equipo}`
|
||||
);
|
||||
const handleSubmit = async (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
// const response = await axios.get(
|
||||
// `${envConfig.apiUrl}/equipo/${Equipo}`
|
||||
// );
|
||||
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
// if (!response) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
setData(response);
|
||||
setData("response");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -37,7 +38,7 @@ export default function Equipos() {
|
||||
}}
|
||||
/>
|
||||
|
||||
<button className="button buttonSearch" onClick={handleSubmit}>
|
||||
<button type="button" className="button buttonSearch" onClick={handleSubmit}>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
@@ -73,7 +74,7 @@ export default function Equipos() {
|
||||
<option value="4">mmmmm</option>
|
||||
<option value="5">mmmmm</option>
|
||||
</select>
|
||||
<div className="containerButton">
|
||||
<div className="containerButton" style={{marginTop:"1rem"}}>
|
||||
<button className="button buttonSearch">Nuevo</button>
|
||||
<button className="button buttonSearch">Editar</button>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import styles from "./Page.module.css";
|
||||
|
||||
export default async function TableEquipos() {
|
||||
return (
|
||||
<section className="containerSection">
|
||||
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr style={{fontSize:"15px"}}>
|
||||
<th>Ubicación</th>
|
||||
<th>Nombre</th>
|
||||
<th>Plataforma</th>
|
||||
<th>Área</th>
|
||||
<th>Activo</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>pcnet1</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>mostrar todos</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>windows</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>mostrar Todo</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>
|
||||
<select style={{ minWidth: "50px" }}>
|
||||
<option style={{ minWidth: "50px" }}>si</option>
|
||||
</select>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* {machines.map((machine, index) => (
|
||||
<tr key={index}>
|
||||
<td>{machine.ubicacion}</td>
|
||||
<td>{machine.nombre}</td>
|
||||
<td>{machine.plataforma}</td>
|
||||
<td>{machine.area}</td>
|
||||
<td className={machine.disponible ? "disponible" : ""}>
|
||||
{machine.disponible ? "si" : "no"}
|
||||
</td>
|
||||
</tr>
|
||||
))} */}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
@@ -12,7 +12,7 @@ const EnviarMensaje = ({ titulo, opciones }: EnviarMensajeProps) => {
|
||||
const [mensaje, setMensaje] = useState("");
|
||||
const [customMsg, setCustomMsg] = useState("");
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
// Aquí puedes manejar el envío (guardar en estado global, enviar a backend, etc.)
|
||||
};
|
||||
@@ -51,6 +51,7 @@ const EnviarMensaje = ({ titulo, opciones }: EnviarMensajeProps) => {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<input type="checkbox" style={{minWidth:"20px", width:"20px",maxWidth:"30px"}}/>
|
||||
</div>
|
||||
|
||||
{/* Mensaje personalizado */}
|
||||
@@ -62,10 +63,12 @@ const EnviarMensaje = ({ titulo, opciones }: EnviarMensajeProps) => {
|
||||
onChange={(e) => setCustomMsg(e.target.value)}
|
||||
placeholder="Escribe tu mensaje..."
|
||||
/>
|
||||
<input type="checkbox" style={{minWidth:"20px", width:"20px",maxWidth:"30px"}}/>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Botón de enviar */}
|
||||
<button className="button buttonSearch" type="submit">
|
||||
<button className="button buttonSearch" type="submit" style={{marginTop:"1rem"}}>
|
||||
Mandar mensaje
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
@keyframes slideInLeft {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
opacity: 0.9;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideOutRight {
|
||||
0% {
|
||||
opacity: 0.9;
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.messageBox {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
padding: 0.5rem 1.25rem;
|
||||
border-radius: 0 4px 4px 0;
|
||||
font-weight: bold;
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
max-width: 500px;
|
||||
max-height: min-content;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.messageBox:not(.hidden) {
|
||||
animation: slideInLeft 0.5s ease forwards;
|
||||
}
|
||||
|
||||
.messageBox.hidden {
|
||||
animation: slideOutRight 0.5s ease forwards;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: #d1f7c4;
|
||||
color: #000000;
|
||||
border: 1px solid #a5d6a7;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: #ffcdd2;
|
||||
color: #000000;
|
||||
border: 1px solid #ef9a9a;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import "./AlertBox.css";
|
||||
import ClearParams from "../ClearParams/ClearParams";
|
||||
|
||||
interface AlertBoxProps {
|
||||
message: string | null;
|
||||
type: "error" | "success";
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
export default function AlertBox({
|
||||
message,
|
||||
type,
|
||||
duration = 6000,
|
||||
}: AlertBoxProps) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [text, setText] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (message) {
|
||||
setText(message);
|
||||
setVisible(true);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
setVisible(false);
|
||||
setTimeout(() => setText(""), 500);
|
||||
}, duration);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
}
|
||||
}, [message, duration]);
|
||||
|
||||
if (!text) return null;
|
||||
|
||||
return (
|
||||
<div className={`messageBox ${type} ${!visible ? "hidden" : ""}`}>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
interface ClearParamsProps {
|
||||
paramsToClear: string[];
|
||||
}
|
||||
|
||||
export default function ClearParams({ paramsToClear }: ClearParamsProps) {
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
const url = new URL(window.location.href);
|
||||
let changed = false;
|
||||
|
||||
paramsToClear.forEach((param) => {
|
||||
if (url.searchParams.has(param)) {
|
||||
url.searchParams.delete(param);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
window.history.replaceState({}, "", url.toString());
|
||||
}
|
||||
}, [paramsToClear]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { ReactNode, useCallback } from "react";
|
||||
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
||||
|
||||
interface FormHandlerProps {
|
||||
children: ReactNode;
|
||||
onSubmit: () => Promise<void>;
|
||||
}
|
||||
|
||||
export default function FormHandler({ children, onSubmit }: FormHandlerProps) {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const pathname = usePathname();
|
||||
|
||||
const updateParams = useCallback(
|
||||
(updates: Record<string, string | null>) => {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
|
||||
Object.entries(updates).forEach(([key, value]) => {
|
||||
if (value === null) params.delete(key);
|
||||
else params.set(key, value);
|
||||
});
|
||||
|
||||
router.push(`${pathname}?${params.toString()}`);
|
||||
},
|
||||
[searchParams, router, pathname]
|
||||
);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await onSubmit();
|
||||
} catch (err: any) {
|
||||
updateParams({ error: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
return <form onSubmit={handleSubmit}>{children}</form>;
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
'use client';
|
||||
|
||||
interface InformationProps {
|
||||
[key: string]: string | number | undefined;
|
||||
}
|
||||
|
||||
export default function Information(props: InformationProps) {
|
||||
// Obtenemos las entradas (key + value) y filtramos los que sean undefined
|
||||
const entries = Object.entries(props).filter(([_, value]) => value !== undefined);
|
||||
const entries = Object.entries(props).filter(
|
||||
([_, value]) => value !== undefined
|
||||
);
|
||||
|
||||
if (entries.length === 0) return null; // no mostrar nada si no hay datos
|
||||
if (entries.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="information">
|
||||
<ul>
|
||||
<ul className="informationList">
|
||||
{entries.map(([key, value]) => (
|
||||
<li key={key}>
|
||||
<b>{key}: </b>{value}
|
||||
<li key={key} className="informationItem">
|
||||
<span className="informationKey">{key}</span>
|
||||
<span className="informationValue">{value}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
//IO
|
||||
|
||||
@@ -19,11 +19,10 @@ function SearchUser(props: urlProp) {
|
||||
}
|
||||
}, [props.value]);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
if (numAcount) {
|
||||
params.delete("error");
|
||||
params.set("numAcount", `${numAcount}`);
|
||||
router.push(`${pathname}?${params.toString()}`);
|
||||
}
|
||||
@@ -57,3 +56,4 @@ function SearchUser(props: urlProp) {
|
||||
}
|
||||
|
||||
export default SearchUser;
|
||||
//IO
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export default function ShowError({ message }: { message: string }) {
|
||||
useEffect(() => {
|
||||
if (message) {
|
||||
toast.error(message);
|
||||
}
|
||||
}, [message]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,50 +1,49 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import { useState, ReactNode } from "react";
|
||||
import "./StepNavigator.css"
|
||||
import "./StepNavigator.css";
|
||||
|
||||
interface StepNavigatorProps {
|
||||
totalSteps: number;
|
||||
children: ReactNode[];
|
||||
onFinish?: () => void;
|
||||
totalSteps: number;
|
||||
children: ReactNode[];
|
||||
onFinish?: () => void;
|
||||
}
|
||||
|
||||
export default function StepNavigator({ totalSteps, children, onFinish }: StepNavigatorProps) {
|
||||
const [step, setStep] = useState(1);
|
||||
export default function StepNavigator({
|
||||
totalSteps,
|
||||
children,
|
||||
onFinish,
|
||||
}: StepNavigatorProps) {
|
||||
const [step, setStep] = useState(1);
|
||||
|
||||
const handleNext = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (step < totalSteps) setStep(step + 1);
|
||||
else if (onFinish) onFinish();
|
||||
};
|
||||
const handleNext = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (step < totalSteps) setStep(step + 1);
|
||||
else if (onFinish) onFinish();
|
||||
};
|
||||
|
||||
const handlePrev = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (step > 1) setStep(step - 1);
|
||||
};
|
||||
const handlePrev = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (step > 1) setStep(step - 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="stepNavigator">
|
||||
{children[step - 1]}
|
||||
return (
|
||||
<section className="stepNavigator">
|
||||
{children[step - 1]}
|
||||
|
||||
<div className="absoluteButton">
|
||||
{step > 1 && (
|
||||
<button
|
||||
onClick={handlePrev}
|
||||
className="button buttonSearch">
|
||||
Atrás
|
||||
</button>
|
||||
)}
|
||||
<div className="absoluteButton">
|
||||
{step > 1 && (
|
||||
<button onClick={handlePrev} className="button buttonSearch">
|
||||
Atrás
|
||||
</button>
|
||||
)}
|
||||
|
||||
{step < totalSteps &&
|
||||
<button
|
||||
onClick={handleNext}
|
||||
className="button buttonSearch"
|
||||
>
|
||||
Siguiente
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
{step < totalSteps && (
|
||||
<button onClick={handleNext} className="button buttonSearch">
|
||||
Siguiente
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import apiClient from "@/app/lib/apiClient";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function selectArea() {
|
||||
const [area, setArea] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchArea = async () => {
|
||||
const response = await apiClient.get("/area-ubicacion");
|
||||
setArea(response.data);
|
||||
};
|
||||
|
||||
fetchArea();
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<label className="label">Seleccione el área</label>
|
||||
<select>
|
||||
{area.map((area) => (
|
||||
<option>{area}</option>
|
||||
))}
|
||||
<option value="0">windows</option>
|
||||
<option value="1">ADOBE CREATIVE SUITE</option>
|
||||
<option value="2">mmmmm</option>
|
||||
<option value="3">mmmmm</option>
|
||||
<option value="4">mmmmm</option>
|
||||
<option value="5">mmmmm</option>
|
||||
</select>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
.tableContainer {
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
overflow-x: hidden;
|
||||
scrollbar-color: #2563eb #ffffff00;
|
||||
scroll-behavior: smooth;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import styles from "./table.module.css";
|
||||
|
||||
interface TableProps {
|
||||
headers: string[];
|
||||
data: Array<Record<string, any>>;
|
||||
}
|
||||
|
||||
export default function Table({ headers, data }: TableProps) {
|
||||
return (
|
||||
<div className={styles.tableContainer}>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{headers.map((header, index) => (
|
||||
<th key={index}>{header}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.length > 0 ? (
|
||||
data.map((row, rowIndex) => (
|
||||
<tr key={rowIndex}>
|
||||
{headers.map((header, colIndex) => (
|
||||
<td key={colIndex}>{row[header]}</td>
|
||||
))}
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={headers.length}>No hay registros</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import AlertBox from "@/app/Components/Global/AlertBox/AlertBox";
|
||||
import ClearParams from "@/app/Components/Global/ClearParams/ClearParams";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
export default function GlobalAlert() {
|
||||
const searchParams = useSearchParams();
|
||||
const [showSuccess, setShowSuccess] = useState<string | null>(null);
|
||||
const [showError, setShowError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const success = searchParams.get("success");
|
||||
const error = searchParams.get("error");
|
||||
|
||||
if (success) setShowSuccess(success);
|
||||
if (error) setShowError(error);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className="containerAlerts">
|
||||
{showError && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showError} type="error" />
|
||||
</>
|
||||
)}
|
||||
|
||||
{showSuccess && (
|
||||
<>
|
||||
<AlertBox key={Date.now()} message={showSuccess} type="success" />
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import Cookies from "js-cookie";
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { PostImpressions } from "@/app/lib/postImpressions";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
interface CostOption {
|
||||
value: number;
|
||||
@@ -27,24 +28,19 @@ function Impressions({ costs, numAcount }: ImpressionsProps) {
|
||||
};
|
||||
|
||||
const handlePayment = async () => {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
const params = new URLSearchParams();
|
||||
|
||||
const setError = (msg: string) => {
|
||||
params.set("error", msg);
|
||||
router.push(`${currentUrl}&${params.toString()}`);
|
||||
};
|
||||
|
||||
if (!numAcount) {
|
||||
return setError("busca de nuevo al estudiante");
|
||||
toast.error("busca de nuevo al estudiante");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pages) {
|
||||
return setError("Ingresa el numero de hojas a imprimir");
|
||||
toast.error("Ingresa el numero de hojas a imprimir");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cost) {
|
||||
return setError("Selecciona un costo");
|
||||
toast.error("Selecciona un costo");
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await PostImpressions({
|
||||
@@ -56,16 +52,16 @@ function Impressions({ costs, numAcount }: ImpressionsProps) {
|
||||
if (result.error) {
|
||||
if (result.error === "Token inválido") handleLogout();
|
||||
else {
|
||||
return setError(`Error: ${result.error}`);
|
||||
toast.error(result.error);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setPages("");
|
||||
setCost("");
|
||||
params.delete("error");
|
||||
params.set("success", "Impresion cobrada correctamente");
|
||||
router.push(`${currentUrl}&${params.toString()}`);
|
||||
toast.success("Impresion cobrada correctamente");
|
||||
router.refresh();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import SelectAreas from "../SelectAreas";
|
||||
|
||||
interface DatosEquipo {
|
||||
titulo: string;
|
||||
@@ -43,7 +44,7 @@ const caracteristicasPorEquipo: Record<string, string[]> = {
|
||||
// Agrega más equipos según necesites
|
||||
};
|
||||
|
||||
function ProgramSelector({ titulo, opcion }: DatosEquipo) {
|
||||
export default function ProgramSelector({ titulo, opcion }: DatosEquipo) {
|
||||
// Estado del equipo seleccionado
|
||||
const [equipoSeleccionado, setEquipoSeleccionado] = useState("");
|
||||
// Estado de los checkboxes (programas)
|
||||
@@ -108,5 +109,3 @@ function ProgramSelector({ titulo, opcion }: DatosEquipo) {
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProgramSelector;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
background-color: #f9f9f9;
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
.machineTable {
|
||||
|
||||
@@ -16,15 +16,15 @@ function QuitarSancion() {
|
||||
const [quitarSanciones, SetQuitarSanciones] = useState<quitarSanciones[]>([]);
|
||||
return (
|
||||
<section className="containerSection">
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableContainer} style={{margin:"1rem 0"}}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>id</th>
|
||||
<th>Nombre</th>
|
||||
<th>Motivo Sancion</th>
|
||||
<th>Motivo Sanción</th>
|
||||
<th>Duracion (semanas) </th>
|
||||
<th>Fecha Sancion</th>
|
||||
<th>Fecha Sanción</th>
|
||||
<th>Podria utilizar el servicio hasta</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -42,7 +42,7 @@ function QuitarSancion() {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button className="button buttonSearch">Quitar Sancion</button>
|
||||
<button className="button buttonSearch" style={{marginTop:"1rem"}}>Quitar Sanción</button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.groupInformation {
|
||||
display: flex;
|
||||
max-width: 500px;
|
||||
min-width: 40px;
|
||||
width: 100%;
|
||||
justify-content: end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.informationButton {
|
||||
text-align: center;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border: 1px solid #cfcfcf;
|
||||
background-color: #fff;
|
||||
max-width: 40px;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.informationButton:hover {
|
||||
border: 1px solid #cfcfcf;
|
||||
background-color: #cfcfcf;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import toast from "react-hot-toast";
|
||||
import { useState } from "react";
|
||||
import { PostReceipt } from "@/app/lib/postReceipt";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -28,28 +29,24 @@ function Receipt({ numAcount }: ReceiptsProps) {
|
||||
//restrict this month//
|
||||
|
||||
const handleSaveReceipt = async () => {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
const params = new URLSearchParams();
|
||||
|
||||
const setError = (msg: string) => {
|
||||
params.set("error", msg);
|
||||
router.push(`${currentUrl}&${params.toString()}`);
|
||||
};
|
||||
|
||||
if (!numAcount) {
|
||||
return setError("busca de nuevo al estudiante");
|
||||
toast.error("busca de nuevo al estudiante");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!folio) {
|
||||
return setError("Ingresa el folio del ticket");
|
||||
toast.error("Ingresa el folio del ticket");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!amount) {
|
||||
return setError("Coloca el monto a depositar");
|
||||
toast.error("Coloca el monto a depositar");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!date) {
|
||||
return setError("Coloca la fecha");
|
||||
toast.error("Coloca la fecha");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -64,11 +61,10 @@ function Receipt({ numAcount }: ReceiptsProps) {
|
||||
setAmount("");
|
||||
setDate("");
|
||||
|
||||
params.delete("error");
|
||||
params.set("success", "Recibo guardado");
|
||||
router.push(`${currentUrl}&${params.toString()}`);
|
||||
toast.success("Recibo guardado");
|
||||
router.refresh();
|
||||
} catch (err: any) {
|
||||
setError(String(err));
|
||||
toast.error(String(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,10 +107,7 @@ function Receipt({ numAcount }: ReceiptsProps) {
|
||||
if (value === "" || numericValue <= 1000) {
|
||||
setAmount(value);
|
||||
} else {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
const params = new URLSearchParams();
|
||||
params.set("error", "El monto no puede superar $1000.00");
|
||||
router.push(`${currentUrl}&${params.toString()}`);
|
||||
toast.error("El monto no puede superar $1000.00");
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
.tableContainer {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #cfcfcf;
|
||||
max-height: 430px;
|
||||
scrollbar-color: rgb(1, 92, 184) rgba(0, 0, 0, 0);
|
||||
background-color: #f9f9f9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.machineTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.machineTable th,
|
||||
.machineTable td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.machineTable th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: rgb(1, 92, 184);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.machineTable tr {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.disponible {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: green;
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ocupado {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.actions {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.resetButton {
|
||||
padding: 8px 16px;
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.resetButton:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import styles from "./Page.module.css";
|
||||
|
||||
interface reportes {
|
||||
Servicio: "Plotter";
|
||||
Total: "$1440.00";
|
||||
}
|
||||
|
||||
function PorRecibos() {
|
||||
const [reportes, SetQuitarSanciones] = useState<reportes[]>([]);
|
||||
return (
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Servicio</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{reportes.map((reporte, index) => (
|
||||
<tr key={index}>
|
||||
<td>{reporte.Servicio}</td>
|
||||
<td>{reporte.Total}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PorRecibos;
|
||||
@@ -0,0 +1,43 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import styles from "./Page.module.css";
|
||||
|
||||
interface servicios {
|
||||
folio_recibo: "100255";
|
||||
monto: "40.00";
|
||||
fecha_recibo: "10/10/2025";
|
||||
fecha_registro: "10/10/2025 05:32:20 pm";
|
||||
usuario: "modulo1";
|
||||
}
|
||||
|
||||
function PorServicios() {
|
||||
const [recibos, setRecibos] = useState<servicios[]>([]);
|
||||
return (
|
||||
<div className={styles.tableContainer}>
|
||||
<table className={styles.machineTable}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Folio Recibo</th>
|
||||
<th>Monto</th>
|
||||
<th>Fecha Recibo</th>
|
||||
<th>Fecha Registro</th>
|
||||
<th>Usuario</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{recibos.map((recibo, index) => (
|
||||
<tr key={index}>
|
||||
<td>{recibo.folio_recibo}</td>
|
||||
<td>{recibo.monto}</td>
|
||||
<td>{recibo.fecha_recibo}</td>
|
||||
<td>{recibo.fecha_registro}</td>
|
||||
<td>{recibo.usuario}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PorServicios;
|
||||
@@ -6,7 +6,7 @@ function SearchDateBetween() {
|
||||
const [startDate, setStartDate] = useState("");
|
||||
const [endDate, setEndDate] = useState("");
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
console.log("Fecha inicio:", startDate);
|
||||
console.log("Fecha fin:", endDate);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
export default function SearchEquipo() {
|
||||
return (
|
||||
<form action="">
|
||||
<form className="containerForm">
|
||||
<label>Numero de equipo</label>
|
||||
|
||||
<input type="text" />
|
||||
<button className="button buttonSearch">Buscar</button>
|
||||
<div className="groupInput">
|
||||
<input type="text" placeholder="Coloca el numero de equipo"/>
|
||||
<button className="button buttonSearch">Buscar</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
export default function SearchTable() {
|
||||
return (
|
||||
<form className="containerForm">
|
||||
{" "}
|
||||
<label>Numero de Mesa</label>
|
||||
<div className="groupInput">
|
||||
<input type="text" placeholder="Coloca el numero de Mesa" />
|
||||
<button className="buttonSearch button">Buscar</button>
|
||||
</div>
|
||||
<label>Numero de Mesa</label>
|
||||
<div className="groupInput">
|
||||
<input type="text" placeholder="Coloca el numero de Mesa" />
|
||||
<button className="buttonSearch button">Buscar</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
"use clien";
|
||||
import React, { useEffect, useState } from "react";
|
||||
"use client";
|
||||
import axios from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function SelectAreas() {
|
||||
const [areas, setAreas] = useState([]); // aquí guardaremos los datos del servidor
|
||||
const [areas, setAreas] = useState([]);
|
||||
const [selectedArea, setSelectedArea] = useState("");
|
||||
|
||||
// useEffect se ejecuta una vez al montar el componente
|
||||
useEffect(() => {
|
||||
fetch("https://venus.acatlan.unam.mx/asignacionTiempo_test/area-ubicacion")
|
||||
.then((response) => response.json())
|
||||
axios
|
||||
.get("https://venus.acatlan.unam.mx/asignacionTiempo_test/area-ubicacion")
|
||||
.then((data) => {
|
||||
console.log("Áreas obtenidas:", data);
|
||||
setAreas(data);
|
||||
setAreas(data.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error al traer las áreas:", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleChange = (e) => {
|
||||
setSelectedArea(e.target.value);
|
||||
console.log("Área seleccionada:", e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label htmlFor="areaSelect">Selecciona un área:</label>
|
||||
<select id="areaSelect" value={selectedArea} onChange={handleChange}>
|
||||
<option value="">-- Selecciona una opción --</option>
|
||||
{areas.map((area) => (
|
||||
|
||||
<select
|
||||
id="areaSelect"
|
||||
value={selectedArea}
|
||||
onChange={(e) => setSelectedArea(e.target.value)}
|
||||
>
|
||||
<option value="">-- Selecciona una opción --</option>
|
||||
{areas.map((area: any, index) => (
|
||||
<option key={index} value={area.area}>
|
||||
{area.area}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"use client";
|
||||
import apiClient from "@/app/lib/apiClient";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function ChangePassword() {
|
||||
@@ -6,10 +7,11 @@ export default function ChangePassword() {
|
||||
const [newPass, setNewPass] = useState("");
|
||||
const [confirmNewPass, setconfirmNewPass] = useState("");
|
||||
|
||||
const handleChangePass = (e: React.FormEvent) => {
|
||||
const handleChangePass = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault;
|
||||
const data = { pass, newPass, confirmNewPass };
|
||||
console.log(data);
|
||||
|
||||
await apiClient.post("/user/create", data);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,33 +3,41 @@ import { useState } from "react";
|
||||
import { loginUser } from "@/app/lib/login";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import toast from "react-hot-toast";
|
||||
import "./Login.css";
|
||||
import AlertBox from "../../Global/AlertBox/AlertBox";
|
||||
|
||||
function Login() {
|
||||
const [user, setUser] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [alert, setAlert] = useState("");
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!user) {
|
||||
toast.error("Coloca un usuario");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
toast.error("Coloca una contraseña");
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await loginUser(user, password);
|
||||
|
||||
if ("error" in data) {
|
||||
setError(data.error);
|
||||
toast.error(data.error);
|
||||
} else {
|
||||
const token = data.access_token;
|
||||
const payload = JSON.parse(atob(token.split(".")[1]));
|
||||
const usuario = payload.usuario;
|
||||
|
||||
document.cookie = `token=${token}; path=/; SameSite=Strict`;
|
||||
document.cookie = `usuario=${usuario}; path=/; SameSite=Strict`;
|
||||
document.cookie = `user=${usuario}; path=/; SameSite=Strict`;
|
||||
|
||||
setAlert("Inicio de sesión exitoso");
|
||||
toast.success("Inicio de sesión exitoso");
|
||||
router.push("/Impresiones");
|
||||
}
|
||||
};
|
||||
@@ -70,9 +78,6 @@ function Login() {
|
||||
>
|
||||
Iniciar sesión
|
||||
</button>
|
||||
|
||||
{error && <AlertBox message={error} type="error" />}
|
||||
{alert && <AlertBox message={alert} type="success" />}
|
||||
</form>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ function BarNavigation() {
|
||||
|
||||
<ul className={openMenu ? "active" : ""}>
|
||||
<li className={`subMenu ${openSubMenu === 0 ? "open" : ""}`}>
|
||||
<span onClick={() => toggleSubMenu(0)}>Inscripcion</span>
|
||||
<span onClick={() => toggleSubMenu(0)}>Inscripción</span>
|
||||
<ul className="containerLinks" onClick={toggleMenu}>
|
||||
<Link href="/Alta" className="links">
|
||||
<li>Alta</li>
|
||||
@@ -33,7 +33,7 @@ function BarNavigation() {
|
||||
<li>Agregar Tiempo</li>
|
||||
</Link>
|
||||
<Link href="/Inscripcion" className="links">
|
||||
<li>Inscripcion</li>
|
||||
<li>Inscripción</li>
|
||||
</Link>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -90,7 +90,7 @@ function BarNavigation() {
|
||||
</li>
|
||||
<li className="subMenu" onClick={toggleMenu}>
|
||||
<Link href="/QuitarSancion" className="links">
|
||||
<span>Quitar sancion</span>
|
||||
<span>Quitar sanción</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="subMenu" onClick={toggleMenu}>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import React from "react";
|
||||
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<Toaster
|
||||
toastOptions={{
|
||||
style: {
|
||||
padding: "16px",
|
||||
fontSize: "16px",
|
||||
maxWidth: "400px",
|
||||
},
|
||||
|
||||
error: {
|
||||
duration: 6000,
|
||||
style: {
|
||||
fontSize: "1.5rem",
|
||||
backgroundColor: "#fee2e2dd",
|
||||
color: "#000000ff",
|
||||
fontWeight: "600",
|
||||
padding: "1.5rem",
|
||||
},
|
||||
},
|
||||
|
||||
success: {
|
||||
duration: 6000,
|
||||
style: {
|
||||
fontSize: "1.5rem",
|
||||
backgroundColor: "#d1fae5dd",
|
||||
color: "#000000ff",
|
||||
fontWeight: "600",
|
||||
padding: "1.5rem",
|
||||
},
|
||||
},
|
||||
}}
|
||||
position="top-left"
|
||||
reverseOrder={false}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
+127
-53
@@ -23,7 +23,7 @@ body {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
min-height: 100dvh;
|
||||
width: 100dvw;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -88,11 +88,12 @@ footer p {
|
||||
.mainContainer {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-rows: 40px 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
@@ -172,35 +173,43 @@ select {
|
||||
border: 1px solid #cfcfcf;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
font-size: 2rem;
|
||||
font-size: 1.5rem;
|
||||
color: black;
|
||||
height: 4rem;
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
select:focus {
|
||||
background-color: #f9f9f9;
|
||||
outline:none;
|
||||
box-shadow: 0px 0px 8px 2px rgba(0, 62, 121, 0.5);
|
||||
outline: none;
|
||||
box-shadow: 0px 0px 8px 2px rgba(0, 62, 121, 0.5);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
input[type="checkbox"]{
|
||||
select:-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
option {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
min-width: 3rem;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 2rem;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 2rem;
|
||||
font-size: 1.5rem;
|
||||
padding: 1rem 1.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
height: 4rem;
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.groupInput {
|
||||
@@ -209,6 +218,8 @@ button {
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.button {
|
||||
@@ -277,26 +288,53 @@ a {
|
||||
.information {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #e5e7eb;
|
||||
background-color: #ffffff;
|
||||
border-radius: 4px;
|
||||
background-color: #f3f4f6;
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
margin-top: 10px;
|
||||
margin-top: 1rem;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
.information ul {
|
||||
padding: 1rem;
|
||||
.informationList {
|
||||
list-style: none;
|
||||
padding: 0 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.informationItem {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.informationItem:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.informationKey {
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.informationValue {
|
||||
color: #555;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
font-size: 3rem;
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
color:#bd8c01;
|
||||
color: #bd8c01;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -323,9 +361,9 @@ form {
|
||||
width: 100%;
|
||||
max-width: 750px;
|
||||
margin-top: 1rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 4px;
|
||||
background-color: #f9fafb;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.toggleGroup {
|
||||
@@ -352,11 +390,11 @@ form {
|
||||
}
|
||||
|
||||
.toggleButton.active {
|
||||
font-weight: 700;
|
||||
background-color: #e5e7eb;
|
||||
font-weight: 600;
|
||||
background-color: #ffffff;
|
||||
color: rgb(1, 92, 184);
|
||||
border-radius: 4px 4px 0 0;
|
||||
border-bottom: 1px solid rgb(1, 92, 184);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
p {
|
||||
@@ -365,28 +403,78 @@ p {
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 1rem;
|
||||
table-layout: auto;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 1.5rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
padding: 0.85rem 1.5rem;
|
||||
}
|
||||
|
||||
table th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: rgb(1, 92, 184);
|
||||
color: white;
|
||||
top: 0;
|
||||
color: #ffffff;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
border: none;
|
||||
}
|
||||
|
||||
table td {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
border: none;
|
||||
}
|
||||
|
||||
table tr {
|
||||
min-width: 400px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
transition: background-color 0.2s ease;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
thead tr {
|
||||
background-color: #2563eb;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
opacity: 1;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
tbody tr.hidden {
|
||||
transform: translateY(-10px);
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
table tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
table tr:hover {
|
||||
background-color: #cfcfcf;
|
||||
}
|
||||
|
||||
table th:first-child,
|
||||
table td:first-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
table th:last-child,
|
||||
table td:last-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.tableContainer {
|
||||
@@ -461,26 +549,6 @@ table tr {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img::after {
|
||||
background: linear-gradient(to right, #f9f9f993, rgba(128, 128, 128, 0));
|
||||
}
|
||||
|
||||
.img::before {
|
||||
display: flex;
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(to left, #f9f9f993, rgba(128, 128, 128, 0));
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
@@ -488,6 +556,11 @@ table tr {
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.containerSection {
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
@@ -541,6 +614,7 @@ table tr {
|
||||
|
||||
.containerSection {
|
||||
align-items: center;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.centerGrid {
|
||||
@@ -563,7 +637,6 @@ table tr {
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
@@ -580,6 +653,7 @@ table tr {
|
||||
|
||||
@media (max-width: 450px) {
|
||||
.title {
|
||||
text-align: center;
|
||||
max-width: 250px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
+6
-3
@@ -5,6 +5,7 @@ import Header from "./Components/layout/Header/Header";
|
||||
import Footer from "./Components/layout/Footer/Footer";
|
||||
|
||||
import "./globals.css";
|
||||
import { ToastProvider } from "./Components/layout/ToastProvider";
|
||||
|
||||
const poppins = Poppins({
|
||||
variable: "--font-poppins",
|
||||
@@ -27,9 +28,11 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="es">
|
||||
<body className={poppins.variable} suppressHydrationWarning>
|
||||
<Header />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
<ToastProvider>
|
||||
<Header />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</ToastProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
+42
-7
@@ -2,22 +2,57 @@ import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
import { envConfig } from "./config";
|
||||
|
||||
if (!envConfig.apiUrl) {
|
||||
throw new Error("API URL is not defined in envConfig");
|
||||
}
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL: envConfig.apiUrl,
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = Cookies.get("token");
|
||||
if (token) {
|
||||
if (config.headers && "set" in config.headers) {
|
||||
config.headers.set("Authorization", `Bearer ${token}`);
|
||||
apiClient.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = Cookies.get("token");
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
return config;
|
||||
});
|
||||
);
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
|
||||
if (status === 401) {
|
||||
Cookies.remove("token");
|
||||
Cookies.remove("user");
|
||||
|
||||
if (
|
||||
typeof window !== "undefined" &&
|
||||
!window.location.pathname.includes("/")
|
||||
) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
}
|
||||
|
||||
if (status === 403) {
|
||||
window.location.href = "/Impresiones";
|
||||
}
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default apiClient;
|
||||
//IO
|
||||
//Mike
|
||||
|
||||
@@ -6,6 +6,7 @@ export async function GetSanciones(numAcount: number) {
|
||||
const response = await axios.get(
|
||||
`${envConfig.apiUrl}/alumno-sancion/${numAcount}`
|
||||
);
|
||||
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
const msg =
|
||||
@@ -15,3 +16,4 @@ export async function GetSanciones(numAcount: number) {
|
||||
return { error: msg };
|
||||
}
|
||||
}
|
||||
//IO
|
||||
@@ -9,7 +9,7 @@ export async function PostReceipt(data: any) {
|
||||
error.response?.data?.message ||
|
||||
error.message ||
|
||||
"Error desconocido al crear recibo";
|
||||
return { error: msg };
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
//IO
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
interface Carrera {
|
||||
carrera: string;
|
||||
}
|
||||
|
||||
interface Student {
|
||||
id_cuenta: number;
|
||||
nombre: string;
|
||||
carrera: Carrera;
|
||||
credito: number;
|
||||
}
|
||||
Generated
+27
-1
@@ -13,6 +13,7 @@
|
||||
"next": "^15.5.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-hot-toast": "^2.6.0",
|
||||
"react-icons": "^5.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -748,7 +749,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/delayed-stream": {
|
||||
@@ -911,6 +911,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/goober": {
|
||||
"version": "2.1.16",
|
||||
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
|
||||
"integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==",
|
||||
"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",
|
||||
@@ -1139,6 +1148,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-icons": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
||||
|
||||
+2
-1
@@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -14,6 +14,7 @@
|
||||
"next": "^15.5.3",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-hot-toast": "^2.6.0",
|
||||
"react-icons": "^5.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Reference in New Issue
Block a user