Se agregarn vistas faltantes al proyecto. Queda pendiente funcionaildades de API
This commit is contained in:
1 parent
eed3b45de3
commit
a2fbd4b675
17 files changed
+7223
-101
No files matched your search
@@ -0,0 +1,47 @@
|
||||
Proyecto Web/Web (solo archivos .aspx)
|
||||
├── Academico/
|
||||
│ ├── CodigosSence.aspx
|
||||
│ ├── CodigosSencePC.aspx
|
||||
│ ├── Cursos.aspx
|
||||
│ ├── CursosPC.aspx
|
||||
│ ├── index.aspx
|
||||
│ ├── Libros.aspx
|
||||
│ ├── PlanDeEstudio.aspx
|
||||
│ └── Ponderaciones.aspx
|
||||
├── Administrador/
|
||||
│ └── ActualizarSesiones.aspx
|
||||
├── Alumnos/
|
||||
│ ├── EvaluacionPresencial.aspx
|
||||
│ ├── Ficha.aspx
|
||||
│ └── Index.aspx
|
||||
├── Clientes/
|
||||
│ ├── Autorizador.aspx
|
||||
│ ├── DesactivaContratos.aspx
|
||||
│ ├── Ficha.aspx
|
||||
│ ├── Index.aspx
|
||||
│ └── InfoEmpresas.aspx
|
||||
├── Cursos/
|
||||
│ ├── Administrador.aspx
|
||||
│ ├── Index.aspx
|
||||
│ └── Reemplazo.aspx
|
||||
├── Informes/
|
||||
│ ├── AlumnosActivos.aspx
|
||||
│ ├── AlumnosCursos.aspx
|
||||
│ ├── AlumnosEmpresas.aspx
|
||||
│ ├── AlumnosPeriodos.aspx
|
||||
│ ├── Autorizados.aspx
|
||||
│ ├── ContratosHistorial.aspx
|
||||
│ ├── CursosActivos.aspx
|
||||
│ ├── CursosAsistencias.aspx
|
||||
│ ├── CursosDocentes.aspx
|
||||
│ ├── CursosDocentesFinalizados.aspx
|
||||
│ ├── CursosFechas.aspx
|
||||
│ ├── CursosInicios.aspx
|
||||
│ ├── Index.aspx
|
||||
│ ├── PollAnalysis.aspx
|
||||
│ ├── PollStudents.aspx
|
||||
│ ├── SesionesEstipuladas.aspx
|
||||
│ └── SesionesProfesores.aspx
|
||||
├── Profesor/
|
||||
│ └── Ficha.aspx
|
||||
└── Index.aspx
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
|
||||
<link href="../css/check-radio.css" rel="stylesheet" />
|
||||
<script src="../js/jquery-ui-1.9.2.custom.min.js"></script>
|
||||
<link href="../css/jquery-ui.css" rel="stylesheet" />
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$(".cargando").click(function () {
|
||||
|
||||
$("#mensajeCargando").modal("show");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
|
||||
$(function () {
|
||||
$(".datepicker").datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dateFormat: "yy-mm-dd",
|
||||
});
|
||||
});
|
||||
|
||||
$(function ($) {
|
||||
$.datepicker.dates = {
|
||||
closeText: 'Cerrar',
|
||||
prevText: '< Ant',
|
||||
nextText: 'Sig >',
|
||||
currentText: 'Hoy',
|
||||
monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
monthNamesShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
|
||||
dayNames: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
|
||||
dayNamesShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Juv', 'Vie', 'Sáb'],
|
||||
dayNamesMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sá"],
|
||||
weekHeader: 'Sm',
|
||||
dateFormat: 'dd-mm-yy',
|
||||
firstDay: 1,
|
||||
isRTL: false,
|
||||
showMonthAfterYear: false,
|
||||
yearSuffix: ''
|
||||
};
|
||||
$.datepicker.setDefaults($.datepicker.regional['es']);
|
||||
});
|
||||
|
||||
function valideKey(evt) {
|
||||
|
||||
// code is the decimal ASCII representation of the pressed key.
|
||||
var code = (evt.which) ? evt.which : evt.keyCode;
|
||||
|
||||
if (code == 8) { // backspace.
|
||||
return true;
|
||||
} else if (code >= 48 && code <= 57) { // is a number.
|
||||
return true;
|
||||
} else { // other keys.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<div class="alert alert-light text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<strong>
|
||||
<i class='bx bx-user' style="font-size: 24px"></i>
|
||||
</strong>
|
||||
<strong>
|
||||
<span class="ms-2">Empresas por mes</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
<a href="<%=Page.ResolveUrl("~/Alumnos/Index.aspx") %>" class="btn btn-warning text-dark btn-sm"><strong>Volver</strong></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="alert alert-light text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="fw-bold">Mes</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<asp:DropDownList ID="ListaMeses" runat="server" CssClass="form-select"></asp:DropDownList>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="fw-bold">Agno</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<asp:TextBox ID="TextBoxYear" class="form-control form-control-sm" runat="server"></asp:TextBox>
|
||||
</div>
|
||||
<div class="col">
|
||||
<asp:LinkButton ID="LinkButtonBuscar" CssClass="btn btn-primary btn-sm d-grid" runat="server" OnClick="LinkButtonBuscar_Click">Buscar</asp:LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12" runat="server" id="div_reporte">
|
||||
<div class="alert alert-light shadow text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col-md-3 mt-5">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mx-auto" runat="server">
|
||||
<asp:LinkButton ID="LinkButtonExcel" runat="server" CssClass="text-decoration-none" OnClick="LinkButtonExcel_Click">
|
||||
<div class="alert alert-success shadow" role="alert">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<h1><i class='bx bx-export'></i></h1>
|
||||
</div>
|
||||
<div class="col text-center">
|
||||
<span class="text-muted"><strong>Excel</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="Label1" runat="server" Text="Exportar"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</asp:LinkButton>
|
||||
</div>
|
||||
<div class="col-md-12" runat="server">
|
||||
<div class="alert alert-light shadow text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col-md-3 text-center">
|
||||
<h1><i class="fa-solid fa-users-line"></i></h1>
|
||||
<span class="fw-bold"><strong>Alumnos</strong></span>
|
||||
</div>
|
||||
<div class="col text-center mt-3">
|
||||
<span class="text-muted"><strong>Total</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="LabelTotAlumnos" runat="server" Text="0"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12" runat="server">
|
||||
<div class="alert alert-light shadow text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col-md-3 text-center">
|
||||
<h1><i class='bx bx-building-house bx-lg'></i></h1>
|
||||
<span class="fw-bold"><strong>Empresas</strong></span>
|
||||
</div>
|
||||
<div class="col text-center mt-3">
|
||||
<span class="text-muted"><strong>Total</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="LabelEmpTotal" runat="server" Text="0"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12" runat="server">
|
||||
<div class="alert alert-light shadow text-dark" role="alert">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-start">
|
||||
<h1><i class="fa-solid fa-swatchbook"></i></h1>
|
||||
<span class="fw-bold"><strong>Alumnos</strong></span>
|
||||
</div>
|
||||
<div class="col-md-12 text-start">
|
||||
<span class="text-muted"><strong>Con SENCE</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="LabelAlmConSNC" runat="server" Text="0"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-md-12 text-start">
|
||||
<span class="text-muted"><strong>Sin SENCE</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="LabelAlmSinSNC" runat="server" Text="0"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-md-12 text-start">
|
||||
<span class="text-muted"><strong>Total</strong></span>
|
||||
<h5><strong>
|
||||
<asp:Label ID="LabelAlumnosTotal" runat="server" Text="0"></asp:Label>
|
||||
</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mt-3" runat="server">
|
||||
<div class="alert alert-light" role="alert">
|
||||
<div class="table-responsive" width="100%">
|
||||
<h3>Alumnos de empresas</h3>
|
||||
<table class="table table-sm mb-0 table-hover" style="font-size: 12px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-start" style="width: 20%">Tipo</th>
|
||||
<th class="text-start" style="width: 5%">Cantidad</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-start" style="width: 20%">Cursos Abierto
|
||||
</td>
|
||||
<td class="text-start" style="width: 5%">
|
||||
<asp:Label ID="Labelcnttipoabierto" runat="server" Text="0"></asp:Label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-start" style="width: 20%">Cursos Cerrado
|
||||
</td>
|
||||
<td class="text-start" style="width: 5%">
|
||||
<asp:Label ID="Labelcnttipocerrado" runat="server" Text="0"></asp:Label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-start" style="width: 20%">Total
|
||||
</th>
|
||||
<th class="text-start" style="width: 5%">
|
||||
<asp:Label ID="LabelcnttipoTotal" runat="server" Text="0"></asp:Label>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12" runat="server">
|
||||
<div class="alert alert-light text-dark" role="alert">
|
||||
<div class="row">
|
||||
<h4 class="text-center"><small><u>Sedes con alumnos de empresas</u></small></h4>
|
||||
<div class="col-md-8 text-start">
|
||||
<h1><i class="fa-solid fa-school"></i></h1>
|
||||
<span class="fw-bold"><strong>Sedes</strong></span>
|
||||
</div>
|
||||
<div class="col-md-4 text-center mt-1">
|
||||
<div class="progress" role="progressbar" aria-label="Default striped example" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">
|
||||
<div class="progress-bar progress-bar-striped" style="width: 100%">Alumnos sin SENCE</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="progress" role="progressbar" aria-label="Warning striped example" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">
|
||||
<div class="progress-bar progress-bar-striped bg-warning text-dark" style="width: 100%">Alumnos con SENCE</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 text-center">
|
||||
<h5>
|
||||
<strong>Moneda</strong>
|
||||
</h5>
|
||||
<div class="progress-stacked">
|
||||
<div class="progress" role="progressbar" aria-label="Segment one" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="mone" runat="server" class="progress-bar progress-bar-striped progress-bar-animated"></div>
|
||||
<div id="moneSNC" runat="server" class="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Providencia</strong>
|
||||
</h5>
|
||||
<div class="progress-stacked">
|
||||
<div class="progress" role="progressbar" aria-label="Info example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="prov" runat="server" class="progress-bar progress-bar-striped progress-bar-animated"></div>
|
||||
<div id="provSNC" runat="server" class="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>La Florida</strong>
|
||||
</h5>
|
||||
<div class="progress-stacked">
|
||||
<div class="progress" role="progressbar" aria-label="Info example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="flor" runat="server" class="progress-bar progress-bar-striped progress-bar-animated"></div>
|
||||
<div id="florSNC" runat="server" class="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Online</strong>
|
||||
</h5>
|
||||
<div class="progress-stacked">
|
||||
<div class="progress" role="progressbar" aria-label="Info example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="onli" runat="server" class="progress-bar progress-bar-striped progress-bar-animated"></div>
|
||||
<div id="onliSNC" runat="server" class="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Empresas</strong>
|
||||
</h5>
|
||||
<div class="progress-stacked">
|
||||
<div class="progress" role="progressbar" aria-label="Info example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="corp" runat="server" class="progress-bar progress-bar-striped progress-bar-animated"></div>
|
||||
<div id="corpSNC" runat="server" class="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 align-middle mt-5">
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="TipoDeVentas">
|
||||
<div class="alert alert-light text-dark offcanvas-lg offcanvas-sm container-md container-sm"
|
||||
role="alert">
|
||||
<h3><span><b><u>Tipos de ventas</u></b></span></h3>
|
||||
<canvas id="ventaPie" class="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
|
||||
<script>
|
||||
var pieLabels;
|
||||
var pieData;
|
||||
const ctz = document.getElementById('ventaPie');
|
||||
new Chart(ctz, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: pieLabels,
|
||||
datasets: [{
|
||||
label: 'Cantidad',
|
||||
data: pieData,
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
}
|
||||
});
|
||||
var $canvas = $("#canvas");
|
||||
var $parent = $canvas.parent();
|
||||
$canvas.width($parent.width());
|
||||
$canvas.height($parent.height());
|
||||
</script>
|
||||
</asp:Content>
|
||||
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@boxicons/react": "^1.0.3",
|
||||
"bootstrap": "5.3.8",
|
||||
"chart.js": "^4.5.1",
|
||||
"next": "16.2.12",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
|
||||
Generated
+115
-95
@@ -14,9 +14,12 @@ importers:
|
||||
bootstrap:
|
||||
specifier: 5.3.8
|
||||
version: 5.3.8(@popperjs/core@2.11.8)
|
||||
chart.js:
|
||||
specifier: ^4.5.1
|
||||
version: 4.5.1
|
||||
next:
|
||||
specifier: 16.2.12
|
||||
version: 16.2.12(@babel/core@7.29.7)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
version: 16.2.12(@babel/core@7.29.7(supports-color@7.2.0))(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
react:
|
||||
specifier: 19.2.4
|
||||
version: 19.2.4
|
||||
@@ -44,10 +47,10 @@ importers:
|
||||
version: 1.0.0
|
||||
eslint:
|
||||
specifier: ^9
|
||||
version: 9.39.5
|
||||
version: 9.39.5(supports-color@7.2.0)
|
||||
eslint-config-next:
|
||||
specifier: 16.2.12
|
||||
version: 16.2.12(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)
|
||||
version: 16.2.12(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
typescript:
|
||||
specifier: ^5
|
||||
version: 5.9.3
|
||||
@@ -365,6 +368,9 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||
|
||||
'@kurkle/color@0.3.4':
|
||||
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.2.0':
|
||||
resolution: {integrity: sha512-kDoONqMa+VnZ4vvvu/ZUurpJ4gkZU57e7g69qpNgWhYcZFPUHZM2CEMKm+cG6ufDVALbjMvfmMjFVqaK7uEMnA==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0}
|
||||
@@ -802,6 +808,10 @@ packages:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
chart.js@4.5.1:
|
||||
resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
|
||||
engines: {pnpm: '>=8'}
|
||||
|
||||
client-only@0.0.1:
|
||||
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
|
||||
|
||||
@@ -1869,20 +1879,20 @@ snapshots:
|
||||
|
||||
'@babel/compat-data@7.29.7': {}
|
||||
|
||||
'@babel/core@7.29.7':
|
||||
'@babel/core@7.29.7(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/generator': 7.29.7
|
||||
'@babel/helper-compilation-targets': 7.29.7
|
||||
'@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
|
||||
'@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
'@babel/helpers': 7.29.7
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/template': 7.29.7
|
||||
'@babel/traverse': 7.29.7
|
||||
'@babel/traverse': 7.29.7(supports-color@7.2.0)
|
||||
'@babel/types': 7.29.7
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.3
|
||||
semver: 6.3.1
|
||||
@@ -1907,19 +1917,19 @@ snapshots:
|
||||
|
||||
'@babel/helper-globals@7.29.7': {}
|
||||
|
||||
'@babel/helper-module-imports@7.29.7':
|
||||
'@babel/helper-module-imports@7.29.7(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.29.7
|
||||
'@babel/traverse': 7.29.7(supports-color@7.2.0)
|
||||
'@babel/types': 7.29.7
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
|
||||
'@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/helper-module-imports': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@7.2.0)
|
||||
'@babel/helper-module-imports': 7.29.7(supports-color@7.2.0)
|
||||
'@babel/helper-validator-identifier': 7.29.7
|
||||
'@babel/traverse': 7.29.7
|
||||
'@babel/traverse': 7.29.7(supports-color@7.2.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -1944,7 +1954,7 @@ snapshots:
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
|
||||
'@babel/traverse@7.29.7':
|
||||
'@babel/traverse@7.29.7(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/generator': 7.29.7
|
||||
@@ -1952,7 +1962,7 @@ snapshots:
|
||||
'@babel/parser': 7.29.7
|
||||
'@babel/template': 7.29.7
|
||||
'@babel/types': 7.29.7
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -1986,17 +1996,17 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)':
|
||||
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(supports-color@7.2.0))':
|
||||
dependencies:
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.2': {}
|
||||
|
||||
'@eslint/config-array@0.21.2':
|
||||
'@eslint/config-array@0.21.2(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
'@eslint/object-schema': 2.1.7
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
minimatch: 3.1.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2009,10 +2019,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/eslintrc@3.3.6':
|
||||
'@eslint/eslintrc@3.3.6(supports-color@7.2.0)':
|
||||
dependencies:
|
||||
ajv: 6.15.0
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
espree: 10.4.0
|
||||
globals: 14.0.0
|
||||
ignore: 5.3.2
|
||||
@@ -2164,6 +2174,8 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@kurkle/color@0.3.4': {}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.2.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.10.0
|
||||
@@ -2250,15 +2262,15 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/scope-manager': 8.65.0
|
||||
'@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.65.0
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
ignore: 7.0.6
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||
@@ -2266,23 +2278,23 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3)':
|
||||
'@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.65.0
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.65.0
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.5
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.65.0(typescript@5.9.3)':
|
||||
'@typescript-eslint/project-service@8.65.0(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2296,13 +2308,13 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.65.0(eslint@9.39.5)(typescript@5.9.3)':
|
||||
'@typescript-eslint/type-utils@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.5
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
@@ -2310,13 +2322,13 @@ snapshots:
|
||||
|
||||
'@typescript-eslint/types@8.65.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.65.0(typescript@5.9.3)':
|
||||
'@typescript-eslint/typescript-estree@8.65.0(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/project-service': 8.65.0(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
'@typescript-eslint/visitor-keys': 8.65.0
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
minimatch: 10.2.6
|
||||
semver: 7.8.5
|
||||
tinyglobby: 0.2.17
|
||||
@@ -2325,13 +2337,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.65.0(eslint@9.39.5)(typescript@5.9.3)':
|
||||
'@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0))
|
||||
'@typescript-eslint/scope-manager': 8.65.0
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3)
|
||||
eslint: 9.39.5
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(supports-color@7.2.0)(typescript@5.9.3)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2579,6 +2591,10 @@ snapshots:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
chart.js@4.5.1:
|
||||
dependencies:
|
||||
'@kurkle/color': 0.3.4
|
||||
|
||||
client-only@0.0.1: {}
|
||||
|
||||
codepage@1.15.0: {}
|
||||
@@ -2623,13 +2639,17 @@ snapshots:
|
||||
es-errors: 1.3.0
|
||||
is-data-view: 1.0.2
|
||||
|
||||
debug@3.2.7:
|
||||
debug@3.2.7(supports-color@7.2.0):
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
optionalDependencies:
|
||||
supports-color: 7.2.0
|
||||
|
||||
debug@4.4.3:
|
||||
debug@4.4.3(supports-color@7.2.0):
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
optionalDependencies:
|
||||
supports-color: 7.2.0
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
@@ -2777,18 +2797,18 @@ snapshots:
|
||||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
eslint-config-next@16.2.12(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3):
|
||||
eslint-config-next@16.2.12(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 16.2.12
|
||||
eslint: 9.39.5
|
||||
eslint-import-resolver-node: 0.3.10
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5))(eslint@9.39.5)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5)
|
||||
eslint-plugin-react: 7.37.5(eslint@9.39.5)
|
||||
eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(supports-color@7.2.0))
|
||||
eslint-plugin-react: 7.37.5(eslint@9.39.5(supports-color@7.2.0))
|
||||
eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
globals: 16.4.0
|
||||
typescript-eslint: 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
typescript-eslint: 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
@@ -2797,52 +2817,52 @@ snapshots:
|
||||
- eslint-plugin-import-x
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-node@0.3.10:
|
||||
eslint-import-resolver-node@0.3.10(supports-color@7.2.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
debug: 3.2.7(supports-color@7.2.0)
|
||||
is-core-module: 2.16.2
|
||||
resolve: 2.0.0-next.7
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5))(eslint@9.39.5):
|
||||
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0):
|
||||
dependencies:
|
||||
'@nolyfill/is-core-module': 1.0.39
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.5
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
get-tsconfig: 4.14.0
|
||||
is-bun-module: 2.0.0
|
||||
stable-hash: 0.0.5
|
||||
tinyglobby: 0.2.17
|
||||
unrs-resolver: 1.12.2
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.14.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5))(eslint@9.39.5))(eslint@9.39.5):
|
||||
eslint-module-utils@2.14.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
debug: 3.2.7(supports-color@7.2.0)
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
eslint: 9.39.5
|
||||
eslint-import-resolver-node: 0.3.10
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5))(eslint@9.39.5)
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5):
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
array.prototype.findlastindex: 1.2.6
|
||||
array.prototype.flat: 1.3.3
|
||||
array.prototype.flatmap: 1.3.3
|
||||
debug: 3.2.7
|
||||
debug: 3.2.7(supports-color@7.2.0)
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.39.5
|
||||
eslint-import-resolver-node: 0.3.10
|
||||
eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5))(eslint@9.39.5))(eslint@9.39.5)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
|
||||
eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)
|
||||
hasown: 2.0.4
|
||||
is-core-module: 2.16.2
|
||||
is-glob: 4.0.3
|
||||
@@ -2854,13 +2874,13 @@ snapshots:
|
||||
string.prototype.trimend: 1.0.10
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5):
|
||||
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@7.2.0)):
|
||||
dependencies:
|
||||
aria-query: 5.3.2
|
||||
array-includes: 3.1.9
|
||||
@@ -2870,7 +2890,7 @@ snapshots:
|
||||
axobject-query: 4.1.0
|
||||
damerau-levenshtein: 1.0.8
|
||||
emoji-regex: 9.2.2
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
hasown: 2.0.4
|
||||
jsx-ast-utils: 3.3.5
|
||||
language-tags: 1.0.9
|
||||
@@ -2879,18 +2899,18 @@ snapshots:
|
||||
safe-regex-test: 1.1.0
|
||||
string.prototype.includes: 2.0.1
|
||||
|
||||
eslint-plugin-react-hooks@7.1.1(eslint@9.39.5):
|
||||
eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@7.2.0)
|
||||
'@babel/parser': 7.29.7
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
hermes-parser: 0.25.1
|
||||
zod: 4.4.3
|
||||
zod-validation-error: 4.0.2(zod@4.4.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-react@7.37.5(eslint@9.39.5):
|
||||
eslint-plugin-react@7.37.5(eslint@9.39.5(supports-color@7.2.0)):
|
||||
dependencies:
|
||||
array-includes: 3.1.9
|
||||
array.prototype.findlast: 1.2.5
|
||||
@@ -2898,7 +2918,7 @@ snapshots:
|
||||
array.prototype.tosorted: 1.1.4
|
||||
doctrine: 2.1.0
|
||||
es-iterator-helpers: 1.4.0
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
estraverse: 5.3.0
|
||||
hasown: 2.0.4
|
||||
jsx-ast-utils: 3.3.5
|
||||
@@ -2923,14 +2943,14 @@ snapshots:
|
||||
|
||||
eslint-visitor-keys@5.0.1: {}
|
||||
|
||||
eslint@9.39.5:
|
||||
eslint@9.39.5(supports-color@7.2.0):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0))
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@eslint/config-array': 0.21.2
|
||||
'@eslint/config-array': 0.21.2(supports-color@7.2.0)
|
||||
'@eslint/config-helpers': 0.4.2
|
||||
'@eslint/core': 0.17.0
|
||||
'@eslint/eslintrc': 3.3.6
|
||||
'@eslint/eslintrc': 3.3.6(supports-color@7.2.0)
|
||||
'@eslint/js': 9.39.5
|
||||
'@eslint/plugin-kit': 0.4.1
|
||||
'@humanfs/node': 0.16.8
|
||||
@@ -2940,7 +2960,7 @@ snapshots:
|
||||
ajv: 6.15.0
|
||||
chalk: 4.1.2
|
||||
cross-spawn: 7.0.6
|
||||
debug: 4.4.3
|
||||
debug: 4.4.3(supports-color@7.2.0)
|
||||
escape-string-regexp: 4.0.0
|
||||
eslint-scope: 8.4.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
@@ -3352,7 +3372,7 @@ snapshots:
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
next@16.2.12(@babel/core@7.29.7)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
next@16.2.12(@babel/core@7.29.7(supports-color@7.2.0))(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
dependencies:
|
||||
'@next/env': 16.2.12
|
||||
'@swc/helpers': 0.5.15
|
||||
@@ -3361,7 +3381,7 @@ snapshots:
|
||||
postcss: 8.4.31
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.4)
|
||||
styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.2.4)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 16.2.12
|
||||
'@next/swc-darwin-x64': 16.2.12
|
||||
@@ -3717,12 +3737,12 @@ snapshots:
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
|
||||
styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.4):
|
||||
styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.2.4):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
react: 19.2.4
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@7.2.0)
|
||||
|
||||
supports-color@7.2.0:
|
||||
dependencies:
|
||||
@@ -3789,13 +3809,13 @@ snapshots:
|
||||
possible-typed-array-names: 1.1.0
|
||||
reflect.getprototypeof: 1.0.10
|
||||
|
||||
typescript-eslint@8.65.0(eslint@9.39.5)(typescript@5.9.3):
|
||||
typescript-eslint@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3)
|
||||
eslint: 9.39.5
|
||||
'@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 8.65.0(supports-color@7.2.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
|
||||
eslint: 9.39.5(supports-color@7.2.0)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -0,0 +1,483 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
User,
|
||||
Buildings,
|
||||
Book,
|
||||
UserCircle,
|
||||
// Export,
|
||||
CheckCircle,
|
||||
// ErrorCircle,
|
||||
} from "@boxicons/react";
|
||||
|
||||
// Interfaz para el listado de cursos
|
||||
interface CursoItem {
|
||||
Codigo: string;
|
||||
Curso: string;
|
||||
TipoCurso: string;
|
||||
Periodo: string;
|
||||
Titular: string;
|
||||
Sede: string;
|
||||
Alumnos: number;
|
||||
Inicio: string;
|
||||
Termino: string;
|
||||
Schedule: string;
|
||||
Estado: "Finalizado" | "En curso" | string;
|
||||
}
|
||||
|
||||
export default function CursosPorMesPage() {
|
||||
// Filtros de búsqueda (Mes y Año)
|
||||
const [mes, setMes] = useState("1");
|
||||
const [agno, setAgno] = useState(new Date().getFullYear().toString());
|
||||
|
||||
// Visibilidad del reporte
|
||||
const [mostrarReporte, setMostrarReporte] = useState(false);
|
||||
|
||||
// Totales
|
||||
const [empTotal, setEmpTotal] = useState("0");
|
||||
const [cursosTotal, setCursosTotal] = useState("0 %");
|
||||
const [almConSnc, setAlmConSnc] = useState("0");
|
||||
const [almSinSnc, setAlmSinSnc] = useState("0");
|
||||
const [alumnosTotal, setAlumnosTotal] = useState("0");
|
||||
|
||||
// Lista de cursos
|
||||
const [cursos, setCursos] = useState<CursoItem[]>([]);
|
||||
|
||||
// Modales de estado
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [modalAlerta, setModalAlerta] = useState<{
|
||||
show: boolean;
|
||||
mensaje: string;
|
||||
}>({ show: false, mensaje: "" });
|
||||
|
||||
// Manejador del botón Buscar
|
||||
const handleBuscar = () => {
|
||||
if (!agno) {
|
||||
setModalAlerta({
|
||||
show: true,
|
||||
mensaje: "Por favor, ingrese un año válido.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
// Simulación de carga de datos
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setMostrarReporte(true);
|
||||
|
||||
// Datos de ejemplo
|
||||
setEmpTotal("8");
|
||||
setCursosTotal("90 %");
|
||||
setAlmConSnc("32");
|
||||
setAlmSinSnc("10");
|
||||
setAlumnosTotal("42");
|
||||
|
||||
setCursos([
|
||||
{
|
||||
Codigo: "CUR-201",
|
||||
Curso: "Inglés de Negocios A2",
|
||||
TipoCurso: "Cerrado",
|
||||
Periodo: `${agno}-${mes}`,
|
||||
Titular: "Carlos Mendoza",
|
||||
Sede: "Santiago Centro",
|
||||
Alumnos: 12,
|
||||
Inicio: `01/${mes.padStart(2, "0")}/${agno}`,
|
||||
Termino: `28/${mes.padStart(2, "0")}/${agno}`,
|
||||
Schedule: "Lun-Mié 10:00 - 12:00",
|
||||
Estado: "Finalizado",
|
||||
},
|
||||
{
|
||||
Codigo: "CUR-202",
|
||||
Curso: "Inglés Conversacional B1",
|
||||
TipoCurso: "Abierto",
|
||||
Periodo: `${agno}-${mes}`,
|
||||
Titular: "Patricia Silva",
|
||||
Sede: "Providencia",
|
||||
Alumnos: 15,
|
||||
Inicio: `05/${mes.padStart(2, "0")}/${agno}`,
|
||||
Termino: `30/${mes.padStart(2, "0")}/${agno}`,
|
||||
Schedule: "Mar-Jue 19:00 - 21:00",
|
||||
Estado: "En curso",
|
||||
},
|
||||
]);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// Restablecer vista
|
||||
const handleVolver = () => {
|
||||
setMostrarReporte(false);
|
||||
setCursos([]);
|
||||
};
|
||||
|
||||
// Exportar Excel
|
||||
const handleExportarExcel = () => {
|
||||
setIsLoading(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setModalAlerta({
|
||||
show: true,
|
||||
mensaje: "El reporte en Excel ha sido generado con éxito.",
|
||||
});
|
||||
}, 800);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="cursos_periodo">
|
||||
<div className="row">
|
||||
{/* ENCABEZADO Y VOLVER */}
|
||||
<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">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Cursos por Mes</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
onClick={handleVolver}
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* FILTROS MES Y AÑO */}
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<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="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">
|
||||
<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)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
onClick={handleBuscar}
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* REPORTE Y RESULTADOS */}
|
||||
{mostrarReporte && (
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="row">
|
||||
{/* METRICA EMPRESAS */}
|
||||
<div className="col-md-2" id="promedio_emp">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<Buildings />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Empresas</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{empTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* METRICA CURSOS */}
|
||||
<div className="col-md-2" id="promedio_cursos">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<Book />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Cursos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{cursosTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* METRICA ALUMNOS */}
|
||||
<div className="col-md-6" id="Div1">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<UserCircle />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-9 text-center mt-3">
|
||||
<div className="row">
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{almConSnc}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{almSinSnc}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{alumnosTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* BOTÓN EXPORTAR EXCEL */}
|
||||
<div className="col-md-2 mx-auto" id="Div2">
|
||||
<div className="alert alert-success shadow-sm" role="alert">
|
||||
<div className="row mt-2 align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link text-decoration-none p-0 d-block mx-auto"
|
||||
onClick={handleExportarExcel}
|
||||
>
|
||||
<h5 className="mb-0 text-success">
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TABLA DE RESULTADOS */}
|
||||
<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-center" style={{ width: "5%" }}>Tipo de Curso</th>
|
||||
<th className="text-start" style={{ width: "23%" }}>Curso</th>
|
||||
<th className="text-start" style={{ width: "6%" }}>Periodo</th>
|
||||
<th className="text-start" style={{ width: "14%" }}>Profesor</th>
|
||||
<th className="text-center" style={{ width: "7%" }}>Sede</th>
|
||||
<th className="text-center" style={{ width: "4%" }}>Alumnos</th>
|
||||
<th className="text-center" style={{ width: "12%" }}>Fecha</th>
|
||||
<th className="text-center" style={{ width: "20%" }}>Schedule</th>
|
||||
<th className="text-center" style={{ width: "8%" }}>Estado</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{cursos.map((item, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="text-start" style={{ width: "3%" }}>
|
||||
{item.TipoCurso === "Cerrado" ? (
|
||||
<a href={`../Cursos/Administrador.aspx?codigo=${item.Codigo}&type=Cerrado`}>
|
||||
<span className="badge bg-primary" style={{ fontWeight: "normal" }}>
|
||||
Ver
|
||||
</span>
|
||||
</a>
|
||||
) : (
|
||||
<a href={`https://sam.norteamericano.cl/academico/Empresas/Cursos/Administrador.aspx?codigo=${item.Codigo}`}>
|
||||
<span className="badge bg-primary" style={{ fontWeight: "normal" }}>
|
||||
Ver
|
||||
</span>
|
||||
</a>
|
||||
)}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "5%" }}>
|
||||
{item.TipoCurso}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "23%" }}>
|
||||
{`${item.Codigo} - ${item.Curso}`}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "6%" }}>
|
||||
{item.Periodo}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "14%" }}>
|
||||
{item.Titular}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "7%" }}>
|
||||
{item.Sede}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "4%" }}>
|
||||
{item.Alumnos}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "12%" }}>
|
||||
{`${item.Inicio} || ${item.Termino}`}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "20%" }}>
|
||||
{item.Schedule}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "8%" }}>
|
||||
{item.Estado === "Finalizado" ? (
|
||||
<span className="text-success d-inline-flex align-items-center">
|
||||
<CheckCircle className="me-1" /> Finalizado
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-warning d-inline-flex align-items-center">
|
||||
{/* <ErrorCircle className="me-1" /> */} En curso
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* MODAL DE ALERTA / MENSAJE */}
|
||||
{modalAlerta.show && (
|
||||
<div
|
||||
className="modal fade show d-block bg-dark bg-opacity-50"
|
||||
tabIndex={-1}
|
||||
role="dialog"
|
||||
aria-labelledby="resultPreAdvanced"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<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"
|
||||
aria-label="Close"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body alert mb-0" style={{ textAlign: "justify" }}>
|
||||
<div className="row">
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center">
|
||||
<h5>
|
||||
<strong>{modalAlerta.mensaje}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL DE CARGANDO */}
|
||||
{isLoading && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
<div className="modal-body">
|
||||
<div className="col-md-12 text-center py-3">
|
||||
<div className="spinner-border text-primary" role="status">
|
||||
<span className="visually-hidden">Cargando...</span>
|
||||
</div>
|
||||
<p className="mt-2 mb-0 fw-bold">Cargando información...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { User, InfoCircle } from "@boxicons/react";
|
||||
|
||||
// Interfaz para la estructura del listado del informe
|
||||
interface InformeItem {
|
||||
Codigo: string;
|
||||
Curso: string;
|
||||
idAlumno: string;
|
||||
Alumno: string;
|
||||
RegsitroAcademico: string;
|
||||
idEmpresas: string;
|
||||
Empresa: string;
|
||||
contrato: string;
|
||||
Sede: string;
|
||||
Jornada: string;
|
||||
Fecha: string;
|
||||
}
|
||||
|
||||
export default function InformeCursosPage() {
|
||||
// Estados para textos e información dinámica
|
||||
const [mensajeLabel, setMensajeLabel] = useState("Información del reporte cargada correctamente.");
|
||||
const [fechTypeLabel, setFechTypeLabel] = useState("Fecha Inicio");
|
||||
|
||||
// Estado para el listado de datos
|
||||
const [informeList, setInformeList] = useState<InformeItem[]>([
|
||||
{
|
||||
Codigo: "CUR-101",
|
||||
Curso: "Inglés Técnico para Empresas",
|
||||
idAlumno: "18.765.432-1",
|
||||
Alumno: "Roberto Gómez",
|
||||
RegsitroAcademico: "REG-2026-01",
|
||||
idEmpresas: "76.543.210-K",
|
||||
Empresa: "Servicios Tecnológicos SpA",
|
||||
contrato: "CTR-88",
|
||||
Sede: "Santiago Centro",
|
||||
Jornada: "Vespertina",
|
||||
Fecha: "15/03/2026",
|
||||
},
|
||||
{
|
||||
Codigo: "CUR-102",
|
||||
Curso: "Inglés Negocios B1",
|
||||
idAlumno: "19.123.456-7",
|
||||
Alumno: "Andrea Morales",
|
||||
RegsitroAcademico: "REG-2026-02",
|
||||
idEmpresas: "77.111.222-3",
|
||||
Empresa: "Consultoras Unidas S.A.",
|
||||
contrato: "CTR-92",
|
||||
Sede: "Providencia",
|
||||
Jornada: "Diurna",
|
||||
Fecha: "18/03/2026",
|
||||
},
|
||||
]);
|
||||
|
||||
// Estados para modales
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [modalAlerta, setModalAlerta] = useState<{
|
||||
show: boolean;
|
||||
mensaje: string;
|
||||
}>({ show: false, mensaje: "" });
|
||||
|
||||
// Evento para descargar Excel
|
||||
const handleDescargarExcel = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setModalAlerta({
|
||||
show: true,
|
||||
mensaje: "El archivo Excel se ha generado y descargado con éxito.",
|
||||
});
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
{/* ENCABEZADO Y BOTÓN VOLVER */}
|
||||
<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">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Informe</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<a
|
||||
href="../Cursos/Index.aspx"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SECCIÓN INFORMACIÓN Y DESCARGA EXCEL */}
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col m-1 d-flex align-items-center">
|
||||
<strong>
|
||||
<InfoCircle style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="fw-bold ms-2">{mensajeLabel}</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col m-1 text-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-success"
|
||||
onClick={handleDescargarExcel}
|
||||
>
|
||||
Descargar Excel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TABLA PRINCIPAL DEL INFORME */}
|
||||
<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 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "5%" }}>
|
||||
Curso ID
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "15%" }}>
|
||||
Curso
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "7%" }}>
|
||||
Alumno RUN
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "15%" }}>
|
||||
Alumno
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "7%" }}>
|
||||
Registro
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "7%" }}>
|
||||
Empresa Rut
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "15%" }}>
|
||||
Empresa
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "5%" }}>
|
||||
Contrato
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "6%" }}>
|
||||
Sede
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "6%" }}>
|
||||
Jornada
|
||||
</th>
|
||||
<th className="text-center" style={{ width: "12%" }}>
|
||||
{fechTypeLabel} Curso
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{informeList.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start" style={{ width: "5%" }}>
|
||||
{item.Codigo}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
{item.Curso}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "7%" }}>
|
||||
{item.idAlumno}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
{item.Alumno}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "7%" }}>
|
||||
{item.RegsitroAcademico}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "7%" }}>
|
||||
{item.idEmpresas}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
{item.Empresa}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "5%" }}>
|
||||
{item.contrato}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "6%" }}>
|
||||
{item.Sede}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "6%" }}>
|
||||
{item.Jornada}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "12%" }}>
|
||||
{item.Fecha}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* MODAL DE ALERTA / MENSAJE DE ERROR O ÉXITO */}
|
||||
{modalAlerta.show && (
|
||||
<div
|
||||
className="modal fade show d-block bg-dark bg-opacity-50"
|
||||
tabIndex={-1}
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<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 - Informe</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close float-end mt-1"
|
||||
aria-label="Close"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body alert mb-0" style={{ textAlign: "justify" }}>
|
||||
<div className="row">
|
||||
<div className="col-md-12 text-center py-2">
|
||||
<h5>
|
||||
<strong>{modalAlerta.mensaje}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL DE CARGANDO / LOADING */}
|
||||
{isLoading && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
<div className="modal-body">
|
||||
<div className="col-md-12 text-center py-3">
|
||||
<div className="spinner-border text-primary" role="status">
|
||||
<span className="visually-hidden">Procesando...</span>
|
||||
</div>
|
||||
<p className="mt-2 mb-0 fw-bold">Procesando descarga...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,483 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
User,
|
||||
Buildings,
|
||||
Book,
|
||||
UserCircle,
|
||||
//Export,
|
||||
CheckCircle,
|
||||
//ErrorCircle,
|
||||
} from "@boxicons/react";
|
||||
|
||||
// Interfaz para la estructura del listado de cursos
|
||||
interface CursoItem {
|
||||
Codigo: string;
|
||||
Curso: string;
|
||||
TipoCurso: string;
|
||||
Periodo: string;
|
||||
Titular: string;
|
||||
Sede: string;
|
||||
Alumnos: number;
|
||||
Inicio: string;
|
||||
Termino: string;
|
||||
Schedule: string;
|
||||
Estado: "Finalizado" | "En curso" | string;
|
||||
}
|
||||
|
||||
export default function CursosIniciadosPage() {
|
||||
// Filtros de fecha
|
||||
const [fechaInicio, setFechaInicio] = useState("");
|
||||
const [fechaTermino, setFechaTermino] = useState("");
|
||||
|
||||
// Visibilidad de datos / reporte
|
||||
const [mostrarReporte, setMostrarReporte] = useState(false);
|
||||
|
||||
// Totales
|
||||
const [empTotal, setEmpTotal] = useState("0");
|
||||
const [cursosTotal, setCursosTotal] = useState("0 %");
|
||||
const [almConSnc, setAlmConSnc] = useState("0");
|
||||
const [almSinSnc, setAlmSinSnc] = useState("0");
|
||||
const [alumnosTotal, setAlumnosTotal] = useState("0");
|
||||
|
||||
// Lista de datos
|
||||
const [cursos, setCursos] = useState<CursoItem[]>([]);
|
||||
|
||||
// Modals de estado
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [modalAlerta, setModalAlerta] = useState<{
|
||||
show: boolean;
|
||||
mensaje: string;
|
||||
}>({ show: false, mensaje: "" });
|
||||
|
||||
// Manejador del botón Buscar
|
||||
const handleBuscar = () => {
|
||||
if (!fechaInicio || !fechaTermino) {
|
||||
setModalAlerta({
|
||||
show: true,
|
||||
mensaje: "Por favor, seleccione un rango de fechas válido.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
// Simulación de consulta API
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setMostrarReporte(true);
|
||||
|
||||
// Datos ficticios de prueba basados en el modelo
|
||||
setEmpTotal("12");
|
||||
setCursosTotal("85 %");
|
||||
setAlmConSnc("45");
|
||||
setAlmSinSnc("15");
|
||||
setAlumnosTotal("60");
|
||||
|
||||
setCursos([
|
||||
{
|
||||
Codigo: "CUR-001",
|
||||
Curso: "Inglés Avanzado B2",
|
||||
TipoCurso: "Cerrado",
|
||||
Periodo: "2026-1",
|
||||
Titular: "Juan Pérez",
|
||||
Sede: "Santiago Centro",
|
||||
Alumnos: 15,
|
||||
Inicio: "01/03/2026",
|
||||
Termino: "30/06/2026",
|
||||
Schedule: "Lun-Mié 09:00 - 11:00",
|
||||
Estado: "Finalizado",
|
||||
},
|
||||
{
|
||||
Codigo: "CUR-002",
|
||||
Curso: "Inglés Intermedio A2",
|
||||
TipoCurso: "Abierto",
|
||||
Periodo: "2026-1",
|
||||
Titular: "María González",
|
||||
Sede: "Providencia",
|
||||
Alumnos: 20,
|
||||
Inicio: "10/03/2026",
|
||||
Termino: "15/07/2026",
|
||||
Schedule: "Mar-Jue 18:30 - 20:30",
|
||||
Estado: "En curso",
|
||||
},
|
||||
]);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// Manejador para volver o limpiar
|
||||
const handleVolver = () => {
|
||||
setMostrarReporte(false);
|
||||
setFechaInicio("");
|
||||
setFechaTermino("");
|
||||
setCursos([]);
|
||||
};
|
||||
|
||||
// Manejador para exportar a Excel
|
||||
const handleExportarExcel = () => {
|
||||
setIsLoading(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setModalAlerta({
|
||||
show: true,
|
||||
mensaje: "El reporte en Excel ha sido generado con éxito.",
|
||||
});
|
||||
}, 800);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="cursos_periodo">
|
||||
<div className="row">
|
||||
{/* ENCABEZADO Y BOTÓN VOLVER */}
|
||||
<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">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Cursos iniciados por fecha</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
onClick={handleVolver}
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* FILTROS DE FECHA Y BÚSQUEDA */}
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">Inicio</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="date"
|
||||
className="form-control form-control-sm"
|
||||
value={fechaInicio}
|
||||
onChange={(e) => setFechaInicio(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<span className="fw-bold">Termino</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="date"
|
||||
className="form-control form-control-sm"
|
||||
value={fechaTermino}
|
||||
onChange={(e) => setFechaTermino(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
onClick={handleBuscar}
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SECCIÓN REPORTE / RESULTADOS */}
|
||||
{mostrarReporte && (
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="row">
|
||||
{/* METRICA EMPRESAS */}
|
||||
<div className="col-md-2" id="promedio_emp">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<Buildings />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Empresas</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{empTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* METRICA CURSOS */}
|
||||
<div className="col-md-2" id="promedio_cursos">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<Book />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Cursos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{cursosTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* METRICA ALUMNOS */}
|
||||
<div className="col-md-6" id="Div1">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
<UserCircle />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-9 text-center mt-3">
|
||||
<div className="row">
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{almConSnc}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{almSinSnc}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>{alumnosTotal}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* BOTÓN EXPORTAR EXCEL */}
|
||||
<div className="col-md-2 mx-auto" id="Div2">
|
||||
<div className="alert alert-success shadow-sm" role="alert">
|
||||
<div className="row mt-2 align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1 className="mb-0">
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link text-decoration-none p-0 d-block mx-auto"
|
||||
onClick={handleExportarExcel}
|
||||
>
|
||||
<h5 className="mb-0 text-success">
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TABLA DE RESULTADOS */}
|
||||
<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-center" style={{ width: "5%" }}>Tipo de Curso</th>
|
||||
<th className="text-start" style={{ width: "23%" }}>Curso</th>
|
||||
<th className="text-start" style={{ width: "6%" }}>Periodo</th>
|
||||
<th className="text-start" style={{ width: "14%" }}>Profesor</th>
|
||||
<th className="text-center" style={{ width: "7%" }}>Sede</th>
|
||||
<th className="text-center" style={{ width: "4%" }}>Alumnos</th>
|
||||
<th className="text-center" style={{ width: "12%" }}>Fecha</th>
|
||||
<th className="text-center" style={{ width: "20%" }}>Schedule</th>
|
||||
<th className="text-center" style={{ width: "8%" }}>Estado</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{cursos.map((item, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="text-start" style={{ width: "3%" }}>
|
||||
{item.TipoCurso === "Cerrado" ? (
|
||||
<a
|
||||
href={`../Cursos/Administrador.aspx?codigo=${item.Codigo}&type=Cerrado`}
|
||||
>
|
||||
<span
|
||||
className="badge bg-primary"
|
||||
style={{ fontWeight: "normal" }}
|
||||
>
|
||||
Ver
|
||||
</span>
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
href={`https://modulos.sam.norteamericano.cl/proyectoSam/Cursos/Administrador.aspx?codigo=${item.Codigo}`}
|
||||
>
|
||||
<span
|
||||
className="badge bg-primary"
|
||||
style={{ fontWeight: "normal" }}
|
||||
>
|
||||
Ver
|
||||
</span>
|
||||
</a>
|
||||
)}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "5%" }}>
|
||||
{item.TipoCurso}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "23%" }}>
|
||||
{`${item.Codigo} - ${item.Curso}`}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "6%" }}>
|
||||
{item.Periodo}
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "14%" }}>
|
||||
{item.Titular}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "7%" }}>
|
||||
{item.Sede}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "4%" }}>
|
||||
{item.Alumnos}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "12%" }}>
|
||||
{`${item.Inicio} || ${item.Termino}`}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "20%" }}>
|
||||
{item.Schedule}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "8%" }}>
|
||||
{item.Estado === "Finalizado" ? (
|
||||
<span className="text-success d-inline-flex align-items-center">
|
||||
<CheckCircle className="me-1" /> Finalizado
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-warning d-inline-flex align-items-center">
|
||||
{/* <ErrorCircle className="me-1" /> En curso */}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* MODAL DE ALERTA / MENSAJE */}
|
||||
{modalAlerta.show && (
|
||||
<div
|
||||
className="modal fade show d-block bg-dark bg-opacity-50"
|
||||
tabIndex={-1}
|
||||
role="dialog"
|
||||
aria-labelledby="resultPreAdvanced"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<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"
|
||||
aria-label="Close"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body alert mb-0" style={{ textAlign: "justify" }}>
|
||||
<div className="row">
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center">
|
||||
<h5>
|
||||
<strong>{modalAlerta.mensaje}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setModalAlerta({ show: false, mensaje: "" })}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL DE CARGANDO */}
|
||||
{isLoading && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
<div className="modal-body">
|
||||
<div className="col-md-12 text-center py-3">
|
||||
<div className="spinner-border text-primary" role="status">
|
||||
<span className="visually-hidden">Cargando...</span>
|
||||
</div>
|
||||
<p className="mt-2 mb-0 fw-bold">Cargando información...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
User,
|
||||
// AlertOctagon,
|
||||
// Export,
|
||||
Buildings,
|
||||
UserCircle,
|
||||
BookLibrary,
|
||||
// Error as ErrorIcon,
|
||||
} from "@boxicons/react";
|
||||
|
||||
import Chart from "chart.js/auto";
|
||||
|
||||
export default function AlumnosPorMesPage() {
|
||||
// Estados para controlar las vistas
|
||||
const [divReporteV2, setDivReporteV2] = useState(true);
|
||||
const [divReporte, setDivReporte] = useState(false);
|
||||
|
||||
// Estados para modales
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("");
|
||||
|
||||
// Datos simulados para tablas
|
||||
const [regiones] = useState([
|
||||
{ Region: "Región Metropolitana", Cantidad: 150 },
|
||||
{ Region: "Valparaíso", Cantidad: 45 },
|
||||
]);
|
||||
|
||||
const [comunas] = useState([
|
||||
{ Comuna: "Santiago", Cantidad: 80 },
|
||||
{ Comuna: "Providencia", Cantidad: 70 },
|
||||
]);
|
||||
|
||||
// Manejador de búsqueda
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setShowLoadingModal(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
// Inicialización de gráficos Chart.js
|
||||
useEffect(() => {
|
||||
// Gráfico de Ocupación (Bar)
|
||||
const ctxOcupacion = document.getElementById(
|
||||
"OcupacionBar"
|
||||
) as HTMLCanvasElement;
|
||||
let chartOcupacion: Chart | null = null;
|
||||
if (ctxOcupacion) {
|
||||
chartOcupacion = new Chart(ctxOcupacion, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: ["Enero", "Febrero", "Marzo"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [12, 19, 3],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: { responsive: true },
|
||||
});
|
||||
}
|
||||
|
||||
// Gráfico de Profesiones (Pie)
|
||||
const ctxProfesion = document.getElementById(
|
||||
"ProfesionPies"
|
||||
) as HTMLCanvasElement;
|
||||
let chartProfesion: Chart | null = null;
|
||||
if (ctxProfesion) {
|
||||
chartProfesion = new Chart(ctxProfesion, {
|
||||
type: "pie",
|
||||
data: {
|
||||
labels: ["Ingeniería", "Medicina", "Educación", "Otros"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [30, 20, 15, 35],
|
||||
},
|
||||
],
|
||||
},
|
||||
options: { responsive: true },
|
||||
});
|
||||
}
|
||||
|
||||
// Limpieza al desmontar componente
|
||||
return () => {
|
||||
if (chartOcupacion) chartOcupacion.destroy();
|
||||
if (chartProfesion) chartProfesion.destroy();
|
||||
};
|
||||
}, [divReporteV2]);
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
<div className="row">
|
||||
{/* Encabezado y Filtros */}
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Alumnos por Mes</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<Link
|
||||
href="/Alumnos/Index"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<form onSubmit={handleBuscar} className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">Mes</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<select id="ListaMeses" className="form-select form-select-sm">
|
||||
<option value="1">Enero</option>
|
||||
<option value="2">Febrero</option>
|
||||
<option value="3">Marzo</option>
|
||||
{/* Agregar el resto de los meses */}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col">
|
||||
<span className="fw-bold">Año</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="number"
|
||||
id="TextBoxAgno"
|
||||
className="form-control form-control-sm"
|
||||
defaultValue={2026}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Reporte V2 */}
|
||||
{divReporteV2 && (
|
||||
<div className="col-md-12" id="div_reporteV2">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
{/* Columna Izquierda (Totales, Exportar y Grafico Bar) */}
|
||||
<div className="col-md-3 mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3 mx-auto">
|
||||
<button
|
||||
type="button"
|
||||
className="btn p-0 border-0 w-100 text-decoration-none"
|
||||
onClick={() => {
|
||||
setMensajeAlerta("Generando reporte Excel...");
|
||||
setShowAlertModal(true);
|
||||
}}
|
||||
>
|
||||
<div className="alert alert-success shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3">
|
||||
<h1>
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<UserCircle />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12 mt-3" id="Ocupacion">
|
||||
<div
|
||||
className="alert alert-light shadow text-dark offcanvas-lg offcanvas-sm"
|
||||
role="alert"
|
||||
>
|
||||
<canvas id="OcupacionBar" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columna Central (Tablas Regiones y Comunas) */}
|
||||
<div className="col-md-4">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="alert alert-light" role="alert">
|
||||
<div className="table-responsive">
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Regiones
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
Cantidad
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{regiones.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start">{item.Region}</td>
|
||||
<td className="text-start">{item.Cantidad}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light" role="alert">
|
||||
<div className="table-responsive">
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Comuna
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
Cantidad
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{comunas.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start">{item.Comuna}</td>
|
||||
<td className="text-start">{item.Cantidad}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columna Derecha (Gráfico de Profesiones) */}
|
||||
<div className="col-md-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="Profesion">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm"
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Profesiones</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas
|
||||
id="ProfesionPies"
|
||||
className="w-100 h-100"
|
||||
></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Reporte V1 (Oculto por defecto) */}
|
||||
{divReporte && (
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="row">
|
||||
<div className="col-md-2">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<Buildings />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-2">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<Buildings />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Cursos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<UserCircle />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-9 text-center mt-3">
|
||||
<div className="row">
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<Buildings />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Empresas</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4" id="resize">
|
||||
<div className="alert alert-light shadow text-dark offcanvas-lg" role="alert">
|
||||
<canvas id="myChart" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-2">
|
||||
<div className="alert alert-primary" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<BookLibrary />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos por Planes</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-9 text-center mt-3" style={{ fontSize: "14px" }}>
|
||||
<div className="row g-0 text-center">
|
||||
<div className="col-6 col-md-4">
|
||||
<span className="fw-bold">
|
||||
<strong>Adults</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-sm-6 col-md-8">
|
||||
<strong>0</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row g-0 text-center">
|
||||
<div className="col-6 col-md-4">
|
||||
<span className="fw-bold">
|
||||
<strong>Business</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-sm-6 col-md-8">
|
||||
<strong>0</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row g-0 text-center">
|
||||
<div className="col-6 col-md-4">
|
||||
<span className="fw-bold">
|
||||
<strong>Teens</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-sm-6 col-md-8">
|
||||
<strong>0</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row g-0 text-center">
|
||||
<div className="col-6 col-md-4">
|
||||
<span className="fw-bold">
|
||||
<strong>Kids</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-sm-6 col-md-8">
|
||||
<strong>0</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<UserCircle />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Condicion de registro</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-9 text-center mt-3">
|
||||
<div className="row">
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Plan Central</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Curso Cerrado</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4" id="resizev2">
|
||||
<div className="alert alert-light shadow text-dark offcanvas-lg" role="alert">
|
||||
<canvas id="myLines" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-4" id="resizev3">
|
||||
<div className="alert alert-light shadow text-dark offcanvas-lg" role="alert">
|
||||
<canvas id="myPies" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* MODAL DE MENSAJES/ALERTAS */}
|
||||
{showAlertModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>Módulo Académico - Reporte</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body text-center">
|
||||
<h5>
|
||||
<strong>{mensajeAlerta}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{showLoadingModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>SAM - Académico Empresas</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5>
|
||||
<strong>Procesando, espere un momento...</strong>
|
||||
</h5>
|
||||
<div className="mt-3">
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,658 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { User,
|
||||
//Export
|
||||
|
||||
} from "@boxicons/react";
|
||||
|
||||
export default function CursosPorMesPage() {
|
||||
// Estados para modales
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("");
|
||||
|
||||
// Datos simulados para la tabla de Planes (DataList en ASP.NET)
|
||||
const [planes] = useState([
|
||||
{ Plan: "Intensivo Adults", Cantidad: 45 },
|
||||
{ Plan: "Regular Kids", Cantidad: 30 },
|
||||
{ Plan: "Business Express", Cantidad: 25 },
|
||||
]);
|
||||
|
||||
// Manejo de búsqueda
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setShowLoadingModal(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
// Manejo de exportación a Excel
|
||||
const handleExportarExcel = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setMensajeAlerta("Generando y descargando archivo Excel...");
|
||||
setShowAlertModal(true);
|
||||
};
|
||||
|
||||
// Carga de Chart.js mediante importación dinámica
|
||||
useEffect(() => {
|
||||
let chartJornadas: any = null;
|
||||
let chartPlan: any = null;
|
||||
|
||||
import("chart.js/auto").then(({ default: Chart }) => {
|
||||
// Gráfico de Jornadas (Bar)
|
||||
const ctxJornadas = document.getElementById(
|
||||
"jornadasBar"
|
||||
) as HTMLCanvasElement;
|
||||
if (ctxJornadas) {
|
||||
chartJornadas = new Chart(ctxJornadas, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: ["Mañana", "Tarde", "Noche", "Sábado"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [15, 25, 40, 10],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Gráfico de Programas (Pie)
|
||||
const ctxPlan = document.getElementById("planPie") as HTMLCanvasElement;
|
||||
if (ctxPlan) {
|
||||
chartPlan = new Chart(ctxPlan, {
|
||||
type: "pie",
|
||||
data: {
|
||||
labels: ["Adults", "Kids", "Teens", "Business"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [45, 30, 15, 25],
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "left",
|
||||
labels: {
|
||||
font: {
|
||||
size: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (chartJornadas) chartJornadas.destroy();
|
||||
if (chartPlan) chartPlan.destroy();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
<div className="row">
|
||||
{/* Filtros superiores */}
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Cursos por mes</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<Link
|
||||
href="/Alumnos/Index"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<form onSubmit={handleBuscar} className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">Mes</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<select
|
||||
id="ListaMeses"
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
<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">
|
||||
<span className="fw-bold">Año</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="number"
|
||||
id="TextBoxAgno"
|
||||
className="form-control form-control-sm"
|
||||
defaultValue={2026}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sección Reporte Principal */}
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
{/* Columna Izquierda: Tarjetas y métricas */}
|
||||
<div className="col-md-3 mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mx-auto">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleExportarExcel}
|
||||
className="btn p-0 border-0 w-100 text-decoration-none"
|
||||
>
|
||||
<div className="alert alert-success shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3">
|
||||
<h1>
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<i className="fa-solid fa-users-line"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<i className="fa-solid fa-book"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Cursos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-12 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-swatchbook"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Inscripción de Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-12 text-start mt-2">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columna Central: Tabla de Planes y Progreso de Sedes */}
|
||||
<div className="col-md-4">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="alert alert-light" role="alert">
|
||||
<div className="table-responsive" style={{ width: "100%" }}>
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Plan
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
Cantidad
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{planes.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start">{item.Plan}</td>
|
||||
<td className="text-start">{item.Cantidad}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover mt-2"
|
||||
style={{ fontSize: "12px", width: "100%" }}
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
<strong>TOTAL</strong>
|
||||
</th>
|
||||
<td className="text-start fw-bold" style={{ width: "20%" }}>
|
||||
{planes.reduce((acc, curr) => acc + curr.Cantidad, 0)}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<h4 className="text-center">
|
||||
<small>
|
||||
<u>Cursos por sedes con alumnos de empresas</u>
|
||||
</small>
|
||||
</h4>
|
||||
<div className="col-md-8 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-school"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Sedes</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-4 text-center mt-1">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Default striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Cursos sin SENCE
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Warning striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped bg-warning text-dark"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Cursos con SENCE
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12 text-center mt-3">
|
||||
<h5>
|
||||
<strong>Moneda</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Segment one"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="mone"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
<div
|
||||
id="moneSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Providencia</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="prov"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "60%" }}
|
||||
></div>
|
||||
<div
|
||||
id="provSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "40%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>La Florida</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="flor"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "70%" }}
|
||||
></div>
|
||||
<div
|
||||
id="florSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "30%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Online</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="onli"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "80%" }}
|
||||
></div>
|
||||
<div
|
||||
id="onliSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "20%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Empresas</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="corp"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "40%" }}
|
||||
></div>
|
||||
<div
|
||||
id="corpSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "60%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columna Derecha: Gráficos de Jornadas y Programas */}
|
||||
<div className="col-md-5 align-middle">
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="Jornadas">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm"
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Jornadas</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas id="jornadasBar" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12" id="Programas">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm container-md container-sm"
|
||||
style={{ height: "40vh" }}
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Programas</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas id="planPie" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* MODAL ALERTA / MENSAJES */}
|
||||
{showAlertModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>Módulo Académico - Cursos</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body text-center py-3">
|
||||
<h5>
|
||||
<strong>{mensajeAlerta}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{showLoadingModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>SAM - Académico Empresas</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5>
|
||||
<strong>Procesando, espere un momento...</strong>
|
||||
</h5>
|
||||
<div className="mt-3">
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,666 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { User } from "@boxicons/react";
|
||||
|
||||
export default function CursosPlanCentralPage() {
|
||||
// Estado para visibilidad del reporte (corresponde a visible="false" en ASP.NET)
|
||||
const [divReporte, setDivReporte] = useState(true);
|
||||
|
||||
// Estados para modales de carga y mensajes/errores
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("");
|
||||
|
||||
// Estado para los filtros de Periodo y Letras
|
||||
const [periodo, setPeriodo] = useState("");
|
||||
const [letras, setLetras] = useState<string[]>([]);
|
||||
|
||||
// Datos para la tabla de Planes (DataList en ASP.NET)
|
||||
const [planes] = useState([
|
||||
{ Plan: "Plan Central General", Cantidad: 35 },
|
||||
{ Plan: "Plan Intensivo", Cantidad: 20 },
|
||||
]);
|
||||
|
||||
// Evento al cambiar Periodo (simula el AutoPostBack de ASP.NET)
|
||||
const handlePeriodoChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const val = e.target.value;
|
||||
setPeriodo(val);
|
||||
|
||||
// Actualización dinámica de select según el periodo seleccionado
|
||||
if (val === "1") {
|
||||
setLetras(["A", "B", "C"]);
|
||||
} else if (val === "2") {
|
||||
setLetras(["D", "E", "F"]);
|
||||
} else {
|
||||
setLetras([]);
|
||||
}
|
||||
};
|
||||
|
||||
// Manejo de búsqueda
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setShowLoadingModal(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
setDivReporte(true); // Hace visible el reporte tras buscar
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
// Exportar a Excel
|
||||
const handleExportarExcel = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setMensajeAlerta("Generando y exportando reporte Excel...");
|
||||
setShowAlertModal(true);
|
||||
};
|
||||
|
||||
// Inicialización de Chart.js dinámico en cliente
|
||||
useEffect(() => {
|
||||
if (!divReporte) return;
|
||||
|
||||
let chartJornadas: any = null;
|
||||
let chartPlan: any = null;
|
||||
|
||||
import("chart.js/auto").then(({ default: Chart }) => {
|
||||
// Gráfico de Jornadas (Bar)
|
||||
const ctxJornadas = document.getElementById(
|
||||
"jornadasBar"
|
||||
) as HTMLCanvasElement;
|
||||
|
||||
if (ctxJornadas) {
|
||||
chartJornadas = new Chart(ctxJornadas, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: ["Mañana", "Tarde", "Noche"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [12, 19, 8],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Gráfico de Programas (Pie)
|
||||
const ctxPlan = document.getElementById("planPie") as HTMLCanvasElement;
|
||||
|
||||
if (ctxPlan) {
|
||||
chartPlan = new Chart(ctxPlan, {
|
||||
type: "pie",
|
||||
data: {
|
||||
labels: ["Programa A", "Programa B", "Programa C"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [20, 15, 10],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "left",
|
||||
labels: {
|
||||
font: {
|
||||
size: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (chartJornadas) chartJornadas.destroy();
|
||||
if (chartPlan) chartPlan.destroy();
|
||||
};
|
||||
}, [divReporte]);
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
<div className="row">
|
||||
{/* Encabezado y Filtros */}
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">
|
||||
Cursos plan central por mes
|
||||
</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<Link
|
||||
href="/Alumnos/Index"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<form onSubmit={handleBuscar} className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">Año</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="number"
|
||||
id="TextBoxAgno"
|
||||
className="form-control form-control-sm"
|
||||
defaultValue={2026}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<span className="fw-bold">Periodo</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<select
|
||||
id="ListaPeriodo"
|
||||
className="form-select form-select-sm"
|
||||
value={periodo}
|
||||
onChange={handlePeriodoChange}
|
||||
>
|
||||
<option value="">Seleccione</option>
|
||||
<option value="1">Periodo 1</option>
|
||||
<option value="2">Periodo 2</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col">
|
||||
<select
|
||||
id="ListaLetras"
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
{letras.map((item, index) => (
|
||||
<option key={index} value={item}>
|
||||
{item}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sección Reporte Principal */}
|
||||
{divReporte && (
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
{/* Métricas y Tarjetas Izquierda */}
|
||||
<div className="col-md-3 mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mx-auto">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleExportarExcel}
|
||||
className="btn p-0 border-0 w-100 text-decoration-none"
|
||||
>
|
||||
<div className="alert alert-success shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3">
|
||||
<h1>
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<i className="fa-solid fa-users-line"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<i className="fa-solid fa-book"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Cursos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-12 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-swatchbook"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Inscripción de Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-12 text-start mt-2">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tabla de Planes y Progreso de Sedes */}
|
||||
<div className="col-md-4">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="alert alert-light" role="alert">
|
||||
<div className="table-responsive" style={{ width: "100%" }}>
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Plan
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
Cantidad
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{planes.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start">{item.Plan}</td>
|
||||
<td className="text-start">{item.Cantidad}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover mt-2"
|
||||
style={{ fontSize: "12px", width: "100%" }}
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
<strong>TOTAL</strong>
|
||||
</th>
|
||||
<td className="text-start fw-bold" style={{ width: "20%" }}>
|
||||
{planes.reduce((acc, curr) => acc + curr.Cantidad, 0)}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<h4 className="text-center">
|
||||
<small>
|
||||
<u>Cursos por sedes con Alumnos de empresas</u>
|
||||
</small>
|
||||
</h4>
|
||||
<div className="col-md-8 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-school"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Sedes</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-4 text-center mt-1">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Default striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Cursos sin SENCE
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Warning striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped bg-warning text-dark"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Cursos con SENCE
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12 text-center mt-3">
|
||||
<h5>
|
||||
<strong>Moneda</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Segment one"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="mone"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
<div
|
||||
id="moneSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Providencia</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="prov"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "60%" }}
|
||||
></div>
|
||||
<div
|
||||
id="provSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "40%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>La Florida</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="flor"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "70%" }}
|
||||
></div>
|
||||
<div
|
||||
id="florSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "30%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Online</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="onli"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "80%" }}
|
||||
></div>
|
||||
<div
|
||||
id="onliSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "20%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Canvas de Gráficos */}
|
||||
<div className="col-md-5 align-middle">
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="Jornadas">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm"
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Jornadas</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas id="jornadasBar" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12" id="Programas">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm container-md container-sm"
|
||||
style={{ height: "40vh" }}
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Programas</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas id="planPie" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* MODAL ALERTA / MENSAJES */}
|
||||
{showAlertModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>Módulo Académico - Plan Central</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body text-center py-3">
|
||||
<h5>
|
||||
<strong>{mensajeAlerta}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{showLoadingModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>SAM - Académico Empresas</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5>
|
||||
<strong>Procesando, espere un momento...</strong>
|
||||
</h5>
|
||||
<div className="mt-3">
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,611 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { User, BuildingHouse } from "@boxicons/react";
|
||||
|
||||
export default function EmpresasPorMesPage() {
|
||||
// Estado de visibilidad del reporte principal (div_reporte)
|
||||
const [divReporte, setDivReporte] = useState(true);
|
||||
|
||||
// Estados para modales de Carga y Alertas/Errores
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("");
|
||||
|
||||
// Manejo de búsqueda
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setShowLoadingModal(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
setDivReporte(true);
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
// Manejo de exportación Excel
|
||||
const handleExportarExcel = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setMensajeAlerta("Generando y exportando reporte Excel...");
|
||||
setShowAlertModal(true);
|
||||
};
|
||||
|
||||
// Carga e inicialización de Chart.js dinámico para Tipo de Ventas (Doughnut)
|
||||
useEffect(() => {
|
||||
if (!divReporte) return;
|
||||
|
||||
let chartVenta: any = null;
|
||||
|
||||
import("chart.js/auto").then(({ default: Chart }) => {
|
||||
const ctxVenta = document.getElementById(
|
||||
"ventaPie"
|
||||
) as HTMLCanvasElement;
|
||||
|
||||
if (ctxVenta) {
|
||||
chartVenta = new Chart(ctxVenta, {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: ["Directa", "Licitación", "Convenio Marco", "Otros"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cantidad",
|
||||
data: [40, 25, 20, 15],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (chartVenta) chartVenta.destroy();
|
||||
};
|
||||
}, [divReporte]);
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
<div className="row">
|
||||
{/* Encabezado y Filtros */}
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Empresas por mes</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<Link
|
||||
href="/Alumnos/Index"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<form onSubmit={handleBuscar} className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">Mes</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<select
|
||||
id="ListaMeses"
|
||||
className="form-select form-select-sm"
|
||||
>
|
||||
<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">
|
||||
<span className="fw-bold">Año</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="number"
|
||||
id="TextBoxYear"
|
||||
className="form-control form-control-sm"
|
||||
defaultValue={2026}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sección Reporte Principal */}
|
||||
{divReporte && (
|
||||
<div className="col-md-12" id="div_reporte">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
{/* Métricas y Tarjetas Izquierda */}
|
||||
<div className="col-md-3 mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mx-auto">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleExportarExcel}
|
||||
className="btn p-0 border-0 w-100 text-decoration-none"
|
||||
>
|
||||
<div className="alert alert-success shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3">
|
||||
<h1>
|
||||
{/* <Export /> */}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Excel</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Exportar</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<i className="fa-solid fa-users-line"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-3 text-center">
|
||||
<h1>
|
||||
<BuildingHouse style={{ fontSize: "36px" }} />
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Empresas</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-center mt-3">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light shadow text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-12 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-swatchbook"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Alumnos</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-12 text-start mt-2">
|
||||
<span className="text-muted">
|
||||
<strong>Con SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Sin SENCE</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-12 text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Total</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>0</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tabla Alumnos de empresas y Progreso de Sedes */}
|
||||
<div className="col-md-4">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="alert alert-light" role="alert">
|
||||
<div className="table-responsive" style={{ width: "100%" }}>
|
||||
<h3>Alumnos de empresas</h3>
|
||||
<table
|
||||
className="table table-sm mb-0 table-hover"
|
||||
style={{ fontSize: "12px" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Tipo
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
Cantidad
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "80%" }}>
|
||||
Cursos Abierto
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
0
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "80%" }}>
|
||||
Cursos Cerrado
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
0
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "80%" }}>
|
||||
Total
|
||||
</th>
|
||||
<th className="text-start" style={{ width: "20%" }}>
|
||||
0
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<h4 className="text-center">
|
||||
<small>
|
||||
<u>Sedes con alumnos de empresas</u>
|
||||
</small>
|
||||
</h4>
|
||||
<div className="col-md-8 text-start">
|
||||
<h1>
|
||||
<i className="fa-solid fa-school"></i>
|
||||
</h1>
|
||||
<span className="fw-bold">
|
||||
<strong>Sedes</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col-md-4 text-center mt-1">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Default striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Alumnos sin SENCE
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Warning striped example"
|
||||
aria-valuenow={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
className="progress-bar progress-bar-striped bg-warning text-dark"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
Alumnos con SENCE
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12 text-center mt-3">
|
||||
<h5>
|
||||
<strong>Moneda</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Segment one"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="mone"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
<div
|
||||
id="moneSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "50%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Providencia</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="prov"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "60%" }}
|
||||
></div>
|
||||
<div
|
||||
id="provSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "40%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>La Florida</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="flor"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "70%" }}
|
||||
></div>
|
||||
<div
|
||||
id="florSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "30%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Online</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="onli"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "80%" }}
|
||||
></div>
|
||||
<div
|
||||
id="onliSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "20%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h5>
|
||||
<strong>Empresas</strong>
|
||||
</h5>
|
||||
<div className="progress-stacked">
|
||||
<div
|
||||
className="progress"
|
||||
role="progressbar"
|
||||
aria-label="Info example"
|
||||
aria-valuenow={50}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<div
|
||||
id="corp"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style={{ width: "40%" }}
|
||||
></div>
|
||||
<div
|
||||
id="corpSNC"
|
||||
className="progress-bar progress-bar-striped progress-bar-animated bg-warning text-dark"
|
||||
style={{ width: "60%" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Canvas de Gráfico Tipos de Ventas */}
|
||||
<div className="col-md-5 align-middle mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-12" id="TipoDeVentas">
|
||||
<div
|
||||
className="alert alert-light text-dark offcanvas-lg offcanvas-sm container-md container-sm"
|
||||
role="alert"
|
||||
>
|
||||
<h3>
|
||||
<span>
|
||||
<b>
|
||||
<u>Tipos de ventas</u>
|
||||
</b>
|
||||
</span>
|
||||
</h3>
|
||||
<canvas id="ventaPie" className="w-100 h-100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* MODAL ALERTA / ERRORES */}
|
||||
{showAlertModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>Módulo Académico - Empresas</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body text-center py-3">
|
||||
<h5>
|
||||
<strong>{mensajeAlerta}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{showLoadingModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="modal-title">
|
||||
<strong>SAM - Académico Empresas</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5>
|
||||
<strong>Procesando, espere un momento...</strong>
|
||||
</h5>
|
||||
<div className="mt-3">
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -15,25 +15,25 @@ export default function Page() {
|
||||
icon: <File className="bx-sm bx-border" />,
|
||||
color: "text-warning",
|
||||
label: "Informe cursos iniciados por fecha",
|
||||
href: "/Informes/Index?boton=periodo",
|
||||
href: "/Informes/CursosInicio",
|
||||
},
|
||||
{
|
||||
icon: <File className="bx-sm bx-border" />,
|
||||
color: "text-warning",
|
||||
label: "Informe cursos activos por mes",
|
||||
href: "/Informes/Index?boton=activos",
|
||||
href: "/Informes/CursosActivos",
|
||||
},
|
||||
{
|
||||
icon: <File className="bx-sm bx-border" />,
|
||||
color: "text-info",
|
||||
label: "Cursos por iniciar",
|
||||
href: "/Informes/CursosInicios?search=CURSOSINICIAN",
|
||||
href: "/Informes/CursosIniTer",
|
||||
},
|
||||
{
|
||||
icon: <File className="bx-sm bx-border" />,
|
||||
color: "text-info",
|
||||
label: "Cursos por finalizar",
|
||||
href: "/Informes/CursosInicios?search=CURSOSFINALIZAN",
|
||||
href: "/Informes/CursosIniTer",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
// TransferAlt,
|
||||
Check,
|
||||
X,
|
||||
// Error as ErrorIcon,
|
||||
// ErrorCircle,
|
||||
CheckCircle,
|
||||
} from "@boxicons/react";
|
||||
|
||||
// Interfaz para los datos del reemplazo
|
||||
interface ReemplazoItem {
|
||||
idCursoAbierto: string;
|
||||
Curso: string;
|
||||
FechaAsistencia: string;
|
||||
HoraInicio: string;
|
||||
HoraSalida: string;
|
||||
rutProfesor: string;
|
||||
Profesor: string;
|
||||
Estado: string;
|
||||
idAsistenciaProfesor: string;
|
||||
Email?: string;
|
||||
}
|
||||
|
||||
// Interfaz para la configuración de la confirmación
|
||||
interface ModalConfirmacionState {
|
||||
show: boolean;
|
||||
accion: "autorizar" | "rechazar" | null;
|
||||
item: ReemplazoItem | null;
|
||||
}
|
||||
|
||||
export default function ReemplazosPendientesPage() {
|
||||
// Estado con datos de ejemplo
|
||||
const [reemplazos, setReemplazos] = useState<ReemplazoItem[]>([
|
||||
{
|
||||
idCursoAbierto: "CUR-101",
|
||||
Curso: "Inglés Básico A1",
|
||||
FechaAsistencia: "15-02-2026",
|
||||
HoraInicio: "09:00",
|
||||
HoraSalida: "10:30",
|
||||
rutProfesor: "12.345.678-9",
|
||||
Profesor: "Juan Pérez",
|
||||
Estado: "Pendiente",
|
||||
idAsistenciaProfesor: "SES-001",
|
||||
Email: "jperez@correo.cl",
|
||||
},
|
||||
{
|
||||
idCursoAbierto: "CUR-102",
|
||||
Curso: "Inglés Intermedio B2",
|
||||
FechaAsistencia: "16-02-2026",
|
||||
HoraInicio: "11:00",
|
||||
HoraSalida: "12:30",
|
||||
rutProfesor: "15.987.654-3",
|
||||
Profesor: "María González",
|
||||
Estado: "Pendiente",
|
||||
idAsistenciaProfesor: "SES-002",
|
||||
Email: "mgonzalez@correo.cl",
|
||||
},
|
||||
]);
|
||||
|
||||
// Estados para diálogos y procesamientos
|
||||
const [modalConfirm, setModalConfirm] = useState<ModalConfirmacionState>({
|
||||
show: false,
|
||||
accion: null,
|
||||
item: null,
|
||||
});
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [modalRespuesta, setModalRespuesta] = useState<{
|
||||
show: boolean;
|
||||
errorMsg: string;
|
||||
okMsg: string;
|
||||
}>({ show: false, errorMsg: "", okMsg: "" });
|
||||
|
||||
// Abrir modal customizado de confirmación
|
||||
const abrirConfirmacion = (item: ReemplazoItem, accion: "autorizar" | "rechazar") => {
|
||||
setModalConfirm({
|
||||
show: true,
|
||||
accion,
|
||||
item,
|
||||
});
|
||||
};
|
||||
|
||||
// Procesar la autorización / rechazo
|
||||
const handleConfirmar = () => {
|
||||
if (!modalConfirm.item || !modalConfirm.accion) return;
|
||||
|
||||
const { idAsistenciaProfesor } = modalConfirm.item;
|
||||
const accion = modalConfirm.accion;
|
||||
|
||||
// Cerrar modal de confirmación y mostrar loader
|
||||
setModalConfirm({ show: false, accion: null, item: null });
|
||||
setIsLoading(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
// Eliminar el ítem procesado de la lista
|
||||
setReemplazos((prev) => prev.filter((r) => r.idAsistenciaProfesor !== idAsistenciaProfesor));
|
||||
setModalRespuesta({
|
||||
show: true,
|
||||
errorMsg: "",
|
||||
okMsg: `El reemplazo se ha ${
|
||||
accion === "autorizar" ? "autorizado" : "rechazado"
|
||||
} correctamente.`,
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
{/* ENCABEZADO */}
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-1 text-center">
|
||||
{/* <TransferAlt className="text-warning fs-3 border rounded p-1" /> */}
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
<span className="text-muted">
|
||||
<strong>Autorización</strong>
|
||||
</span>
|
||||
<h5 className="mb-0">
|
||||
<strong>Reemplazos Pendientes</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TABLA O ALERTA */}
|
||||
{reemplazos.length > 0 ? (
|
||||
<div className="col-md-12" id="divTablaReemplazos">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<div className="table-responsive">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: "14px" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "18%" }}>Curso</th>
|
||||
<th className="text-center" style={{ width: "10%" }}>Sesión</th>
|
||||
<th className="text-center" style={{ width: "8%" }}>Inicio</th>
|
||||
<th className="text-center" style={{ width: "8%" }}>Salida</th>
|
||||
<th className="text-center" style={{ width: "14%" }}>Run</th>
|
||||
<th className="text-center" style={{ width: "14%" }}>Reemplazante</th>
|
||||
<th className="text-center" style={{ width: "10%" }}>Estado Sesion</th>
|
||||
<th className="text-center" style={{ width: "18%" }}>Acción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{reemplazos.map((item) => (
|
||||
<tr key={item.idAsistenciaProfesor}>
|
||||
<td className="text-start" style={{ width: "18%" }}>
|
||||
<strong>{item.Curso}</strong>
|
||||
<span className="badge bg-secondary ms-1">
|
||||
{item.idCursoAbierto}
|
||||
</span>
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "10%" }}>
|
||||
{item.FechaAsistencia}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "8%" }}>
|
||||
{item.HoraInicio}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "8%" }}>
|
||||
{item.HoraSalida}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "14%" }}>
|
||||
{item.rutProfesor}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "14%" }}>
|
||||
{item.Profesor}
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "10%" }}>
|
||||
<span className="badge bg-warning text-dark">
|
||||
{item.Estado}
|
||||
</span>
|
||||
</td>
|
||||
<td className="text-center" style={{ width: "18%" }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-success btn-sm me-1"
|
||||
onClick={() => abrirConfirmacion(item, "autorizar")}
|
||||
>
|
||||
<Check className="me-1" /> Autorizar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-danger btn-sm"
|
||||
onClick={() => abrirConfirmacion(item, "rechazar")}
|
||||
>
|
||||
<X className="me-1" /> Rechazar
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="col-md-12" id="divSinReemplazos">
|
||||
<div className="alert alert-light text-dark shadow text-center py-4" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3"></div>
|
||||
<div className="col-md-6 text-center">
|
||||
<div className="alert alert-light text-dark mt-5" role="alert">
|
||||
<strong>
|
||||
{/* <ErrorIcon className="text-primary" style={{ fontSize: "90px" }} /> */}
|
||||
</strong>
|
||||
<br />
|
||||
<br />
|
||||
<h5>
|
||||
<strong>No hay reemplazos pendientes de autorización</strong>
|
||||
</h5>
|
||||
<hr />
|
||||
<strong className="text-muted">
|
||||
Si cree que esto es un error, contáctenos.{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://norteamericano.freshdesk.com/support/tickets/new"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Generar Ticket
|
||||
</a>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* MODAL PERSONALIZADO DE CONFIRMACIÓN (REEMPLAZO DE SWEETALERT2) */}
|
||||
{modalConfirm.show && modalConfirm.item && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content rounded-4 p-3">
|
||||
<div className="modal-body text-center">
|
||||
{modalConfirm.accion === "autorizar" ? (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#198754" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
||||
<polyline points="22 4 12 14.01 9 11.01" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#dc3545" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="15" y1="9" x2="9" y2="15" />
|
||||
<line x1="9" y1="9" x2="15" y2="15" />
|
||||
</svg>
|
||||
)}
|
||||
|
||||
<h4 className="mt-2 mb-1 fw-bold" style={{ color: "#1f2937" }}>
|
||||
{modalConfirm.accion === "autorizar" ? "Autorizar Reemplazo" : "Rechazar Reemplazo"}
|
||||
</h4>
|
||||
<p className="text-muted mb-3" style={{ fontSize: "14px" }}>
|
||||
{modalConfirm.accion === "autorizar"
|
||||
? "Se asignará al profesor reemplazante"
|
||||
: "Se rechazará al profesor reemplazante"}
|
||||
</p>
|
||||
|
||||
<div
|
||||
className="p-3 text-start rounded-3"
|
||||
style={{
|
||||
backgroundColor: modalConfirm.accion === "autorizar" ? "#f0fdf4" : "#fef2f2",
|
||||
border: `1px solid ${modalConfirm.accion === "autorizar" ? "#a3cfbb" : "#f1aeb5"}`,
|
||||
fontSize: "13px",
|
||||
color: "#374151",
|
||||
}}
|
||||
>
|
||||
<div className="d-flex justify-content-between mb-2">
|
||||
<span className="fw-bold">Curso</span>
|
||||
<span>
|
||||
{modalConfirm.item.Curso}{" "}
|
||||
<span className="badge bg-secondary ms-1">
|
||||
{modalConfirm.item.idCursoAbierto}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="d-flex justify-content-between mb-2">
|
||||
<span className="fw-bold">Sesión</span>
|
||||
<span>
|
||||
{modalConfirm.item.FechaAsistencia} | {modalConfirm.item.HoraInicio} - {modalConfirm.item.HoraSalida}
|
||||
</span>
|
||||
</div>
|
||||
<div className="d-flex justify-content-between mb-2">
|
||||
<span className="fw-bold">Profesor</span>
|
||||
<span>{modalConfirm.item.rutProfesor}</span>
|
||||
</div>
|
||||
<div className="d-flex justify-content-between">
|
||||
<span className="fw-bold">Reemplazante</span>
|
||||
<span
|
||||
className="fw-bold"
|
||||
style={{
|
||||
color: modalConfirm.accion === "autorizar" ? "#198754" : "#dc3545",
|
||||
}}
|
||||
>
|
||||
{modalConfirm.item.Profesor}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="d-flex justify-content-end gap-2 mt-4">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setModalConfirm({ show: false, accion: null, item: null })}
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn ${modalConfirm.accion === "autorizar" ? "btn-success" : "btn-danger"}`}
|
||||
onClick={handleConfirmar}
|
||||
>
|
||||
{modalConfirm.accion === "autorizar" ? "Sí, autorizar" : "Sí, rechazar"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL RESPUESTA */}
|
||||
{modalRespuesta.show && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header text-white text-center" style={{ backgroundColor: "#373193" }}>
|
||||
<h5 className="modal-title">Reemplazos</h5>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{modalRespuesta.errorMsg && (
|
||||
<div>
|
||||
<strong style={{ color: "#e22523" }}>
|
||||
{/* <ErrorCircle className="me-1" /> */}
|
||||
<span>{modalRespuesta.errorMsg}</span>
|
||||
</strong>
|
||||
</div>
|
||||
)}
|
||||
{modalRespuesta.okMsg && (
|
||||
<div>
|
||||
<strong style={{ color: "#00285d" }}>
|
||||
<CheckCircle className="me-1" />
|
||||
<span>{modalRespuesta.okMsg}</span>
|
||||
</strong>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setModalRespuesta({ show: false, errorMsg: "", okMsg: "" })}
|
||||
>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{isLoading && (
|
||||
<div className="modal fade show d-block bg-dark bg-opacity-50" tabIndex={-1} role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
<div className="modal-body">
|
||||
<div className="col-md-12 text-center py-3">
|
||||
<div className="spinner-border text-info" role="status">
|
||||
<span className="visually-hidden">Procesando...</span>
|
||||
</div>
|
||||
<p className="mt-2 mb-0">Procesando la información...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { User, Save, Receipt } from "@boxicons/react";
|
||||
|
||||
export default function EvaluacionAlumnosPage() {
|
||||
// Estados para visibilidad de secciones (equivalente a Visible="false")
|
||||
const [showCreateAlm, setShowCreateAlm] = useState(false);
|
||||
const [showUpdatePlacement, setShowUpdatePlacement] = useState(false);
|
||||
|
||||
// Estados para modales
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("Mensaje de prueba");
|
||||
|
||||
// Estados para botones con estado de carga
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [isSavingAlumno, setIsSavingAlumno] = useState(false);
|
||||
const [isSavingEvaluacion, setIsSavingEvaluacion] = useState(false);
|
||||
|
||||
// Handlers para simular acciones
|
||||
const handleBuscar = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSearching(true);
|
||||
setShowLoadingModal(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsSearching(false);
|
||||
setShowLoadingModal(false);
|
||||
// Muestra la sección deseada al terminar la búsqueda
|
||||
setShowUpdatePlacement(true);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const handleGuardarAlumno = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSavingAlumno(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsSavingAlumno(false);
|
||||
setMensajeAlerta("Alumno guardado correctamente.");
|
||||
setShowAlertModal(true);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const handleGuardarEvaluacion = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSavingEvaluacion(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsSavingEvaluacion(false);
|
||||
setMensajeAlerta("Evaluación guardada correctamente.");
|
||||
setShowAlertModal(true);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
<div className="row">
|
||||
{/* Búsqueda del alumno */}
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<strong>
|
||||
<User style={{ fontSize: "24px" }} />
|
||||
</strong>
|
||||
<strong>
|
||||
<span className="ms-2">Evaluación alumnos</span>
|
||||
</strong>
|
||||
</div>
|
||||
<div className="col text-end">
|
||||
<Link
|
||||
href="/Academico/Index"
|
||||
className="btn btn-warning text-dark btn-sm"
|
||||
>
|
||||
<strong>Volver</strong>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-7">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<form onSubmit={handleBuscar} className="row align-items-center">
|
||||
<div className="col">
|
||||
<span className="fw-bold">RUN del alumno</span>
|
||||
</div>
|
||||
<div className="col">
|
||||
<input
|
||||
type="text"
|
||||
id="TextBoxIDRun"
|
||||
className="form-control form-control-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-sm d-grid w-100"
|
||||
disabled={isSearching}
|
||||
>
|
||||
<div className="contenedor-boton">
|
||||
{isSearching ? (
|
||||
<div className="col-12 text-center py-1">
|
||||
<span
|
||||
className="spinner-border spinner-border-sm me-2"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<strong>Buscando alumno...</strong>
|
||||
</div>
|
||||
) : (
|
||||
"Buscar"
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Carta de ingreso alumno nuevo */}
|
||||
{showCreateAlm && (
|
||||
<div className="col-md-6 mx-auto" id="create_alm">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<table className="table w-100">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
R.U.N.
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<input type="text" id="TextBoxId" className="form-control" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Nombre
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<input type="text" id="TextBoxName" className="form-control" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Apellido Paterno
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<input
|
||||
type="text"
|
||||
id="TextBoxApPaterno"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Apellido Materno
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<input
|
||||
type="text"
|
||||
id="TextBoxApMaterno"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Dirección
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<input
|
||||
type="text"
|
||||
id="TextBoxDirAlm"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Región
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<select id="ListRegion" className="form-select">
|
||||
<option value="0">Seleccionar</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
Comuna
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "15%" }}>
|
||||
<select id="ListComuna" className="form-select">
|
||||
<option value="0">Seleccionar</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
Telefono
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "35%" }}>
|
||||
<input
|
||||
type="tel"
|
||||
id="TextBoxFono"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
Email
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "35%" }}>
|
||||
<input
|
||||
type="email"
|
||||
id="TextBoxEmail"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
Fecha de nacimiento
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "35%" }}>
|
||||
<input
|
||||
type="date"
|
||||
id="TextBoxNacimiento"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "20%" }}>
|
||||
Profesion
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "35%" }}>
|
||||
<input
|
||||
type="text"
|
||||
id="TextBoxProfesion"
|
||||
className="form-control"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "20%" }}></td>
|
||||
<td className="text-start" style={{ width: "35%" }}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleGuardarAlumno}
|
||||
className="btn p-0 border-0 text-start w-100"
|
||||
disabled={isSavingAlumno}
|
||||
>
|
||||
<div className="alert alert-success shadow mb-0" role="alert">
|
||||
<div className="row contenedor-boton">
|
||||
{isSavingAlumno ? (
|
||||
<div className="col-12 text-center py-2">
|
||||
<span
|
||||
className="spinner-border spinner-border-sm me-2"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<strong>Guardando alumno...</strong>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="col text-end">
|
||||
<h2>
|
||||
<Save />
|
||||
</h2>
|
||||
</div>
|
||||
<div className="col text-start">
|
||||
<span className="text-muted">
|
||||
<strong>Guardar</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Evaluacion</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Carta del alumno y selección de nivel */}
|
||||
{showUpdatePlacement && (
|
||||
<div className="col-md-12" id="update_placement">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-4 text-end">
|
||||
<table className="table table-sm table-borderless shadow mb-0 text-center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<User
|
||||
className="text-primary bx-border mb-2 bx-burst-hover"
|
||||
style={{ fontSize: "50px" }}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<span className="fs-5">Juan Pérez</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<strong>
|
||||
<span className="fs-5">12.345.678-9</span>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<strong>
|
||||
<span className="fs-5">Nivel Inicial</span>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="col-md-4 text-center">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<h3>Evaluacion</h3>
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id="CheckBox1"
|
||||
/>
|
||||
<label className="form-check-label" htmlFor="CheckBox1">
|
||||
Presencial/Online
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id="CheckBox2"
|
||||
/>
|
||||
<label className="form-check-label" htmlFor="CheckBox2">
|
||||
Placement Test
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 mt-3">
|
||||
<span>Nivel</span>
|
||||
<select id="listNiveles" className="form-select">
|
||||
<option value="0">Seleccionar Nivel</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-4 text-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleGuardarEvaluacion}
|
||||
className="btn p-0 border-0 text-decoration-none w-100"
|
||||
disabled={isSavingEvaluacion}
|
||||
>
|
||||
<div
|
||||
className="alert alert-success shadow mb-0"
|
||||
role="alert"
|
||||
id="ContenedorBoton"
|
||||
>
|
||||
<div className="row contenedor-boton align-items-center">
|
||||
{isSavingEvaluacion ? (
|
||||
<div className="col-12 text-center py-2">
|
||||
<span
|
||||
className="spinner-border spinner-border-sm me-2"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<strong>Guardando evaluación...</strong>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="col-md-3">
|
||||
<h2>
|
||||
<Receipt />
|
||||
</h2>
|
||||
</div>
|
||||
<div className="col text-center">
|
||||
<span className="text-muted">
|
||||
<strong>Guardar</strong>
|
||||
</span>
|
||||
<h5>
|
||||
<strong>Evaluacion</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* POPUPS Y MODALES */}
|
||||
|
||||
{/* Modal Alerta */}
|
||||
{showAlertModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="float-start mt-2">
|
||||
<strong>Módulo Academico - Empresa</strong>
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close float-end"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body alert text-justify">
|
||||
<div className="row">
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center">
|
||||
<h5>
|
||||
<strong>{mensajeAlerta}</strong>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => setShowAlertModal(false)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Modal Cargando */}
|
||||
{showLoadingModal && (
|
||||
<div
|
||||
className="modal fade show d-block"
|
||||
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
|
||||
tabIndex={-1}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="float-start mt-2">
|
||||
<strong>SAM - Académico Empresas </strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="modal-body alert text-justify">
|
||||
<div className="row">
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center"></div>
|
||||
<div className="col-md-12 text-center">
|
||||
<h5>
|
||||
<strong>Procesando, espere un momento</strong>
|
||||
</h5>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-primary me-1"
|
||||
role="status"
|
||||
></div>
|
||||
<div
|
||||
className="spinner-grow spinner-grow-sm text-danger me-1"
|
||||
role="status"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,846 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import {
|
||||
//Transfer,
|
||||
User,
|
||||
// PhoneCall,
|
||||
// MailSend,
|
||||
Envelope,
|
||||
// CurrentLocation,
|
||||
// Cake,
|
||||
Edit,
|
||||
Pencil,
|
||||
File,
|
||||
UserPlus,
|
||||
Certification,
|
||||
// Comment,
|
||||
// Error as ErrorIcon,
|
||||
RefreshCwDot,
|
||||
// Download,
|
||||
// FilePdf,
|
||||
Save
|
||||
} from '@boxicons/react';
|
||||
|
||||
export default function FichaAlumnoPage() {
|
||||
// --- ESTADOS DE PESTAÑAS ---
|
||||
const [activeTab, setActiveTab] = useState<'cursos' | 'contratos' | 'apoderados' | 'certificados' | 'comentarios'>('cursos');
|
||||
|
||||
// --- ESTADOS DE VISTAS INTERNAS ---
|
||||
const [subViewCursos, setSubViewCursos] = useState<'reporte' | 'error' | 'detalle' | 'confirma_cambio'>('reporte');
|
||||
const [hasCursosError, setHasCursosError] = useState(false);
|
||||
|
||||
// --- ESTADOS DE MODALS ---
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showErrorModal, setShowErrorModal] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
|
||||
const [showModalNotas, setShowModalNotas] = useState(false);
|
||||
const [showModalAsistencia, setShowModalAsistencia] = useState(false);
|
||||
const [showModalCursosDisp, setShowModalCursosDisp] = useState(false);
|
||||
const [showModalEditarAlumno, setShowModalEditarAlumno] = useState(false);
|
||||
|
||||
// --- ESTADOS DE FORMULARIOS ---
|
||||
const [comentarioInput, setComentarioInput] = useState('');
|
||||
const [confirmCambioCheck, setConfirmCambioCheck] = useState(false);
|
||||
|
||||
const [editForm, setEditForm] = useState({
|
||||
nombre: '',
|
||||
paterno: '',
|
||||
materno: '',
|
||||
nacimiento: '',
|
||||
fono: '',
|
||||
mail: '',
|
||||
direccion: '',
|
||||
region: '',
|
||||
comuna: '',
|
||||
ocupacion: '',
|
||||
profesion: ''
|
||||
});
|
||||
|
||||
// --- DISPARADORES DE EJEMPLO PARA ACCIONES Y CARGAS ---
|
||||
const handleSimulateLoading = (action: () => void) => {
|
||||
setShowLoadingModal(true);
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
action();
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
const triggerError = (msg: string) => {
|
||||
setErrorMessage(msg);
|
||||
setShowErrorModal(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
{/* BARRA SUPERIOR */}
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-md-6">
|
||||
<h5 className="mb-0">
|
||||
<strong className="text-muted">Ficha</strong> <strong>Alumno</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-6 text-end">
|
||||
<Link href="/index" className="btn btn-primary btn-sm">
|
||||
{/* <Transfer className="me-2" /> */}
|
||||
Cambiar Alumno
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* PANEL IZQUIERDO: INFORMACIÓN DE CONTACTO */}
|
||||
<div className="col-md-3">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<table className="table table-sm table-borderless mb-0 text-center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<User className="text-primary mb-2" style={{ fontSize: '50px' }} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<span className="fs-5 fw-bold">Juan Pérez González</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<strong>12.345.678-9</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm"
|
||||
// onClick={() => handleTokyPopup('+56912345678')}
|
||||
>
|
||||
{/* <PhoneCall className="me-1" /> */}
|
||||
Llamar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-light btn-sm border"
|
||||
// onClick={() => handleGmailPopup('alumno@email.com')}
|
||||
>
|
||||
{/* <MailSend className="me-1" /> */}
|
||||
Mensaje
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<div className="table-responsive">
|
||||
<table className="table table-sm table-borderless mb-0" style={{ fontSize: '14px' }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<span className="text-dark" style={{ fontSize: '18px' }}>Contacto</span>
|
||||
<hr className="my-2" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ width: '25px' }}>
|
||||
{/* <PhoneCall /> */}
|
||||
</td>
|
||||
<td>+56 9 1234 5678</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><Envelope /></td>
|
||||
<td>alumno@email.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <CurrentLocation /> */}
|
||||
</td>
|
||||
<td>Av. Providencia 1234</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <CurrentLocation /> */}
|
||||
</td>
|
||||
<td>Providencia, Región Metropolitana</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <Cake /> */}
|
||||
</td>
|
||||
<td>15/08/1995</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<button
|
||||
className="btn btn-warning btn-sm"
|
||||
onClick={() => setShowModalEditarAlumno(true)}
|
||||
>
|
||||
<strong><Edit className="me-1" /> Editar</strong>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* PANEL DERECHO: PESTAÑAS Y CONTENIDOS */}
|
||||
<div className="col-md-9">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
{/* NAVEGACIÓN TAB */}
|
||||
<div className="d-grid gap-2 mb-3">
|
||||
<div className="btn-group" role="group">
|
||||
<button
|
||||
className={`btn btn-light border-top-0 border-end-0 border-start-0 border-3 ${activeTab === 'cursos' ? 'border-primary active' : ''}`}
|
||||
onClick={() => setActiveTab('cursos')}
|
||||
>
|
||||
<Pencil className="me-2" style={{ fontSize: '18px' }} /> Cursos
|
||||
</button>
|
||||
<button
|
||||
className={`btn btn-light border-top-0 border-end-0 border-start-0 border-3 ${activeTab === 'contratos' ? 'border-primary active' : ''}`}
|
||||
onClick={() => setActiveTab('contratos')}
|
||||
>
|
||||
<File className="me-2" style={{ fontSize: '18px' }} /> Contratos
|
||||
</button>
|
||||
<button
|
||||
className={`btn btn-light border-top-0 border-end-0 border-start-0 border-3 ${activeTab === 'apoderados' ? 'border-primary active' : ''}`}
|
||||
onClick={() => setActiveTab('apoderados')}
|
||||
>
|
||||
<UserPlus className="me-2" style={{ fontSize: '18px' }} /> Apoderado
|
||||
</button>
|
||||
<button
|
||||
className={`btn btn-light border-top-0 border-end-0 border-start-0 border-3 ${activeTab === 'certificados' ? 'border-primary active' : ''}`}
|
||||
onClick={() => setActiveTab('certificados')}
|
||||
>
|
||||
<Certification className="me-2" style={{ fontSize: '18px' }} /> Certificados
|
||||
</button>
|
||||
<button
|
||||
className={`btn btn-light border-top-0 border-end-0 border-start-0 border-3 ${activeTab === 'comentarios' ? 'border-primary active' : ''}`}
|
||||
onClick={() => setActiveTab('comentarios')}
|
||||
>
|
||||
{/* <Comment className="me-2" style={{ fontSize: '18px' }} /> */}
|
||||
Comentarios
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* --- PESTAÑA: CURSOS --- */}
|
||||
{activeTab === 'cursos' && (
|
||||
<div>
|
||||
{subViewCursos === 'reporte' && !hasCursosError && (
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="table-responsive mt-3">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{ width: '10%' }}></th>
|
||||
<th scope="col" className="text-center" style={{ width: '5%' }}><strong>Year</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '6%' }}><strong>ID</strong></th>
|
||||
<th scope="col" className="text-start" style={{ width: '32%' }}><strong>Curso</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '20%' }}><strong>Contrato</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '17%' }}><strong>Fecha</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '10%' }}><strong>Estado</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start">
|
||||
<button
|
||||
className="btn btn-link p-0 text-decoration-none"
|
||||
onClick={() => setSubViewCursos('detalle')}
|
||||
>
|
||||
<h6><span className="badge bg-secondary style-normal">Ingresar</span></h6>
|
||||
</button>
|
||||
</td>
|
||||
<td className="text-center">2026</td>
|
||||
<td className="text-center">1024</td>
|
||||
<td className="text-start">2026-1 - Inglés Avanzado C1</td>
|
||||
<td className="text-center">
|
||||
<strong className="text-primary">PARTICULAR</strong>
|
||||
</td>
|
||||
<td className="text-center">01/03/2026 | 30/06/2026</td>
|
||||
<td className="text-center">
|
||||
<span className="badge bg-primary style-normal" style={{ fontSize: '12px' }}>
|
||||
<span className="me-2 ms-2">Cursando</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasCursosError && (
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3"></div>
|
||||
<div className="col-md-6 text-center">
|
||||
<div className="alert alert-light text-dark mt-5" role="alert">
|
||||
{/* <ErrorIcon className="text-primary" style={{ fontSize: '90px' }} /> */}
|
||||
<br /><br />
|
||||
<h5><strong>El alumno no tiene Cursos disponibles</strong></h5>
|
||||
<hr />
|
||||
<strong className="text-muted">
|
||||
Si cree que esto es un error, contáctenos.{' '}
|
||||
<a target="_blank" rel="noreferrer" href="https://norteamericano.freshdesk.com/support/tickets/new">Generar Ticket</a>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{subViewCursos === 'detalle' && (
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row mt-4">
|
||||
<div className="col-md-7">
|
||||
<table className="table table-sm mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Curso</td>
|
||||
<td style={{ fontSize: '16px' }}><strong>Inglés Avanzado C1</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Código</td>
|
||||
<td><strong>1024</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Estado</td>
|
||||
<td><strong>Cursando</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sede</td>
|
||||
<td><strong>Providencia</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Profesor</td>
|
||||
<td><strong>John Doe</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sala</td>
|
||||
<td><strong>Lab 402</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Horario</td>
|
||||
<td><strong>Lu-Mi-Vi 19:00 - 21:00</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inicio</td>
|
||||
<td><strong>01/03/2026</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Término</td>
|
||||
<td><strong>30/06/2026</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="col-md-5">
|
||||
<table className="table table-sm mb-4">
|
||||
<tbody>
|
||||
<tr className="table-secondary text-dark">
|
||||
<td colSpan={3}><strong>Opciones</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={3}>
|
||||
<button
|
||||
className="btn btn-link p-0 fw-bold text-decoration-none"
|
||||
onClick={() => setSubViewCursos('confirma_cambio')}
|
||||
>
|
||||
Cambiar de Curso
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<table className="table table-sm mb-0">
|
||||
<tbody>
|
||||
<tr className="table-secondary text-dark">
|
||||
<td colSpan={3}><strong>RollBook</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nota</td>
|
||||
<td colSpan={2}>
|
||||
<button
|
||||
className="btn btn-link p-0 fw-bold text-decoration-none"
|
||||
onClick={() => setShowModalNotas(true)}
|
||||
>
|
||||
Ver
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Asistencia</td>
|
||||
<td colSpan={2}>
|
||||
<button
|
||||
className="btn btn-link p-0 fw-bold text-decoration-none"
|
||||
onClick={() => setShowModalAsistencia(true)}
|
||||
>
|
||||
Ver
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Estado</td>
|
||||
<td colSpan={2}><strong>En proceso</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Certificado</td>
|
||||
<td>
|
||||
<button className="btn btn-link p-0 text-decoration-none">
|
||||
<RefreshCwDot /> Refrescar certificado
|
||||
</button>
|
||||
</td>
|
||||
<td><strong>---</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{subViewCursos === 'confirma_cambio' && (
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-5">
|
||||
<table className="table table-sm mb-0 caption-top">
|
||||
<caption><strong><u>Actual Curso</u></strong></caption>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Curso</td>
|
||||
<td style={{ fontSize: '16px' }}><strong>Inglés Avanzado C1</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Código</td>
|
||||
<td><strong>1024</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sede</td>
|
||||
<td><strong>Providencia</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="col-md-2 style-center-vh">
|
||||
<h2 className="text-center">
|
||||
{/* <Transfer /> */}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="col-md-5">
|
||||
<table className="table table-sm mb-0 caption-top">
|
||||
<caption><strong><u>Nuevo Curso</u></strong></caption>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Curso</td>
|
||||
<td style={{ fontSize: '16px' }}><strong>Inglés Intensivo C1</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Código</td>
|
||||
<td><strong>2048</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sede</td>
|
||||
<td><strong>Santiago Centro</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="col-md-12 text-center mb-0 mt-3">
|
||||
<div className="form-check d-inline-block">
|
||||
<input
|
||||
className="form-check-input me-2"
|
||||
type="checkbox"
|
||||
id="chkConfirm"
|
||||
checked={confirmCambioCheck}
|
||||
onChange={(e) => setConfirmCambioCheck(e.target.checked)}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor="chkConfirm">
|
||||
Confirmo y autorizo el cambio de curso con la información mostrada en pantalla.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 text-center mt-2">
|
||||
<button
|
||||
className="btn btn-success"
|
||||
onClick={() => handleSimulateLoading(() => setSubViewCursos('detalle'))}
|
||||
disabled={!confirmCambioCheck}
|
||||
>
|
||||
Actualizar Curso
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- PESTAÑA: CONTRATOS --- */}
|
||||
{activeTab === 'contratos' && (
|
||||
<div>
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="table-responsive mt-3">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '11px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{ width: '10%' }}></th>
|
||||
<th scope="col" style={{ width: '7%' }}><strong>Fecha</strong></th>
|
||||
<th scope="col" style={{ width: '7%' }}><strong>Contrato</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '8%' }}><strong>Tipo</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '12%' }}><strong>RUT Empresa</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '25%' }}><strong>Empresa</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '15%' }}><strong>Curso</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '10%' }}><strong>Registro</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<button className="btn btn-secondary btn-sm p-0 px-2" style={{ fontSize: '10px' }}>
|
||||
Ver
|
||||
</button>
|
||||
</td>
|
||||
<td>01/01/2026</td>
|
||||
<td><strong>CNT-991</strong></td>
|
||||
<td className="text-center">Empresa</td>
|
||||
<td className="text-center">76.123.456-7</td>
|
||||
<td className="text-center"><strong>Corporación X</strong></td>
|
||||
<td className="text-center">Inglés C1</td>
|
||||
<td className="text-center">SENCE</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- PESTAÑA: APODERADOS --- */}
|
||||
{activeTab === 'apoderados' && (
|
||||
<div>
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="table-responsive mt-3">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{ width: '10%' }}></th>
|
||||
<th scope="col" style={{ width: '12%' }}><strong>Fecha</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '12%' }}><strong>RUT Empresa</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '30%' }}><strong>Empresa</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>10/02/2026</td>
|
||||
<td className="text-center"><strong>76.123.456-7</strong></td>
|
||||
<td className="text-center"><strong>Corporación X</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- PESTAÑA: CERTIFICADOS --- */}
|
||||
{activeTab === 'certificados' && (
|
||||
<div>
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="table-responsive mt-3">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{ width: '10%' }}></th>
|
||||
<th scope="col" style={{ width: '20%' }}><strong>Cursos</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '10%' }}><strong>Estado</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '15%' }}><strong>Fecha</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '10%' }}><strong>Nota</strong></th>
|
||||
<th scope="col" className="text-center" style={{ width: '10%' }}><strong>Asistencia</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#" target="_blank" rel="noreferrer" className="text-decoration-none">
|
||||
{/* <FilePdf className="me-1" style={{ fontSize: '12px' }} /> */}
|
||||
Ver Certificado
|
||||
</a>
|
||||
</td>
|
||||
<td>Inglés B2 Finalizado</td>
|
||||
<td className="text-center">
|
||||
<span className="badge bg-success" style={{ fontWeight: 100, fontSize: '12px' }}>Aprobado</span>
|
||||
</td>
|
||||
<td className="text-center"><strong>20/12/2025</strong></td>
|
||||
<td className="text-center"><strong>6.5</strong></td>
|
||||
<td className="text-center"><strong>95%</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- PESTAÑA: COMENTARIOS --- */}
|
||||
{activeTab === 'comentarios' && (
|
||||
<div>
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-3">
|
||||
<div className="table-responsive mt-3">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{ width: '10%' }}><strong>Fecha</strong></th>
|
||||
<th scope="col" style={{ width: '10%' }}><strong>Hora</strong></th>
|
||||
<th scope="col" style={{ width: '60%' }}><strong>Comentario</strong></th>
|
||||
<th scope="col" style={{ width: '20%' }}><strong>Usuario</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>14/09/2026</td>
|
||||
<td>10:30</td>
|
||||
<td>Alumno solicita cambio de horario.</td>
|
||||
<td>Admin_User</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 mt-5">
|
||||
<div className="row">
|
||||
<div className="col-md-1"></div>
|
||||
<div className="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Escribe un comentario"
|
||||
className="form-control"
|
||||
value={comentarioInput}
|
||||
onChange={(e) => setComentarioInput(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<button
|
||||
className="btn btn-primary btn-sm w-100"
|
||||
onClick={() => handleSimulateLoading(() => setComentarioInput(''))}
|
||||
>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* --- MODAL NOTAS --- */}
|
||||
{showModalNotas && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Notas</h5>
|
||||
<button type="button" className="btn-close" onClick={() => setShowModalNotas(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-center" style={{ width: '20%' }}><strong>Fecha</strong></th>
|
||||
<th className="text-center" style={{ width: '60%' }}><strong>Test</strong></th>
|
||||
<th className="text-center" style={{ width: '20%' }}><strong>Grade</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: '20%' }}><strong>05/04/2026</strong></td>
|
||||
<td className="text-start" style={{ width: '60%' }}><strong>Midterm Exam</strong></td>
|
||||
<td className="text-center" style={{ width: '20%' }}><strong>92%</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-secondary" onClick={() => setShowModalNotas(false)}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- MODAL ASISTENCIA --- */}
|
||||
{showModalAsistencia && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Asistencia</h5>
|
||||
<button type="button" className="btn-close" onClick={() => setShowModalAsistencia(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '18px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-center" style={{ width: '50%' }}><strong>Fecha</strong></th>
|
||||
<th className="text-center" style={{ width: '50%' }}><strong>Marcaciones</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-center"><strong>01/03/2026</strong></td>
|
||||
<td className="text-center"><strong className="text-success">Present</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-secondary" onClick={() => setShowModalAsistencia(false)}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- MODAL EDITAR ALUMNO --- */}
|
||||
{showModalEditarAlumno && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Editar Alumno</h5>
|
||||
<button type="button" className="btn-close" onClick={() => setShowModalEditarAlumno(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<table className="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Nombre</strong></td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={editForm.nombre}
|
||||
onChange={(e) => setEditForm({ ...editForm, nombre: e.target.value })}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Paterno</strong></td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={editForm.paterno}
|
||||
onChange={(e) => setEditForm({ ...editForm, paterno: e.target.value })}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
className="btn btn-warning text-dark"
|
||||
onClick={() => handleSimulateLoading(() => setShowModalEditarAlumno(false))}
|
||||
>
|
||||
<strong><Save className="me-2" /> Guardar</strong>
|
||||
</button>
|
||||
<button type="button" className="btn btn-secondary" onClick={() => setShowModalEditarAlumno(false)}>Cancelar</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- MODAL CARGANDO (LOADING) --- */}
|
||||
{showLoadingModal && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<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="mt-2"><strong>SAM - Empresas</strong></h5>
|
||||
</div>
|
||||
<div className="modal-body alert text-center" style={{ textAlign: 'justify' }}>
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center">
|
||||
<h5 className="mb-3"><strong>Procesando, espere un momento</strong></h5>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger mx-1" role="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* --- MODAL ERROR / ALERTA --- */}
|
||||
{showErrorModal && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<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" onClick={() => setShowErrorModal(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body alert" style={{ textAlign: 'justify' }}>
|
||||
<div className="row mb-2">
|
||||
<div className="col-md-12 text-center">
|
||||
<h5><strong>{errorMessage || 'Ocurrió un error en la operación.'}</strong></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-primary" onClick={() => setShowErrorModal(false)}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,703 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
// UserDetail,
|
||||
Plus,
|
||||
Save,
|
||||
User,
|
||||
// MailSend,
|
||||
// PhoneCall,
|
||||
Envelope,
|
||||
// CurrentLocation,
|
||||
// Cake,
|
||||
Flag,
|
||||
Edit,
|
||||
UserCheck,
|
||||
Pencil,
|
||||
File,
|
||||
Book,
|
||||
// Error as ErrorIcon,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
} from "@boxicons/react";
|
||||
|
||||
export default function ProfesorPage() {
|
||||
// Estados para controlar vistas del flujo ASP.NET
|
||||
const [vistas, setVistas] = useState({
|
||||
divBuscar: true,
|
||||
divBuscarResultado: false,
|
||||
agregarProfe: false,
|
||||
fichaProfe: false,
|
||||
profeCursosActivos: true,
|
||||
profeCursosActivosOk: false,
|
||||
profeCursosActivosError: false,
|
||||
profeCursosFinalizados: false,
|
||||
profeCursosFinalizadosOk: false,
|
||||
profeCursosFinalizadosError: false,
|
||||
profePerfil: false,
|
||||
});
|
||||
|
||||
// Estados para Modales
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showAlertModal, setShowAlertModal] = useState(false);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [mensajeAlerta, setMensajeAlerta] = useState("Mensaje de prueba");
|
||||
|
||||
// Función equivalente a GmailPopup
|
||||
const handleGmailPopup = (mail: string, name: string) => {
|
||||
const title = "Contacto";
|
||||
const w = 800;
|
||||
const h = 600;
|
||||
const options = "scrollbars=no,resizable=no";
|
||||
const url = `https://mail.google.com/mail/u/0/?view=cm&fs=1&to=${mail.toLowerCase()}&su=Contacto%20Ichn`;
|
||||
|
||||
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
|
||||
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
|
||||
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
const left = width / 2 - w / 2 + dualScreenLeft;
|
||||
const top = height / 2 - h / 2 + dualScreenTop;
|
||||
|
||||
window.open(url, title, `${options}, width=${w}, height=${h}, top=${top}, left=${left}`);
|
||||
};
|
||||
|
||||
// Solo números para teléfono
|
||||
const handleOnlyNumbers = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (!/[0-9]/.test(e.key) && e.key !== "Backspace" && e.key !== "Tab") {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-3">
|
||||
{/* SECCIÓN DE BÚSQUEDA */}
|
||||
{vistas.divBuscar && (
|
||||
<div className="row" id="div_buscar">
|
||||
<div className="col-md-1"></div>
|
||||
<div className="col-md-10">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-1 mt-2 text-end">
|
||||
<div className="mt-2">
|
||||
<strong>Profesor</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-3 mt-2">
|
||||
<select className="form-select" id="ListaTipoBusqueda">
|
||||
<option value="">Seleccione filtro...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-md-2 mt-2">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="TextBoxProfe"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-1 mt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={() => setVistas({ ...vistas, divBuscarResultado: true })}
|
||||
>
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
<div className="col-md-3 text-end mt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-success text-dark"
|
||||
>
|
||||
{/* <UserDetail className="me-1" /> */}
|
||||
<strong>Listado Profesores</strong>
|
||||
</button>
|
||||
</div>
|
||||
<div className="col-md-2 text-end mt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-warning text-dark me-4"
|
||||
onClick={() => setVistas({ ...vistas, agregarProfe: true })}
|
||||
>
|
||||
<Plus className="me-1" /> <strong>Agregar</strong>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RESULTADOS BÚSQUEDA */}
|
||||
{vistas.divBuscarResultado && (
|
||||
<div className="row" id="div_buscar_resultado">
|
||||
<div className="col-md-12 mt-4">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: "14px" }}>
|
||||
<thead className="alert-secondary text-dark">
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "10%" }}></th>
|
||||
<th className="text-start" style={{ width: "10%" }}><strong>Run</strong></th>
|
||||
<th className="text-start" style={{ width: "28%" }}><strong>Nombre</strong></th>
|
||||
<th className="text-center" style={{ width: "10%" }}><strong>Estado</strong></th>
|
||||
<th className="text-start" style={{ width: "10%" }}><strong>Fono</strong></th>
|
||||
<th className="text-start" style={{ width: "29%" }}><strong>Mail</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" style={{ width: "10%" }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link p-0 text-decoration-none"
|
||||
onClick={() => setVistas({ ...vistas, fichaProfe: true })}
|
||||
>
|
||||
<span className="badge bg-primary" style={{ fontWeight: "normal" }}>
|
||||
Seleccionar
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "10%" }}><strong>12345678-9</strong></td>
|
||||
<td className="text-start" style={{ width: "14%" }}><strong>Pérez</strong></td>
|
||||
<td className="text-start" style={{ width: "14%" }}><strong>Juan</strong></td>
|
||||
<td className="text-center" style={{ width: "10%" }}>
|
||||
<span className="badge rounded-pill bg-success">Activo</span>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: "10%" }}><strong>912345678</strong></td>
|
||||
<td className="text-start" style={{ width: "29%" }}><strong>juan.perez@example.com</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<nav aria-label="...">
|
||||
<ul className="pagination justify-content-center">
|
||||
<li className="page-item"><button className="page-link">First</button></li>
|
||||
<li className="page-item"><button className="page-link">Previous</button></li>
|
||||
<li className="page-item"><button className="page-link">Next</button></li>
|
||||
<li className="page-item"><button className="page-link">Last</button></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* SECCIÓN AGREGAR PROFESOR */}
|
||||
{vistas.agregarProfe && (
|
||||
<div className="row" id="agregar_profe">
|
||||
<div className="col-md-1"></div>
|
||||
<div className="col-md-10">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<table className="table table-sm mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" colSpan={4}>
|
||||
<h5><strong>Información Personal</strong></h5>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ width: "20%" }}><strong className="text-muted">Run</strong></td>
|
||||
<td><input type="text" className="form-control" autoComplete="off" /></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Nombre</strong></td>
|
||||
<td><input type="text" className="form-control" autoComplete="off" /></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Paterno</strong></td>
|
||||
<td><input type="text" className="form-control" autoComplete="off" /></td>
|
||||
<td><strong className="text-muted">Materno</strong></td>
|
||||
<td><input type="text" className="form-control" autoComplete="off" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Nacimiento</strong></td>
|
||||
<td><input type="date" className="form-control datepicker" autoComplete="off" /></td>
|
||||
<td><strong className="text-muted">Nacionalidad</strong></td>
|
||||
<td><select className="form-select"><option value="">Seleccione...</option></select></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<table className="table table-sm mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start" colSpan={2}>
|
||||
<h5><strong>Información de contacto</strong></h5>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Fono (+56)</strong></td>
|
||||
<td colSpan={3}>
|
||||
<input
|
||||
type="tel"
|
||||
maxLength={9}
|
||||
onKeyDown={handleOnlyNumbers}
|
||||
className="form-control"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr className="needs-validation">
|
||||
<td><strong className="text-muted">Mail</strong></td>
|
||||
<td colSpan={3}>
|
||||
<input type="email" className="form-control" placeholder="name@example.com" autoComplete="off" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Dirección</strong></td>
|
||||
<td colSpan={3}><input type="text" className="form-control" autoComplete="off" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong className="text-muted">Región</strong></td>
|
||||
<td style={{ width: "35%" }}><select className="form-select"><option value="">Seleccione...</option></select></td>
|
||||
<td style={{ width: "10%" }}><strong className="text-muted">Comuna</strong></td>
|
||||
<td style={{ width: "35%" }}><select className="form-select"><option value="">Seleccione...</option></select></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table className="table table-sm mb-0 mt-3">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: "70%" }}></td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button type="button" className="btn btn-primary">
|
||||
<Save className="me-2" /> Guardar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setVistas({ ...vistas, agregarProfe: false })}
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* SECCIÓN FICHA PROFESOR */}
|
||||
{vistas.fichaProfe && (
|
||||
<div className="row" id="ficha_profe">
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-6">
|
||||
<h5>
|
||||
<strong className="text-muted">Ficha</strong> <strong>Profesor</strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="col-md-6 text-end">
|
||||
<button type="button" className="btn btn-primary btn-sm">
|
||||
<i className="bx bx-transfer me-2"></i> Cambiar Profesor
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-3">
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<table className="table table-sm table-borderless mb-0 text-center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<User className="text-primary mb-2" style={{ fontSize: "50px" }} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<span className="fs-5">Juan Pérez</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<strong><span className="fs-5">12.345.678-9</span></strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-light btn-sm border"
|
||||
onClick={() => handleGmailPopup("juan@example.com", "Juan")}
|
||||
>
|
||||
{/* <MailSend className="me-1" /> */}
|
||||
Mensaje
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="alert alert-light text-dark shadow" role="alert">
|
||||
<table className="table table-sm table-borderless mb-0" style={{ fontSize: "14px" }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<span className="text-dark" style={{ fontSize: "18px" }}>Contacto</span>
|
||||
<hr />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <PhoneCall /> */}
|
||||
</td>
|
||||
<td>+56 9 1234 5678</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Envelope />
|
||||
</td>
|
||||
<td>juan.perez@example.com</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <CurrentLocation /> */}
|
||||
</td>
|
||||
<td>Av. Siempre Viva 123</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <CurrentLocation /> */}
|
||||
</td>
|
||||
<td>Santiago</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <Cake /> */}
|
||||
</td>
|
||||
<td>01/01/1990</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><Flag /></td>
|
||||
<td>Chilena</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<div className="d-grid gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-warning btn-sm"
|
||||
onClick={() => setShowEditModal(true)}
|
||||
>
|
||||
<strong><Edit className="me-1" /> Editar</strong>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-9">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark mb-0" role="alert">
|
||||
<div className="d-grid gap-2">
|
||||
<div className="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-light border-top-0 border-end-0 border-start-0 border border-primary border-3"
|
||||
onClick={() => setVistas({ ...vistas, profePerfil: true, profeCursosActivos: false, profeCursosFinalizados: false })}
|
||||
>
|
||||
<UserCheck className="me-2" style={{ fontSize: "18px" }} />Perfil
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-light border-top-0 border-end-0 border-start-0 border border-3"
|
||||
onClick={() => setVistas({ ...vistas, profePerfil: false, profeCursosActivos: true, profeCursosFinalizados: false })}
|
||||
>
|
||||
<Pencil className="me-2" style={{ fontSize: "18px" }} />Cursos Activos
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-light border-top-0 border-end-0 border-start-0 border border-3"
|
||||
onClick={() => setVistas({ ...vistas, profePerfil: false, profeCursosActivos: false, profeCursosFinalizados: true })}
|
||||
>
|
||||
<File className="me-2" style={{ fontSize: "18px" }} />Cursos Finalizados
|
||||
</button>
|
||||
<button type="button" className="btn btn-light border-top-0 border-end-0 border-start-0 border border-3 disabled"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CURSOS ACTIVOS */}
|
||||
{vistas.profeCursosActivos && (
|
||||
<div id="profe_cursos_activos">
|
||||
{vistas.profeCursosActivosOk ? (
|
||||
<div className="row mt-3">
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="row text-center">
|
||||
<div className="col-md-3"></div>
|
||||
<div className="col-md-1">
|
||||
<Book className="text-primary mt-2" style={{ fontSize: "50px" }} />
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<span className="text-muted"><strong>Cursos</strong></span>
|
||||
<h3><strong>2</strong></h3>
|
||||
</div>
|
||||
<div className="col-md-1">
|
||||
<User className="text-success mt-2" style={{ fontSize: "50px" }} />
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<span className="text-muted"><strong>Alumnos</strong></span>
|
||||
<h3><strong>25</strong></h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-12">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<div className="table-responsive">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: "14px" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" style={{ width: "5%" }}></th>
|
||||
<th className="text-start" style={{ width: "5%" }}>ID</th>
|
||||
<th className="text-start" style={{ width: "10%" }}>Curso</th>
|
||||
<th className="text-start" style={{ width: "27%" }}>Curso</th>
|
||||
<th className="text-center" style={{ width: "7%" }}>Participantes</th>
|
||||
<th className="text-center" style={{ width: "10%" }}>Dias</th>
|
||||
<th className="text-center" style={{ width: "18%" }}>Horas</th>
|
||||
<th className="text-center" style={{ width: "20%" }}>Fechas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start">
|
||||
<a href="#"><span className="badge bg-primary" style={{ fontWeight: "normal" }}>Ver</span></a>
|
||||
</td>
|
||||
<td className="text-start">101</td>
|
||||
<td className="text-start">Inglés</td>
|
||||
<td className="text-start">Inglés Básico</td>
|
||||
<td className="text-center">12</td>
|
||||
<td className="text-center">Lu-Mi</td>
|
||||
<td className="text-center">19:00 - 21:00</td>
|
||||
<td className="text-center">01/03 / 30/04</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="alert alert-light text-dark mt-3" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3"></div>
|
||||
<div className="col-md-6 text-center">
|
||||
<div className="alert alert-light text-dark" role="alert">
|
||||
<strong>
|
||||
{/* <ErrorIcon className="text-primary" style={{ fontSize: "90px" }} /> */}
|
||||
</strong>
|
||||
<br /><br />
|
||||
<h5><strong>El profesor no tiene Cursos Activos</strong></h5>
|
||||
<hr />
|
||||
<strong className="text-muted">
|
||||
Si cree que esto es un error, contáctenos.{" "}
|
||||
<a target="_blank" rel="noreferrer" href="https://norteamericano.freshdesk.com/support/tickets/new">
|
||||
Generar Ticket
|
||||
</a>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* CURSOS FINALIZADOS */}
|
||||
{vistas.profeCursosFinalizados && (
|
||||
<div id="profe_cursos_finalizados">
|
||||
<div className="alert alert-light text-dark mt-3" role="alert">
|
||||
<div className="row">
|
||||
<div className="col-md-3"></div>
|
||||
<div className="col-md-6">
|
||||
<table className="table table-sm table-borderless mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span className="text-muted"><strong>Año</strong></span></td>
|
||||
<td><input type="text" className="form-control form-control-sm" /></td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button type="button" className="btn btn-primary btn-sm">Buscar</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* PERFIL */}
|
||||
{vistas.profePerfil && (
|
||||
<div id="profe_perfil" className="mt-3">
|
||||
<div className="alert alert-light text-dark">
|
||||
<div className="row">
|
||||
<div className="col-md-4">
|
||||
<div className="progress text-start mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> DIURNO</strong></div>
|
||||
</div>
|
||||
<div className="progress text-center mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> VESPERTINO</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="progress mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> 0</strong></div>
|
||||
</div>
|
||||
<div className="progress mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> 0</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4">
|
||||
<div className="progress text-start mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> PRESENCIAL</strong></div>
|
||||
</div>
|
||||
<div className="progress text-center mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> ONLINE</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2">
|
||||
<div className="progress mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> 0</strong></div>
|
||||
</div>
|
||||
<div className="progress mb-2" style={{ height: "61px" }}>
|
||||
<div style={{ fontSize: "20px", marginTop: "17px" }}><strong> 0</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL CARGANDO */}
|
||||
{showLoadingModal && (
|
||||
<div className="modal fade show d-block" style={{ backgroundColor: "rgba(0,0,0,0.5)" }} tabIndex={-1}>
|
||||
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="float-start mt-2"><strong>SAM - Empresas</strong></h5>
|
||||
</div>
|
||||
<div className="modal-body alert text-center">
|
||||
<h5><strong>Procesando, espere un momento</strong></h5>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary me-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger me-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary me-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger me-1" role="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL ALERTA / MENSAJES */}
|
||||
{showAlertModal && (
|
||||
<div className="modal fade show d-block" style={{ backgroundColor: "rgba(0,0,0,0.5)" }} tabIndex={-1}>
|
||||
<div className="modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary">
|
||||
<h5 className="float-start mt-2"><strong>Módulo Academico - Empresa</strong></h5>
|
||||
<button type="button" className="btn-close float-end" onClick={() => setShowAlertModal(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body alert text-center">
|
||||
<h5><strong>{mensajeAlerta}</strong></h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-primary" onClick={() => setShowAlertModal(false)}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL EDITAR PROFESOR */}
|
||||
{showEditModal && (
|
||||
<div className="modal fade show d-block" style={{ backgroundColor: "rgba(0,0,0,0.5)" }} tabIndex={-1}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Editar Profe</h5>
|
||||
<button type="button" className="btn-close" onClick={() => setShowEditModal(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<table className="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Nombre</strong></td>
|
||||
<td><input type="text" className="form-control" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Paterno</strong></td>
|
||||
<td><input type="text" className="form-control" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Materno</strong></td>
|
||||
<td><input type="text" className="form-control" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Fono (+56)</strong></td>
|
||||
<td><input type="text" maxLength={9} className="form-control" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Mail</strong></td>
|
||||
<td><input type="email" className="form-control" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<div className="d-grid gap-2">
|
||||
<button type="button" className="btn btn-warning text-dark">
|
||||
<strong><Save className="me-2" /> Guardar</strong>
|
||||
</button>
|
||||
<button type="button" className="btn btn-secondary" onClick={() => setShowEditModal(false)}>Cancelar</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+401
-2
@@ -1,3 +1,402 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import {
|
||||
User,
|
||||
//Graduation,
|
||||
File,
|
||||
//IdCard,
|
||||
ContactBook,
|
||||
Book,
|
||||
AddressBook,
|
||||
//ErrorAlt
|
||||
} from '@boxicons/react';
|
||||
|
||||
interface Alumno {
|
||||
idAlumno: string;
|
||||
AP_Paterno: string;
|
||||
AP_Materno: string;
|
||||
Nombres: string;
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
return <h1>Hello, Next.js!</h1>;
|
||||
}
|
||||
// --- ESTADOS DE VISTA ---
|
||||
const [currentView, setCurrentView] = useState<'menu' | 'buscar'>('menu');
|
||||
const [errorData, setErrorData] = useState(false);
|
||||
|
||||
// --- ESTADOS DE FORMULARIO DE BÚSQUEDA ---
|
||||
const [tipoBusqueda, setTipoBusqueda] = useState('run');
|
||||
const [textoBusqueda, setTextoBusqueda] = useState('');
|
||||
|
||||
// --- ESTADOS DE MODALES ---
|
||||
const [showModalResultados, setShowModalResultados] = useState(false);
|
||||
const [showLoadingModal, setShowLoadingModal] = useState(false);
|
||||
const [showErrorModal, setShowErrorModal] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
|
||||
// --- DATOS DE EJEMPLO PARA RESULTADOS ---
|
||||
const [alumnosEncontrados, setAlumnosEncontrados] = useState<Alumno[]>([]);
|
||||
|
||||
// --- MANEJADORES DE EVENTOS ---
|
||||
const handleOpenBuscarAlumno = () => {
|
||||
setCurrentView('buscar');
|
||||
setErrorData(false);
|
||||
};
|
||||
|
||||
const handleBuscarAlumno = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!textoBusqueda.trim()) {
|
||||
setErrorData(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setErrorData(false);
|
||||
setShowLoadingModal(true);
|
||||
|
||||
// Simulación de búsqueda
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
const mockResultados: Alumno[] = [
|
||||
{ idAlumno: '12.345.678-9', AP_Paterno: 'Pérez', AP_Materno: 'González', Nombres: 'Juan Carlos' },
|
||||
{ idAlumno: '98.765.432-1', AP_Paterno: 'Pérez', AP_Materno: 'Muñoz', Nombres: 'María José' }
|
||||
];
|
||||
setAlumnosEncontrados(mockResultados);
|
||||
setShowModalResultados(true);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const handleSeleccionarAlumno = (alumno: Alumno) => {
|
||||
setShowModalResultados(false);
|
||||
setShowLoadingModal(true);
|
||||
|
||||
// Redirección o acción con el alumno seleccionado
|
||||
setTimeout(() => {
|
||||
setShowLoadingModal(false);
|
||||
alert(`Alumno seleccionado: ${alumno.Nombres} ${alumno.AP_Paterno}`);
|
||||
}, 800);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid py-4">
|
||||
{/* VISTA: MENÚ PRINCIPAL */}
|
||||
{currentView === 'menu' && (
|
||||
<div id="menu">
|
||||
<div className="row">
|
||||
<div className="col-md-2" />
|
||||
|
||||
{/* SECCIÓN SECRETARÍA */}
|
||||
<div className="col-md-4">
|
||||
<div className="alert alert-light text-dark shadow-sm">
|
||||
<h5><strong>Secretaria</strong></h5>
|
||||
<hr />
|
||||
<table className="table table-hover mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: '5%' }}>
|
||||
<User className="text-primary border rounded p-1" style={{ fontSize: '32px' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpenBuscarAlumno}
|
||||
className="btn btn-link text-start p-0 text-decoration-none alert-link"
|
||||
>
|
||||
Ficha del Alumno
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{/* <Graduation className="text-primary border rounded p-1" style={{ fontSize: '32px' }} /> */}
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/secretaria/FichaProfesor" className="text-decoration-none alert-link">
|
||||
Ficha del Profesor
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<File className="text-success border rounded p-1" style={{ fontSize: '32px' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/secretaria/EvaluacionPO" className="text-decoration-none alert-link">
|
||||
Ingreso de evaluación
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SECCIÓN INFORMES */}
|
||||
<div className="col-md-4">
|
||||
<div className="alert alert-light text-dark shadow-sm">
|
||||
<h5><strong>Informes</strong></h5>
|
||||
<hr />
|
||||
<table className="table table-hover mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: '5%' }}>
|
||||
{/* <IdCard className="text-danger border rounded p-1" style={{ fontSize: '32px' }} /> */}
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/Informes/SEAlumnos" className="text-decoration-none alert-link">
|
||||
Informes de Alumnos
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ContactBook className="text-warning border rounded p-1" style={{ fontSize: '32px' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/Informes/SEAlumnosCursosCC" className="text-decoration-none alert-link">
|
||||
Informes de Alumnos por cursos
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Book className="text-warning border rounded p-1" style={{ fontSize: '32px' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/Informes/SEAlumnosCursosPC" className="text-decoration-none alert-link">
|
||||
Informes de Alumnos por cursos (Plan central)
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<AddressBook className="text-danger-emphasis border rounded p-1" style={{ fontSize: '32px' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<Link href="/Informes/SEAlumnosEmpresas" className="text-decoration-none alert-link">
|
||||
Informes de Alumnos por empresas
|
||||
</Link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-2" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* VISTA: BUSCAR ALUMNO */}
|
||||
{currentView === 'buscar' && (
|
||||
<div id="buscar_alumno">
|
||||
<div className="row" style={{ marginTop: '5%' }}>
|
||||
<div className="col-md-4" />
|
||||
<div className="col-md-4 text-center">
|
||||
<strong>
|
||||
<User className="text-primary border rounded p-2 mb-2" style={{ fontSize: '60px' }} />
|
||||
</strong>
|
||||
|
||||
<div className="alert alert-light text-dark shadow-sm" role="alert">
|
||||
<form onSubmit={handleBuscarAlumno}>
|
||||
<table className="table table-borderless mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-start">
|
||||
<h5><strong>Ficha del Alumno</strong></h5>
|
||||
</td>
|
||||
<td className="text-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link p-0 text-decoration-none"
|
||||
onClick={() => setCurrentView('menu')}
|
||||
>
|
||||
Volver
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<br />
|
||||
<select
|
||||
className="form-select"
|
||||
value={tipoBusqueda}
|
||||
onChange={(e) => setTipoBusqueda(e.target.value)}
|
||||
>
|
||||
<option value="run">Búsqueda por RUN</option>
|
||||
<option value="nombre">Búsqueda por Nombre</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
autoComplete="off"
|
||||
placeholder="Ingrese término de búsqueda..."
|
||||
value={textoBusqueda}
|
||||
onChange={(e) => setTextoBusqueda(e.target.value)}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{errorData && (
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<div className="alert alert-danger text-center mb-0 mt-2">
|
||||
<h5 className="mb-0 d-flex align-items-center justify-center gap-2">
|
||||
{/* <ErrorAlt /> */}
|
||||
Error en el RUN seleccionado
|
||||
</h5>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<div className="d-grid gap-2 mt-2">
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Buscar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-4" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL: RESULTADOS ALUMNOS */}
|
||||
{showModalResultados && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Ficha Alumno</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShowModalResultados(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="modal-body text-center">
|
||||
<table className="table table-sm mb-0" style={{ fontSize: '14px' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-start" scope="col" style={{ width: '11%' }}></th>
|
||||
<th className="text-start" scope="col" style={{ width: '12%' }}><strong>Run</strong></th>
|
||||
<th className="text-start" scope="col" style={{ width: '25%' }}><strong>Paterno</strong></th>
|
||||
<th className="text-start" scope="col" style={{ width: '25%' }}><strong>Materno</strong></th>
|
||||
<th className="text-start" scope="col" style={{ width: '27%' }}><strong>Nombre</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{alumnosEncontrados.map((alumno, index) => (
|
||||
<tr key={index}>
|
||||
<td className="text-start" style={{ width: '11%' }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn p-0 border-0 background-transparent"
|
||||
onClick={() => handleSeleccionarAlumno(alumno)}
|
||||
>
|
||||
<span className="badge bg-warning text-dark">Seleccionar</span>
|
||||
</button>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: '12%' }}>
|
||||
<strong>{alumno.idAlumno}</strong>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: '25%' }}>
|
||||
<span>{alumno.AP_Paterno}</span>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: '25%' }}>
|
||||
<span>{alumno.AP_Materno}</span>
|
||||
</td>
|
||||
<td className="text-start" style={{ width: '27%' }}>
|
||||
<span>{alumno.Nombres}</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setShowModalResultados(false)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL: CARGANDO (LOADING) */}
|
||||
{showLoadingModal && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-secondary mb-0">
|
||||
<h5 className="mt-2 mb-0"><strong>Secretaría</strong></h5>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5 className="mb-3"><strong>Procesando, espere un momento</strong></h5>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-primary mx-1" role="status"></div>
|
||||
<div className="spinner-grow spinner-grow-sm text-danger mx-1" role="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* MODAL: ERROR */}
|
||||
{showErrorModal && (
|
||||
<div className="modal fade show d-block" tabIndex={-1} style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
<div className="modal-content text-dark">
|
||||
<div className="modal-header alert alert-danger mb-0">
|
||||
<h5 className="mt-2 mb-0"><strong>Error</strong></h5>
|
||||
<button type="button" className="btn-close" onClick={() => setShowErrorModal(false)}></button>
|
||||
</div>
|
||||
<div className="modal-body text-center py-4">
|
||||
<h5><strong>{errorMessage || 'Ocurrió un error en la operación.'}</strong></h5>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-secondary" onClick={() => setShowErrorModal(false)}>
|
||||
Cerrar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user