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}
)}
@@ -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}.
+
+
+ setQuitar(null)} disabled={quitando}
+ style={{ padding: "9px 18px", borderRadius: 9, border: "1px solid #cbd5e1",
+ background: "#fff", color: "#475569", fontWeight: 600, fontSize: 13.5,
+ cursor: quitando ? "default" : "pointer", opacity: quitando ? .6 : 1 }}>
+ Cancelar
+
+
+ {quitando ? "Guardando…" : "Sí, pasar a EN CURSO"}
+
+
+
+
+ )}
+
{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).` });