first commit

This commit is contained in:
2025-09-02 19:50:17 -04:00
parent fe4a89f81e
commit 685c92a82f
37 changed files with 1460 additions and 301 deletions
@@ -0,0 +1,145 @@
.barNavigation {
text-align: center;
background-color: rgb(1, 92, 184);
padding: 0 20px;
}
.barNavigation ul {
display: flex;
justify-content: space-around;
width: 100%;
}
.barNavigation li {
transition: all 0.3s ease;
cursor: pointer;
color: white;
font-weight: bold;
}
.barNavigation li:hover {
background-color: #f9f9f9;
color: rgba(0, 61, 121, 1);
}
.barNavigation ul.active {
display: flex;
width: 100%;
}
.menuToggle {
display: none;
flex-direction: column;
align-items: center;
gap: 4px;
cursor: pointer;
padding: 10px;
margin-right: 10px;
}
.menuToggle div {
width: 25px;
height: 3px;
background-color: white;
border-radius: 4px;
}
.subMenu {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
gap: 10px;
position: relative;
z-index: 1;
border-radius: 4px 4px 0 0;
padding: 15px 0;
}
.subMenu ul {
display: none;
position: absolute;
flex-direction: column;
top: 100%;
width: 100%;
background-color: rgba(0, 61, 121, 1);
transition: max-height 0.3s ease, opacity 0.3s ease;
}
.subMenu.open ul {
display: flex;
color: rgba(0, 61, 121, 1);
}
.subMenu ul:hover {
color: #5b8cc9;
}
.subMenu:hover ul {
display: flex;
}
.subMenu li {
padding: 10px 0;
}
.containerLinks{
padding: 0 !important;
}
.links {
color: white;
width: 100%;
}
@media (max-width: 800px) {
.menuToggle {
display: flex;
position: relative;
align-items: end;
transition: transform 0.3s ease;
}
.menuToggle.center {
align-items: center;
transform: translateX(-50%);
left: 50%;
}
.barNavigation {
font-size: 15px;
}
.barNavigation ul {
position: absolute;
background-color: rgb(1, 92, 184);
flex-direction: column;
gap: 10px;
padding: 10px 0;
align-items: center;
display: none;
z-index: 1;
height: auto;
}
.barNavigation {
padding: 0;
}
.barNavigation li:hover {
background-color: rgba(0, 61, 121, 1);
color: white;
border-radius: 0;
border: none;
}
.subMenu ul {
width: 90%;
border-radius: 4px;
position: relative;
background-color: rgba(0, 61, 121, 1);
}
}
@@ -0,0 +1,92 @@
'use client';
import { useState } from "react";
import './BarNavigation.css';
import Link from "next/link";
function BarNavigation() {
const [openMenu, setOpenMenu] = useState(false);
const [openSubMenu, setOpenSubMenu] = useState<number | null>(null);
const toggleMenu = () => setOpenMenu(!openMenu);
const toggleSubMenu = (index: number) => {
setOpenSubMenu(openSubMenu === index ? null : index);
};
return (
<nav className="barNavigation">
<div
className={`menuToggle ${openMenu ? 'center' : ''}`}
onClick={toggleMenu}>
<div></div>
<div></div>
<div></div>
</div>
<ul className={openMenu ? "active" : ""}>
<li className={`subMenu ${openSubMenu === 0 ? "open" : ""}`} onClick={() => toggleSubMenu(0)}>
Inscripciones
<ul className="containerLinks">
<Link href="/Alta" className="links">
<li >Alta</li>
</Link>
<Link href="/AgregarTiempo" className="links">
<li >Agregar Tiempo</li>
</Link>
<Link href="/Inscripciones" className="links">
<li>Inscripciones</li>
</Link>
</ul>
</li>
<li className={`subMenu ${openSubMenu === 1 ? "open" : ""}`} onClick={() => toggleSubMenu(1)}>
Servicios
<ul>
<Link href="/Impresiones" className="links">
<li >
Impresiones y Ploteo
</li>
</Link>
<Link href="/AsignacionMesas" className="links">
<li>
Asignacion de Mesas
</li>
</Link>
<Link href="/AsignacionEquipo" className="links">
<li>
Asignacion de Equipos
</li>
</Link>
<Link href="/Monitor" className="links">
<li>
Monitor
</li>
</Link>
</ul>
</li>
<li className={`subMenu ${openSubMenu === 2 ? "open" : ""}`} onClick={() => toggleSubMenu(2)}>
Equipo
<ul >
<Link href="/InformacionEquipo" className="links">
<li>Informacion de Equipos</li>
</Link>
<Link href="/ActivosMantenimiento" className="links">
<li >Activos y en Mantenimiento</li>
</Link>
<Link href="/Mensajes" className="links">
<li>Mensajes</li>
</Link>
<Link href="/Programas" className="links">
<li>Programas</li>
</Link>
</ul>
</li>
<li className={`subMenu ${openSubMenu === 2 ? "open" : ""}`}>Reportes</li>
<li className={`subMenu ${openSubMenu === 2 ? "open" : ""}`}>Quitar sancion</li>
<li className={`subMenu ${openSubMenu === 2 ? "open" : ""}`}>Cambiar contraseña</li>
</ul>
</nav>
);
}
export default BarNavigation;
+12
View File
@@ -0,0 +1,12 @@
function Footer() {
return (
<footer>
Hecho en México. Todos los derechos reservados 2025.
Esta página puede ser reproducida con fines no lucrativos, siempre y cuando no se mutile, se cite la fuente completa y su dirección electrónica. De otra forma, requiere permiso previo por escrito de la institución.
</footer>
)
}
export default Footer;
//IO
+34
View File
@@ -0,0 +1,34 @@
.logo {
position: relative;
filter: invert(1);
z-index: 3;
}
.cedetecContainer {
position: absolute;
top: 0;
right: 0;
width: 300px;
height: 100%;
z-index: -1;
}
.cedetecContainer::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(to right, #f9f9f9, rgba(128, 128, 128, 0));
}
.yellowPart {
position: absolute;
content: "";
top: 0;
left: -20px;
width: 30%;
height: 50%;
min-width: 300px;
background-color: #d59f0f;
transform: skew(-45deg);
z-index: 0;
}
+31
View File
@@ -0,0 +1,31 @@
import Image from "next/image";
import "./Header.css";
import Link from "next/link";
function Header() {
return (
<header>
<Link href="https://www.unam.mx/" className="center">
<Image
className="logo"
src="/logo_fes.png"
alt="Logo FES"
width={200}
height={50}
/>
</Link>
<div className="yellowPart"></div>
<div className="cedetecContainer">
<Image
src="/cedetec.jpg"
alt="Image of CEDETEC"
width={300}
height={71}
/>
</div>
</header>
);
}
export default Header;
//IO
@@ -0,0 +1,6 @@
.impressions {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
}
+103
View File
@@ -0,0 +1,103 @@
'use client'
import { useState } from "react";
import './Impressions.css'
function Impressions() {
const [pages, setPages] = useState('');
const [error, setError] = useState('');
const [alert, setAlert] = useState('');
const [showError, setShowError] = useState(false);
const [showAlert, setShowAlert] = useState(false);
// const handlePayment = async () => {
// setAlert('')
// setError('')
// if (!studentData) {
// setError('Error busca denuevo al estudiante');
// return;
// }
// if (!pages) {
// setError('Ingresa el numero de hojas a imprimir')
// return;
// }
// try {
// await axios.post(
// `${url}/impressions`,
// {
// numAccount: numAccount,
// pages: parseInt(pages),
// cost: parseInt(pages),
// },
// { headers }
// );
// handleSearch()
// setAlert('Cobro realizado correctamente');
// setPages('')
// } catch (error) {
// const errorMessage = error.response?.data?.error || 'No se encontró el estudiante';
// if (errorMessage === 'Token inválido') {
// handleLogout();
// }
// setError(errorMessage);
// }
// };
return (
<form
onSubmit={(e) => {
e.preventDefault();
// handlePayment();
}}>
<div className='impressions'>
<div className='groupLabel'>
<label className='label'>Costo: $1.00</label>
</div>
<div className='groupInput'>
<label className='label'>Hojas:</label>
<input
type='text'
value={pages}
onChange={(e) => {
const value = e.target.value;
if (/^\d*$/.test(value)) {
setPages(value);
}
}}
placeholder='Numero de hojas a imprimir...'
inputMode='numeric'
pattern='[0-9]*'
/>
</div>
<div className='groupLabel'>
<label className='label'>Total: {pages && `$${pages}.00`}</label>
</div>
<div className='containerButton'>
<button
className='button buttonCharge'
type='submit'>
Cobrar
</button>
{error &&
<div className={`messageBox error ${!showError ? 'hidden' : ''}`}>
{error}
</div>
}
{alert &&
<div className={`messageBox success ${!showAlert ? 'hidden' : ''}`}>
{alert}
</div>
}
</div>
</div>
</form>
)
}
export default Impressions
+19
View File
@@ -0,0 +1,19 @@
.login {
width: 300px;
}
.relative {
position: relative;
}
.eyeClose,
.eyeOpen {
position: absolute;
right: 10px;
bottom: -1px;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-size: cover;
cursor: pointer;
}
+59
View File
@@ -0,0 +1,59 @@
import "./Login.css";
function Login() {
return (
<section className='containerSection'>
<form
className='login'
//onSubmit={(e) => {
//e.preventDefault();
//handleLogin();
//</section>}}
>
<h2 className='textHeader'>Inicio de sesión</h2>
<div className='containerInput'>
<label className='label'>Usuario</label>
<input
type='text'
//value={user}
//onChange={(e) => setUser(e.target.value)}
placeholder='Coloca tu usuario...'
/>
</div>
<div className='containerInput relative'>
<label className='label'>Contraseña</label>
<input
//type={showPassword ? 'text' : 'password'}
//value={password}
//onChange={(e) => setPassword(e.target.value)}
placeholder='Coloca tu contraseña...'
/>
<span
//onClick={() => setShowPassword(!showPassword)}
//className={showPassword ? 'eyeOpen' : 'eyeClose'}
/>
</div>
<button
className='button buttonSearch'
style={{ maxWidth: '100%', width: '100%' }}
type='submit'
>Iniciar sesión
</button>
</form>
{/*message &&
<div
className={`messageBox ${message.includes('exitoso') ? 'success' : 'error'}`}
style={{ marginTop: '10px' }}
>
{message}
</div>
*/}
</section>
);
}
export default Login;
View File
+128
View File
@@ -0,0 +1,128 @@
'use client'
import { useEffect, useState } from "react";
import "./Receipt.css"
import Selection from "../Selection/Selection";
function Receipt() {
const [folio, setFolio] = useState('');
const [amount, setAmount] = useState('');
const [date, setDate] = useState('');
const [error, setError] = useState('');
const [alert, setAlert] = useState('');
const [showError, setShowError] = useState(false);
const [showAlert, setShowAlert] = useState(false);
//restrict this month//
const day = new Date();
const year = day.getFullYear();
const month = day.getMonth();
const today = day.getDate();
const minFecha = new Date(year, month, 1).toISOString().split('T')[0];
const maxFecha = new Date(year, month, today).toISOString().split('T')[0];
//restrict this month//
//fadeOut alert and error
useEffect(() => {
if (alert) {
setShowAlert(true);
const timeout = setTimeout(() => {
setShowAlert(false);
setTimeout(() => setAlert(''), 500);
}, 6000);
return () => clearTimeout(timeout);
}
}, [alert]);
useEffect(() => {
if (error) {
setShowError(true);
const timeout = setTimeout(() => {
setShowError(false);
setTimeout(() => setError(''), 500);
}, 6000);
return () => clearTimeout(timeout);
}
}, [error]);
//fadeOut alert and error//
return (
<form
onSubmit={(e) => {
e.preventDefault();
// handleSaveReceipt();
}}
>
<div className='groupInput'>
<label className='label'>Folio:</label>
<input
type='text'
value={folio}
onChange={(e) => {
const value = e.target.value;
if (/^\d*$/.test(value)) {
setFolio(value);
}
}}
placeholder='Numero de folio...'
inputMode='numeric'
pattern='[0-9]*'
/>
</div>
<div className='groupInput'>
<label className='label'>Monto:</label>
<input
type='text'
value={amount}
onChange={(e) => {
const value = e.target.value;
if (/^\d*\.?\d*$/.test(value)) {
const numericValue = parseFloat(value);
if (value === '' || (numericValue <= 1000)) {
setAmount(value);
} else {
setAlert('')
setError('El monto no puede superar $1000.00')
}
}
}}
placeholder='Monto recibido...'
inputMode='numeric'
pattern="^\d*\.?\d+$"
/>
</div>
<div className='groupInput'>
<label className='label'>Fecha de Pago:</label>
<input
type='date'
value={date}
onChange={(e) => setDate(e.target.value)}
min={minFecha}
max={maxFecha}
/>
</div>
<div className='containerButton'>
{error &&
<div className={`messageBox error ${!showError ? 'hidden' : ''}`}>
{error}
</div>
}
{alert &&
<div className={`messageBox success ${!showAlert ? 'hidden' : ''}`}>
{alert}
</div>
}
</div>
</form>
)
}
export default Receipt
//IO
+42
View File
@@ -0,0 +1,42 @@
'use client'
import { useState } from "react";
function SearchUser() {
const [numAccount, setNumAccount] = useState('');
return (
<>
<form>
<label className='label'>No.Cuenta</label>
<div className='groupInput'>
<input
type='text'
value={numAccount}
onChange={(e) => {
const value = e.target.value;
if (/^\d*$/.test(value) && value.length <= 9) {
setNumAccount(value);
}
}}
placeholder='Coloca un número de cuenta...'
inputMode='numeric'
pattern='[0-9]*'
/>
<button
className='button buttonSearch'
type='submit'
>Buscar
</button>
</div>
</form>
<div className='information'>
<label><b>No.Cuenta: </b>id_cuenta</label>
<label><b>Nombre: </b>nombre</label>
<label><b>Carrera: </b>carrera</label>
<label><b>Crédito: </b>credito</label>
</div>
</>
)
}
export default SearchUser
+41
View File
@@ -0,0 +1,41 @@
.selection {
display: flex;
gap: 1rem;
justify-content: center;
align-items: center;
margin: 10px;
flex-wrap: wrap;
}
.selectionItem {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.buttonSelection {
width: 50px;
height: 50px;
border-radius: 100%;
border: 2px solid #5b8cc9;
background-color: #f0f0f0;
transition: all 0.3s ease;
}
.buttonSelection:hover {
transform: scale(1.1);
background-color: #d0e1ff;
}
.buttonSelection.active {
background-color: #5b8cc9;
box-shadow: 0 0 10px #5b8cc9;
}
.buttonLabel {
margin-top: 8px;
font-weight: bold;
color: #333;
text-align: center;
}
+57
View File
@@ -0,0 +1,57 @@
'use client';
import { useState } from "react";
import "./Selection.css";
function Selection() {
const [selected, setSelected] = useState<string | null>(null);
const options = [
{
name: "WINDOWS",
img: "https://images.icon-icons.com/2235/PNG/512/windows_os_logo_icon_134678.png",
},
{
name: "MACINTOSH",
img: "https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg",
},
{
name: "LINUX",
img: "https://upload.wikimedia.org/wikipedia/commons/3/35/Tux.svg",
},
{
name: "PROFESORES",
img: "https://cdn-icons-png.flaticon.com/512/3135/3135715.png",
},
];
const handleSelect = (optionName: string) => {
setSelected(selected === optionName ? null : optionName);
};
return (
<section className="selection">
{options.map((option, index) => (
<div
key={index}
className="selectionItem"
onClick={() => handleSelect(option.name)}
>
<button
className={`buttonSelection ${selected === option.name ? "active" : ""}`}
>
<img
src={option.img}
alt={option.name.toLowerCase()}
height={30}
width={30}
/>
</button>
<span className="buttonLabel">{option.name}</span>
</div>
))}
</section>
);
}
export default Selection;
@@ -0,0 +1,10 @@
.receipt {
max-width: 600px;
margin-top: 1rem;
border: 1px solid #e5e7eb;
border-radius: 4px;
background-color: #f9fafb;
padding: 1rem;
display: flex;
flex-direction: column;
}
@@ -0,0 +1,48 @@
'use client'
import { useState, ReactNode } from "react";
import "./StepNavigator.css"
interface StepNavigatorProps {
totalSteps: number;
children: ReactNode[];
onFinish?: () => void;
}
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 handlePrev = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
if (step > 1) setStep(step - 1);
};
return (
<div className="receipt">
{children[step - 1]}
<div className="buttonContainer">
{step > 1 && (
<button
onClick={handlePrev}
className="button buttonSearch">
Atrás
</button>
)}
<button
onClick={handleNext}
className="button buttonSearch"
>
{step === totalSteps ? "Inscribir" : "Siguiente"}
</button>
</div>
</div>
);
}