diff --git a/api/alumnos.php b/api/alumnos.php
index f34a914..e897bac 100644
--- a/api/alumnos.php
+++ b/api/alumnos.php
@@ -36,6 +36,26 @@ try {
exit;
}
+ // Verificar email duplicado
+ $stmt = $pdo->prepare("SELECT id FROM alumnos WHERE email = ?");
+ $stmt->execute([$data['email']]);
+ if ($stmt->fetch()) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'El correo ya está registrado']);
+ exit;
+ }
+
+ // Verificar teléfono duplicado
+ if (!empty($data['telefono'])) {
+ $stmt = $pdo->prepare("SELECT id FROM alumnos WHERE telefono = ?");
+ $stmt->execute([$data['telefono']]);
+ if ($stmt->fetch()) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'El teléfono ya está registrado']);
+ exit;
+ }
+ }
+
$pdo->beginTransaction();
try {
// Insertar alumno
@@ -71,60 +91,81 @@ try {
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Error al registrar: ' . $e->getMessage()]);
}
- break;
+ break;
+
- case 'PUT':
- $data = json_decode(file_get_contents('php://input'), true);
-
- if (empty($data['id']) || empty($data['nombre']) || empty($data['email'])) {
- http_response_code(400);
- echo json_encode(['success' => false, 'error' => 'Datos incompletos']);
- exit;
- }
-
- $stmt = $pdo->prepare("
- UPDATE alumnos SET
- nombre = ?,
- email = ?,
- telefono = ?
- WHERE id = ?
- ");
- $stmt->execute([
- $data['nombre'],
- $data['email'],
- $data['telefono'] ?? null,
- $data['id']
- ]);
-
- // Si curso_id viene en la actualización, actualizar también el curso
- if (!empty($data['curso_id'])) {
- // Verifica si ya tiene una relación previa
- $check = $pdo->prepare("SELECT id FROM alumnos_cursos WHERE alumno_id = ?");
- $check->execute([$data['id']]);
-
- if ($check->fetch()) {
- // Si ya tiene relación, actualizamos el curso asignado
- $updateCurso = $pdo->prepare("
- UPDATE alumnos_cursos SET curso_id = ?, estado = 'cursando'
- WHERE alumno_id = ?
+ case 'PUT':
+ $data = json_decode(file_get_contents('php://input'), true);
+
+ if (empty($data['id']) || empty($data['nombre']) || empty($data['email'])) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'Datos incompletos']);
+ exit;
+ }
+
+ // Verificar email duplicado (excluyendo el mismo alumno)
+ $stmt = $pdo->prepare("SELECT id FROM alumnos WHERE email = ? AND id != ?");
+ $stmt->execute([$data['email'], $data['id']]);
+ if ($stmt->fetch()) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'El correo ya está registrado por otro alumno']);
+ exit;
+ }
+
+ // Verificar teléfono duplicado (excluyendo el mismo alumno)
+ if (!empty($data['telefono'])) {
+ $stmt = $pdo->prepare("SELECT id FROM alumnos WHERE telefono = ? AND id != ?");
+ $stmt->execute([$data['telefono'], $data['id']]);
+ if ($stmt->fetch()) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'El teléfono ya está registrado por otro alumno']);
+ exit;
+ }
+ }
+
+ $stmt = $pdo->prepare("
+ UPDATE alumnos SET
+ nombre = ?,
+ email = ?,
+ telefono = ?
+ WHERE id = ?
");
- $updateCurso->execute([$data['curso_id'], $data['id']]);
- } else {
- // Si no tiene relación previa, la insertamos
- $insertCurso = $pdo->prepare("
- INSERT INTO alumnos_cursos (alumno_id, curso_id, estado)
- VALUES (?, ?, 'cursando')
- ");
- $insertCurso->execute([$data['id'], $data['curso_id']]);
- }
- }
-
-
- echo json_encode([
- 'success' => true,
- 'message' => 'Alumno actualizado exitosamente'
- ]);
- break;
+ $stmt->execute([
+ $data['nombre'],
+ $data['email'],
+ $data['telefono'] ?? null,
+ $data['id']
+ ]);
+
+ // Si curso_id viene en la actualización, actualizar también el curso
+ if (!empty($data['curso_id'])) {
+ // Verifica si ya tiene una relación previa
+ $check = $pdo->prepare("SELECT id FROM alumnos_cursos WHERE alumno_id = ?");
+ $check->execute([$data['id']]);
+
+ if ($check->fetch()) {
+ // Si ya tiene relación, actualizamos el curso asignado
+ $updateCurso = $pdo->prepare("
+ UPDATE alumnos_cursos SET curso_id = ?, estado = 'cursando'
+ WHERE alumno_id = ?
+ ");
+ $updateCurso->execute([$data['curso_id'], $data['id']]);
+ } else {
+ // Si no tiene relación previa, la insertamos
+ $insertCurso = $pdo->prepare("
+ INSERT INTO alumnos_cursos (alumno_id, curso_id, estado)
+ VALUES (?, ?, 'cursando')
+ ");
+ $insertCurso->execute([$data['id'], $data['curso_id']]);
+ }
+ }
+
+ echo json_encode([
+ 'success' => true,
+ 'message' => 'Alumno actualizado exitosamente'
+ ]);
+ break;
+
case 'DELETE':
$id = $_GET['id'] ?? null;
diff --git a/api/cursos.php b/api/cursos.php
index 3ada92b..3dada2d 100644
--- a/api/cursos.php
+++ b/api/cursos.php
@@ -29,18 +29,29 @@ switch ($method) {
http_response_code(500);
echo json_encode(['error' => 'Error al cargar cursos']);
}
- break;
-
+ break;
+
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
-
+
if (empty($data['nombre']) || empty($data['tipo'])) {
http_response_code(400);
echo json_encode(['error' => 'Nombre y tipo son requeridos']);
exit;
}
-
+
try {
+ // Validar que no exista otro curso con el mismo nombre y tipo para ese profesor
+ $stmt = $pdo->prepare("SELECT id FROM cursos WHERE nombre = ? AND tipo = ? AND profesor_id = ?");
+ $stmt->execute([$data['nombre'], $data['tipo'], $profesorId]);
+ if ($stmt->fetch()) {
+ echo json_encode([
+ 'success' => false,
+ 'error' => "Ya existe un curso llamado '{$data['nombre']}' de tipo '{$data['tipo']}'."
+ ]);
+ exit;
+ }
+
$stmt = $pdo->prepare("
INSERT INTO cursos (nombre, descripcion, tipo, competencias, estado, profesor_id)
VALUES (?, ?, ?, ?, ?, ?)
@@ -53,42 +64,53 @@ switch ($method) {
$data['estado'],
$profesorId
]);
-
+
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
-
+
break;
-
+
case 'PUT':
$data = json_decode(file_get_contents('php://input'), true);
-
- if (empty($data['id']) || empty($data['nombre']) || empty($data['tipo'])) {
- http_response_code(400);
- echo json_encode(['error' => 'Datos incompletos']);
- exit;
+
+ if (empty($data['id']) || empty($data['nombre']) || empty($data['tipo'])) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Datos incompletos']);
+ exit;
}
-
+
try {
// Verificar que el curso pertenece al profesor
$stmt = $pdo->prepare("SELECT id FROM cursos WHERE id = ? AND profesor_id = ?");
$stmt->execute([$data['id'], $profesorId]);
-
+
if (!$stmt->fetch()) {
http_response_code(403);
echo json_encode(['error' => 'No autorizado']);
exit;
}
-
+
+ // Validar que no haya otro curso con el mismo nombre y tipo (excluyendo el actual)
+ $stmt = $pdo->prepare("SELECT id FROM cursos WHERE nombre = ? AND tipo = ? AND profesor_id = ? AND id != ?");
+ $stmt->execute([$data['nombre'], $data['tipo'], $profesorId, $data['id']]);
+ if ($stmt->fetch()) {
+ echo json_encode([
+ 'success' => false,
+ 'error' => "Ya existe otro curso llamado '{$data['nombre']}' de tipo '{$data['tipo']}'."
+ ]);
+ exit;
+ }
+
$stmt = $pdo->prepare("
UPDATE cursos SET
- nombre = ?,
- descripcion = ?,
- tipo = ?,
- competencias = ?,
- estado = ?
+ nombre = ?,
+ descripcion = ?,
+ tipo = ?,
+ competencias = ?,
+ estado = ?
WHERE id = ?
");
$stmt->execute([
@@ -99,14 +121,14 @@ switch ($method) {
$data['estado'],
$data['id']
]);
-
+
echo json_encode(['success' => true]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Error al actualizar curso']);
}
break;
-
+
case 'DELETE':
$id = $_GET['id'] ?? null;
if (!$id) {
@@ -114,30 +136,30 @@ switch ($method) {
echo json_encode(['error' => 'ID de curso no proporcionado']);
exit;
}
-
+
try {
// Verificar que el curso pertenece al profesor
$stmt = $pdo->prepare("SELECT id FROM cursos WHERE id = ? AND profesor_id = ?");
$stmt->execute([$id, $profesorId]);
-
+
if (!$stmt->fetch()) {
http_response_code(403);
echo json_encode(['error' => 'No autorizado']);
exit;
}
-
+
$stmt = $pdo->prepare("DELETE FROM cursos WHERE id = ?");
$stmt->execute([$id]);
-
+
echo json_encode(['success' => true]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Error al eliminar curso']);
}
break;
-
+
default:
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
}
-?>
\ No newline at end of file
+?>
diff --git a/api/importar_csv.php b/api/importar_csv.php
index 0ce5be5..e8f8999 100644
--- a/api/importar_csv.php
+++ b/api/importar_csv.php
@@ -1,67 +1,109 @@
false, 'error' => 'No autenticado']);
- exit;
+ http_response_code(401);
+ echo json_encode(['success' => false, 'error' => 'No autenticado']);
+ exit;
}
-$data = json_decode(file_get_contents('php://input'), true);
-$alumnos = $data['alumnos'] ?? [];
+$input = json_decode(file_get_contents('php://input'), true);
+$alumnos = $input['alumnos'] ?? [];
if (empty($alumnos)) {
- http_response_code(400);
- echo json_encode(['success' => false, 'error' => 'No se enviaron alumnos']);
- exit;
+ echo json_encode(['success' => false, 'error' => 'No se recibieron alumnos']);
+ exit;
+}
+
+function limpiar($s) {
+ return trim($s, "\"' ");
}
-// Paso 1: Validar todos los cursos
$errores = [];
-$profesorId = $_SESSION['profesor']['id'] ?? null;
+$importados = 0;
foreach ($alumnos as $index => $alumno) {
- $nombreCurso = trim($alumno['nombreCurso']);
- $tipoCurso = trim($alumno['tipoCurso']);
+ $fila = $index + 2;
- $stmt = $pdo->prepare("SELECT id FROM cursos WHERE nombre = ? AND tipo = ? AND profesor_id = ?");
- $stmt->execute([$nombreCurso, $tipoCurso, $profesorId]);
- $curso = $stmt->fetch();
+ $nombre = limpiar($alumno['nombre'] ?? '');
+ $email = limpiar($alumno['email'] ?? '');
+ $telefono = limpiar($alumno['telefono'] ?? '');
+ $tipoCurso = strtolower(limpiar($alumno['tipoCurso'] ?? ''));
+ $nombreCurso = limpiar($alumno['nombreCurso'] ?? '');
- if (!$curso) {
- $errores[] = "El curso \"{$nombreCurso}\" de tipo \"{$tipoCurso}\" en {$alumno['nombre']} ({$alumno['email']}) es inválido.";
- } else {
- $alumnos[$index]['curso_id'] = $curso['id']; // Guardamos para usar después
- }
+ if (!$nombre || !$email || !$telefono || !$tipoCurso || !$nombreCurso) {
+ $errores[] = "Fila $fila: faltan datos obligatorios.";
+ continue;
+ }
+
+ // Verificar curso+tipo
+ $stmtCurso = $pdo->prepare("
+ SELECT id
+ FROM cursos
+ WHERE nombre = ? AND tipo = ?
+ ");
+ $stmtCurso->execute([$nombreCurso, $tipoCurso]);
+ $curso = $stmtCurso->fetch(PDO::FETCH_ASSOC);
+
+ if (!$curso) {
+ $errores[] = "Fila $fila: el curso '$nombreCurso' con tipo '$tipoCurso' no existe.";
+ continue;
+ }
+
+ // Verificar duplicados por separado
+ $emailDuplicado = false;
+ $telefonoDuplicado = false;
+
+ $stmtEmail = $pdo->prepare("SELECT id FROM alumnos WHERE email = ?");
+ $stmtEmail->execute([$email]);
+ if ($stmtEmail->fetch()) {
+ $emailDuplicado = true;
+ }
+
+ $stmtTel = $pdo->prepare("SELECT id FROM alumnos WHERE telefono = ?");
+ $stmtTel->execute([$telefono]);
+ if ($stmtTel->fetch()) {
+ $telefonoDuplicado = true;
+ }
+
+ if ($emailDuplicado || $telefonoDuplicado) {
+ if ($emailDuplicado && $telefonoDuplicado) {
+ $errores[] = "Fila $fila: el email '$email' y el teléfono '$telefono' ya están registrados.";
+ } elseif ($emailDuplicado) {
+ $errores[] = "Fila $fila: el email '$email' ya está registrado.";
+ } elseif ($telefonoDuplicado) {
+ $errores[] = "Fila $fila: el teléfono '$telefono' ya está registrado.";
+ }
+ continue;
+ }
+
+ try {
+ $pdo->beginTransaction();
+
+ $stmtAlumno = $pdo->prepare("INSERT INTO alumnos (nombre, email, telefono) VALUES (?, ?, ?)");
+ $stmtAlumno->execute([$nombre, $email, $telefono]);
+ $alumnoId = $pdo->lastInsertId();
+
+ $stmtAsignar = $pdo->prepare("INSERT INTO alumnos_cursos (alumno_id, curso_id, estado) VALUES (?, ?, 'cursando')");
+ $stmtAsignar->execute([$alumnoId, $curso['id']]);
+
+ $pdo->commit();
+ $importados++;
+ } catch (PDOException $e) {
+ $pdo->rollBack();
+ $errores[] = "Fila $fila: error al guardar en base de datos.";
+ }
}
if (!empty($errores)) {
- echo json_encode([
- 'success' => false,
- 'error' => "Error en cursos: " . count($errores) . " conflictos encontrados",
- 'conflicts' => $errores
- ]);
- exit;
-}
-
-// Paso 2: Insertar alumnos
-try {
- $pdo->beginTransaction();
-
- foreach ($alumnos as $a) {
- $stmt = $pdo->prepare("INSERT INTO alumnos (nombre, email, telefono) VALUES (?, ?, ?)");
- $stmt->execute([$a['nombre'], $a['email'], $a['telefono'] ?? null]);
- $alumnoId = $pdo->lastInsertId();
-
- $stmt = $pdo->prepare("INSERT INTO alumnos_cursos (alumno_id, curso_id, estado) VALUES (?, ?, 'cursando')");
- $stmt->execute([$alumnoId, $a['curso_id']]);
- }
-
- $pdo->commit();
- echo json_encode(['success' => true, 'message' => 'Todos los alumnos fueron importados correctamente.']);
-} catch (PDOException $e) {
- $pdo->rollBack();
- http_response_code(500);
- echo json_encode(['success' => false, 'error' => 'Error al guardar en la base de datos: ' . $e->getMessage()]);
+ echo json_encode([
+ 'success' => false,
+ 'conflicts' => $errores
+ ]);
+} else {
+ echo json_encode([
+ 'success' => true,
+ 'message' => "$importados alumnos importados exitosamente."
+ ]);
}
diff --git a/assets/css/styles.css b/assets/css/styles.css
index e9e13db..5e69df1 100644
--- a/assets/css/styles.css
+++ b/assets/css/styles.css
@@ -965,3 +965,36 @@ textarea {
font-size: 0.85rem;
font-weight: 500;
}
+
+.description-cell {
+ max-width: 250px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.truncated-text {
+ display: inline-block;
+ max-width: 200px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+}
+
+.modal-description {
+ max-height: 300px;
+ overflow-y: auto;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ line-height: 1.4;
+}
+
+.read-more {
+ color: #2563eb;
+ font-size: 0.85rem;
+ text-decoration: underline;
+ margin-left: 6px;
+ cursor: pointer;
+}
+
diff --git a/assets/js/main copy.js b/assets/js/main copy.js
deleted file mode 100644
index f6dd55c..0000000
--- a/assets/js/main copy.js
+++ /dev/null
@@ -1,1333 +0,0 @@
-document.addEventListener("DOMContentLoaded", function () {
- // Manejo del formulario de login
- const loginForm = document.getElementById("loginForm");
- if (loginForm) {
- loginForm.addEventListener("submit", handleLogin);
- }
-
- // Configuración inicial del dashboard
- if (document.body.classList.contains("admin")) {
- initializeDashboard();
- }
-});
-
-// Función para manejar el login
-function handleLogin(e) {
- e.preventDefault();
- const formData = new FormData(this);
-
- fetch(this.action, {
- method: "POST",
- body: formData,
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- window.location.href = data.redirect;
- } else {
- alert(data.message);
- }
- })
- .catch((error) => console.error("Error:", error));
-}
-
-// Inicialización del dashboard
-function initializeDashboard() {
- setupSidebarNavigation();
- loadInitialData();
-
- const activeSection = document.querySelector(".sidebar-menu li.active");
- if (activeSection) {
- const sectionId = activeSection.getAttribute("data-section");
- showSection(sectionId, true);
- }
-}
-
-// Configuración del menú lateral
-function setupSidebarNavigation() {
- document.querySelectorAll(".sidebar-menu li").forEach((item) => {
- if (item.getAttribute("data-section")) {
- item.addEventListener("click", function () {
- const section = this.getAttribute("data-section");
- showSection(section);
- });
- }
- });
-}
-
-// Carga de datos iniciales
-function loadInitialData() {
- const profesorId = getProfesorId();
-
- if (!profesorId) {
- console.error("No se pudo obtener el ID del profesor");
- return;
- }
-
- fetch(`api/cursos.php?profesor_id=${profesorId}`)
- .then((response) => response.json())
- .then((courses) => {
- // Cargar estudiantes y diplomas
- Promise.all([
- fetch(`api/alumnos.php?profesor_id=${profesorId}`).then((res) =>
- res.json()
- ),
- fetch(`api/diplomas.php?profesor_id=${profesorId}`).then((res) =>
- res.json()
- ),
- ]).then(([students, diplomas]) => {
- updateProfessorStats(courses, students, diplomas);
- });
- })
- .catch((error) => console.error("Error:", error));
-}
-
-// Actualización de estadísticas
-function updateProfessorStats(courses, students, diplomas) {
- document.getElementById("active-courses-count").textContent = courses.length;
- document.getElementById("students-count").textContent = students.length;
- document.getElementById("diplomas-count").textContent = diplomas.length || 0;
-}
-
-// Obtención del ID del profesor
-function getProfesorId() {
- try {
- // 1. Verificar en el elemento del DOM (primera opción)
- const profesorElement = document.getElementById("current-profesor");
- if (profesorElement && profesorElement.dataset.id) {
- return profesorElement.dataset.id;
- }
-
- // 2. Verificar en sessionStorage/localStorage
- const storedUser =
- sessionStorage.getItem("currentUser") ||
- localStorage.getItem("currentUser");
- if (storedUser) {
- const user = JSON.parse(storedUser);
- if (user && user.profesor_id) {
- return user.profesor_id;
- }
- }
-
- console.log(
- "No se encontró el ID del profesor en el DOM o en el almacenamiento"
- );
- return null;
- } catch (error) {
- console.error("Error en getProfesorId:", error);
- return null;
- }
-}
-
-function showModal(title, content, buttons = []) {
- const modalHtml = `
-
- `;
-
- const modalContainer = document.createElement("div");
- modalContainer.innerHTML = modalHtml;
- document.body.appendChild(modalContainer);
- document.body.style.overflow = "hidden";
-}
-
-function closeModal() {
- const modal = document.getElementById("modal-overlay");
- if (modal) {
- modal.remove();
- document.body.style.overflow = "";
- }
-}
-
-function showToast(type, message) {
- const toast = document.createElement("div");
- toast.className = `toast toast-${type}`;
- toast.textContent = message;
- document.body.appendChild(toast);
-
- setTimeout(() => {
- toast.classList.add("fade-out");
- setTimeout(() => toast.remove(), 300);
- }, 3000);
-}
-
-// Manejo de secciones
-function showSection(sectionId, isInitialLoad = false) {
- updateActiveMenu(sectionId);
-
- const sectionElement = document.getElementById(`${sectionId}-content`);
- if (!sectionElement) return;
-
- document.querySelectorAll(".content-section").forEach((s) => {
- s.classList.remove("active");
- });
- sectionElement.classList.add("active");
-
- // Cargar siempre los datos del dashboard al acceder
- if (sectionId === "dashboard") {
- loadInitialData();
- } else {
- loadDynamicContent(sectionId, sectionElement);
- }
-}
-
-function updateActiveMenu(sectionId) {
- document.querySelectorAll(".sidebar-menu li").forEach((li) => {
- li.classList.remove("active");
- });
-
- const activeItem = document.querySelector(
- `.sidebar-menu li[data-section="${sectionId}"]`
- );
- if (activeItem) activeItem.classList.add("active");
-}
-
-// Carga de contenido dinámico
-function loadDynamicContent(sectionId, container) {
- container.innerHTML = 'Cargando...
';
-
- switch (sectionId) {
- case "dashboard":
- loadDashboardContent(container);
- break;
- case "courses":
- loadProfessorCourses(container);
- break;
- case "students":
- loadStudentsManagement(container);
- break;
- case "diplomas":
- loadDiplomasSection(container);
- break;
- default:
- container.innerHTML =
- 'Sección no implementada
';
- }
-}
-
-// Carga del dashboard
-async function loadDashboardContent(container, forceReload = false) {
- try {
- // Mostrar loader
- container.innerHTML = 'Cargando datos...
';
-
- // Obtener siempre los datos frescos del servidor
- const profesorId = getProfesorId();
- if (!profesorId) {
- throw new Error("Debes iniciar sesión nuevamente");
- }
-
- // Usar caché solo si no es un forceReload
- const cacheKey = `dashboardData-${profesorId}`;
- if (!forceReload && sessionStorage.getItem(cacheKey)) {
- const cachedData = JSON.parse(sessionStorage.getItem(cacheKey));
- renderDashboard(container, cachedData);
- return;
- }
-
- // Obtener datos frescos
- const [coursesRes, studentsRes, diplomasRes] = await Promise.all([
- fetch(`api/cursos.php?profesor_id=${profesorId}&t=${Date.now()}`),
- fetch(`api/alumnos.php?t=${Date.now()}`),
- fetch(`api/diplomas.php?profesor_id=${profesorId}&t=${Date.now()}`),
- ]);
-
- const [coursesData, studentsData, diplomasData] = await Promise.all([
- coursesRes.json(),
- studentsRes.json(),
- diplomasRes.json(),
- ]);
-
- if (
- !coursesData.success ||
- !studentsData.success ||
- !diplomasData.success
- ) {
- throw new Error("Error en los datos recibidos");
- }
-
- const dashboardData = {
- cursos: coursesData.data,
- alumnos: studentsData.data,
- diplomas: diplomasData.data,
- lastUpdated: new Date().toLocaleTimeString(),
- };
-
- // Guardar en caché y renderizar
- sessionStorage.setItem(cacheKey, JSON.stringify(dashboardData));
- renderDashboard(container, dashboardData);
- } catch (error) {
- console.error("Error:", error);
- container.innerHTML = `
-
-
Error al cargar datos
-
${error.message}
-
-
`;
- }
-}
-function renderDashboard(container, data) {
- const activeCourses = data.cursos.filter((c) => c.estado === "activo");
- const totalStudents = data.alumnos.length;
- const totalDiplomas = data.diplomas.length;
-
- container.innerHTML = `
-
-
-
-
Resumen:
-
• ${
- activeCourses.length
- } cursos activos
-
• ${totalStudents} alumnos registrados
-
• ${totalDiplomas} diplomas emitidos
-
-
-
-
Mis Cursos Activos
- ${renderCoursesPreview(activeCourses)}
- `;
-}
-
-// Gestión de cursos
-function loadProfessorCourses(container) {
- fetch(`api/cursos.php?profesor_id=${getProfesorId()}`)
- .then((response) => response.json())
- .then((res) => {
- if (!res.success) throw new Error("No se pudieron cargar los cursos");
- const courses = res.data;
-
- container.innerHTML = `
-
-
-
Lista de Cursos
-
-
-
-
- Nombre |
- Descripción |
- Tipo |
- Estado |
- Acciones |
-
-
-
- ${courses
- .map(
- (course) => `
-
- ${course.nombre} |
- ${course.descripcion || "-"} |
- ${formatCourseType(course.tipo)} |
-
- ${course.estado}
- |
-
-
-
-
-
- |
-
- `
- )
- .join("")}
-
-
-
-
`;
-
- setupCourseForm();
- })
- .catch((err) => {
- console.error("Error al cargar cursos:", err);
- container.innerHTML = `No se pudieron cargar los cursos
`;
- });
-}
-
-function formatCourseType(type) {
- const types = {
- pildora: "Píldora",
- inyeccion: "Inyección",
- tratamiento: "Tratamiento"
- };
- return types[type] || type;
-}
-
-function setupCourseForm() {
- const courseTypeSelect = document.getElementById('courseType');
- const competencesField = document.getElementById('competencesField');
- const competenciasInput = competencesField
- ? competencesField.querySelector('input[name="competencias"]')
- : null;
-
- if (courseTypeSelect && competenciasInput) {
- courseTypeSelect.addEventListener('change', function () {
- const isTratamiento = this.value === 'tratamiento';
- competencesField.classList.toggle('oculto', !isTratamiento);
- competenciasInput.required = isTratamiento;
- if (!isTratamiento) {
- competenciasInput.value = '';
- }
- });
-
- const isTratamiento = courseTypeSelect.value === 'tratamiento';
- competencesField.classList.toggle('oculto', !isTratamiento);
- competenciasInput.required = isTratamiento;
- }
-
- const form = document.getElementById("courseForm");
- if (!form) return;
-
- const cancelBtn = document.getElementById("cancelCourseBtn");
- if (cancelBtn) {
- cancelBtn.addEventListener("click", function () {
- form.reset();
- competencesField.classList.add("oculto");
- form.dataset.editing = "false";
- delete form.dataset.courseId;
- form.querySelector("button[type='submit']").textContent = "Guardar";
- cancelBtn.style.display = "none";
- });
- }
-
- form.addEventListener("submit", function (e) {
- e.preventDefault();
- const formData = new FormData(this);
- const jsonData = {
- nombre: formData.get("nombre"),
- descripcion: formData.get("descripcion"),
- competencias: formData.get("competencias"),
- tipo: formData.get("tipo"),
- estado: formData.get("estado"),
- profesor_id: getProfesorId(),
- };
-
- const isEdit = form.dataset.editing === "true";
- const courseId = form.dataset.courseId;
-
- if (isEdit) {
- updateCourse(courseId, jsonData);
- } else {
- createCourse(jsonData);
- }
- });
-}
-
-window.createCourse = function (data) {
- fetch("api/cursos.php", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- showSection("courses");
- }
- })
- .catch((error) => console.error("Error:", error));
-};
-
-window.updateCourse = function (id, data) {
- data.id = id;
-
- fetch("api/cursos.php", {
- method: "PUT",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- showSection("courses");
- }
- })
- .catch((error) => console.error("Error:", error));
-};
-
-window.editCourse = function (id) {
- fetch(`api/cursos.php?profesor_id=${getProfesorId()}`)
- .then((response) => response.json())
- .then((res) => {
- const course = res.data.find((c) => c.id == id);
- if (!course) return;
-
- const form = document.getElementById("courseForm");
- form.nombre.value = course.nombre;
- form.descripcion.value = course.descripcion || "";
- form.tipo.value = course.tipo;
- form.estado.value = course.estado || "activo";
-
- const competencesField = document.getElementById("competencesField");
- const competenciasInput = competencesField.querySelector('input[name="competencias"]');
- if (course.tipo === "tratamiento") {
- competencesField.classList.remove("oculto");
- competenciasInput.value = course.competencias || "";
- competenciasInput.required = true;
- } else {
- competencesField.classList.add("oculto");
- competenciasInput.value = "";
- competenciasInput.required = false;
- }
-
- form.dataset.editing = "true";
- form.dataset.courseId = id;
- form.querySelector("button[type='submit']").textContent = "Actualizar Curso";
- document.getElementById("cancelCourseBtn").style.display = "inline-block";
- form.scrollIntoView({ behavior: "smooth" });
- });
-};
-
-
-window.deleteCourse = function (id) {
- if (!confirm("¿Estás seguro de eliminar este curso?")) return;
-
- fetch(`api/cursos.php?id=${id}`, {
- method: "DELETE",
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- showSection("courses");
- }
- })
- .catch((error) => console.error("Error:", error));
-};
-
-// Gestión de alumnos
-function loadStudentsManagement(container) {
- container.innerHTML = 'Cargando alumnos...
';
-
- fetch("api/alumnos.php")
- .then((response) => {
- if (!response.ok) throw new Error("Error en la respuesta del servidor");
- return response.json();
- })
- .then((data) => {
- if (!data.success)
- throw new Error(data.error || "Error al obtener alumnos");
-
- container.innerHTML = `
-
- ${renderStudentForm()}
- ${renderStudentsTable(data.data || [])}
-
- `;
-
- setupStudentForm();
- (data.data || []).forEach((alumno) => loadStudentCourses(alumno.id));
- })
- .catch((error) => {
- console.error("Error:", error);
- container.innerHTML = `
-
-
Error al cargar alumnos
-
${error.message}
-
-
`;
- });
-}
-
-
-function renderStudentForm() {
- return `
-
-
Gestión de Alumnos
-
-
`;
-}
-
-function setupStudentForm() {
- const form = document.getElementById("studentForm");
- if (!form) return;
-
- // Referencias a selects
- const tipoCurso = document.getElementById("tipoCurso");
- const curso = document.getElementById("curso");
-
- // Cargar cursos dinámicamente
- tipoCurso.addEventListener("change", () => {
- const tipo = tipoCurso.value;
- curso.innerHTML = '';
- fetch(`api/cursos.php?tipo=${tipo}`)
- .then((res) => res.json())
- .then((data) => {
- if (data.success) {
- curso.innerHTML = '';
- data.data.forEach((c) => {
- const opt = document.createElement("option");
- opt.value = c.id;
- opt.textContent = c.nombre;
- curso.appendChild(opt);
- });
- } else {
- curso.innerHTML = '';
- }
- })
- .catch(() => {
- curso.innerHTML = '';
- });
- });
-
- // Guardar alumno
- form.addEventListener("submit", function (e) {
- e.preventDefault();
- submitStudentForm(); // ✅ Usa función unificada que detecta si es edición o nuevo
- });
-
- const searchInput = document.getElementById("studentSearch");
- if (searchInput) {
- searchInput.addEventListener("input", function () {
- filterStudents(this.value.toLowerCase());
- });
- }
-}
-
-function submitStudentForm() {
- const form = document.getElementById("studentForm");
- const submitBtn = form.querySelector('button[type="submit"]');
- const submitText = document.getElementById("submitText");
- const spinner = document.getElementById("submitSpinner");
-
- // Mostrar spinner
- submitText.textContent = "Procesando...";
- spinner.style.display = "inline-block";
- submitBtn.disabled = true;
-
- const formData = new FormData(form);
- const jsonData = {
- nombre: formData.get("nombre"),
- email: formData.get("email"),
- telefono: formData.get("telefono"),
- curso_id: document.getElementById("curso").value, // ✅ Cambio aquí
- };
-
- const isEdit = form.dataset.editing === "true";
- const studentId = form.dataset.studentId;
- const url = "api/alumnos.php";
- const method = isEdit ? "PUT" : "POST";
-
- if (isEdit) {
- jsonData.id = studentId;
- }
-
- fetch(url, {
- method: method,
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(jsonData),
- })
- .then((response) => response.json())
- .then((data) => {
- if (!data.success)
- throw new Error(data.error || "Error al guardar alumno");
-
- showToast(
- "success",
- data.message || (isEdit ? "Alumno actualizado" : "Alumno creado")
- );
- resetStudentForm();
- loadStudentsManagement(document.querySelector("#students-content"));
- })
- .catch((error) => {
- showToast("error", error.message || "Error en el servidor");
- })
- .finally(() => {
- submitText.textContent = "Guardar";
- spinner.style.display = "none";
- submitBtn.disabled = false;
- });
-}
-
-window.createStudent = function (data) {
- fetch("api/alumnos.php", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- showSection("students");
- }
- })
- .catch((error) => console.error("Error:", error));
-};
-
-window.updateStudent = function (id, data) {
- data.id = id;
-
- fetch("api/alumnos.php", {
- method: "PUT",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- })
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- showSection("students");
- }
- })
- .catch((error) => console.error("Error:", error));
-};
-
-window.editStudent = function (id) {
- fetch(`api/alumnos.php`)
- .then((response) => response.json())
- .then((data) => {
- if (!data.success)
- throw new Error(data.error || "Error al obtener alumnos");
-
- const alumno = data.data.find((a) => a.id == id);
- if (!alumno) throw new Error("Alumno no encontrado");
-
- const form = document.getElementById("studentForm");
- form.nombre.value = alumno.nombre;
- form.email.value = alumno.email;
- form.telefono.value = alumno.telefono || "";
-
- form.dataset.editing = "true";
- form.dataset.studentId = id;
-
- document.getElementById("submitText").textContent = "Actualizar";
- document.getElementById("cancelBtn").style.display = "inline-block";
-
- // 👇 Precargar tipo y curso si el alumno tiene asignación
- fetch(`api/alumnos-cursos.php?alumno_id=${id}`)
- .then((res) => res.json())
- .then((asignaciones) => {
- if (asignaciones.success && asignaciones.data.length > 0) {
- const curso = asignaciones.data[0];
- const tipoCursoSelect = document.getElementById("tipoCurso");
- const cursoSelect = document.getElementById("curso");
-
- tipoCursoSelect.value = curso.tipo;
- tipoCursoSelect.dispatchEvent(new Event("change"));
-
- setTimeout(() => {
- cursoSelect.value = curso.id;
- }, 300);
- }
- });
-
- form.scrollIntoView({ behavior: "smooth" });
- })
- .catch((error) => {
- showToast("error", error.message || "Error al cargar alumno");
- });
-};
-
-window.deleteStudent = function (id) {
- if (!id) {
- showToast("error", "ID de alumno no proporcionado");
- return;
- }
-
- fetch(`api/alumnos.php?id=${id}`, {
- method: "DELETE",
- })
- .then((response) => response.json())
- .then((data) => {
- if (!data.success)
- throw new Error(data.error || "Error al eliminar alumno");
-
- showToast("success", data.message || "Alumno eliminado");
- closeModal();
- loadStudentsManagement(document.querySelector("#students-content"));
- })
- .catch((error) => {
- showToast("error", error.message || "Error al eliminar alumno");
- });
-};
-
-
-window.confirmDeleteStudent = function (id) {
- showModal(
- "Confirmar eliminación",
- "¿Estás seguro de eliminar este alumno? Esta acción no se puede deshacer.",
- [
- {
- text: "Cancelar",
- class: "btn-outline",
- handler: "closeModal",
- },
- {
- text: "Eliminar",
- class: "btn-danger",
- handler: "deleteStudent(" + id + ")"
- },
- ]
- );
-};
-
-window.resetStudentForm = function () {
- const form = document.getElementById("studentForm");
- form.reset();
- form.dataset.editing = "false";
- delete form.dataset.studentId;
-
- document.getElementById("submitText").textContent = "Guardar";
- document.getElementById("cancelBtn").style.display = "none";
-};
-function filterStudents(searchTerm) {
- const rows = document.querySelectorAll(".students-table tbody tr");
-
- rows.forEach((row) => {
- const nombre = row.cells[0].textContent.toLowerCase();
- const email = row.cells[1].textContent.toLowerCase();
- const telefono = row.cells[2].textContent.toLowerCase();
-
- if (
- nombre.includes(searchTerm) ||
- email.includes(searchTerm) ||
- telefono.includes(searchTerm)
- ) {
- row.style.display = "";
- } else {
- row.style.display = "none";
- }
- });
-}
-
-//alumnos-cursos
-
-function renderStudentsTable(alumnos) {
- if (alumnos.length === 0) {
- return `
-
-
-
-
No hay alumnos registrados
-
Comienza agregando tu primer alumno
-
-
`;
- }
-
- return `
-
-
-
-
-
-
- Nombre |
- Email |
- Teléfono |
- Cursos |
- Acciones |
-
-
-
- ${alumnos
- .map(
- (alumno) => `
-
- ${alumno.nombre} |
- ${alumno.email} |
- ${alumno.telefono || "-"} |
-
-
- ${renderCourseBadges(alumno.id)}
-
- |
-
-
-
-
-
- |
-
- `
- )
- .join("")}
-
-
-
-
`;
-}
-
-function renderCourseBadges(alumnoId) {
- return ''; // Se cargará dinámicamente
-}
-
-async function loadStudentCourses(alumnoId) {
- try {
- const response = await fetch(
- `api/alumnos-cursos.php?alumno_id=${alumnoId}`
- );
- const data = await response.json();
-
- if (data.success) {
- const container = document.getElementById(`courses-${alumnoId}`);
- if (container) {
- container.innerHTML =
- data.data
- .map(
- (curso) => `
-
- ${curso.nombre}
-
-
- `
- )
- .join("") || 'Sin cursos';
- }
- }
- } catch (error) {
- console.error("Error loading student courses:", error);
- }
-}
-
-window.showAssignStudentModal = async function () {
- try {
- console.log("Mostrando modal de vinculación");
-
- const profesorId = getProfesorId();
- if (!profesorId) {
- console.error("No se pudo obtener el ID del profesor");
- showToast("error", "No se pudo identificar al profesor");
- return;
- }
-
- // Mostrar loader mientras se cargan los datos
- const tempModalContent = `Cargando datos...
`;
- showModal("Vincular Alumnos a Curso", tempModalContent);
-
- // Cargar cursos y alumnos en paralelo
- const [cursosRes, alumnosRes] = await Promise.all([
- fetch(`api/cursos.php?profesor_id=${profesorId}`),
- fetch("api/alumnos.php"),
- ]);
-
- const [cursosData, alumnosData] = await Promise.all([
- cursosRes.json(),
- alumnosRes.json(),
- ]);
-
- if (!cursosData || !alumnosData || !alumnosData.success) {
- closeModal();
- throw new Error("Error al cargar datos necesarios");
- }
-
- // Crear contenido del modal
- const modalHtml = `
-
-
-
-
-
-
- `;
-
- // Actualizar el contenido del modal
- const modalBody = document.querySelector(".modal-body");
- if (modalBody) {
- modalBody.innerHTML = modalHtml;
- }
-
- // Crear el footer si no existe
- let modalFooter = document.querySelector(".modal-footer");
- if (!modalFooter) {
- modalFooter = document.createElement("div");
- modalFooter.className = "modal-footer";
- document.querySelector(".modal").appendChild(modalFooter);
- }
-
- // Actualizar el contenido del footer
- modalFooter.innerHTML = `
-
-
- `;
-
- // Función para vincular alumnos seleccionados
- window.assignStudentsToCourse = async function () {
- const cursoId = document.getElementById("selectCurso").value;
- const selectedAlumnos = Array.from(
- document.querySelectorAll('input[name="alumnos"]:checked')
- ).map((input) => input.value);
-
- if (selectedAlumnos.length === 0) {
- showToast("warning", "Selecciona al menos un alumno");
- return;
- }
-
- try {
- const response = await fetch("api/alumnos-cursos.php", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- curso_id: cursoId,
- alumnos: selectedAlumnos,
- }),
- });
-
- const result = await response.json();
- if (result.success) {
- showToast("success", "Alumnos vinculados exitosamente");
- closeModal();
- loadStudentsManagement(document.querySelector("#students-content"));
- } else {
- showToast("error", result.error || "Error al vincular");
- }
- } catch (error) {
- console.error("Error al vincular:", error);
- showToast("error", "Error al realizar la vinculación");
- }
- };
- } catch (error) {
- console.error("Error en showAssignStudentModal:", error);
- closeModal();
- showToast("error", "Error al cargar datos para vinculación");
- }
-};
-
-window.unassignStudent = async function (alumnoId, cursoId) {
- if (confirm("¿Desvincular este alumno del curso?")) {
- try {
- const response = await fetch(
- `api/alumnos-cursos.php?alumno_id=${alumnoId}&curso_id=${cursoId}`,
- {
- method: "DELETE",
- }
- );
-
- const data = await response.json();
-
- if (data.success) {
- showToast("success", data.message);
- loadStudentCourses(alumnoId);
- } else {
- showToast("error", data.error || "Error al desvincular");
- }
- } catch (error) {
- showToast("error", "Error en la conexión");
- }
- }
-};
-
-// Gestión de diplomas
-function loadDiplomasSection(container) {
- container.innerHTML = 'Cargando diplomas...
';
-
- fetch(`api/diplomas.php?profesor_id=${getProfesorId()}`)
- .then((response) => {
- if (!response.ok) throw new Error("Error en la respuesta del servidor");
- return response.json();
- })
- .then((data) => {
- if (!data.success)
- throw new Error(data.error || "Error al obtener diplomas");
-
- if (data.data.length === 0) {
- container.innerHTML = `
-
-
Diplomas Emitidos
-
No hay diplomas registrados aún
-
`;
- return;
- }
-
- container.innerHTML = `
-
-
Diplomas Emitidos
-
-
-
-
- Alumno |
- Email |
- Curso |
- Tipo |
- Fecha |
- Código |
- Acciones |
-
-
-
- ${data.data
- .map(
- (diploma) => `
-
- ${diploma.alumno_nombre} |
- ${diploma.alumno_email} |
- ${diploma.curso_nombre} |
- ${diploma.curso_tipo} |
- ${diploma.fecha_formateada} |
- ${diploma.codigo_unico} |
-
-
-
- |
-
- `
- )
- .join("")}
-
-
-
-
`;
- })
- .catch((error) => {
- console.error("Error:", error);
- container.innerHTML = `
-
-
Error al cargar diplomas
-
${error.message}
-
-
`;
- });
-}
-
-// Funciones auxiliares
-function generateCoursesPreview(courses) {
- if (!courses.length) return "No tienes cursos activos
";
-
- return `
-
-
-
-
- Nombre |
- Tipo |
- Estado |
-
-
-
- ${courses
- .map(
- (course) => `
-
- ${course.nombre || "Sin nombre"} |
- ${
- course.tipo || "N/A"
- } |
- ${course.estado || "N/A"} |
-
- `
- )
- .join("")}
-
-
-
`;
-}
-
-function getCourseTypeClass(type) {
- const types = {
- inyeccion: "type-inyeccion",
- pildora: "type-pildora",
- tratamiento: "type-tratamiento",
- };
- return types[type] || "";
-}
-
-// Funciones globales para diplomas
-window.downloadDiploma = function (codigo) {
- window.open(`certificado.php?codigo=${codigo}`, "_blank");
-};
-
-window.resendDiploma = function (codigo) {
- fetch(`api/diplomas.php?action=resend&codigo=${codigo}`)
- .then((response) => response.json())
- .then((data) => {
- if (data.success) {
- alert("Diploma reenviado exitosamente");
- } else {
- alert("Error: " + (data.error || "No se pudo reenviar el diploma"));
- }
- })
- .catch((error) => {
- console.error("Error:", error);
- alert("Error al reenviar el diploma");
- });
-};
diff --git a/assets/js/main.js b/assets/js/main.js
index ddfb411..963ff90 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -120,47 +120,68 @@ function getProfesorId() {
}
function showModal(title, content, buttons = []) {
- const modalHtml = `
-
-
+ // Remover modal existente si hay
+ const existing = document.getElementById("modal-overlay");
+ if (existing) existing.remove();
+
+ const modalOverlay = document.createElement("div");
+ modalOverlay.className = "modal-overlay";
+ modalOverlay.id = "modal-overlay";
+
+ const modal = document.createElement("div");
+ modal.className = "modal";
+
+ modal.innerHTML = `
+
+
${content}
+
`;
- const modalContainer = document.createElement("div");
- modalContainer.innerHTML = modalHtml;
- document.body.appendChild(modalContainer);
+ modalOverlay.appendChild(modal);
+ document.body.appendChild(modalOverlay);
document.body.style.overflow = "hidden";
+
+ // Cerrar con el botón de la esquina
+ document.getElementById("modal-close-btn").addEventListener("click", closeModal);
+
+ // Agregar botones y handlers
+ const footer = document.getElementById("modal-footer");
+
+ buttons.forEach((btn) => {
+ const button = document.createElement("button");
+ button.className = "btn " + btn.class;
+ button.innerText = btn.text;
+
+ button.addEventListener("click", () => {
+ if (typeof btn.handler === "function") {
+ btn.handler();
+ } else if (typeof btn.handler === "string") {
+ if (btn.handler.endsWith(")")) {
+ eval(btn.handler); // deleteStudent(5)
+ } else if (typeof window[btn.handler] === "function") {
+ window[btn.handler](); // closeModal
+ }
+ }
+ });
+
+ footer.appendChild(button);
+ });
}
-function closeModal() {
+window.showFullDescription = function (descripcion) {
+ showModal("Descripción del Curso", `
${descripcion}
`);
+};
+
+window.closeModal = function () {
const modal = document.getElementById("modal-overlay");
if (modal) {
modal.remove();
document.body.style.overflow = "";
}
-}
+};
function showToast(type, message) {
const toast = document.createElement("div");
@@ -343,7 +364,7 @@ function loadProfessorCourses(container) {
-
+
`;
+ // Evaluar si se debe mostrar "Leer más" en cada descripción
+ setTimeout(() => {
+ courses.forEach(course => {
+ const span = document.getElementById(`desc-${course.id}`);
+ const leerMas = document.getElementById(`readmore-${course.id}`);
+
+ if (span && leerMas && span.scrollWidth > span.clientWidth) {
+ const safeDesc = (course.descripcion || "")
+ .replace(/'/g, "\\'")
+ .replace(/"/g, """)
+ .replace(/\n/g, "\\n");
+
+ leerMas.innerHTML = `
+
+ Leer más
+ `;
+ }
+ });
+ }, 0);
+
setupCourseForm();
})
.catch((err) => {
@@ -954,12 +1001,6 @@ function renderStudentsTable(alumnos) {
-
-
-
-
@@ -1343,51 +1384,64 @@ window.resendDiploma = function (codigo) {
console.error("Error:", error);
alert("Error al reenviar el diploma");
});
-
- window.handleCSVUpload = function (event) {
- const file = event.target.files[0];
- if (!file) return;
-
- const reader = new FileReader();
- reader.onload = function (e) {
- const lines = e.target.result.split("\n").map(line => line.trim()).filter(Boolean);
- const alumnos = [];
-
- for (let i = 1; i < lines.length; i++) {
- const [nombre, email, telefono, tipoCurso, nombreCurso] = lines[i].split(",").map(s => s.trim());
-
- // Validación básica de columnas mínimas
- if (!nombre || !email || !tipoCurso || !nombreCurso) continue;
-
- alumnos.push({ nombre, email, telefono, tipoCurso, nombreCurso });
- }
-
- fetch("api/importar_csv.php", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ alumnos }),
- })
- .then(res => res.json())
- .then(data => {
- if (data.success) {
- showToast("success", data.message || "Alumnos importados correctamente");
- loadStudentsManagement(document.querySelector("#students-content"));
- } else {
- // Si vienen errores detallados, los mostramos
- if (data.conflicts && data.conflicts.length > 0) {
- const list = `
${data.conflicts.map(msg => `- ${msg}
`).join("")}
`;
- showModal("Errores en Importación CSV", `
No se importaron alumnos por los siguientes errores:
${list}`);
- } else {
- showToast("error", data.error || "Error al importar alumnos");
- }
- }
- })
- .catch(() => {
- showToast("error", "Error al procesar el archivo");
- });
- };
-
- reader.readAsText(file);
- };
-
};
+
+window.handleCSVUpload = function (event) {
+ const file = event.target.files[0];
+ if (!file) return;
+
+ const resultadoDiv = document.getElementById("resultadoCSV");
+ if (resultadoDiv) resultadoDiv.innerHTML = "";
+
+ const reader = new FileReader();
+ reader.onload = function (e) {
+ const lines = e.target.result.split("\n").map(line => line.trim()).filter(Boolean);
+ const alumnos = [];
+
+ for (let i = 1; i < lines.length; i++) {
+ const [nombre, email, telefono, tipoCurso, nombreCurso] = lines[i].split(",").map(s => s.trim());
+
+ if (!nombre || !email || !telefono || !tipoCurso || !nombreCurso) {
+ continue;
+ }
+
+ alumnos.push({ nombre, email, telefono, tipoCurso, nombreCurso });
+ }
+
+ if (alumnos.length === 0) {
+ showToast("error", "El archivo CSV no contiene datos válidos");
+ if (resultadoDiv) resultadoDiv.innerHTML = `
No se encontraron alumnos válidos en el archivo.
`;
+ return;
+ }
+
+ fetch("api/importar_csv.php", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ alumnos }),
+ })
+ .then(res => res.json())
+ .then(data => {
+ if (data.success) {
+ showToast("success", data.message || "Alumnos importados correctamente");
+ if (resultadoDiv) resultadoDiv.innerHTML = `
${data.message}
`;
+ loadStudentsManagement(document.querySelector("#students-content"));
+ } else {
+ if (data.conflicts && data.conflicts.length > 0) {
+ const list = `
${data.conflicts.map(msg => `- ${msg}
`).join("")}
`;
+ showModal("Errores en Importación CSV", `
No se importaron alumnos por los siguientes errores:
${list}`);
+ if (resultadoDiv) resultadoDiv.innerHTML = `
${list}
`;
+ } else {
+ showToast("error", data.error || "Error al importar alumnos");
+ if (resultadoDiv) resultadoDiv.innerHTML = `
${data.error || "Error desconocido"}
`;
+ }
+ }
+ })
+ .catch(() => {
+ showToast("error", "Error al procesar el archivo");
+ if (resultadoDiv) resultadoDiv.innerHTML = `
Error al procesar el archivo.
`;
+ });
+ };
+
+ reader.readAsText(file);
+};
+