/**
* @fileoverview Funciones para rellenar selects con alumnos y generar Excel de inscripciones.
* @author Mauricio Peña
*/
import M_obtenerAlumnos from "/InscripcionesEVG/assets/js/models/m_obtenerAlumnos.js";
import { ModalConfirmacion } from "/InscripcionesEVG/assets/js/utils/modalConfirmacion.js";
/**
* Rellena los selects masculinos y femeninos con alumnos de una clase dada,
* asegurando que las opciones seleccionadas no se repitan entre selects.
*
* @param {string|number} idClase - Identificador de la clase para obtener alumnos.
* @returns {Promise<void>}
*/
async function rellenarSelectsConAlumnos(idClase) {
try {
const modelo = new M_obtenerAlumnos();
const alumnos = await modelo.obtenerAlumnos(idClase);
const contenedorMasculino = document.getElementById(
"camposPruebasMasculina",
);
const contenedorFemenino = document.getElementById("camposPruebasFemenina");
if (!contenedorMasculino || !contenedorFemenino) {
console.warn("Contenedores no encontrados.");
return;
}
const selectsMasculinos = contenedorMasculino.querySelectorAll("select");
const selectsFemeninos = contenedorFemenino.querySelectorAll("select");
const seleccionadosGenerales = new Set(); // Para selects normales
const seleccionadosTipoC = new Set(); // Para selects con name "C"
const anteriores = new Map(); // Guardamos el valor anterior de cada select
/**
* Actualiza la visibilidad de las opciones en los selects para evitar duplicados.
*/
function actualizarSelects() {
[...selectsMasculinos, ...selectsFemeninos].forEach((select) => {
const options = select.querySelectorAll("option");
const esTipoC = select.name === "C";
options.forEach((option) => {
const alumnoId = option.value;
if (!alumnoId) return;
// Ocultar las opciones de alumnos ya seleccionados excepto la opción actual del select
if (esTipoC) {
option.style.display =
seleccionadosTipoC.has(alumnoId) &&
anteriores.get(select) !== alumnoId
? "none"
: "";
} else {
option.style.display =
seleccionadosGenerales.has(alumnoId) &&
anteriores.get(select) !== alumnoId
? "none"
: "";
}
});
});
}
// Rellenar selects masculinos con alumnos de sexo masculino
selectsMasculinos.forEach((select) => {
const esTipoC = select.name === "C";
select.innerHTML = `<option value="">Selecciona</option>`;
alumnos
.filter((a) => {
if (a.sexo !== "M") return false;
if (!esTipoC && seleccionadosGenerales.has(a.idAlumno.toString()))
return false;
return true;
})
.forEach((alumno) => {
const option = document.createElement("option");
option.value = alumno.idAlumno;
option.textContent = alumno.nombre;
select.appendChild(option);
});
});
// Rellenar selects femeninos con alumnos de sexo femenino
selectsFemeninos.forEach((select) => {
const esTipoC = select.name === "C";
select.innerHTML = `<option value="">Selecciona</option>`;
alumnos
.filter((a) => {
if (a.sexo !== "F") return false;
if (!esTipoC && seleccionadosGenerales.has(a.idAlumno.toString()))
return false;
return true;
})
.forEach((alumno) => {
const option = document.createElement("option");
option.value = alumno.idAlumno;
option.textContent = alumno.nombre;
select.appendChild(option);
});
});
// Añadir eventos para controlar selección y actualizar visibilidad
[...selectsMasculinos, ...selectsFemeninos].forEach((select) => {
anteriores.set(select, ""); // valor inicial vacío
select.addEventListener("change", (event) => {
const actual = event.target.value.toString();
const anterior = anteriores.get(select);
const esTipoC = select.name === "C";
console.log(
`Cambio en select name="${select.name}": anterior="${anterior}" -> actual="${actual}"`,
);
// Quitar la selección anterior de los sets correspondientes
if (anterior) {
if (esTipoC) {
seleccionadosTipoC.delete(anterior);
console.log(`Quitado de seleccionadosTipoC: ${anterior}`);
} else {
seleccionadosGenerales.delete(anterior);
console.log(`Quitado de seleccionadosGenerales: ${anterior}`);
}
}
// Añadir la nueva selección
if (actual) {
if (esTipoC) {
seleccionadosTipoC.add(actual);
console.log(`Añadido a seleccionadosTipoC: ${actual}`);
} else {
seleccionadosGenerales.add(actual);
console.log(`Añadido a seleccionadosGenerales: ${actual}`);
}
}
anteriores.set(select, actual); // actualizar valor anterior
actualizarSelects(); // actualizar opciones visibles
});
});
actualizarSelects(); // Inicializa el estado
} catch (error) {
console.error("Error al rellenar los selects con alumnos:", error);
}
}
/**
* Rellena los selects con alumnos ya seleccionados previamente, permitiendo editar la selección,
* y evita que se repitan alumnos en distintos selects.
*
* @param {string|number} idClase - Identificador de la clase para obtener alumnos y seleccionados.
* @returns {Promise<void>}
*/
async function rellenarSelectsConSeleccionados(idClase) {
try {
const modelo = new M_obtenerAlumnos();
const alumnos = await modelo.obtenerAlumnos(idClase);
const response = await fetch(
"/InscripcionesEVG/index.php?controlador=alumnosSeleccionados&accion=extraer&j=1",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ idClase }),
},
);
const seleccionados = await response.json();
const contenedorMasculino = document.getElementById(
"camposPruebasMasculina",
);
const contenedorFemenino = document.getElementById("camposPruebasFemenina");
if (!contenedorMasculino || !contenedorFemenino) {
console.warn("Contenedores no encontrados.");
return;
}
const selectsMasculinos = contenedorMasculino.querySelectorAll("select");
const selectsFemeninos = contenedorFemenino.querySelectorAll("select");
const seleccionadosGenerales = new Set();
const seleccionadosTipoC = new Set();
const anteriores = new Map();
/**
* Actualiza la visibilidad de las opciones en los selects para evitar duplicados.
*/
function actualizarSelects() {
[...selectsMasculinos, ...selectsFemeninos].forEach((select) => {
const options = select.querySelectorAll("option");
const esTipoC = select.name === "C";
options.forEach((option) => {
const alumnoId = option.value;
if (!alumnoId) return;
if (esTipoC) {
option.style.display =
seleccionadosTipoC.has(alumnoId) &&
anteriores.get(select) !== alumnoId
? "none"
: "";
} else {
option.style.display =
seleccionadosGenerales.has(alumnoId) &&
anteriores.get(select) !== alumnoId
? "none"
: "";
}
});
});
}
/**
* Rellena un conjunto de selects filtrando por sexo y controlando los alumnos usados.
*
* @param {NodeListOf<HTMLSelectElement>} selects - Selects a rellenar.
* @param {string} sexo - Sexo de los alumnos a mostrar ("M" o "F").
*/
function rellenarSelects(selects, sexo) {
const usadosPorPruebaTipo = new Map();
const selectsPorPrueba = new Map();
selects.forEach((select) => {
const idPrueba = select.getAttribute("data-idprueba");
if (!selectsPorPrueba.has(idPrueba)) {
selectsPorPrueba.set(idPrueba, []);
}
selectsPorPrueba.get(idPrueba).push(select);
});
selectsPorPrueba.forEach((selectsPrueba, idPrueba) => {
const selectsPorTipo = new Map();
selectsPrueba.forEach((sel) => {
const tipo = sel.name;
if (!selectsPorTipo.has(tipo)) selectsPorTipo.set(tipo, []);
selectsPorTipo.get(tipo).push(sel);
});
selectsPorTipo.forEach((selectsTipo, tipo) => {
const keyPruebaTipo = `${idPrueba}_${tipo}`;
if (!usadosPorPruebaTipo.has(keyPruebaTipo))
usadosPorPruebaTipo.set(keyPruebaTipo, new Set());
const usados = usadosPorPruebaTipo.get(keyPruebaTipo);
selectsTipo.forEach((select, idx) => {
select.innerHTML = `<option value="">Selecciona</option>`;
alumnos
.filter(
(a) => a.sexo === sexo && !usados.has(a.idAlumno.toString()),
)
.forEach((alumno) => {
const option = document.createElement("option");
option.value = alumno.idAlumno;
option.textContent = alumno.nombre;
select.appendChild(option);
});
});
});
});
}
// Inicializamos los sets con los alumnos ya seleccionados
seleccionados.forEach(({ idAlumno, tipo }) => {
if (tipo === "C") {
seleccionadosTipoC.add(idAlumno.toString());
} else {
seleccionadosGenerales.add(idAlumno.toString());
}
});
// Rellenar selects masculinos y femeninos
rellenarSelects(selectsMasculinos, "M");
rellenarSelects(selectsFemeninos, "F");
// Asignar los valores seleccionados previamente a cada select
seleccionados.forEach(({ idAlumno, idPrueba, tipo }) => {
const selector = `select[name="${tipo}"][data-idprueba="${idPrueba}"]`;
const select = document.querySelector(selector);
if (select) {
select.value = idAlumno;
anteriores.set(select, idAlumno.toString());
}
});
/**
* Función para actualizar el conjunto de seleccionados y la visibilidad.
*/
function onChangeSelect(event) {
const select = event.target;
const actual = select.value.toString();
const anterior = anteriores.get(select);
const esTipoC = select.name === "C";
console.log(
`Cambio en select name="${select.name}": anterior="${anterior}" -> actual="${actual}"`,
);
if (anterior) {
if (esTipoC) {
seleccionadosTipoC.delete(anterior);
console.log(`Quitado de seleccionadosTipoC: ${anterior}`);
} else {
seleccionadosGenerales.delete(anterior);
console.log(`Quitado de seleccionadosGenerales: ${anterior}`);
}
}
if (actual) {
if (esTipoC) {
seleccionadosTipoC.add(actual);
console.log(`Añadido a seleccionadosTipoC: ${actual}`);
} else {
seleccionadosGenerales.add(actual);
console.log(`Añadido a seleccionadosGenerales: ${actual}`);
}
}
anteriores.set(select, actual);
actualizarSelects();
}
[...selectsMasculinos, ...selectsFemeninos].forEach((select) => {
select.addEventListener("change", onChangeSelect);
});
actualizarSelects();
} catch (error) {
console.error("Error al rellenar selects con seleccionados:", error);
}
}
/**
* Genera y descarga un fichero Excel con las inscripciones de la clase especificada.
*
* @param {string|number} idClase - Identificador de la clase para obtener inscripciones.
* @returns {Promise<void>}
*/
async function generarExcelInscripciones(idClase) {
try {
const modelo = new M_obtenerAlumnos();
const inscripciones = await modelo.obtenerInscripciones(idClase);
if (!inscripciones.length) {
ModalConfirmacion.mostrar(
"Atención",
"No hay inscripciones para esta clase.",
"info",
);
return;
}
const titulo = `Inscripciones de la clase ${idClase}`;
const filas = inscripciones.map((insc) => [
insc.nombreAlumno,
insc.email,
insc.telefono,
insc.fechaInscripcion,
]);
// Aquí deberías implementar la lógica para generar el Excel con la librería que uses.
// Ejemplo (con SheetJS o similar) no incluido porque depende de tus dependencias.
ModalConfirmacion.mostrar(
"Éxito",
`Archivo Excel generado para la clase ${idClase}.`,
"success",
);
} catch (error) {
console.error("Error al generar Excel de inscripciones:", error);
ModalConfirmacion.mostrar(
"Error",
"Ha ocurrido un error al generar el Excel.",
"error",
);
}
}
export {
rellenarSelectsConAlumnos,
rellenarSelectsConSeleccionados,
generarExcelInscripciones,
};