diff --git a/frontend/src/pages/Ocupabilidad.jsx b/frontend/src/pages/Ocupabilidad.jsx index ff3d98a..a31b8b3 100644 --- a/frontend/src/pages/Ocupabilidad.jsx +++ b/frontend/src/pages/Ocupabilidad.jsx @@ -3,14 +3,14 @@ import { useState, useEffect, useMemo } from "react"; import { api } from "../lib/api"; import { Loader, ErrorBox, ProgressBar, Filters, Select } from "../components/UI"; import { useColumnasAjustables } from "../lib/useColumnasAjustables"; +import Modal from "../components/Modal"; const MESES = ["ENERO","FEBRERO","MARZO","ABRIL","MAYO","JUNIO","JULIO","AGOSTO","SEPTIEMBRE","OCTUBRE","NOVIEMBRE","DICIEMBRE"]; const ANOS = [2024, 2025, 2026]; const SEDES = ["TODOS", "LIMA", "AREQUIPA", "PIURA", "TRUJILLO"]; const PROGRAMAS = ["TODOS", "SEMINARIOS", "OTROS", "TEAC", "TERC"]; -const COLS = ["PROGRAMA","FECHA INICIO","DÍAS PARA INICIO","TOTAL INSCRITOS","RETIRADOS","INSCRITOS EN CURSO","META INSCRITOS","AVANCE INSCRITOS","INSCRITOS MES","INSCRITOS P.C","INSCRITOS REFRIPERU","INSCRITOS CONTINUIDAD"]; - +const COLS = ["PROGRAMA","FECHA INICIO","DÍAS PARA INICIO","TOTAL INSCRITOS","RETIRADOS","INSCRITOS EN CURSO","META INSCRITOS","AVANCE INSCRITOS","INSCRITOS MES","INSCRITOS P.C","INSCRITOS REFRIPERU","INSCRITOS CONTINUIDAD","OPC."]; function toNum(v) { const n = parseFloat(String(v).replace("%","").trim()); return isNaN(n) ? 0 : n; } export default function Ocupabilidad() { @@ -23,7 +23,8 @@ export default function Ocupabilidad() { const [datos, setDatos] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const cols = useColumnasAjustables([280, 110, 120, 110, 100, 120, 110, 120, 100, 100, 130, 140]); + const [modalCurso, setModalCurso] = useState(null); + const cols = useColumnasAjustables([280, 110, 120, 110, 100, 120, 110, 120, 100, 100, 130, 140, 80]); useEffect(() => { let activo = true; @@ -170,6 +171,14 @@ export default function Ocupabilidad() { {cel(parseInt(d.Inscritos_PC)||0)} {cel(parseInt(d.Descuento)||0)} {cel(parseInt(d.Inscritos_Continuidad)||0)} + + {esInicio ? "-" : ( + + )} + ); })} @@ -183,12 +192,110 @@ export default function Ocupabilidad() { {totales.meta} 0 ? totales.total/totales.meta*100 : 0} /> {totales.mes}{totales.pc}{totales.refri}{totales.cont} + — )} } + + {modalCurso && ( + setModalCurso(null)} + /> + )} ); } + +function ModalAlumnosCurso({ numIndice, programa, onClose }) { + const [alumnos, setAlumnos] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + let activo = true; + setLoading(true); + api.ocupabilidadAlumnos(numIndice) + .then((res) => { if (activo) { setAlumnos(res.alumnos || []); setLoading(false); } }) + .catch(() => { if (activo) { setAlumnos([]); setLoading(false); } }); + return () => { activo = false; }; + }, [numIndice]); + + const colorEstado = (e) => { + if (e === "ALU") return { bg:"#ecfdf5", fg:"#047857", bd:"#a7f3d0" }; + if (e === "PRE") return { bg:"#eff6ff", fg:"#1e40af", bd:"#bfdbfe" }; + if (e === "RET") return { bg:"#fef2f2", fg:"#b91c1c", bd:"#fecaca" }; + return { bg:"#f1f5f9", fg:"#475569", bd:"#e2e8f0" }; + }; + + const conteo = useMemo(() => { + const c = {}; + alumnos.forEach((a) => { c[a.estado] = (c[a.estado] || 0) + 1; }); + return c; + }, [alumnos]); + + return ( + + {loading ? : + alumnos.length === 0 ?
Sin alumnos.
: + <> +
+ + 👥 Total: {alumnos.length} alumno{alumnos.length!==1?"s":""} + + {["ALU","PRE","RET"].map((e)=> conteo[e] ? ( + + {e}: {conteo[e]} + + ) : null)} +
+
+ + + + + + + + + {alumnos.map((a, i) => { + const c = colorEstado(a.estado); + const tieneAnt = a.curso_anterior && a.curso_anterior !== "-"; + const cAnt = colorEstado(a.estado_anterior); + return ( + + + + + + + ); + })} + +
ALUMNOESTADOCURSO ANTERIOR (TEAC/TERC)ESTADO ANTERIOR
{a.alumno} + + {a.estado} + + + {a.curso_anterior || "-"} + + {tieneAnt ? ( + + {a.estado_anterior} + + ) : -} +
+
+ } +
+ ); +}