Arreglo de node_modules
This commit is contained in:
commit
eed3b45de3
40 files changed
+13127
No files matched your search
Executable
+349
@@ -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
@@ -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>
|
||||
);
|
||||
}
|
||||
Executable
+634
@@ -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>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
Executable
+304
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user