'use client'; import React, { useState, useEffect, MouseEvent,Suspense } from 'react'; import { useSearchParams } from "next/navigation"; export default function Detalle() { const searchParams = useSearchParams(); //const codigo = searchParams.get("codigo"); const tipo = searchParams.get("tipo"); const rb = searchParams.get("rollbook"); const cursoId = searchParams.get("codigo"); const [filtro, setFiltro] = useState('TODAS'); const [curso, setCurso] = useState>({}); const [horarios, setHorarios] = useState([ { Dias: "LU MA ", Horario: "10:00:00 - 17:00:00" }, { Dias: "VI ", Horario: "11:00:00 - 18:00:00" }, ]); const [alumnos, setAlumnos] = useState([ { idAlumno: 1, AP_Paterno: "Pérez", Nombres: "Juan", "Tipo de registro": "PERSONA", // Puede ser "PERSONA" (verde) o cualquier otro texto (azul) contrato: "12345", sesion01: "Present", // O el tipo de dato que espere tu función renderAsistenciaBadge sesion02: "Absent", sesion03: "Late", sesion04: "Present", sesion05: "Present", Asistencia: 80, CA1: 100, CA2: 100, CA3: 100, CA4: 100, CA5: 100, CA6: 100, MWT: 80, MOT: 90, FOT: 95, FWT: 92, idDetalleContrato: 101, idCertificado: 9948, PromedioFinal: 92, // Mapea a 'Average' o 'PromedioFinal' }, { idAlumno: 2, AP_Paterno: "Munoz", Nombres: "Ignacio", "Tipo de registro": "Empresa", // Puede ser "PERSONA" (verde) o cualquier otro texto (azul) contrato: "12345", sesion01: "Absent", // O el tipo de dato que espere tu función renderAsistenciaBadge sesion02: "Present", sesion03: "Present", sesion04: "Late", sesion05: "Absent", Asistencia: 75, CA1: 98, CA2: 99, CA3: 93, CA4: 94, CA5: 95, CA6: 100, MWT: 75, MOT: 80, FOT: 92, FWT: 93, idDetalleContrato: 102, idCertificado: 9949, PromedioFinal: 89, // Mapea a 'Average' o 'PromedioFinal' } ]); const [contenidos, setContenidos] = useState([ { Fecha: "2026-07-22", Contenido: "SKILLS: listening, interaction, Unit 1-5, Page 2-53, UNITS 1-5 REVIEW Final oral test" } ]); const [alumnoSeleccionado, setAlumnoSeleccionado] = useState(null); const detalleNotas = [ { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 1 (CA1)", Nota: alumnoSeleccionado?.CA1 }, { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 2 (CA2)", Nota: alumnoSeleccionado?.CA2 }, { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 3 (CA3)", Nota: alumnoSeleccionado?.CA3 }, { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 4 (CA4)", Nota: alumnoSeleccionado?.CA4 }, { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 5 (CA5)", Nota: alumnoSeleccionado?.CA5 }, { Fecha: "28/07/2026", Descripcion: "Continuous Assessment 6 (CA6)", Nota: alumnoSeleccionado?.CA6 }, { Fecha: "28/07/2026", Descripcion: "Mid-Term Written Test (MWT)", Nota: alumnoSeleccionado?.MWT }, { Fecha: "28/07/2026", Descripcion: "Mid-Term Oral Test (MOT)", Nota: alumnoSeleccionado?.MOT }, { Fecha: "28/07/2026", Descripcion: "Final Oral Test (FOT)", Nota: alumnoSeleccionado?.FOT }, { Fecha: "28/07/2026", Descripcion: "Final Written Test (FWT)", Nota: alumnoSeleccionado?.FWT }, ]; const [sesiones, setSesiones] = useState([ { Fecha: '2026-07-20', Titular: 'Prof. Carlos Ortega', Reemplazo: 'no', Inicio: '09:00', Estado: 'ACTIVA' }, // Realizada (pasada) { Fecha: '2026-07-21', Titular: 'Prof. Carlos Ortega', Reemplazo: 'Prof. Luis Gómez', Inicio: '10:30', Estado: 'ACTIVA' }, // Realizada (pasada) { Fecha: '2026-07-28', Titular: 'Prof. Carlos Ortega', Reemplazo: 'Prof. Luis Gómez', Inicio: '10:30', Estado: 'ACTIVA' }, // Pendiente (futura) { Fecha: '2026-07-29', Titular: 'Prof. Carlos Ortega', Reemplazo: 'Prof. Luis Gómez', Inicio: '10:30', Estado: 'ACTIVA' }, // Pendiente (futura) { Fecha: '2026-07-30', Titular: 'Prof. Carlos Ortega', Reemplazo: 'Prof. Luis Gómez', Inicio: '10:30', Estado: 'ACTIVA' }, // Pendiente (futura) { Fecha: '2026-07-31', Titular: 'Prof. Carlos Ortega', Reemplazo: 'Prof. Luis Gómez', Inicio: '10:30', Estado: 'ACTIVA' }, // Pendiente (futura) { Fecha: '2026-07-22', Titular: 'Prof. Carlos Ortega', Reemplazo: 'no', Inicio: '09:00', Estado: 'SUSPENDIDA' }, // Suspendida ]); const sesionesIniciales = sesiones.length; const clasesSuspendidas = sesiones.filter(s => s.Estado === 'SUSPENDIDAS').length; const porcentajeSuspendidas = sesionesIniciales > 0 ? ((clasesSuspendidas / sesionesIniciales) * 100).toFixed(0) : 0; const sesionesFiltradas = sesiones.filter(sesion => { const hoy = new Date(); // Fecha actual simulada const fechaSesion = new Date(sesion.Fecha); if (filtro === 'TODAS'){ return sesion.Estado !== 'SUSPENDIDA'; } if (filtro === 'SUSPENDIDAS') { return sesion.Estado === 'SUSPENDIDA'; } // Si no está suspendida, filtramos por fecha if (filtro === 'REALIZADAS') { return fechaSesion < hoy && sesion.Estado !== 'SUSPENDIDA'; } if (filtro === 'PENDIENTES') { return fechaSesion >= hoy && sesion.Estado !== 'SUSPENDIDA'; } // return true; // 'TODAS' }); // --- CONTROL DE VISIBILIDAD (Equivalente a Visible="false/true" de ASP.NET) --- const [activeTab, setActiveTab] = useState('asistencias'); // 'asistencias', 'notas', 'contenido' const [vistaActiva, setVistaActiva] = useState('curso'); const [esRollbookExistente, setEsRollbookExistente] = useState(()=> rb !== "0"); const [showInfoCurso, setShowInfoCurso] = useState(true); const [showCierreAcademico, setShowCierreAcademico] = useState(false); const [showDetalleAlumnos, setShowDetalleAlumnos] = useState(true); // con_alumnos const [loadingCurso, setLoadingCurso] = useState(true); const [loadingHorario, setLoadingHorario] = useState(false); useEffect(() => { CargaDatosCursos(); // CargaHorario(); }, [cursoId]); async function CargaDatosCursos(){ if (!cursoId) return; const fetchCurso = async () => { try {`` let variable = ""; if(tipo === "Cerrado"){ variable = "DETALLECURSOSV1" }else{ variable = "DETALLECURSOSV3" } const params = new URLSearchParams({ tipo: variable, varA: "0", varB: "0", varC: "0", cursoId, }); const res = await fetch(`/api/cursos?${params.toString()}`, { method: "GET", headers: { "Content-Type": "application/json" }, }); if (!res.ok) { const errData = await res.json().catch(() => ({})); const errMsg = errData.error || `Error ${res.status}: ${res.statusText}`; console.error("Error fetching detalle curso", errMsg); setLoadingCurso(false); return; } const data = await res.json(); console.log("fetchCurso response:", data); if (data) { const d = Array.isArray(data) ? data[0] : data; const rawFechaTermino = d.FechaTermino || d.fechatermino || ""; setCurso(prev => ({ ...prev, nombre: d.Curso || "", periodo: d.Periodo || "", codigo: d.Codigo || "", fechaInicio: d.FechaInicio || d.fechainicio || "", fechaTermino: d.FechaTermino || d.fechatermino || "", sede: d.Sede || "", estado: d.Estado || "", sala: d.Sala || "", profesor: d.Profesor || "", sesiones: d.Sesiones || 0, estadoAcademico: d.EstadoAcademico || d.estadoacademico || "" })); // Validación segura para evitar que el split rompa la aplicación if (typeof rawFechaTermino === "string" && rawFechaTermino.includes("-")) { const [dia, mes, anio] = rawFechaTermino.split('-'); const fechaTerminoObj = new Date(Number(anio), Number(mes) - 1, Number(dia)); const ahora = new Date(); // Seteamos las horas a 00:00:00 para comparar solo las fechas ahora.setHours(0, 0, 0, 0); fechaTerminoObj.setHours(0, 0, 0, 0); setShowDetalleAlumnos(fechaTerminoObj >= ahora); } else { // Comportamiento por defecto si la fecha no es válida o viene vacía setShowDetalleAlumnos(false); } } } catch (err) { console.error("Error fetching detalle curso", err); } finally { setLoadingCurso(false); } }; fetchCurso(); } async function CargaHorario(){ if (!cursoId) return; const fetchHorarios = async () => { try { const params = new URLSearchParams({ tipo: "HORARIOV1", varA: "0", varB: "0", varC: "0", cursoId, }); const res = await fetch(`/api/cursos?${params.toString()}`, { method: "GET", headers: { "Content-Type": "application/json" }, }); if (!res.ok) { const errData = await res.json().catch(() => ({})); const errMsg = errData.error || `Error ${res.status}: ${res.statusText}`; console.error("Error fetching horarios", errMsg); setLoadingHorario(false); return; } const data = await res.json(); console.log("fetchHorarios response:", data); if (Array.isArray(data)) { setHorarios(data); } } catch (err) { console.error("Error fetching horarios", err); } finally { setLoadingHorario(false); } }; fetchHorarios(); } // --- MANEJADORES DE EVENTOS (OnClick) --- const handleVerSesiones = (e: { preventDefault: () => void; }) => { e.preventDefault(); console.log("Ver más sesiones"); }; const handleActionAlumno = (idAlumno: string, tipo: string) => { console.log(`Acción ${tipo} para alumno: ${idAlumno}`); const alumnoEncontrado = alumnos.find(al => al.idAlumno === idAlumno); if (alumnoEncontrado) { setAlumnoSeleccionado(alumnoEncontrado); } if (tipo === "Asistencia"){ setActiveTab('detalleasistencia'); } else if (tipo === "Notas"){ setActiveTab('detallenotas'); } }; // Helper para renderizar badges de asistencia (P, A, L) const renderAsistenciaBadge = (status: string) => { const trimmed = status?.trim(); if (trimmed === "Present") return P; if (trimmed === "Absent") return A; return L; }; return (
{/* COLUMNA IZQUIERDA: INFORMACIÓN DEL CURSO */}
{/* Bloque General */}
{loadingCurso ? (
Cargando información del curso...
) : (
Curso {curso.nombre} {curso.periodo && ( )}
Código {curso.codigo || cursoId || "—"}
Fecha {curso.fechaInicio || "—"} / {curso.fechaTermino || "—"}
Sede {curso.sede || "—"}
Estado {curso.estado || "—"}
)}
{/* Bloque Horario */}
Horario
{loadingHorario ? (
Cargando horario...
) : horarios.length === 0 ? (
Sin horario disponible
) : (
{horarios.map((item, index) => ( ))}
Dia Hora
{item.Dias} {item.Horario}
)}
{/* Bloque Sesiones */} {showInfoCurso && (
{showCierreAcademico && ( )}
Sala {curso.sala}
Profesor {curso.profesor}
Sesiones {curso.sesiones} setActiveTab('detallesesiones')}> Ver más
Cierre Académico {curso.estadoAcademico}
)}
{/* COLUMNA DERECHA: DETALLE PANEL (ALUMNOS / ASISTENCIAS / NOTAS) */}
{showDetalleAlumnos ? (
{/* Menú de Botones de Navegación (Tabs) */}
{/* SECCIÓN DINÁMICA DE ASISTENCIAS */} {activeTab === 'asistencias' && (
Asistencia
Promedio: 85%
Present Absent Late
{alumnos.length === 0 ? ( ) : ( alumnos.map((alumno, index) => ( )) )}
Name Contrato S1 S2 S3 S4 S5 % ver
Sin alumnos en el curso.
{`${alumno.AP_Paterno} ${alumno.Nombres}`} {`${alumno["Tipo de registro"]} ${alumno.contrato}`} {renderAsistenciaBadge(alumno.sesion01)} {renderAsistenciaBadge(alumno.sesion02)} {renderAsistenciaBadge(alumno.sesion03)} {renderAsistenciaBadge(alumno.sesion04)} {renderAsistenciaBadge(alumno.sesion05)} {alumno.Asistencia}%
)} {/* SECCIÓN DINÁMICA DE NOTAS */} {activeTab === 'notas' && (
Notas
{alumnos.length === 0 ? ( ) : ( alumnos.map((alumno, index) => ( )) )}
Name CA1 CA2 CA3 CA4 CA5 CA6 MWT MOT FOT FWT Ver
Sin alumnos en el curso
{/* Reemplazo de Visible bajo condición inline numérica */}
{`${alumno.AP_Paterno} ${alumno.Nombres}`} {alumno.CA1} {alumno.CA2} {alumno.CA3} {alumno.CA4} {alumno.CA5} {alumno.CA6}{alumno.MWT !== -1 ? alumno.MWT : '-'} {alumno.MOT !== -1 ? alumno.MOT : '-'} {alumno.FOT !== -1 ? alumno.FOT : '-'} {alumno.FWT !== -1 ? alumno.FWT : '-'}
)} {/* SECCIÓN DINÁMICA DE CONTENIDO */} {activeTab === 'contenido' && (
Contenido
{contenidos.map((cont, index) => ( ))}
Fecha Contenido
{cont.Fecha} {cont.Contenido}
)} {/* SECCION DETALLE ASISTENCIA */} {activeTab == 'detalleasistencia' && (
{/* Volver */}
Student: {alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}
{/* Tabla de Asistencias */}
)} {/* SECCION DETALLE NOTAS */} {activeTab == 'detallenotas' && (
{/* Alerta Superior: Información del Alumno y Botón Volver */}
{/* Volver */}
Student: {alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}
{/* Contenedor de la Tabla de Notas */}
)} {/* SECCION DETALLE SESIONES */} {activeTab == 'detallesesiones' && (
{/* termino div */}
)}
):(
{/* Pestaña: Curso */}
{/* Pestaña: Comentarios */}
{/* CONTENEDOR: CURSO (rollbook_curso) */} {vistaActiva === 'curso' && (
{/* MODO 1: ROLLBOOK EXISTENTE */} {esRollbookExistente && (
Roll Book

{alumnos.map((alumno) => ( ))}
Student Contrato Grade Attendance Cert.
{`${alumno.AP_Paterno} ${alumno.Nombres}`} {alumno.Tipo} {alumno.contrato} {alumno.PromedioFinal} {alumno.Asistencia}% Ver
{/* Tarjetas de Promedios Inferiores */}

Promedio Notas
Vespertino

Promedio Asistencia
Vespertino
)} {/* MODO 2: ROLLBOOK CREAR (CIERRE CURSO) */} {!esRollbookExistente && (
{alumnos.map((alumno) => ( ))}
Cierre Curso
Ficha Student Contrato Grade Attendance Nota Asisten.
{/* Ver */} {`${alumno.AP_Paterno} ${alumno.Nombres}`} {alumno.Tipo === "EMPRESA SIN SENCE" ? ( {alumno.Tipo} ) : ( {alumno.Tipo} {alumno.Contrato} )} {alumno.PromedioFinal} {alumno.Asistencia}%
)}
)} {/* CONTENEDOR: COMENTARIOS (rollbook_comentarios) */} {vistaActiva === 'comentarios' && (
{contenidos.map((item, index) => ( ))}
Fecha Contenidos
{item.Fecha} {item.Contenido}
)} {vistaActiva === 'detallenotasR' && (
{/* Alerta Superior: Información del Alumno y Botón Volver */}
{/* Volver */}
Student: {alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}
{/* Contenedor de la Tabla de Notas */}
)} {vistaActiva === 'detalleasistenaciaR' &&(
{/* Volver */}
Student: Nombre del Alumno
{/* Tabla de Asistencias */}
)}
)}
); }