Arreglo de node_modules

This commit is contained in:
Fimm committed 2026-09-07 15:17:43 +00:00
commit eed3b45de3
40 files changed
+13127

No files matched your search

+349
View File
@@ -0,0 +1,349 @@
"use client";
import React, { useState } from "react";
import Link from "next/link";
import { User } from "@boxicons/react";
// Interface para mapear la estructura de la lista de contratos anulados
interface ContratoAnuladoItem {
idEmpresas: string;
empresa: string;
Contrato: string;
Fecha: string;
DescripcionActividad: string;
usuarioResponsable: string;
}
export default function ContratosHistorialPage() {
// --- ESTADOS DE CONTROLES Y SECCIONES ---
const [mes, setMes] = useState("");
const [agno, setAgno] = useState("");
const [showSearch, setShowSearch] = useState(false);
const [mensajeLabel, setMensajeLabel] = useState("");
// --- ESTADOS DE MODALES Y CARGA ---
const [isLoading, setIsLoading] = useState(false);
const [modalAlerta, setModalAlerta] = useState({ show: false, message: "" });
// --- DATOS SIMULADOS (DataList / Grid) ---
const [contratosAnulados, setContratosAnulados] = useState<ContratoAnuladoItem[]>([
{
idEmpresas: "76.123.456-7",
empresa: "Empresa Ejemplo S.A.",
Contrato: "1002",
Fecha: "2026-02-10",
DescripcionActividad: "Anulación solicitada por el cliente por cambio de presupuesto",
usuarioResponsable: "AdminUser",
},
]);
// --- MANEJADORES DE EVENTOS ---
const handleBuscar = (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
// Simulación de respuesta de backend
setTimeout(() => {
setIsLoading(false);
if (!mes || !agno) {
setModalAlerta({
show: true,
message: "Por favor seleccione un mes e ingrese un año válido.",
});
return;
}
setShowSearch(true);
setMensajeLabel("");
}, 800);
};
const handleExportarExcel = (e: React.MouseEvent) => {
e.preventDefault();
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
setModalAlerta({
show: true,
message: "Informe mensual exportado correctamente a Excel.",
});
}, 1000);
};
return (
<div className="container-fluid py-3">
<div className="row">
<div className="col-md-12">
<div className="row">
{/* CABECERA IZQUIERDA */}
<div className="col-md-5">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="row align-items-center">
<div className="col-8 d-flex align-items-center">
<strong>
<User style={{ fontSize: "24px" }} />
</strong>
<strong>
<span className="ms-2">Contratos anulados por mes</span>
</strong>
</div>
<div className="col text-end">
<Link
href="/Clientes/Index"
className="btn btn-warning text-dark btn-sm fw-bold"
>
Volver
</Link>
</div>
</div>
</div>
</div>
{/* CABECERA DERECHA / FILTROS DE BÚSQUEDA */}
<div className="col-md-7">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<form onSubmit={handleBuscar} className="row align-items-center">
<div className="col text-end">
<span className="fw-bold">Mes</span>
</div>
<div className="col">
<select
className="form-select form-select-sm"
value={mes}
onChange={(e) => setMes(e.target.value)}
>
<option value="">-- Seleccione --</option>
<option value="1">Enero</option>
<option value="2">Febrero</option>
<option value="3">Marzo</option>
<option value="4">Abril</option>
<option value="5">Mayo</option>
<option value="6">Junio</option>
<option value="7">Julio</option>
<option value="8">Agosto</option>
<option value="9">Septiembre</option>
<option value="10">Octubre</option>
<option value="11">Noviembre</option>
<option value="12">Diciembre</option>
</select>
</div>
<div className="col text-end">
<span className="fw-bold">Agno</span>
</div>
<div className="col">
<input
type="number"
className="form-control form-control-sm"
value={agno}
onChange={(e) => setAgno(e.target.value)}
placeholder="AAAA"
/>
</div>
<div className="col">
<button
type="submit"
className="btn btn-primary btn-sm d-grid w-100"
>
Buscar
</button>
</div>
</form>
</div>
</div>
{/* BOTÓN EXPORTAR EXCEL */}
<div className="col-md-12 mx-auto">
<button
type="button"
className="btn p-0 text-start w-100 text-decoration-none border-0 bg-transparent"
onClick={handleExportarExcel}
>
<div className="alert alert-success shadow" role="alert">
<div className="row align-items-center">
<div className="col-md-3">
<h1 className="mb-0">
{/* <Export /> */}
</h1>
</div>
<div className="col text-center">
<span className="text-muted">
<strong>Excel</strong>
</span>
<h5 className="mb-0">
<strong>Exportar Mensual</strong>
</h5>
</div>
</div>
</div>
</button>
</div>
{/* TABLA DE RESULTADOS */}
{showSearch && (
<div className="col-md-12 mt-3" id="div_search">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="table-responsive">
<table
className="table table-sm mb-0"
style={{ fontSize: "12px" }}
>
<thead>
<tr>
<th className="text-start" style={{ width: "3%" }}></th>
<th className="text-start" style={{ width: "7%" }}>
RUT Empresa
</th>
<th className="text-start" style={{ width: "20%" }}>
Empresa
</th>
<th className="text-start" style={{ width: "7%" }}>
Contrato
</th>
<th className="text-start" style={{ width: "12%" }}>
Fecha
</th>
<th className="text-start" style={{ width: "40%" }}>
Observacion
</th>
<th className="text-start" style={{ width: "11%" }}>
Responsable
</th>
</tr>
</thead>
<tbody>
{contratosAnulados.map((item, index) => (
<tr key={index}>
<td className="text-start" style={{ width: "3%" }}></td>
<td className="text-start" style={{ width: "7%" }}>
{item.idEmpresas}
</td>
<td className="text-start" style={{ width: "20%" }}>
{item.empresa}
</td>
<td className="text-start" style={{ width: "7%" }}>
{item.Contrato}
</td>
<td className="text-start" style={{ width: "12%" }}>
{item.Fecha}
</td>
<td className="text-start" style={{ width: "40%" }}>
{item.DescripcionActividad}
</td>
<td className="text-start" style={{ width: "11%" }}>
{item.usuarioResponsable}
</td>
</tr>
))}
</tbody>
</table>
{mensajeLabel && (
<h4 className="mt-2">
<span>{mensajeLabel}</span>
</h4>
)}
</div>
</div>
</div>
)}
</div>
</div>
</div>
{/* --- MODAL ALERTA / ERRORES --- */}
{modalAlerta.show && (
<div
className="modal fade show d-block bg-dark bg-opacity-50"
tabIndex={-1}
role="dialog"
>
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div className="modal-content text-dark">
<div className="modal-header alert alert-secondary mb-0">
<h5 className="float-start mt-2">
<strong>Módulo Académico - Empresa</strong>
</h5>
<button
type="button"
className="btn-close float-end mt-1"
onClick={() => setModalAlerta({ show: false, message: "" })}
aria-label="Close"
></button>
</div>
<div
className="modal-body alert mb-0"
style={{ textAlign: "justify" }}
>
<div className="row mb-2">
<div className="col-md-12 text-center">
<h5>
<strong>{modalAlerta.message}</strong>
</h5>
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-primary"
onClick={() => setModalAlerta({ show: false, message: "" })}
>
Cerrar
</button>
</div>
</div>
</div>
</div>
)}
{/* --- MODAL CARGANDO (LOADING SPINNER) --- */}
{isLoading && (
<div
className="modal fade show d-block bg-dark bg-opacity-50"
tabIndex={-1}
role="dialog"
>
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div className="modal-content text-dark">
<div className="modal-header alert alert-secondary mb-0">
<h5 className="float-start mt-2">
<strong>Procesando</strong>
</h5>
</div>
<div
className="modal-body alert mb-0"
style={{ textAlign: "justify" }}
>
<div className="row mb-2">
<div className="col-md-12 text-center">
<h5>
<strong>Espere un momento, por favor...</strong>
</h5>
<div className="d-flex justify-content-center gap-1 mt-3">
<div
className="spinner-grow spinner-grow-sm text-primary"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-danger"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-primary"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-danger"
role="status"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
}
+865
View File
@@ -0,0 +1,865 @@
"use client";
import React, { useState } from "react";
import Link from "next/link";
import {
User,
// Transfer,
// Export,
// BxsFilePdf,
SearchPlus,
} from "@boxicons/react";
// Types para los datos de las tablas
interface ArchivoItem {
contrato: string;
cotizacion: string;
tipoVenta: string;
empresa: string;
tipoContrato: string;
Responsable: string;
observacion: string;
fechaobservacion: string;
}
interface ContratoDetalleItem {
Url: string;
Contrato: string;
"Firma Estado": number;
"CURSO ID": string;
CURSO: string;
JORNADA: string;
DIREMP: string;
Fecha: string;
Valor: string;
}
interface OCItem {
Detalle: string;
"Numero interno": string;
"Fecha de subida pago": string;
"Tipo documento": string;
Responsable: string;
}
interface SNCItem {
Detalle: string;
codInscripcion: string;
"Fecha de subida": string;
Responsable: string;
}
interface AlumnoItem {
run: string;
nombreCompleto: string;
tipoRegistro: string;
empresaApoderada: string;
}
export default function AutorizadosPage() {
// --- ESTADOS DE SECCIONES (Visibilidad) ---
const [showSearch, setShowSearch] = useState(true);
const [showBusqueda, setShowBusqueda] = useState(false);
const [showDetalle, setShowDetalle] = useState(false);
// --- ESTADOS DE CONTROLES ---
const [estado, setEstado] = useState("");
const [mes, setMes] = useState("");
const [agno, setAgno] = useState("");
// --- ESTADOS DE VALORES DE DETALLE ---
const [neto, setNeto] = useState("0");
const [descuento, setDescuento] = useState("0");
const [total, setTotal] = useState("0");
// --- ESTADOS DE MODALES ---
const [isLoading, setIsLoading] = useState(false);
const [modalAlerta, setModalAlerta] = useState({ show: false, message: "" });
const [modalAlumnos, setModalAlumnos] = useState(false);
// --- DATOS SIMULADOS ---
const [filesList, setFilesList] = useState<ArchivoItem[]>([
{
contrato: "1001",
cotizacion: "5001",
tipoVenta: "Cerrado",
empresa: "Empresa Ejemplo S.A.",
tipoContrato: "Anual",
Responsable: "Juan Pérez",
observacion: "Contrato Aprobado",
fechaobservacion: "2026-02-15",
},
]);
const [contratosDetalleList, setContratosDetalleList] = useState<
ContratoDetalleItem[]
>([
{
Url: "https://empresas.norteamericano.cl/documento.pdf",
Contrato: "1001",
"Firma Estado": 1,
"CURSO ID": "ENG-01",
CURSO: "Inglés Avanzado",
JORNADA: "Vespertina",
DIREMP: "Providencia",
Fecha: "2026-02-01",
Valor: "$500.000",
},
]);
const [ocList, setOcList] = useState<OCItem[]>([
{
Detalle: "comprobante_1.pdf",
"Numero interno": "OC-9982",
"Fecha de subida pago": "2026-02-10",
"Tipo documento": "Orden de Compra",
Responsable: "Maria Lopez",
},
]);
const [sncList, setSncList] = useState<SNCItem[]>([
{
Detalle: "sence_1.pdf",
codInscripcion: "SNC-2026-A",
"Fecha de subida": "2026-02-12",
Responsable: "Pedro Gomez",
},
]);
const [alumnosList, setAlumnosList] = useState<AlumnoItem[]>([
{
run: "12.345.678-9",
nombreCompleto: "Carlos Mendoza",
tipoRegistro: "Regular",
empresaApoderada: "Empresa Ejemplo S.A.",
},
]);
// --- MANEJADORES DE EVENTOS ---
const handleEstadoChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value;
setEstado(value);
if (value) {
setShowSearch(false);
setShowBusqueda(true);
}
};
const handleBuscar = () => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
}, 1000);
};
const handleVerDetalle = (cont: string, cotz: string, type: string) => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
setShowBusqueda(false);
setShowDetalle(true);
}, 800);
};
const handleVerParticipantes = (contratoId: string) => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
setModalAlumnos(true);
}, 600);
};
const handleExportarExcel = () => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
setModalAlerta({
show: true,
message: "Informe generado correctamente.",
});
}, 1000);
};
return (
<div className="container-fluid py-3">
<div className="row">
<div className="col-md-12" id="contratos_autorizados">
<div className="row">
{/* CABECERA IZQUIERDA */}
<div className="col-md-5">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="row align-items-center">
<div className="col d-flex align-items-center">
<User style={{ fontSize: "24px" }} />
<strong className="ms-2">Contratos Autorizados</strong>
</div>
<div className="col text-end">
<Link
href="../Clientes/Index"
className="btn btn-warning text-dark btn-sm fw-bold"
>
Volver
</Link>
</div>
</div>
</div>
</div>
{/* CABECERA DERECHA / SELECCIÓN DE ESTADO */}
<div className="col-md-7">
<div className="alert alert-light text-dark shadow-sm" role="alert">
{showSearch && (
<div className="row align-items-center" id="div_search">
<div className="col">
<span className="fw-bold">Estado</span>
</div>
<div className="col">
<select
className="form-select"
value={estado}
onChange={handleEstadoChange}
>
<option value="">-- Seleccione --</option>
<option value="1">Autorizados</option>
<option value="2">Pendientes</option>
</select>
</div>
</div>
)}
{!showSearch && (
<div className="row" id="div_back">
<div className="col">
<button
type="button"
className="btn btn-warning text-dark btn-sm fw-bold d-inline-flex align-items-center gap-1"
onClick={() => {
setShowSearch(true);
setShowBusqueda(false);
setShowDetalle(false);
}}
>
{/* <Transfer /> */}
Volver
</button>
</div>
</div>
)}
</div>
</div>
{/* SECCIÓN DE BÚSQUEDA Y LISTADO PRINCIPAL */}
{showBusqueda && (
<div className="col-md-12" id="div_busqueda">
<div className="row">
<div className="col-md-9">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="row align-items-center">
<div className="col-1">
<span className="fw-bold">Month</span>
</div>
<div className="col">
<select
className="form-select"
value={mes}
onChange={(e) => setMes(e.target.value)}
>
<option value="">Seleccione Mes</option>
<option value="01">Enero</option>
<option value="02">Febrero</option>
<option value="03">Marzo</option>
</select>
</div>
<div className="col-1">
<span className="fw-bold">Year</span>
</div>
<div className="col">
<input
type="text"
className="form-control"
value={agno}
onChange={(e) => setAgno(e.target.value)}
/>
</div>
<div className="col-2">
<button
type="button"
className="btn btn-primary btn-sm w-100"
onClick={handleBuscar}
>
Buscar
</button>
</div>
</div>
</div>
</div>
<div className="col-md-3 mx-auto">
<button
type="button"
className="btn p-0 text-start w-100 text-decoration-none border-0 bg-transparent"
onClick={handleExportarExcel}
>
<div className="alert alert-success shadow" role="alert">
<div className="row align-items-center">
<div className="col-md-3">
<h1 className="mb-0">
{/* <Export /> */}
</h1>
</div>
<div className="col text-center">
<span className="text-muted">
<strong>Excel</strong>
</span>
<h5 className="mb-0">
<strong>Exportar Mensual</strong>
</h5>
</div>
</div>
</div>
</button>
</div>
<div className="col-md-12">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="table-responsive">
<table
className="table table-sm mb-0"
style={{ fontSize: "12px" }}
>
<thead>
<tr>
<th className="text-start" style={{ width: "3%" }}></th>
<th className="text-start" style={{ width: "5%" }}>
Contrato
</th>
<th className="text-start" style={{ width: "7%" }}>
Tipo
</th>
<th className="text-start" style={{ width: "18%" }}>
Empresa
</th>
<th className="text-start" style={{ width: "7%" }}>
Tipo Curso
</th>
<th className="text-start" style={{ width: "12%" }}>
Observacion
</th>
<th className="text-start" style={{ width: "10%" }}>
Fecha
</th>
</tr>
</thead>
<tbody>
{filesList.map((item, index) => (
<tr key={index}>
<td className="text-start" style={{ width: "3%" }}>
<button
type="button"
className="btn p-0 border-0 bg-transparent"
onClick={() =>
handleVerDetalle(
item.contrato,
item.cotizacion,
item.tipoVenta === "Cerrado" ? "C" : "A"
)
}
>
<span
className="badge bg-primary"
style={{ fontWeight: "normal" }}
>
Ver
</span>
</button>
</td>
<td className="text-start" style={{ width: "5%" }}>
{item.contrato}
</td>
<td className="text-start" style={{ width: "7%" }}>
{item.tipoVenta}
</td>
<td className="text-start" style={{ width: "18%" }}>
{item.empresa}
</td>
<td className="text-start" style={{ width: "7%" }}>
{item.tipoContrato === ""
? item.Responsable
: item.tipoContrato}
</td>
<td className="text-start" style={{ width: "12%" }}>
{item.observacion}
</td>
<td className="text-start" style={{ width: "10%" }}>
{item.fechaobservacion}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
)}
{/* SECCIÓN DE DETALLE DE EMPRESA Y TABLAS SECUNDARIAS */}
{showDetalle && (
<div className="col-md-12" id="div_detalle">
<div className="row">
<div className="col-md-3">
<div className="col-md-12">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<div className="table-responsive">
<table className="table" style={{ fontSize: "13px" }}>
<tbody className="table-group-divider">
<tr>
<td>
<h5 className="fs-6 mb-0">R.U.T.</h5>
</td>
<td>76.123.456-7</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Razon Social</h5>
</td>
<td className="text-wrap">Empresa Ejemplo S.A.</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Giro</h5>
</td>
<td className="text-wrap">Capacitaciones e Instrucción</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Direccion</h5>
</td>
<td className="text-wrap">Av. Providencia 1234, Santiago</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Fono</h5>
</td>
<td>+56 2 2222 3333</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Email</h5>
</td>
<td className="text-wrap">contacto@empresa.cl</td>
</tr>
<tr>
<td>
<h5 className="fs-6 mb-0">Contacto</h5>
</td>
<td className="text-wrap">Juan Pérez</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="col-md-12">
<div className="alert alert-light text-dark shadow table-responsive">
<table className="table table-sm mb-0 caption-top">
<caption>
<h4>
<strong>Valores</strong>
</h4>
</caption>
<tbody>
<tr>
<th className="text-end align-middle">
<h4 className="mb-0">SubTotal</h4>
</th>
<td className="text-start">
<input
type="text"
className="form-control"
value={neto}
onChange={(e) => setNeto(e.target.value)}
/>
</td>
</tr>
<tr>
<th className="text-end align-middle mt-1">
<h4 className="mb-0">Descuento</h4>
</th>
<td className="text-start">
<input
type="text"
className="form-control"
value={descuento}
onChange={(e) => setDescuento(e.target.value)}
/>
</td>
</tr>
<tr>
<th className="text-end align-middle mt-1">
<h4 className="mb-0">Total</h4>
</th>
<td className="text-start">
<input
type="text"
className="form-control"
value={total}
onChange={(e) => setTotal(e.target.value)}
/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="col-md-9 col-sm-12">
<div className="row">
{/* TABLA CONTRATOS DETALLE */}
<div className="col-12">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<table className="table table-sm caption-top mb-0">
<thead>
<tr>
<th className="text-center" style={{ width: "5%" }}>
Ver contrato
</th>
<th className="text-center" style={{ width: "10%" }}>
Contrato
</th>
<td className="text-center" style={{ width: "10%" }}>
Estado
</td>
<td className="text-center" style={{ width: "20%" }}>
Curso
</td>
<td className="text-center" style={{ width: "5%" }}>
Participantes
</td>
<td className="text-center" style={{ width: "15%" }}>
Valor
</td>
</tr>
</thead>
<tbody>
{contratosDetalleList.map((item, idx) => (
<tr key={idx}>
<td className="text-center" style={{ width: "5%" }}>
<a
target="_blank"
href={item.Url}
className="btn btn-primary btn-sm"
rel="noreferrer"
>
{/* <BxsFilePdf /> */}
</a>
</td>
<th className="text-center" style={{ width: "10%" }}>
{item.Contrato}
</th>
<th
className="text-center mx-auto"
style={{ width: "10%" }}
>
{item["Firma Estado"] === 1
? "CONTRATO FIRMADO"
: "CONTRATO SIN FIRMAR"}
</th>
<td className="text-center" style={{ width: "20%" }}>
{`${item["CURSO ID"]} ${item.CURSO} ${item.JORNADA} ${item.DIREMP} ${item.Fecha}`}
</td>
<td className="text-center" style={{ width: "5%" }}>
<button
type="button"
className="btn btn-link p-0 text-decoration-none d-inline-flex align-items-center gap-1"
onClick={() =>
handleVerParticipantes(item.Contrato)
}
>
<SearchPlus /> Ver Participantes
</button>
</td>
<td className="text-center" style={{ width: "15%" }}>
{item.Valor}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* TABLA COMPROBANTES / OC */}
<div className="col-md-6">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<table className="table table-sm caption-top mb-0">
<caption>Comprobantes de Pagos u Orden de Compras</caption>
<thead>
<tr>
<th className="text-start" style={{ width: "5%" }}></th>
<th className="text-start small" style={{ width: "10%" }}>
Número Interno
</th>
<th className="text-center small" style={{ width: "10%" }}>
Fecha de Subida
</th>
<th className="text-center small" style={{ width: "10%" }}>
Tipo Documento
</th>
<th className="text-center small" style={{ width: "10%" }}>
Responsable
</th>
</tr>
</thead>
<tbody>
{ocList.map((oc, idx) => (
<tr key={idx}>
<td className="text-start" style={{ width: "5%" }}>
<a
target="_blank"
href={`https://empresas.norteamericano.cl/ComprobantesPagos/${oc.Detalle}`}
className="btn btn-primary btn-sm"
rel="noreferrer"
>
Ver
</a>
</td>
<td
className="text-start small text-wrap"
style={{ width: "10%" }}
>
{oc["Numero interno"]}
</td>
<td className="text-center small" style={{ width: "10%" }}>
{oc["Fecha de subida pago"]}
</td>
<td className="text-center small" style={{ width: "10%" }}>
{oc["Tipo documento"]}
</td>
<td className="text-center small" style={{ width: "10%" }}>
{oc.Responsable}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* TABLA INSCRIPCIÓN SENCE */}
<div className="col-md-6">
<div className="alert alert-light text-dark shadow-sm" role="alert">
<table className="table table-sm caption-top mb-0">
<caption>Inscripcion SENCE</caption>
<thead>
<tr>
<th className="text-center" style={{ width: "10%" }}></th>
<th className="text-center" style={{ width: "40%" }}>
Inscripción sence
</th>
<th className="text-center" style={{ width: "20%" }}>
Fecha de subida
</th>
<th className="text-center" style={{ width: "30%" }}>
Responsable
</th>
</tr>
</thead>
<tbody>
{sncList.map((snc, idx) => (
<tr key={idx}>
<th className="text-center" style={{ width: "10%" }}>
<a
target="_blank"
href={`https://empresas.norteamericano.cl/DocumentosSence/${snc.Detalle}`}
className="btn btn-primary btn-sm"
rel="noreferrer"
>
Ver
</a>
</th>
<td className="text-center small" style={{ width: "40%" }}>
{snc.codInscripcion}
</td>
<td className="text-center small" style={{ width: "20%" }}>
{snc["Fecha de subida"]}
</td>
<td className="text-center small" style={{ width: "30%" }}>
{snc.Responsable}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>
{/* --- MODAL PARTICIPANTES (ALUMNOS) --- */}
{modalAlumnos && (
<div
className="modal fade show d-block bg-dark bg-opacity-50"
tabIndex={-1}
role="dialog"
>
<div className="modal-dialog modal-dialog-centered modal-xl" role="document">
<div className="modal-content">
<div
className="modal-header text-white text-center"
style={{ backgroundColor: "#373193" }}
>
<h5 className="modal-title">Alumnos</h5>
<button
type="button"
className="btn-close btn-close-white"
onClick={() => setModalAlumnos(false)}
></button>
</div>
<div className="modal-body">
<table
className="table table-bordered table-hover table-sm mb-0"
style={{ backgroundColor: "white", fontSize: "12px" }}
>
<thead>
<tr>
<th className="text-start" style={{ width: "10%" }}>
RUN
</th>
<th className="text-center" style={{ width: "30%" }}>
Nombre Alumno
</th>
<th className="text-center" style={{ width: "20%" }}>
Tipo Registro
</th>
<th className="text-center" style={{ width: "40%" }}>
Empresa Apoderada
</th>
</tr>
</thead>
<tbody>
{alumnosList.map((alm, index) => (
<tr key={index}>
<td className="text-start">{alm.run}</td>
<td className="text-center">{alm.nombreCompleto}</td>
<td className="text-center">{alm.tipoRegistro}</td>
<td className="text-center">{alm.empresaApoderada}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={() => setModalAlumnos(false)}
>
Cerrar
</button>
</div>
</div>
</div>
</div>
)}
{/* --- MODAL ALERTA DE MENSAJES --- */}
{modalAlerta.show && (
<div
className="modal fade show d-block bg-dark bg-opacity-50"
tabIndex={-1}
role="dialog"
>
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div className="modal-content text-dark">
<div className="modal-header alert alert-secondary mb-0">
<h5 className="float-start mt-2">
<strong>Módulo Academico - Empresa</strong>
</h5>
<button
type="button"
className="btn-close float-end mt-1"
onClick={() => setModalAlerta({ show: false, message: "" })}
aria-label="Close"
></button>
</div>
<div className="modal-body alert mb-0" style={{ textAlign: "justify" }}>
<div className="row mb-2">
<div className="col-md-12 text-center">
<h5>
<strong>{modalAlerta.message}</strong>
</h5>
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-primary"
onClick={() => setModalAlerta({ show: false, message: "" })}
>
Close
</button>
</div>
</div>
</div>
</div>
)}
{/* --- MODAL CARGANDO (SPINNER) --- */}
{isLoading && (
<div
className="modal fade show d-block bg-dark bg-opacity-50"
tabIndex={-1}
role="dialog"
>
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div className="modal-content text-dark">
<div className="modal-header alert alert-secondary mb-0">
<h5 className="float-start mt-2">
<strong>Procesando</strong>
</h5>
</div>
<div className="modal-body alert mb-0" style={{ textAlign: "justify" }}>
<div className="row mb-2">
<div className="col-md-12 text-center">
<h5>
<strong>Espere un momento, por favor...</strong>
</h5>
<div className="d-flex justify-content-center gap-1 mt-2">
<div
className="spinner-grow spinner-grow-sm text-primary"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-danger"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-primary"
role="status"
></div>
<div
className="spinner-grow spinner-grow-sm text-danger"
role="status"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
}
+634
View File
@@ -0,0 +1,634 @@
'use client'
import { ArrowToBottomStroke, MessageCaptions, TrendingUp, UserCheck, Star, StarHalf } from "@boxicons/react";
import { useEffect, useState } from "react";
const mapaSedes: Record<string, string> = {
"0": "TODAS",
"1": "MONEDA",
"2": "PROVIDENCIA",
"3": "LA FLORIDA",
"4": "ONLINE",
"5": "EMPRESAS",
};
const mapaEncuesta: Record<string, string> = {
"0": "ALL",
"1": "OPINION",
"2": "CERTIFICADO",
"3": "OBSERVACION",
};
export default function Page() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [activeTab, setActiveTab] = useState('');
const [tabMetrica, setMetricTab] = useState(false);
const [tabDetalle, setDetalle] = useState(false);
const [SelectF, setFiltro] = useState('');
const [sedeSelect, setSedeSelect] = useState('0');
const [encuestaSelect, setEncuestaSelect] = useState('0');
const handleActionFiltro = (tipo: number) => {
if (tipo === 1) {
setFiltro('1')
setActiveTab('todos');
}
else if (tipo === 2) {
setFiltro('2')
setActiveTab('cerrados');
}
else if (tipo === 3) {
setFiltro('3')
setActiveTab('abiertos');
}
};
useEffect(() => {
try {
handleActionFiltro(1);
} catch (err) {
console.error("Error al ejecutar filtro inicial:", err);
} finally {
// 2. 'finally' garantiza que setLoading(false) se ejecute SIEMPRE, haya o no error
setLoading(false);
}
}, []);
if (loading) return <div className="text-center py-5">Cargando...</div>;
if (error) return <div className="alert alert-danger my-3">{error}</div>;
//Metricas
const dataMetric = [
{
idKey: 0,
representatividad: 25,
promedioTotal: "43 %",
cursos: 10,
alumnos: 18,
respondieron: 6,
},
{
idKey: 1,
representatividad: 10,
promedioTotal: "19 %",
cursos: 9,
alumnos: 1,
respondieron: 0,
}
];
const dataSummary = [
{
docenteID: "18172636-9",
docente: "FELIPE MENA",
tipo: "Cerrado",
cursoID: "6203",
curso: "PRE-INTERMEDIATE 1",
sede: "EMPRESAS",
almTotal: "25",
Answ: "9",
},
{
docenteID: "18636172-9",
docente: "IGNACIO MUNOZ",
tipo: "ABIERTO",
cursoID: "6318",
curso: "BEGINNER 1",
sede: "MONEDA",
almTotal: "12",
Answ: "0",
},
];
const datosFiltrados = dataSummary.filter((item) => {
if (sedeSelect === "0") return true;
const sedeNombre = mapaSedes[sedeSelect];
return item.sede.toUpperCase() === sedeNombre.toUpperCase();
});
const metricaActual = dataMetric.find((m) => m.idKey === Number(sedeSelect)) || {
representatividad: 0,
promedioTotal: "0 %",
cursos: 0,
alumnos: 0,
respondieron: 0,
};
const dataDetalle = [
{id: "6203",
nombre: "PRE-INTERMEDIATE 1",
tipo: "Cerrado",
horario: "19:00 - 21:00",
fechaInicio: "01/03/2026",
alumnos: 0,
respuestas: 0,
detractores: 0,
pasivos: 0,
promotores: 0},
];
const dataAlumnos =[
{
id:1,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "OPINION",
question: "Recomendarias el norteamericano?",
answer: 0,
},
{ id:2,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "OPINION",
question: "Recomendarias el norteamericano?",
answer: 1,
},
{ id:3,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "CERTIFICADO",
question: "Recomendarias el norteamericano?",
answer: 2,
},
{ id:4,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "CERTIFICADO",
question: "Recomendarias el norteamericano?",
answer: 3,
},
{ id:5,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "OBSERVACION",
question: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ut explicabo nostrum blanditiis quisquam quos deleniti voluptate.",
answer: 4,
},
{ id:6,
run: "11726398-3",
ap_p: "Lillo",
nombre: "Juan",
tipoQ: "OBSERVACION",
question: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ut explicabo nostrum blanditiis quisquam quos deleniti voluptate, ipsam voluptates repellendus odio nam accusamus error nihil, porro quae, illum dolore consequuntur vel.",
answer: 5,
}
];
const datosFiltradosAlumno = dataAlumnos.filter((item) => {
if (encuestaSelect === "0") return true;
const tipoNombre = mapaEncuesta[encuestaSelect];
return item.tipoQ.toUpperCase() === tipoNombre.toUpperCase();
});
const renderEstrellas = (rating: number) => {
const estrellas = [];
const max = 5;
for (let i = 1; i <= max; i++) {
if (rating >= i) {
// Estrella llena
estrellas.push(<Star key={i} size="sm" type="solid" className="text-warning" />);
} else if (rating >= i - 0.75 && rating < i) {
// Media estrella (para decimales como 4.3, 4.5, 4.7)
estrellas.push(<StarHalf key={i} size="sm" type="solid" className="text-warning" />);
} else {
// Estrella vacía
estrellas.push(<Star key={i} size="sm" className="text-muted" />);
}
}
return estrellas;
};
return (
<div className="row">
{/* Seccion de Filtros y Rango de Fechas */}
<div className="col-md-12">
<div className="row">
<div className="col-md-5">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col">
<strong>
<i className="bx bx-user" style={{ fontSize: '24px' }}></i>
</strong>
<strong>
<span className="ms-2">Encuesta de alumnos</span>
</strong>
</div>
<div className="col-3 text-end">
<button type="button" id="LinkButtonVolver"
className="btn btn-warning btn-sm">
<strong>Volver</strong>
</button>
</div>
</div>
</div>
</div>
<div className="col-md-7">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-3">
<span className="fw-bold">Rango de búsqueda</span>
</div>
<div className="col-md-9">
<select id="ListaSedes"
className="form-control"
value={SelectF}
onChange={(e) => handleActionFiltro(Number(e.target.value))}>
<option value="1">TODAS</option>
<option value="2">Cursos Cerrados</option>
<option value="3">Cursos Plan Central</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Filtro de Todos*/}
{activeTab === 'todos' && (
<div className="col-md-12">
<div className="row justify-content-center">
<div className="col-md-8 text-center">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-3">
<span className="fw-bold">Rango de búsqueda</span>
</div>
<div className="col-md-3">
<input type="date"
id="allIni"
className="form-control form-control-sm"
value="2026-01-01"
// onChange={(e) => setFechaAgno(e.target.value)}
/>
</div>
<div className="col-md-3">
<input type="date"
id="allTer"
className="form-control form-control-sm"
value="2026-12-31"
// onChange={(e) => setFechaAgno(e.target.value)}
/>
</div>
<div className="col-md-3">
<button
type="button"
className="btn btn-primary btn-sm w-100"
onClick={() => { setMetricTab(true) }}
>
Buscar
</button>
</div>
</div>
</div>
</div>
</div>
</div>
)}
{/* Filtro de Cerrados*/}
{activeTab === 'cerrados' && (<div> Cerrados</div>)}
{/* Filtro de Abiertos*/}
{activeTab === 'abiertos' && (<div> Plan Central</div>)}
{/* Metricas de representatividad, cursos y alumnos */}
{tabMetrica && (
<div className="row align-items-center">
<div className="col-md-4 col-sm-12">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-3 col-sm-12 text-center">
<UserCheck removePadding size="xl" />
</div>
<div className="col text-center">
<span className="text-muted">
<strong>Representatividad de alumnos que respondieron</strong>
</span>
<h3>
{metricaActual.representatividad}
</h3>
</div>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12 text-center">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-3 col-sm-12">
<TrendingUp removePadding size="xl" />
</div>
<div className="col text-center">
<span className="text-muted">
<strong>Promedio de cursos que respondieron</strong>
</span>
<h3>{metricaActual.promedioTotal}</h3>
</div>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-2 col-sm-12 text-center">
<MessageCaptions removePadding size="lg" />
</div>
<div className="col-md-10 text-center col-sm-12">
<table className="table table-sm mb-0 table-borderless">
<thead>
<tr>
<td><span className="text-muted"><strong>Cursos</strong></span></td>
<td><span className="text-muted"><strong>Alumnos</strong></span></td>
<td><span className="text-muted"><strong>Respondieron</strong></span></td>
</tr>
</thead>
<tbody>
<tr>
<td><strong>{metricaActual.cursos}</strong></td>
<td><strong>{metricaActual.alumnos}</strong></td>
<td><strong>{metricaActual.respondieron}</strong></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div className="col-md-6">
<button type="button"
id="LinkButton1"
className="btn p-0 border-0 w-100 text-center text-decoration-none"
//onClick={handleDescargar}
>
<div className="alert alert-success" role="alert">
<div className="row align-items-center text-center">
<div className="col-md-6 text-end col-sm-6">
<h1 className="m-0"><ArrowToBottomStroke /></h1>
</div>
<div className="col text-start">
<span className="text-muted"><strong>Exportar</strong></span>
<h5 className="m-0">
<strong><span id="Label1">NPS Empresas</span></strong>
</h5>
</div>
</div>
</div>
</button>
</div>
<div className="col-md-6">
<button type="button"
id="LinkButton1"
className="btn p-0 border-0 w-100 text-center text-decoration-none"
//onClick={handleDescargar}
>
<div className="alert alert-success" role="alert">
<div className="row align-items-center text-center">
<div className="col-md-6 text-end col-sm-6">
<h1 className="m-0"><ArrowToBottomStroke /></h1>
</div>
<div className="col text-start">
<span className="text-muted"><strong>Exportar</strong></span>
<h5 className="m-0">
<strong><span id="Label1">Opinion Empresas</span></strong>
</h5>
</div>
</div>
</div>
</button>
</div>
<div className="col-md-12">
<div className="alert alert-light text-dark" role="alert">
<div className="table-responsive">
<table className="table table-sm table-hover mb-0 caption-top" style={{ fontSize: '12px' }}>
<caption className="text-center">
<h6>SEDE:</h6>
<select id="ListaSedes"
className="form-control text-center"
value={sedeSelect}
onChange={(e) => setSedeSelect(e.target.value)}
>{Object.entries(mapaSedes).map(([value, label]) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
</caption>
<thead>
<tr>
<th className="text-start" style={{ width: '8%' }}> </th>
<th className="text-start" style={{ width: '15%' }}>Docente</th>
<th className="text-start" style={{ width: '8%' }}>Tipo Curso</th>
<th className="text-start" style={{ width: '5%' }}>ID Curso</th>
<th className="text-start" style={{ width: '15%' }}>Curso</th>
<th className="text-start" style={{ width: '12%' }}>Sede</th>
<th className="text-start" style={{ width: '7%' }}>Total de Alumnos</th>
<th className="text-start" style={{ width: '7%' }}>Respuestas</th>
</tr>
</thead>
<tbody>
{/* Fila de ejemplo estática para mapear con data dynamic (.map) */}
{datosFiltrados.length === 0 ? (
<tr>
<td colSpan={8} className="text-center py-4 text-muted fw-bold">
Sin datos asociados a la sede
</td>
</tr>
) : (
datosFiltrados.map((a) => (
<tr key={`${a.docenteID}-${a.cursoID}`}>
<td className="text-start fs-6" style={{ width: '8%' }}>
<button className="btn btn-primary btn-sm" onClick={() => { setDetalle(true), setMetricTab(false) } }>Ver detalle</button>
</td>
<td className="text-start" style={{ width: '15%' }}>{a.docente}</td>
<td className="text-start" style={{ width: '8%' }}>{a.tipo}</td>
<td className="text-start" style={{ width: '5%' }}>{a.cursoID}</td>
<td className="text-start" style={{ width: '15%' }}>{a.curso}</td>
<td className="text-start" style={{ width: '12%' }}>{a.sede}</td>
<td className="text-start" style={{ width: '7%' }}>{a.almTotal}</td>
<td className="text-start" style={{ width: '7%' }}>{a.Answ}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
)}
{tabDetalle && (
<div className="row align-items-center">
<div className="col-md-4">
<div className="alert alert-light text-dark" role="alert">
<table className="table table-sm mb-1" style={{ fontSize: "14px" }}>
<tbody>
<tr>
<td style={{ width: "15%" }}>
<strong className="text-muted">Curso</strong>
</td>
<td colSpan={2}>
<strong>{dataDetalle[0].nombre}</strong>
</td>
</tr>
<tr>
<td style={{ width: "15%" }}>
<strong className="text-muted">Horario</strong>
</td>
<td colSpan={2}>
<strong>{dataDetalle[0].horario}</strong>
</td>
</tr>
<tr>
<td style={{ width: "15%" }}>
<strong className="text-muted">Fecha</strong>
</td>
<td colSpan={2}>
<strong>{dataDetalle[0].fechaInicio}</strong>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div className="col-md-3">
<div className="alert alert-light text-dark" role="alert">
<table className="table mb-0" style={{ fontSize: "14px" }}>
<tbody>
<tr>
<td>
<strong className="text-muted">Alumnos</strong>
</td>
<td>
<strong>{dataDetalle[0].alumnos}</strong>
</td>
</tr>
<tr>
<td>
<strong className="text-muted">Respondieron</strong>
</td>
<td>
<strong>{dataDetalle[0].respuestas}</strong>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div className="col-md-5">
<div className="alert alert-light text-dark" role="alert">
<table className="table text-center mb-0" style={{ fontSize: "14px" }}>
<tbody>
<tr>
<td>
<strong className="text-muted">Detractores</strong>
</td>
<td>
<strong className="text-muted">Pasivos</strong>
</td>
<td>
<strong className="text-muted">Promotores</strong>
</td>
</tr>
<tr>
<td>
<strong>{dataDetalle[0].detractores}</strong>
</td>
<td>
<strong>{dataDetalle[0].pasivos}</strong>
</td>
<td>
<strong>{dataDetalle[0].promotores}</strong>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div className="col-md-12">
<button type="button"
className="btn p-0 border-0 w-100 text-center text-decoration-none"
//onClick={handleDescargar}
>
<div className="alert alert-success" role="alert">
<div className="row align-items-center text-center">
<div className="col-md-6 text-end col-sm-6">
<h1 className="m-0"><ArrowToBottomStroke /></h1>
</div>
<div className="col text-start">
<span className="text-muted"><strong>Exportar</strong></span>
<h5 className="m-0">
<strong><span id="Label1">Encuesta curso</span></strong>
</h5>
</div>
</div>
</div>
</button>
</div>
{/* Cambiar profe por alumnos detalle del curso y respuestas en numeros por estrellas representativas */}
<div className="col-md-12">
<div className="alert alert-light text-dark" role="alert">
<div className="table-responsive">
<table className="table table-sm table-hover mb-0 caption-top" style={{ fontSize: '12px' }}>
<caption className="text-center">
<h6>SEDE:</h6>
<select
className="form-control text-center"
value={encuestaSelect}
onChange={(e) => setEncuestaSelect(e.target.value)}
>{Object.entries(mapaEncuesta).map(([value, label]) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
</caption>
<thead>
<tr>
<th className="text-start" style={{ width: '8%' }}>Ficha</th>
<th className="text-start" style={{ width: '15%' }}>R.U.N.</th>
<th className="text-start" style={{ width: '8%' }}>Apellido</th>
<th className="text-start" style={{ width: '5%' }}>Nombre</th>
<th className="text-start" style={{ width: '15%' }}>Tipo Encuesta</th>
<th className="text-start" style={{ width: '12%' }}>Pregunta</th>
<th className="text-start" style={{ width: '7%' }}>Respuesta</th>
</tr>
</thead>
<tbody>
{/* Fila de ejemplo estática para mapear con data dynamic (.map) */}
{datosFiltradosAlumno.length === 0 ? (
<tr>
<td colSpan={8} className="text-center py-4 text-muted fw-bold">
Sin datos asociados a la sede
</td>
</tr>
) : (
datosFiltradosAlumno.map((a) => (
<tr key={`${a.id}-${a.run}`}>
<td className="text-start fs-6" style={{ width: '8%' }}>
<button className="btn btn-primary btn-sm" >Ver</button>
</td>
<td className="text-start" style={{ width: '15%' }}>{a.run}</td>
<td className="text-start" style={{ width: '8%' }}>{a.ap_p}</td>
<td className="text-start" style={{ width: '5%' }}>{a.nombre}</td>
<td className="text-start" style={{ width: '15%' }}>{a.tipoQ}</td>
<td className="text-start" style={{ width: '12%' }}>{a.question}</td>
{/* Muestra las estrellas dinámicamente */}
<td className="text-start" style={{ width: '7%' }}>{renderEstrellas(a.answer)}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
)}
</div>
);
}
+304
View File
@@ -0,0 +1,304 @@
'use client';
import { ArrowToBottomStroke } from "@boxicons/react";
import { useState, useEffect } from "react";
import { descargarExcelProfesor } from '../../excel'; // O donde guardes la función
// bx-export
export default function SesionesEstipuladasPage() {
/* constantes de validaciones cargas, errores y visibles*/
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [mostrarSesiones,setSesiones] = useState(false);
const dataSesionesProfesor = [
{ TitularID: "18172636-9",
paterno: "MENA",
materno: "MUNOZ",
nombre: "FELIPE",
CursoID: "6203",
Curso: "PRE-INTERMEDIATE 1",
AsignacionDocente: "TITULAR",
FechaInicio: "01-06-2026",
FechaFin: "05-09-2026",
Schedule:"LU MI 10:00:00 - 12:00:00 / MA JU 15:00:00 - 16:00:00",
DuracionEstipulada:"01:00:00",
Sesion:"12-08-2026",
},
{ TitularID: "18172636-9",
paterno: "MENA",
materno: "MUNOZ",
nombre: "FELIPE",
CursoID: "6213",
Curso: "PRE-INTERMEDIATE 2",
AsignacionDocente: "TITULAR",
FechaInicio: "01-06-2026",
FechaFin: "05-09-2026",
Schedule:"LU MI 10:00:00 - 12:00:00 / MA JU 15:00:00 - 16:00:00",
DuracionEstipulada:"01:00:00",
Sesion:"12-08-2026",
},
];
useEffect(() => {
setIni();
return setLoading(false);
}, []);
const handleDescargar = () => {
descargarExcelProfesor(dataSesionesProfesor, 'Reporte_Sesiones');
};
const [fechaAgno, setFechaAgno] = useState('');
const [mesSelect, setFechaMes] = useState('');
const [fechaIni, setFechaIni] = useState('');
const [fechaTer, setFechaTer] = useState('');
function setIni(){
const hoy = new Date();
const anio = hoy.getFullYear();
const mes = String(hoy.getMonth() + 1);
const varA = `${anio}`;
setFechaAgno(varA);
setFechaMes(mes);
}
function CargaSesiones(){
setFechasSearch();
setSesiones(true);
}
function setFechasSearch(){
const anioNum = Number(fechaAgno);
const mesNum = Number(mesSelect); // Valor de 1 a 12
const anioA = fechaAgno;
const mesA = String(mesNum).padStart(2, '0');
const diaA = "21";
const varA = `${anioA}-${mesA}-${diaA}`;
const fechaAnterior = new Date(anioNum, mesNum - 2, 20);
const anioB = fechaAnterior.getFullYear();
const mesB = String(fechaAnterior.getMonth() + 1).padStart(2, '0');
const diaB = "20";
const varB = `${anioB}-${mesB}-${diaB}`;
setFechaIni(varA);
setFechaTer(varB);
}
if (loading) return <div className="text-center py-5">Cargando...</div>;
if (error) return <div className="alert alert-danger my-3">{error}</div>;
return (
<>
<div className="row">
{/* Seccion de Filtros y Rango de Fechas */}
<div className="col-md-12">
<div className="row">
<div className="col-md-5">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col">
<strong>
<i className="bx bx-user" style={{ fontSize: '24px' }}></i>
</strong>
<strong>
<span className="ms-2">Sesiones estipuladas del profesores</span>
</strong>
</div>
<div className="col-3 text-end">
<button type="button" id="LinkButtonVolver"
className="btn btn-warning text-dark btn-sm"
>
<strong>Volver</strong>
</button>
</div>
</div>
</div>
</div>
<div className="col-md-7">
<div className="alert alert-light" role="alert">
<div className="row align-items-center">
<div className="col-md-3">
<span className="fw-bold">Rango de búsqueda</span>
</div>
<div className="col-md-3">
<input type="number"
id="fechaIni"
className="form-control form-control-sm"
value={fechaAgno}
onChange={(e) => setFechaAgno(e.target.value)}
/>
</div>
<div className="col-md-3">
<select id="ListaSedes"
className="form-control"
value={mesSelect}
onChange={(e) => setFechaMes(e.target.value)}
>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</div>
<div className="col-md-3">
<button
type="button"
id="LinkButtonBuscar"
className="btn btn-primary btn-sm w-100"
onClick={() => CargaSesiones()}>
Buscar
</button>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Sección de Resultados */}
{mostrarSesiones && (
<div className="col-md-12">
<div className="row">
{/* Botón Exportar a Excel */}
<div className="col-md-12 mt-2">
<button type="button"
id="LinkButton1"
className="btn p-0 border-0 w-100 text-center text-decoration-none"
onClick={handleDescargar}
>
<div className="alert alert-success" role="alert">
<div className="row align-items-center text-center">
<div className="col-md-6 text-end col-sm-6">
<h1 className="m-0"><ArrowToBottomStroke /></h1>
</div>
<div className="col text-start">
<span className="text-muted"><strong>Excel</strong></span>
<h5 className="m-0">
<strong><span id="Label1">Exportar</span></strong>
</h5>
</div>
</div>
</div>
</button>
</div>
{/* Tabla de Informe Docente */}
<div className="col-md-12">
<div className="alert alert-light text-dark" role="alert">
<div className="table-responsive">
<table className="table table-sm table-hover mb-0 caption-top" style={{ fontSize: '12px' }}>
<caption><h6>Rango de Fecha: {fechaTer} ~ {fechaIni} </h6></caption>
<thead>
<tr>
<th className="text-start" style={{ width: '7%' }}>ID</th>
<th className="text-start" style={{ width: '8%' }}>Apellido Paterno</th>
<th className="text-start" style={{ width: '8%' }}>Apellido Materno</th>
<th className="text-start" style={{ width: '8%' }}>Nombre</th>
<th className="text-start" style={{ width: '5%' }}>ID Curso</th>
<th className="text-start" style={{ width: '15%' }}>Curso</th>
<th className="text-start" style={{ width: '7%' }}>Asignación</th>
<th className="text-start" style={{ width: '7%' }}>Inicio Curso</th>
<th className="text-start" style={{ width: '7%' }}>Término Curso</th>
<th className="text-start" style={{ width: '16%' }}>Schedule</th>
<th className="text-start" style={{ width: '5%' }}>Duración</th>
<th className="text-start" style={{ width: '7%' }}>Sesión</th>
</tr>
</thead>
<tbody>
{/* Fila de ejemplo estática para mapear con data dynamic (.map) */}
{dataSesionesProfesor.map((a) =>(
<tr key={`${a.TitularID}-${a.CursoID}-${a.Sesion}`}>
<td className="text-start" style={{ width: '7%' }}>{a.TitularID}</td>
<td className="text-start" style={{ width: '8%' }}>{a.paterno}</td>
<td className="text-start" style={{ width: '8%' }}>{a.materno}</td>
<td className="text-start" style={{ width: '8%' }}>{a.nombre}</td>
<td className="text-start" style={{ width: '5%' }}>{a.CursoID}</td>
<td className="text-start" style={{ width: '15%' }}>{a.Curso}</td>
<td className="text-start" style={{ width: '7%' }}>{a.AsignacionDocente}</td>
<td className="text-start" style={{ width: '7%' }}>{a.FechaInicio}</td>
<td className="text-start" style={{ width: '7%' }}>{a.FechaFin}</td>
<td className="text-start" style={{ width: '16%' }}>{a.Schedule}</td>
<td className="text-start" style={{ width: '5%' }}>{a.DuracionEstipulada}</td>
<td className="text-start" style={{ width: '7%' }}>{a.Sesion}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
)
}
</div>
{/* MODAL DE CARGA (LOADING) */}
<div className="modal fade" id="modalCargando" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex={-1} aria-hidden="true">
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content text-dark">
<div className="modal-header alert alert-secondary mb-0">
<h5 className="modal-title">
<strong><i className="bx bx-loader-alt bx-spin me-2"></i>Procesando</strong>
</h5>
</div>
<div className="modal-body text-center py-4">
<h5 className="mb-3"><strong>Por favor espere un momento...</strong></h5>
<div className="d-flex justify-content-center gap-2">
<div className="spinner-grow spinner-grow-sm text-primary" role="status"><span className="visually-hidden">Cargando...</span></div>
<div className="spinner-grow spinner-grow-sm text-secondary" role="status"><span className="visually-hidden">Cargando...</span></div>
<div className="spinner-grow spinner-grow-sm text-primary" role="status"><span className="visually-hidden">Cargando...</span></div>
<div className="spinner-grow spinner-grow-sm text-secondary" role="status"><span className="visually-hidden">Cargando...</span></div>
</div>
</div>
</div>
</div>
</div>
{/* MODAL DE ERROR */}
<div className="modal fade" id="modalError" tabIndex={-1} aria-hidden="true">
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content text-dark">
<div className="modal-header alert alert-danger mb-0">
<h5 className="modal-title text-danger d-flex align-items-center">
<i className="bx bx-error-circle me-2 fs-4"></i>
<strong>Error de Sistema</strong>
</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body text-center py-4">
<p className="mb-0 fs-6" id="mensajeErrorText">
Ocurrió un problema al procesar la solicitud. Por favor intente nuevamente.
</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cerrar</button>
</div>
</div>
</div>
</div>
</>
);
}