diff --git a/frontend/src/pages/Retiros.jsx b/frontend/src/pages/Retiros.jsx index a933a3c..4c11db0 100644 --- a/frontend/src/pages/Retiros.jsx +++ b/frontend/src/pages/Retiros.jsx @@ -60,8 +60,12 @@ const COLS = [ { k: "detalle_retiro", t: "DETALLE DE RETIRO", al: "left", w: 400, vacio: true, elip: true }, { k: "fch_retiro", t: "FECHA DE RETIRO", al: "center", w: 130, fecha: true }, { k: "_info", t: "INFO", al: "center", w: 80, info: true }, + { k: "_quitar", t: "", al: "center", w: 56, quitar: true }, ]; +// Columnas que se suman en la fila TOTAL GENERAL +const COLS_SUMA = ["num_cuotas_pagadas","num_cuotas_vencidas","monto_venc_ant","monto_venc_cur","monto_dejo_pagar"]; + // Campos editables del popup INFO (los 9 manuales) const INFO_CAMPOS = [ { k: "n_asistencia", t: "N° ASISTENCIA", tipo: "number" }, @@ -112,6 +116,24 @@ export default function Retiros() { // Exportar const [exportando, setExportando] = useState(false); + // Quitar alumno (pasar a EN CURSO) — con confirmación + const [quitar, setQuitar] = useState(null); // fila a quitar (o null) + const [quitando, setQuitando] = useState(false); + + const confirmarQuitar = async () => { + if (!quitar || quitando) return; + setQuitando(true); + try { + await api.alumnoEstadoGuardar(quitar.matricula, ano, mes, "EN CURSO", [], "BUSCADOR_RETIROS"); + setFilas((prev) => prev.filter((f) => f.matricula !== quitar.matricula)); + setQuitar(null); + } catch (e) { + alert("No se pudo cambiar el estado: " + (e.message || "")); + } finally { + setQuitando(false); + } + }; + const abrirInfo = (f) => { setErrGuardar(null); setForm({ ...INFO_VACIO(), ...Object.fromEntries(INFO_CAMPOS.map((c) => [c.k, f[c.k] ?? ""])) }); @@ -209,7 +231,7 @@ export default function Retiros() { setExportando(true); try { const XLSX = await import("xlsx-js-style"); - const COLS_EXP = COLS.filter((c) => !c.info); // sin la columna INFO + const COLS_EXP = COLS.filter((c) => !c.info && !c.quitar); // sin INFO ni X const headerStyle = { font:{bold:true,color:{rgb:"FFFFFF"},sz:11}, fill:{fgColor:{rgb:"1E40AF"}}, alignment:{horizontal:"center",vertical:"center"} }; const manualStyle = { fill:{fgColor:{rgb:"EEF4F1"}} }; // celdas manuales verde suave @@ -257,23 +279,23 @@ export default function Retiros() { -
+
{msgTotal && ( - {msgTotal.txt} )} + + ); + } if (c.info) { return ( @@ -378,8 +416,9 @@ export default function Retiros() { color: rojo ? "#dc2626" : undefined, borderRight: "1px solid #e2e8f0", borderBottom: "1px solid #e2e8f0", - // Fondo verde suave para las celdas de columnas manuales - background: c.vacio ? "#eef4f1" : undefined, + // Fondo verde suave para columnas manuales; si la fila viene + // del buscador, dejar transparente para que se vea el azul. + background: f.origen_buscador ? "transparent" : (c.vacio ? "#eef4f1" : undefined), }}> {val} @@ -387,6 +426,31 @@ export default function Retiros() { })} ))} + {filasFiltradas.length > 0 && ( + + {COLS.map((c, ci) => { + if (ci === 0) return ( + + TOTAL GENERAL + + ); + if (COLS_SUMA.includes(c.k)) { + const tot = filasFiltradas.reduce((a, f) => a + (Number(f[c.k]) || 0), 0); + const val = c.money + ? "S/ " + tot.toLocaleString("es-PE", { maximumFractionDigits: 0 }) + : tot; + return ( + + {val} + + ); + } + return ; + })} + + )}
@@ -429,6 +493,43 @@ export default function Retiros() {
)} + {quitar && ( +
!quitando && setQuitar(null)} + style={{ position: "fixed", inset: 0, background: "rgba(15,23,42,.55)", + backdropFilter: "blur(2px)", display: "flex", alignItems: "center", + justifyContent: "center", zIndex: 1100, padding: 16 }}> +
e.stopPropagation()} + style={{ background: "#fff", borderRadius: 16, width: 440, maxWidth: "94vw", + overflow: "hidden", boxShadow: "0 24px 70px rgba(15,23,42,.35)", border: "1px solid #e2e8f0" }}> +
+
↩️
+
Pasar a EN CURSO
+
+
+ El alumno {quitar.alumno || quitar.matricula} pasará a EN CURSO y + dejará de aparecer en la tabla de Retiros de {MESES[mes-1]} {ano}. +
+
+ + +
+
+
+ )} + {info && (
setInfo(null)} style={{ position: "fixed", inset: 0, background: "rgba(15,23,42,.55)", @@ -698,7 +799,7 @@ function ModalBuscarRetiro({ ano, mes, onClose, onCambio }) { setGuardando(true); setMsg(null); try { // Guardar en paralelo (rápido). Cada uno actualiza (matrícula, año, mes). - await Promise.all(cambios.map((c) => api.alumnoEstadoGuardar(c.mat, ano, mes, c.estado, []))); + await Promise.all(cambios.map((c) => api.alumnoEstadoGuardar(c.mat, ano, mes, c.estado, [], "BUSCADOR_RETIROS"))); setOrig({ ...estados }); // ya quedó guardado if (onCambio) onCambio(); // recargar la tabla principal de Retiros setMsg({ ok: true, txt: `✅ ${cambios.length} cambio(s) guardado(s).` });