new function lock
This commit is contained in:
@@ -43,11 +43,16 @@ export default function AddTime({
|
||||
const month = day.getMonth();
|
||||
const today = day.getDate();
|
||||
|
||||
const minFecha = new Date(year, month, 1).toISOString().split("T")[0];
|
||||
let minMount = month
|
||||
if (!lock) {
|
||||
minMount = month - 1
|
||||
}
|
||||
|
||||
const minFecha = new Date(year, minMount, 1).toISOString().split("T")[0];
|
||||
const maxFecha = new Date(year, month, today).toISOString().split("T")[0];
|
||||
|
||||
const handleSaveReceipt = async () => {
|
||||
if (numAcount == null) {
|
||||
if (numAcount == null) {
|
||||
|
||||
Swal.fire({
|
||||
title: "Busca de nuevo al estudiante!",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
.buttonOpenLock {
|
||||
padding: 0.8rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 100px;
|
||||
background-color: #8cd32f;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ export default async function Page(props: {
|
||||
console.error("Error obteniendo costos:", error);
|
||||
}
|
||||
|
||||
|
||||
const getCostsByService = (id_servicio: number) => {
|
||||
return costos
|
||||
.filter((c) => c.id_servicio === id_servicio)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { envConfig } from "@/app/lib/config";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
@@ -9,9 +10,11 @@ interface Periodo {
|
||||
semestre: string;
|
||||
fecha_inicio_servicio: string;
|
||||
fecha_fin_servicio: string;
|
||||
activo: boolean;
|
||||
activo: {
|
||||
type: string;
|
||||
data: number[];
|
||||
};
|
||||
}
|
||||
|
||||
export default function PeriodoPage() {
|
||||
|
||||
const [periodos, setPeriodos] = useState<Periodo[]>([]);
|
||||
@@ -21,7 +24,7 @@ export default function PeriodoPage() {
|
||||
const [modoEdicion, setModoEdicion] = useState(false);
|
||||
const [idEditar, setIdEditar] = useState<number | null>(null);
|
||||
|
||||
const API = "http://localhost:5000/periodo";
|
||||
const API = `${envConfig.apiUrl}/periodo`;
|
||||
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
@@ -39,10 +42,8 @@ export default function PeriodoPage() {
|
||||
obtenerPeriodos();
|
||||
}, []);
|
||||
|
||||
// VALIDAR SEMESTRE
|
||||
const handleSemestreChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const valor = e.target.value;
|
||||
|
||||
|
||||
if (/^\d{0,6}$/.test(valor)) {
|
||||
setSemestre(valor);
|
||||
@@ -74,16 +75,6 @@ export default function PeriodoPage() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const eliminarPeriodo = async (id_periodo: number) => {
|
||||
try {
|
||||
await axios.delete(`${API}/${id_periodo}`, { headers });
|
||||
obtenerPeriodos();
|
||||
} catch (error) {
|
||||
console.error("Error al eliminar periodo", error);
|
||||
}
|
||||
};
|
||||
|
||||
const cargarPeriodo = (p: Periodo) => {
|
||||
setModoEdicion(true);
|
||||
setIdEditar(p.id_periodo);
|
||||
@@ -129,7 +120,6 @@ export default function PeriodoPage() {
|
||||
<div>
|
||||
<h1 style={{ color: "rgb(3, 1, 72)" }}>PERIODO ESCOLAR</h1>
|
||||
|
||||
{/* ================= FORMULARIO ================= */}
|
||||
<div style={{ marginBottom: "10px" }}>
|
||||
<input
|
||||
type="text"
|
||||
@@ -183,7 +173,6 @@ export default function PeriodoPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ================= TABLA ================= */}
|
||||
<div style={{ overflow: "auto", maxHeight: "350px" }}>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -203,7 +192,7 @@ export default function PeriodoPage() {
|
||||
<td>{p.semestre}</td>
|
||||
<td>{p.fecha_inicio_servicio}</td>
|
||||
<td>{p.fecha_fin_servicio}</td>
|
||||
<td>{p.activo === true ? "Sí" : "No"}</td>
|
||||
<td>{p.activo.data[0] === 1 ? "Sí" : "No"}</td>
|
||||
<td>
|
||||
<button
|
||||
className="button buttonSearch"
|
||||
@@ -211,13 +200,6 @@ export default function PeriodoPage() {
|
||||
>
|
||||
Modificar
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="button buttonCancel"
|
||||
onClick={() => eliminarPeriodo(p.id_periodo)}
|
||||
>
|
||||
Borrar
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { envConfig } from "../lib/config";
|
||||
import { getEquipoByCount } from "../lib/getEquipoByCount";
|
||||
|
||||
import SearchUser from "./Global/SearchUser/searchUser";
|
||||
import SearchEquipo from "./SearchEquipo";
|
||||
import axios from "axios";
|
||||
@@ -18,8 +17,9 @@ async function getEquipoId(idEquipo: number) {
|
||||
|
||||
const res = await axios.get(
|
||||
`${envConfig.apiUrl}/bitacora/equipo/${idEquipo}`,
|
||||
{ headers },
|
||||
{ headers }
|
||||
);
|
||||
|
||||
return res.data;
|
||||
} catch (error: any) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
@@ -27,7 +27,6 @@ async function getEquipoId(idEquipo: number) {
|
||||
error: error.response?.data?.message || "Error al consultar equipo",
|
||||
};
|
||||
}
|
||||
|
||||
return { error: "Error desconocido" };
|
||||
}
|
||||
}
|
||||
@@ -38,25 +37,31 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
const [modo, setModo] = useState<"Equipo" | "Cuenta" | null>("Cuenta");
|
||||
const [bitacora, setBitacora] = useState<any>(null);
|
||||
const [tiempoRestante, setTiempoRestante] = useState<string>("");
|
||||
const [minutos, setMinutos] = useState<number>();
|
||||
const [error, setError] = useState()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [modo, setModo] = useState<"Equipo" | "Cuenta">("Cuenta");
|
||||
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
const [bitacoraCuenta, setBitacoraCuenta] = useState<any>(null);
|
||||
const [bitacoraEquipo, setBitacoraEquipo] = useState<any>(null);
|
||||
|
||||
const [tiempoRestante, setTiempoRestante] = useState("");
|
||||
const [minutos, setMinutos] = useState<number>(0);
|
||||
|
||||
const [errorCuenta, setErrorCuenta] = useState<string | null>(null);
|
||||
const [errorEquipo, setErrorEquipo] = useState<string | null>(null);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const bitacora =
|
||||
modo === "Cuenta" ? bitacoraCuenta : bitacoraEquipo;
|
||||
|
||||
const fetchByCuenta = async (idCuenta: number) => {
|
||||
const result = await getEquipoByCount(idCuenta);
|
||||
|
||||
if (result?.error) {
|
||||
setError(result.error);
|
||||
setBitacora(null);
|
||||
setErrorCuenta(result.error);
|
||||
setBitacoraCuenta(null);
|
||||
} else {
|
||||
setBitacora(result);
|
||||
setErrorCuenta(null);
|
||||
setBitacoraCuenta(result);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,28 +69,27 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
const result = await getEquipoId(idEquipo);
|
||||
|
||||
if (result?.error) {
|
||||
setError(result.error);
|
||||
setBitacora(null);
|
||||
setErrorEquipo(result.error);
|
||||
setBitacoraEquipo(null);
|
||||
} else {
|
||||
setBitacora(result);
|
||||
setErrorEquipo(null);
|
||||
setBitacoraEquipo(result);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!numAcount) return;
|
||||
const idCuenta = parseInt(numAcount);
|
||||
if (isNaN(idCuenta)) return;
|
||||
if (modo !== "Cuenta" || !numAcount) return;
|
||||
|
||||
fetchByCuenta(idCuenta);
|
||||
}, [numAcount]);
|
||||
const idCuenta = parseInt(numAcount);
|
||||
if (!isNaN(idCuenta)) fetchByCuenta(idCuenta);
|
||||
}, [numAcount, modo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!machine) return;
|
||||
const idEquipo = parseInt(machine);
|
||||
if (isNaN(idEquipo)) return;
|
||||
if (modo !== "Equipo" || !machine) return;
|
||||
|
||||
fetchByEquipo(idEquipo);
|
||||
}, [machine]);
|
||||
const idEquipo = parseInt(machine);
|
||||
if (!isNaN(idEquipo)) fetchByEquipo(idEquipo);
|
||||
}, [machine, modo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!bitacora) return;
|
||||
@@ -93,19 +97,32 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
const entrada = new Date(bitacora.tiempo_entrada).getTime();
|
||||
const asignadoMs = bitacora.tiempo_asignado * 60 * 1000;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
const updateTimer = () => {
|
||||
const ahora = Date.now();
|
||||
const restante = entrada + asignadoMs - ahora;
|
||||
|
||||
if (restante <= 0) {
|
||||
setTiempoRestante("agotado");
|
||||
clearInterval(interval);
|
||||
} else {
|
||||
const minutos = Math.floor(restante / 60000);
|
||||
setMinutos(minutos + 1);
|
||||
const segundos = Math.floor((restante % 60000) / 1000);
|
||||
setTiempoRestante(`${minutos} minutos con ${segundos} segundos`);
|
||||
setMinutos(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
const minutosRestantes = Math.floor(restante / 60000);
|
||||
const segundos = Math.floor((restante % 60000) / 1000);
|
||||
|
||||
setMinutos(minutosRestantes+1);
|
||||
setTiempoRestante(
|
||||
`${minutosRestantes} minuto(s) con ${segundos} segundo(s)`
|
||||
);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
|
||||
const interval = setInterval(() => {
|
||||
const sigue = updateTimer();
|
||||
if (!sigue) clearInterval(interval);
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
@@ -113,29 +130,40 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
|
||||
const handleButton = async (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
setLoading(false)
|
||||
if (!bitacora) return;
|
||||
|
||||
await axios.patch(
|
||||
`${envConfig.apiUrl}/bitacora/cancelar/${bitacora.id_bitacora}`,
|
||||
{ tiempo_asignado: minutos },
|
||||
{ headers }
|
||||
);
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const token = Cookies.get("token");
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
|
||||
Swal.fire({
|
||||
title: "Tiempo cancelado Correctamente!",
|
||||
icon: "success",
|
||||
draggable: true,
|
||||
});
|
||||
await axios.patch(
|
||||
`${envConfig.apiUrl}/bitacora/cancelar/${bitacora.id_bitacora}`,
|
||||
{ tiempo_asignado: minutos },
|
||||
{ headers }
|
||||
);
|
||||
|
||||
if (modo === "Cuenta" && numAcount) {
|
||||
fetchByCuenta(parseInt(numAcount));
|
||||
Swal.fire({
|
||||
title: "Tiempo cancelado correctamente!",
|
||||
icon: "success",
|
||||
});
|
||||
|
||||
if (modo === "Cuenta" && numAcount) {
|
||||
fetchByCuenta(parseInt(numAcount));
|
||||
}
|
||||
|
||||
if (modo === "Equipo" && machine) {
|
||||
fetchByEquipo(parseInt(machine));
|
||||
}
|
||||
} catch (error) {
|
||||
Swal.fire({
|
||||
title: "Error al cancelar tiempo",
|
||||
icon: "error",
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
if (modo === "Equipo" && machine) {
|
||||
fetchByEquipo(parseInt(machine));
|
||||
}
|
||||
setLoading(true)
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -144,7 +172,6 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
<label className="radio-card">
|
||||
<input
|
||||
type="radio"
|
||||
name="modo"
|
||||
checked={modo === "Equipo"}
|
||||
onChange={() => setModo("Equipo")}
|
||||
/>
|
||||
@@ -155,7 +182,6 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
<label className="radio-card">
|
||||
<input
|
||||
type="radio"
|
||||
name="modo"
|
||||
checked={modo === "Cuenta"}
|
||||
onChange={() => setModo("Cuenta")}
|
||||
/>
|
||||
@@ -164,10 +190,19 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{modo === "Cuenta" && <SearchUser value={numAcount ?? null} />}
|
||||
{modo === "Equipo" && <SearchEquipo value={machine ?? null} />}
|
||||
{modo === "Cuenta" && (
|
||||
<>
|
||||
<SearchUser value={numAcount ?? null} />
|
||||
<h2>{errorCuenta}</h2>
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 style={{ marginTop: "10px" }}>{error}</h2>
|
||||
{modo === "Equipo" && (
|
||||
<>
|
||||
<SearchEquipo value={machine ?? null} />
|
||||
<h2>{errorEquipo}</h2>
|
||||
</>
|
||||
)}
|
||||
|
||||
{bitacora && tiempoRestante !== "agotado" && (
|
||||
<>
|
||||
@@ -182,7 +217,7 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
className="button buttonSearch"
|
||||
style={{ marginTop: "1rem" }}
|
||||
onClick={handleButton}
|
||||
disabled={loading || !minutos}
|
||||
disabled={loading || minutos === 0}
|
||||
>
|
||||
Cancelar tiempo
|
||||
</button>
|
||||
@@ -190,5 +225,4 @@ export default function CheckBoxEquipo({ numAcount, machine }: Props) {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
}
|
||||
@@ -47,7 +47,12 @@ export default function Inscripcion({
|
||||
const month = day.getMonth();
|
||||
const today = day.getDate();
|
||||
|
||||
const minFecha = new Date(year, month, 1).toISOString().split("T")[0];
|
||||
let minMount = month
|
||||
if(!lock){
|
||||
minMount = month-1
|
||||
}
|
||||
|
||||
const minFecha = new Date(year, minMount, 1).toISOString().split("T")[0];
|
||||
const maxFecha = new Date(year, month, today).toISOString().split("T")[0];
|
||||
//restrict this month//
|
||||
|
||||
|
||||
@@ -23,21 +23,21 @@
|
||||
background-color: #cfcfcf;
|
||||
}
|
||||
|
||||
.buttonLock{
|
||||
.buttonLock {
|
||||
padding: 0.8rem;
|
||||
position: absolute;
|
||||
right: 100px;
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
|
||||
.buttonOpenLock{
|
||||
.buttonOpenLock {
|
||||
padding: 0.8rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 100px;
|
||||
background-color: #8cd32f;
|
||||
}
|
||||
|
||||
.buttonOpenLock:hover{
|
||||
.buttonOpenLock:hover {
|
||||
background-color: #78b32c;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,12 @@ export default function Receipt({ numAcount }: ReceiptsProps) {
|
||||
const month = day.getMonth();
|
||||
const today = day.getDate();
|
||||
|
||||
const minFecha = new Date(year, month, 1).toISOString().split("T")[0];
|
||||
let minMount = month
|
||||
if(!lock){
|
||||
minMount = month-1
|
||||
}
|
||||
|
||||
const minFecha = new Date(year, minMount, 1).toISOString().split("T")[0];
|
||||
const maxFecha = new Date(year, month, today).toISOString().split("T")[0];
|
||||
//restrict this month//
|
||||
|
||||
|
||||
Reference in New Issue
Block a user