1373 lines
73 KiB
Plaintext
1373 lines
73 KiB
Plaintext
'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<Record<string, any>>({});
|
|
const [horarios, setHorarios] = useState<any[]>([
|
|
{
|
|
Dias: "LU MA ",
|
|
Horario: "10:00:00 - 17:00:00"
|
|
},
|
|
{
|
|
Dias: "VI ",
|
|
Horario: "11:00:00 - 18:00:00"
|
|
},
|
|
|
|
]);
|
|
const [alumnos, setAlumnos] = useState<any[]>([
|
|
{
|
|
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<any[]>([
|
|
{
|
|
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<any>(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 <span className='badge bg-success' style={{ fontSize: '12px', fontWeight: 'normal' }}>P</span>;
|
|
if (trimmed === "Absent") return <span className='badge bg-danger' style={{ fontSize: '12px', fontWeight: 'normal' }}>A</span>;
|
|
return <span className='badge bg-warning text-dark' style={{ fontSize: '12px', fontWeight: 'normal' }}>L</span>;
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
<div className="col-md-12 mt-4">
|
|
<div className="row">
|
|
|
|
{/* COLUMNA IZQUIERDA: INFORMACIÓN DEL CURSO */}
|
|
<div className="col-md-4">
|
|
|
|
{/* Bloque General */}
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
{loadingCurso ? (
|
|
<div className="text-center py-3">Cargando información del curso...</div>
|
|
) : (
|
|
<div className="table-responsive">
|
|
<table className="table table-sm mb-0">
|
|
<tbody>
|
|
<tr>
|
|
<td className="auto-style1"><strong className="text-muted">Curso</strong></td>
|
|
<td colSpan={2} className="auto-style2">
|
|
<strong>
|
|
{curso.nombre}
|
|
{curso.periodo && (
|
|
<button className="badge bg-primary border-0 ms-1" onClick={() => setActiveTab('Asistencia')}>
|
|
{curso.periodo}
|
|
</button>
|
|
)}
|
|
</strong>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td className="auto-style1"><strong className="text-muted">Código</strong></td>
|
|
<td colSpan={2} className="auto-style2">
|
|
<strong>{curso.codigo || cursoId || "—"}</strong>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Fecha</strong></td>
|
|
<td><strong>{curso.fechaInicio || "—"} / {curso.fechaTermino || "—"}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong className="text-muted">Sede</strong></td>
|
|
<td colSpan={2}><strong>{curso.sede || "—"}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Estado</strong></td>
|
|
<td><strong>{curso.estado || "—"}</strong></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Bloque Horario */}
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="table-responsive">
|
|
<table className="table">
|
|
<tbody>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Horario</strong></td>
|
|
<td className="text-end"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colSpan={2}>
|
|
{loadingHorario ? (
|
|
<div className="text-center py-2">Cargando horario...</div>
|
|
) : horarios.length === 0 ? (
|
|
<div className="text-center py-2 text-muted">Sin horario disponible</div>
|
|
) : (
|
|
<div className="table-responsive">
|
|
<table className="table">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" style={{ width: '20%' }} className="text-center">Dia</th>
|
|
<th scope="col" style={{ width: '80%' }} className="text-start">Hora</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{horarios.map((item, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={2} className="p-0">
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '20%' }}>{item.Dias}</td>
|
|
<td className="text-start" style={{ width: '80%' }}>{item.Horario}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bloque Sesiones */}
|
|
{showInfoCurso && (
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm mb-0">
|
|
<tbody>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Sala</strong></td>
|
|
<td style={{ width: '65%' }}><strong>{curso.sala}</strong></td>
|
|
<td style={{ width: '10%' }}><div className="d-grid gap-2"></div></td>
|
|
</tr>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Profesor</strong></td>
|
|
<td style={{ width: '65%' }}><strong>{curso.profesor}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Sesiones</strong></td>
|
|
<td style={{ width: '65%' }}><strong>{curso.sesiones}</strong></td>
|
|
<td className="text-end">
|
|
<a href="#" className="badge bg-warning text-dark text-decoration-none" style={{ fontWeight: 'normal' }} onClick={() => setActiveTab('detallesesiones')}>
|
|
Ver más
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{showCierreAcademico && (
|
|
<tr>
|
|
<td style={{ width: '15%' }}><strong className="text-muted">Cierre</strong></td>
|
|
<td><strong>Académico</strong></td>
|
|
<td className="text-end">{curso.estadoAcademico}</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
|
|
{/* COLUMNA DERECHA: DETALLE PANEL (ALUMNOS / ASISTENCIAS / NOTAS) */}
|
|
<div className="col-md-8">
|
|
<div className="row">
|
|
<div className="col-md-12">
|
|
{showDetalleAlumnos ? (
|
|
<div className="row">
|
|
|
|
{/* Menú de Botones de Navegación (Tabs) */}
|
|
<div className="col-md-12">
|
|
<div className="row">
|
|
<div className="col-md-4">
|
|
<button onClick={() => setActiveTab('asistencias')} className="w-100 text-start border-0 bg-transparent p-0 text-decoration-none">
|
|
<div className={`alert ${activeTab === 'asistencias' ? 'alert-success' : 'alert-light'} text-dark shadow`} role="alert">
|
|
<div className="mb-4">
|
|
<h5 className="float-start me-1"><i className='bx bx-user-check'></i></h5>
|
|
<span className="float-start"><strong>Asistencias</strong></span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
<div className="col-md-4">
|
|
<button onClick={() => setActiveTab('notas')} className="w-100 text-start border-0 bg-transparent p-0 text-decoration-none">
|
|
<div className={`alert ${activeTab === 'notas' ? 'alert-success' : 'alert-light'} text-dark shadow`} role="alert">
|
|
<div className="mb-4">
|
|
<h5 className="float-start me-1"><i className='bx bx-pencil'></i></h5>
|
|
<span className="float-start"><strong>Notas</strong></span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
<div className="col-md-4">
|
|
<button onClick={() => setActiveTab('contenido')} className="w-100 text-start border-0 bg-transparent p-0 text-decoration-none">
|
|
<div className={`alert ${activeTab === 'contenido' ? 'alert-success' : 'alert-light'} text-dark shadow`} role="alert">
|
|
<div className="mb-4">
|
|
<h5 className="float-start me-1"><i className='bx bx-file'></i></h5>
|
|
<span className="float-start"><strong>Contenido</strong></span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* SECCIÓN DINÁMICA DE ASISTENCIAS */}
|
|
{activeTab === 'asistencias' && (
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-6 mb-4"><strong>Asistencia</strong></div>
|
|
<div className="col-md-6 text-end">
|
|
<h5><strong className="text-muted">Promedio: </strong><strong>85%</strong></h5>
|
|
</div>
|
|
<div className="col-md-12 text-end mb-3">
|
|
<span className="badge bg-success me-1" style={{ fontSize: '12px', fontWeight: 'normal' }}>Present</span>
|
|
<span className="badge bg-danger me-1" style={{ fontSize: '12px', fontWeight: 'normal' }}>Absent</span>
|
|
<span className="badge bg-warning text-dark" style={{ fontSize: '12px', fontWeight: 'normal' }}>Late</span>
|
|
</div>
|
|
|
|
<div className="col-md-12">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm mb-0" style={{ fontSize: '12px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" className="text-start" style={{ width: '30%' }}>Name</th>
|
|
<th scope="col" className="text-center" style={{ width: '20%' }}>Contrato</th>
|
|
<th scope="col" className="text-center" style={{ width: '5%' }}>S1</th>
|
|
<th scope="col" className="text-center" style={{ width: '5%' }}>S2</th>
|
|
<th scope="col" className="text-center" style={{ width: '5%' }}>S3</th>
|
|
<th scope="col" className="text-center" style={{ width: '5%' }}>S4</th>
|
|
<th scope="col" className="text-center" style={{ width: '5%' }}>S5</th>
|
|
<th scope="col" className="text-center" style={{ width: '8%' }}>%</th>
|
|
<th scope="col" className="text-center" style={{ width: '7%' }}>ver</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{alumnos.length === 0 ? (
|
|
<tr><td colSpan={9}>Sin alumnos en el curso.</td></tr>
|
|
) : (
|
|
alumnos.map((alumno, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={9} className="p-0">
|
|
<table className="table table-sm mb-0 table-hover" style={{ fontSize: '12px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-start" style={{ width: '30%' }}>{`${alumno.AP_Paterno} ${alumno.Nombres}`}</td>
|
|
<td className="text-center" style={{ width: '20%' }}>
|
|
<strong className={alumno["Tipo de registro"] === "PERSONA" ? "text-success" : "text-primary"}>
|
|
{`${alumno["Tipo de registro"]} ${alumno.contrato}`}
|
|
</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{renderAsistenciaBadge(alumno.sesion01)}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{renderAsistenciaBadge(alumno.sesion02)}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{renderAsistenciaBadge(alumno.sesion03)}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{renderAsistenciaBadge(alumno.sesion04)}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{renderAsistenciaBadge(alumno.sesion05)}</td>
|
|
<td className="text-center" style={{ width: '8%', fontSize: '14px' }}><strong>{alumno.Asistencia}%</strong></td>
|
|
<td className="text-center" style={{ width: '7%' }}>
|
|
<button onClick={() => handleActionAlumno(alumno.idAlumno, 'Asistencia') }
|
|
className='badge bg-secondary border-0' style={{ fontWeight: 'normal' }}>Ver más</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* SECCIÓN DINÁMICA DE NOTAS */}
|
|
{activeTab === 'notas' && (
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-12 mb-4"><strong>Notas</strong></div>
|
|
<div className="col-md-12">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" style={{ width: '30%' }}>Name</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA1</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA2</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA3</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA4</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA5</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">CA6</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">MWT</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">MOT</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">FOT</th>
|
|
<th scope="col" style={{ width: '5%' }} className="text-center">FWT</th>
|
|
<th scope="col" style={{ width: '7%' }}>Ver</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{alumnos.length === 0 ? (
|
|
<tr><td colSpan={12}>Sin alumnos en el curso</td></tr>
|
|
) : (
|
|
alumnos.map((alumno, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={12} className="p-0">
|
|
<table className="table table-hover table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-start" style={{ width: '30%' }}>{`${alumno.AP_Paterno} ${alumno.Nombres}`}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA1}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA2}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA3}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA4}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA5}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.CA6}</td>
|
|
|
|
{/* Reemplazo de Visible bajo condición inline numérica */}
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.MWT !== -1 ? alumno.MWT : '-'}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.MOT !== -1 ? alumno.MOT : '-'}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.FOT !== -1 ? alumno.FOT : '-'}</td>
|
|
<td className="text-center" style={{ width: '5%' }}>{alumno.FWT !== -1 ? alumno.FWT : '-'}</td>
|
|
|
|
<td className="text-start" style={{ width: '7%' }}>
|
|
<button onClick={() => {handleActionAlumno(alumno.idAlumno, 'Notas'); console.log("alumnoID:",alumno.idAlumno)}} className='badge bg-warning text-dark border-0' style={{ fontWeight: 'normal' }}>Ver más</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* SECCIÓN DINÁMICA DE CONTENIDO */}
|
|
{activeTab === 'contenido' && (
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-12 mb-4"><strong>Contenido</strong></div>
|
|
<div className="col-md-12">
|
|
<div className="table-responsive" style={{ maxHeight: '500px' }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" style={{ width: '10%' }}>Fecha</th>
|
|
<th scope="col" style={{ width: '80%' }}>Contenido</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{contenidos.map((cont, index) => (
|
|
<tr key={index}>
|
|
<td>{cont.Fecha}</td>
|
|
<td>{cont.Contenido}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* SECCION DETALLE ASISTENCIA */}
|
|
{activeTab == 'detalleasistencia' && (
|
|
<div className="col-md-12 mt-4">
|
|
<div id="con_asistencias">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-2">
|
|
<div className="d-grid gap-2">
|
|
{/* <Link href="#" className="btn btn-primary btn-sm">
|
|
Volver
|
|
</Link> */}
|
|
</div>
|
|
</div>
|
|
<div className="col text-end">
|
|
<h5>
|
|
<strong className="text-muted">Student: </strong>
|
|
<strong>{alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}</strong>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tabla de Asistencias */}
|
|
<div className="alert alert-light text-dark shadow" role="alert" id="div_libro_asistencia">
|
|
<div className="row">
|
|
<div className="col-md-2"></div>
|
|
<div className="col-md-8">
|
|
<table className="table table-sm table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}>
|
|
<strong>Fecha</strong>
|
|
</th>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}>
|
|
<strong>Asistencia</strong>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
{/* Fila de Ejemplo: Presente */}
|
|
<tr>
|
|
<td colSpan={2} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-hover table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
27/07/2026
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong className="text-success">Present</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Fila de Ejemplo: Ausente */}
|
|
<tr>
|
|
<td colSpan={2} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-hover table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
28/07/2026
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong className="text-danger">Absent</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
)}
|
|
|
|
{/* SECCION DETALLE NOTAS */}
|
|
{activeTab == 'detallenotas' && (
|
|
<div className='col-md-12 mt-4'>
|
|
<div id="con_notas">
|
|
{/* Alerta Superior: Información del Alumno y Botón Volver */}
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-2">
|
|
<div className="d-grid gap-2">
|
|
{/* <Link href="#" className="btn btn-primary btn-sm">
|
|
Volver
|
|
</Link> */}
|
|
</div>
|
|
</div>
|
|
<div className="col text-end">
|
|
<h5>
|
|
<strong className="text-muted">Student: </strong>
|
|
<strong>
|
|
{alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}
|
|
</strong>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Contenedor de la Tabla de Notas */}
|
|
<div role="alert" id="div_libro_notes">
|
|
<div className="alert alert-light text-dark shadow">
|
|
<div className="col-md-12">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th className="text-center" scope="col" style={{ width: '20%' }}><strong>Fecha</strong></th>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}><strong>Test</strong></th>
|
|
<th className="text-center" scope="col" style={{ width: '10%' }}><strong>Nota</strong></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
{/* Estructura del .map() reemplazando al DataList original */}
|
|
{detalleNotas.map((item, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={3} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-bordered mb-0 table-hover" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '20%' }}>
|
|
<strong>{item.Fecha}</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong>{item.Descripcion}</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '10%' }}>
|
|
<strong>{item.Nota}</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
)}
|
|
|
|
{/* SECCION DETALLE SESIONES */}
|
|
{activeTab == 'detallesesiones' && (
|
|
<div className='col-md-12 mt-4'>
|
|
<div id="con_sesiones">
|
|
<div className="alert alert-light text-dark shadow" id="div_listado_sesiones" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-2">
|
|
<div className="d-grid gap-2">
|
|
{/* <Link href="#" className="btn btn-primary btn-sm">
|
|
Volver
|
|
</Link> */}
|
|
</div>
|
|
</div>
|
|
<div className="col text-end">
|
|
<h5><strong className="text-muted">Sesiones</strong> <strong>Clases</strong></h5>
|
|
</div>
|
|
<div className="col-md-12">
|
|
<hr />
|
|
</div>
|
|
<div className="col-md-12 text-center">
|
|
<div className="row align-items-center">
|
|
<div className="col-md-4">
|
|
<div className="row">
|
|
<div className="col-3">
|
|
<h3 className="text-end">
|
|
<i className="bx-fw bx bx-book-bookmark bx-tada-hover"></i>
|
|
</h3>
|
|
</div>
|
|
<div className="col-9">
|
|
<h5 className="fw-bold text-start">Sesiones Iniciales
|
|
<br />
|
|
<span className="fw-bold">{sesionesIniciales}</span>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="col-md-4">
|
|
<div className="row">
|
|
<div className="col-3">
|
|
<h3 className="text-end">
|
|
<i className="bx-fw bx bxs-edit bx-tada-hover"></i>
|
|
</h3>
|
|
</div>
|
|
<div className="col-9 text-start">
|
|
<h5 className="fw-bold text-start">Sesiones Suspendidas
|
|
<br />
|
|
<span className="fw-bold">{clasesSuspendidas}</span>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="col-md-4">
|
|
<div className="row">
|
|
<div className="col-3">
|
|
<h3 className="text-end">
|
|
<i className="bx-fw bx bxs-error-alt bx-tada-hover"></i>
|
|
</h3>
|
|
</div>
|
|
<div className="col-9">
|
|
<h5 className="fw-bold text-start">Porcentaje
|
|
<br />
|
|
<span className="fw-bold">{porcentajeSuspendidas}%</span>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="col-md-12">
|
|
<hr />
|
|
</div>
|
|
|
|
{/* DropDownList nativo de HTML manejado con React */}
|
|
<div className="col-md-4 text-end"><strong>Mostrando sesiones</strong></div>
|
|
<div className="col-md-4">
|
|
<select
|
|
id="ListaTipoSesion"
|
|
className="form-select fw-bold"
|
|
value={filtro}
|
|
onChange={(e) => setFiltro(e.target.value)}
|
|
>
|
|
<option value="TODAS">TODAS</option>
|
|
<option value="PENDIENTES">PENDIENTES</option>
|
|
<option value="REALIZADAS">REALIZADAS</option>
|
|
<option value="SUSPENDIDAS">SUSPENDIDAS</option>
|
|
</select>
|
|
</div>
|
|
<div className="col-md-4"></div>
|
|
|
|
<div className="col-md-12">
|
|
<hr />
|
|
</div>
|
|
|
|
{/* Listado Principal de Sesiones */}
|
|
<div className="col-md-12 text-end">
|
|
<div className="table-responsive" style={{ backgroundColor: 'white', fontSize: '16px' }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" className="text-center" style={{ width: '15%' }}>Fecha</th>
|
|
<th scope="col" className="text-center" style={{ width: '45%' }}>Responsable</th>
|
|
<th scope="col" className="text-center" style={{ width: '10%' }}>Inicio</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{sesionesFiltradas.length > 0 ? (
|
|
sesionesFiltradas.map((sesion, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={3} style={{ padding: 0 }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '15%' }}>
|
|
{sesion.Fecha.split('-').reverse().join('/')}
|
|
</td>
|
|
<td className="text-center" style={{ width: '45%' }}>
|
|
{sesion.Reemplazo === 'no' ? sesion.Titular : sesion.Reemplazo}
|
|
</td>
|
|
<td className="text-center" style={{ width: '10%' }}>
|
|
{sesion.Inicio}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
/* Etiqueta de reemplazo para LabelMsjSesiones */
|
|
<tr>
|
|
<td colSpan={3} className="text-center p-3 text-muted">
|
|
Sin sesiones registradas
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* termino div */}
|
|
</div>
|
|
)}
|
|
</div>
|
|
):(
|
|
<div id="con_rollbook">
|
|
<div className="row">
|
|
<div className="col-md-12">
|
|
<div className="row">
|
|
{/* Pestaña: Curso */}
|
|
<div className="col-md-6">
|
|
|
|
<button onClick={() => setVistaActiva('curso')} className="w-100 text-start border-0 bg-transparent p-0 text-decoration-none">
|
|
<div className={`alert ${vistaActiva === 'curso' ? 'alert-primary' : 'alert-light'} text-dark shadow`} role="alert" id="roll_curso">
|
|
<div className="mb-4">
|
|
<h5 className="float-start me-1"><i className='bx bx-user-check'></i></h5>
|
|
<span className="float-start"><strong>Curso</strong></span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Pestaña: Comentarios */}
|
|
<div className="col-md-6">
|
|
|
|
<button onClick={() => setVistaActiva('comentarios')} className="w-100 text-start border-0 bg-transparent p-0 text-decoration-none">
|
|
<div className={`alert ${vistaActiva === 'comentarios' ? 'alert-primary' : 'alert-light'} text-dark shadow`} role="alert" id="roll_comentario">
|
|
<div className="mb-4">
|
|
<h5 className="float-start me-1"><i className='bx bx-user-check'></i></h5>
|
|
<span className="float-start"><strong>Contenidos</strong></span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* CONTENEDOR: CURSO (rollbook_curso) */}
|
|
{vistaActiva === 'curso' && (
|
|
<div className="col-md-12" id="rollbook_curso">
|
|
<div className="row">
|
|
|
|
{/* MODO 1: ROLLBOOK EXISTENTE */}
|
|
{esRollbookExistente && (
|
|
<div className="col-md-12" id="rollbook_existente">
|
|
<div className="row">
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<h5><strong className="text-muted">Roll</strong> <strong>Book</strong></h5>
|
|
<br />
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" style={{ width: '37%' }}>Student</th>
|
|
<th scope="col" style={{ width: '24%' }}>Contrato</th>
|
|
<th scope="col" style={{ width: '14%' }} colSpan={2}>Grade</th>
|
|
<th scope="col" style={{ width: '14%' }} colSpan={2}>Attendance</th>
|
|
<th scope="col" style={{ width: '8%' }}>Cert.</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{alumnos.map((alumno) => (
|
|
<tr key={alumno.idAlumno}>
|
|
<td colSpan={7} style={{ padding: 0 }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td style={{ width: '37%' }}>
|
|
{`${alumno.AP_Paterno} ${alumno.Nombres}`}
|
|
</td>
|
|
<td style={{ width: '24%' }}>
|
|
<strong>
|
|
<span className='text-primary'>{alumno.Tipo} {alumno.contrato}</span>
|
|
</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '7%' }}>{alumno.PromedioFinal}</td>
|
|
<td style={{ width: '7%' }}>
|
|
<button type="button" className="btn p-0 border-0" onClick={() => {setVistaActiva('detallenotasR');}}>
|
|
<span className='badge bg-warning text-dark' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</button>
|
|
</td>
|
|
<td className="text-center" style={{ width: '7%' }}>{alumno.Asistencia}%</td>
|
|
<td style={{ width: '7%' }}>
|
|
<button type="button" className="btn p-0 border-0" onClick={() => {setVistaActiva('detalleasistenaciaR');}}>
|
|
<span className='badge bg-success' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</button>
|
|
</td>
|
|
<td style={{ width: '8%' }}>
|
|
<a href={`https://sam.norteamericano.cl/documentos/certificado/empresa/${alumno.idCertificado}.pdf`} target="_blank" rel="noreferrer">
|
|
<span className='badge bg-secondary' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tarjetas de Promedios Inferiores */}
|
|
<div className="col-md-4" id="promedio_notas">
|
|
<div className="alert alert-light text-dark" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-3">
|
|
<h1><i className='bx bx-pencil'></i></h1>
|
|
</div>
|
|
<div className="col text-center">
|
|
<span className="text-muted"><strong>Promedio Notas</strong></span>
|
|
<h5><strong>Vespertino</strong></h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="col-md-4" id="promedio_asistencia">
|
|
<div className="alert alert-light text-dark" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-3">
|
|
<h1><i className='bx bx-calendar-check'></i></h1>
|
|
</div>
|
|
<div className="col text-center">
|
|
<span className="text-muted"><strong>Promedio Asistencia</strong></span>
|
|
<h5><strong>Vespertino</strong></h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* MODO 2: ROLLBOOK CREAR (CIERRE CURSO) */}
|
|
{!esRollbookExistente && (
|
|
<div className="col-md-12" id="rollbook_crear">
|
|
<div className="row">
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="row" colSpan={7}>
|
|
<h5><strong className="text-muted">Cierre</strong> <strong>Curso</strong></h5>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th scope="col" style={{ width: '5%' }}>Ficha</th>
|
|
<th scope="col" style={{ width: '39%' }}>Student</th>
|
|
<th scope="col" style={{ width: '24%' }}>Contrato</th>
|
|
<th className="text-center" scope="col" style={{ width: '8%' }}>Grade</th>
|
|
<th className="text-center" scope="col" style={{ width: '10%' }}>Attendance</th>
|
|
<th scope="col" style={{ width: '7%' }}>Nota</th>
|
|
<th scope="col" style={{ width: '7%' }}>Asisten.</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{alumnos.map((alumno) => (
|
|
<tr key={alumno.idAlumno}>
|
|
<td colSpan={7} style={{ padding: 0 }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td style={{ width: '5%' }}>
|
|
{/* <Link href={`/Alumnos/Ficha?idAlumno=${alumno.idAlumno}`}>
|
|
<span className='badge bg-primary' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</Link> */}
|
|
</td>
|
|
<td style={{ width: '39%' }}>
|
|
{`${alumno.AP_Paterno} ${alumno.Nombres}`}
|
|
</td>
|
|
<td style={{ width: '24%' }}>
|
|
<strong>
|
|
{alumno.Tipo === "EMPRESA SIN SENCE" ? (
|
|
<span className='text-success'>{alumno.Tipo}</span>
|
|
) : (
|
|
<span className='text-primary'>{alumno.Tipo} {alumno.Contrato}</span>
|
|
)}
|
|
</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '8%' }}>{alumno.PromedioFinal}</td>
|
|
<td className="text-center" style={{ width: '10%' }}>{alumno.Asistencia}%</td>
|
|
<td style={{ width: '7%' }}>
|
|
<button type="button" className="btn p-0 border-0" onClick={() => {setVistaActiva('detallenotasR');}}>
|
|
<span className='badge bg-warning text-dark' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</button>
|
|
</td>
|
|
<td style={{ width: '7%' }}>
|
|
<button type="button" className="btn p-0 border-0" onClick={() => {setVistaActiva('detalleasistenaciaR');}}>
|
|
<span className='badge bg-success' style={{ fontWeight: 'normal' }}>Ver</span>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* CONTENEDOR: COMENTARIOS (rollbook_comentarios) */}
|
|
{vistaActiva === 'comentarios' && (
|
|
<div className="col-md-12" id="rollbook_contenidos">
|
|
<div className="row">
|
|
<div className="col-md-12">
|
|
<div className="alert alert-light text-dark shadow">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" className="text-center" style={{ width: '10%' }}>Fecha</th>
|
|
<th scope="col" className="text-center" style={{ width: '90%' }}>Contenidos</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{contenidos.map((item, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={2} style={{ padding: 0 }}>
|
|
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-start" style={{ width: '15%' }}>{item.Fecha}</td>
|
|
<td className="text-start" style={{ width: '80%' }}>{item.Contenido}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{vistaActiva === 'detallenotasR' && (
|
|
<div className='col-md-12 mt-4'>
|
|
<div id="con_notas">
|
|
{/* Alerta Superior: Información del Alumno y Botón Volver */}
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-2">
|
|
<div className="d-grid gap-2">
|
|
{/* <Link href="#" className="btn btn-primary btn-sm">
|
|
Volver
|
|
</Link> */}
|
|
</div>
|
|
</div>
|
|
<div className="col text-end">
|
|
<h5>
|
|
<strong className="text-muted">Student: </strong>
|
|
<strong>
|
|
{alumnoSeleccionado ? `${alumnoSeleccionado.Nombres} ${alumnoSeleccionado.AP_Paterno}` : 'Label'}
|
|
</strong>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Contenedor de la Tabla de Notas */}
|
|
<div role="alert" id="div_libro_notes">
|
|
<div className="alert alert-light text-dark shadow">
|
|
<div className="col-md-12">
|
|
<div className="table-responsive">
|
|
<table className="table table-sm table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th className="text-center" scope="col" style={{ width: '20%' }}><strong>Fecha</strong></th>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}><strong>Test</strong></th>
|
|
<th className="text-center" scope="col" style={{ width: '10%' }}><strong>Nota</strong></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
{/* Estructura del .map() reemplazando al DataList original */}
|
|
{detalleNotas.map((item, index) => (
|
|
<tr key={index}>
|
|
<td colSpan={3} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-bordered mb-0 table-hover" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '20%' }}>
|
|
<strong>{item.Fecha}</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong>{item.Descripcion}</strong>
|
|
</td>
|
|
<td className="text-center" style={{ width: '10%' }}>
|
|
<strong>{item.Nota}</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{vistaActiva === 'detalleasistenaciaR' &&(
|
|
<div className="col-md-12 mt-4">
|
|
<div id="con_asistencias">
|
|
<div className="alert alert-light text-dark shadow" role="alert">
|
|
<div className="row">
|
|
<div className="col-md-2">
|
|
<div className="d-grid gap-2">
|
|
{/* <Link href="#" className="btn btn-primary btn-sm">
|
|
Volver
|
|
</Link> */}
|
|
</div>
|
|
</div>
|
|
<div className="col text-end">
|
|
<h5>
|
|
<strong className="text-muted">Student: </strong>
|
|
<strong>Nombre del Alumno</strong>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tabla de Asistencias */}
|
|
<div className="alert alert-light text-dark shadow" role="alert" id="div_libro_asistencia">
|
|
<div className="row">
|
|
<div className="col-md-2"></div>
|
|
<div className="col-md-8">
|
|
<table className="table table-sm table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<thead>
|
|
<tr>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}>
|
|
<strong>Fecha</strong>
|
|
</th>
|
|
<th className="text-center" scope="col" style={{ width: '40%' }}>
|
|
<strong>Asistencia</strong>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
{/* Fila de Ejemplo: Presente */}
|
|
<tr>
|
|
<td colSpan={2} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-hover table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
27/07/2026
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong className="text-success">Present</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Fila de Ejemplo: Ausente */}
|
|
<tr>
|
|
<td colSpan={2} style={{ padding: 0 }}>
|
|
<table className="table table-sm table-hover table-bordered mb-0" style={{ fontSize: '16px' }}>
|
|
<tbody>
|
|
<tr>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
28/07/2026
|
|
</td>
|
|
<td className="text-center" style={{ width: '40%' }}>
|
|
<strong className="text-danger">Absent</strong>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
</div>
|
|
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
);
|
|
} |