add time fixed i thing
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Selection from "@/app/Components/Selection/Selection";
|
||||
import { PostReceipt } from "@/app/lib/postReceipt";
|
||||
|
||||
import "./addTime.css";
|
||||
import SelectionCo from "@/app/Components/Selection/SelectionCo";
|
||||
|
||||
const PLATAFORMA_MAP: Record<string, number> = {
|
||||
WINDOWS: 1,
|
||||
MACINTOSH: 2,
|
||||
PROFESORES: 5,
|
||||
};
|
||||
|
||||
interface AddTimeProps {
|
||||
numAcount: number;
|
||||
plataformasInscritas: string[];
|
||||
}
|
||||
|
||||
export default function AddTime({
|
||||
numAcount,
|
||||
plataformasInscritas,
|
||||
}: AddTimeProps) {
|
||||
const router = useRouter();
|
||||
|
||||
// 🔹 selección plataforma
|
||||
const [plataformaSeleccionada, setPlataformaSeleccionada] =
|
||||
useState<string | null>(null);
|
||||
|
||||
// 🔹 datos del recibo
|
||||
const [folio, setFolio] = useState("");
|
||||
const [amount, setAmount] = useState("");
|
||||
const [date, setDate] = useState("");
|
||||
|
||||
// 🔹 restricción de fechas
|
||||
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];
|
||||
|
||||
// 🔹 lógica central (AQUÍ crecerá después)
|
||||
const handleSaveReceipt = async () => {
|
||||
if (!numAcount) {
|
||||
toast.error("Busca de nuevo al estudiante");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plataformaSeleccionada) {
|
||||
toast.error("Selecciona una plataforma");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!folio) {
|
||||
toast.error("Ingresa el folio del ticket");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!amount) {
|
||||
toast.error("Coloca el monto a depositar");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!date) {
|
||||
toast.error("Coloca la fecha");
|
||||
return;
|
||||
}
|
||||
|
||||
const id_plataforma = PLATAFORMA_MAP[plataformaSeleccionada];
|
||||
|
||||
try {
|
||||
// 1️⃣ Guardar recibo
|
||||
await PostReceipt({
|
||||
id_cuenta: numAcount,
|
||||
folio_recibo: folio,
|
||||
monto: Number(amount),
|
||||
fecha_recibo: date,
|
||||
});
|
||||
|
||||
// 🔜 2️⃣ AQUÍ luego:
|
||||
// await inscribirAlumno(...)
|
||||
// await agregarTiempo(...)
|
||||
// await marcarPago(...)
|
||||
|
||||
setFolio("");
|
||||
setAmount("");
|
||||
setDate("");
|
||||
|
||||
toast.success("Recibo guardado correctamente");
|
||||
router.refresh();
|
||||
} catch (err: any) {
|
||||
toast.error(err.message || "Error al guardar");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="addTime">
|
||||
<SelectionCo
|
||||
plataformasInscritas={plataformasInscritas}
|
||||
onSelect={setPlataformaSeleccionada}
|
||||
/>
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleSaveReceipt();
|
||||
}}
|
||||
>
|
||||
<div className="gap">
|
||||
<div className="groupInput">
|
||||
<label className="label">Ticket:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={folio}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
if (/^\d*$/.test(value) && value.length <= 7) {
|
||||
setFolio(value);
|
||||
}
|
||||
}}
|
||||
placeholder="Numero de ticket..."
|
||||
inputMode="numeric"
|
||||
/>
|
||||
</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 {
|
||||
toast.error("El monto no puede superar $1000.00");
|
||||
}
|
||||
}
|
||||
}}
|
||||
placeholder="Monto recibido..."
|
||||
inputMode="numeric"
|
||||
/>
|
||||
</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">
|
||||
<button className="button buttonSearch" type="submit">
|
||||
Guardar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,52 +1,76 @@
|
||||
import SearchUser from "@/app/Components/Global/SearchUser/searchUser";
|
||||
import Information from "@/app/Components/Global/Information/information";
|
||||
import Receipt from "@/app/Components/Receipt/Receipt";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
|
||||
import { GetRegisterStudent } from "@/app/lib/getRegisterStudent";
|
||||
import { envConfig } from "@/app/lib/config";
|
||||
|
||||
import "./addTime.css";
|
||||
import Selection from "@/app/Components/Selection/Selection";
|
||||
import ShowError from "@/app/Components/Global/ShowError";
|
||||
import { GetRegisterStudent } from "@/app/lib/getRegisterStudent";
|
||||
import AddTime from "./Addtime";
|
||||
|
||||
async function getInscripcion(idCuenta: number) {
|
||||
try {
|
||||
const res = await fetch(`${envConfig.apiUrl}/alumno-inscrito/${idCuenta}`, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error("No se pudo cargar inscripción");
|
||||
|
||||
return await res.json();
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Page(props: {
|
||||
searchParams?: Promise<{
|
||||
numAcount: string;
|
||||
}>;
|
||||
searchParams?: Promise<{ numAcount: string }>;
|
||||
}) {
|
||||
const params = await props.searchParams;
|
||||
const numAcount = params?.numAcount ? params.numAcount : null;
|
||||
const numAcount = params?.numAcount ?? null;
|
||||
|
||||
let student = null;
|
||||
let inscripcion: any[] = [];
|
||||
let errorMessage = "";
|
||||
|
||||
let student: any = null;
|
||||
if (numAcount) {
|
||||
const result = await GetRegisterStudent(parseInt(numAcount));
|
||||
const idCuenta = parseInt(numAcount);
|
||||
|
||||
if (result.error) {
|
||||
errorMessage = `${result.error}`;
|
||||
return;
|
||||
const result = await GetRegisterStudent(idCuenta);
|
||||
if (result?.error) {
|
||||
errorMessage = result.error;
|
||||
} else {
|
||||
student = result[0]?.alumno;
|
||||
inscripcion = await getInscripcion(idCuenta);
|
||||
}
|
||||
}
|
||||
|
||||
const plataformasInscritas = inscripcion.map(
|
||||
(ins) => ins.plataforma?.nombre
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="containerSection">
|
||||
{errorMessage && <ShowError key={Date.now()} message={errorMessage} />}
|
||||
{errorMessage && <ShowError message={errorMessage} />}
|
||||
|
||||
<h2 className="title"> AGREGAR TIEMPO </h2>
|
||||
<h2 className="title">AGREGAR TIEMPO</h2>
|
||||
|
||||
<SearchUser value={numAcount} />
|
||||
|
||||
{student && (
|
||||
<>
|
||||
<Information NoCuenta={student.id_cuenta} Nombre={student.nombre} />
|
||||
<Information
|
||||
NoCuenta={student.id_cuenta}
|
||||
Nombre={student.nombre}
|
||||
/>
|
||||
|
||||
<div className="addTime">
|
||||
<Selection />
|
||||
<Receipt numAcount={student.id_cuenta} />
|
||||
</div>
|
||||
<AddTime
|
||||
numAcount={student.id_cuenta}
|
||||
plataformasInscritas={plataformasInscritas}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
//IO
|
||||
//IO
|
||||
@@ -0,0 +1,74 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import "./Selection.css";
|
||||
|
||||
function SelectionCo({
|
||||
plataformasInscritas = [],
|
||||
onSelect,
|
||||
}: {
|
||||
plataformasInscritas: string[];
|
||||
onSelect: (plataforma: string | null) => void;
|
||||
}) {
|
||||
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: "PROFESORES",
|
||||
img: "https://cdn-icons-png.flaticon.com/512/3135/3135715.png",
|
||||
},
|
||||
];
|
||||
|
||||
// ✅ SOLO las inscritas
|
||||
const opcionesInscritas = options.filter((option) =>
|
||||
plataformasInscritas.includes(option.name),
|
||||
);
|
||||
|
||||
const handleSelect = (optionName: string) => {
|
||||
const value = selected === optionName ? null : optionName;
|
||||
setSelected(value);
|
||||
onSelect(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="selection">
|
||||
{opcionesInscritas.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>
|
||||
))}
|
||||
|
||||
{opcionesInscritas.length === 0 && (
|
||||
<p style={{ opacity: 0.6 }}>
|
||||
El alumno no está inscrito en ninguna plataforma
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectionCo;
|
||||
Reference in New Issue
Block a user