diff --git a/api/alumnos-cursos.php b/api/alumnos-cursos.php
index 32165b3..a055224 100644
--- a/api/alumnos-cursos.php
+++ b/api/alumnos-cursos.php
@@ -14,27 +14,27 @@ $profesorId = $_SESSION['profesor']['id'] ?? null;
try {
switch ($method) {
case 'GET':
- $alumnoId = $_GET['alumno_id'] ?? null;
-
+ $alumnoId = $_GET['alumno_id'] ?? null;
+
if ($alumnoId) {
- // Obtener cursos de un alumno específico
- $query = "SELECT c.* FROM cursos c
- JOIN alumnos_cursos ac ON c.id = ac.curso_id
- WHERE ac.alumno_id = ? AND c.profesor_id = ?";
+ // Obtener cursos de un alumno específico (con tipo)
+ $query = "SELECT c.id, c.nombre, c.tipo FROM cursos c
+ JOIN alumnos_cursos ac ON c.id = ac.curso_id
+ WHERE ac.alumno_id = ? AND c.profesor_id = ?";
$stmt = $pdo->prepare($query);
$stmt->execute([$alumnoId, $profesorId]);
} else {
- // Obtener todos los alumnos
- $query = "SELECT * FROM alumnos";
- $stmt = $pdo->prepare($query);
- $stmt->execute();
- }
-
- echo json_encode([
- 'success' => true,
- 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)
- ]);
- break;
+ // Obtener todos los alumnos
+ $query = "SELECT * FROM alumnos";
+ $stmt = $pdo->prepare($query);
+ $stmt->execute();
+ }
+
+ echo json_encode([
+ 'success' => true,
+ 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)
+ ]);
+ break;
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
diff --git a/api/alumnos.php b/api/alumnos.php
index 27adf55..f34a914 100644
--- a/api/alumnos.php
+++ b/api/alumnos.php
@@ -27,31 +27,51 @@ try {
]);
break;
- case 'POST':
- $data = json_decode(file_get_contents('php://input'), true);
+ case 'POST':
+ $data = json_decode(file_get_contents('php://input'), true);
- if (empty($data['nombre']) || empty($data['email'])) {
- http_response_code(400);
- echo json_encode(['success' => false, 'error' => 'Nombre y email son requeridos']);
- exit;
- }
+ if (empty($data['nombre']) || empty($data['email'])) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'Nombre y email son requeridos']);
+ exit;
+ }
- $stmt = $pdo->prepare("
- INSERT INTO alumnos (nombre, email, telefono)
- VALUES (?, ?, ?)
- ");
- $stmt->execute([
- $data['nombre'],
- $data['email'],
- $data['telefono'] ?? null
- ]);
+ $pdo->beginTransaction();
+ try {
+ // Insertar alumno
+ $stmt = $pdo->prepare("
+ INSERT INTO alumnos (nombre, email, telefono)
+ VALUES (?, ?, ?)
+ ");
+ $stmt->execute([
+ $data['nombre'],
+ $data['email'],
+ $data['telefono'] ?? null
+ ]);
- echo json_encode([
- 'success' => true,
- 'id' => $pdo->lastInsertId(),
- 'message' => 'Alumno creado exitosamente'
- ]);
- break;
+ $alumnoId = $pdo->lastInsertId();
+
+ // Si viene curso_id, asignar también a curso
+ if (!empty($data['curso_id'])) {
+ $stmt = $pdo->prepare("
+ INSERT INTO alumnos_cursos (alumno_id, curso_id, estado)
+ VALUES (?, ?, 'cursando')
+ ");
+ $stmt->execute([$alumnoId, $data['curso_id']]);
+ }
+
+ $pdo->commit();
+ echo json_encode([
+ 'success' => true,
+ 'id' => $alumnoId,
+ 'message' => 'Alumno creado y asignado exitosamente'
+ ]);
+ } catch (PDOException $e) {
+ $pdo->rollBack();
+ http_response_code(500);
+ echo json_encode(['success' => false, 'error' => 'Error al registrar: ' . $e->getMessage()]);
+ }
+ break;
case 'PUT':
$data = json_decode(file_get_contents('php://input'), true);
@@ -75,6 +95,30 @@ try {
$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,
diff --git a/api/cursos.php b/api/cursos.php
index ba0a6da..3ada92b 100644
--- a/api/cursos.php
+++ b/api/cursos.php
@@ -14,15 +14,22 @@ $profesorId = $_SESSION['profesor']['id'];
switch ($method) {
case 'GET':
try {
- $query = "SELECT * FROM cursos WHERE profesor_id = ?";
- $stmt = $pdo->prepare($query);
- $stmt->execute([$profesorId]);
- echo json_encode($stmt->fetchAll());
+ $tipo = $_GET['tipo'] ?? null;
+ if ($tipo) {
+ $query = "SELECT * FROM cursos WHERE profesor_id = ? AND tipo = ?";
+ $stmt = $pdo->prepare($query);
+ $stmt->execute([$profesorId, $tipo]);
+ } else {
+ $query = "SELECT * FROM cursos WHERE profesor_id = ?";
+ $stmt = $pdo->prepare($query);
+ $stmt->execute([$profesorId]);
+ }
+ echo json_encode(['success' => true, 'data' => $stmt->fetchAll()]);
} catch (PDOException $e) {
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);
@@ -50,8 +57,9 @@ switch ($method) {
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
} catch (PDOException $e) {
http_response_code(500);
- echo json_encode(['error' => 'Error al crear curso']);
+ echo json_encode(['error' => $e->getMessage()]);
}
+
break;
case 'PUT':
diff --git a/api/importar_csv.php b/api/importar_csv.php
new file mode 100644
index 0000000..0ce5be5
--- /dev/null
+++ b/api/importar_csv.php
@@ -0,0 +1,67 @@
+ false, 'error' => 'No autenticado']);
+ exit;
+}
+
+$data = json_decode(file_get_contents('php://input'), true);
+$alumnos = $data['alumnos'] ?? [];
+
+if (empty($alumnos)) {
+ http_response_code(400);
+ echo json_encode(['success' => false, 'error' => 'No se enviaron alumnos']);
+ exit;
+}
+
+// Paso 1: Validar todos los cursos
+$errores = [];
+$profesorId = $_SESSION['profesor']['id'] ?? null;
+
+foreach ($alumnos as $index => $alumno) {
+ $nombreCurso = trim($alumno['nombreCurso']);
+ $tipoCurso = trim($alumno['tipoCurso']);
+
+ $stmt = $pdo->prepare("SELECT id FROM cursos WHERE nombre = ? AND tipo = ? AND profesor_id = ?");
+ $stmt->execute([$nombreCurso, $tipoCurso, $profesorId]);
+ $curso = $stmt->fetch();
+
+ 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 (!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()]);
+}
diff --git a/assets/js/main copy.js b/assets/js/main copy.js
new file mode 100644
index 0000000..f6dd55c
--- /dev/null
+++ b/assets/js/main copy.js
@@ -0,0 +1,1333 @@
+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 e1fd946..ddfb411 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -331,7 +331,10 @@ function renderDashboard(container, data) {
function loadProfessorCourses(container) {
fetch(`api/cursos.php?profesor_id=${getProfesorId()}`)
.then((response) => response.json())
- .then((courses) => {
+ .then((res) => {
+ if (!res.success) throw new Error("No se pudieron cargar los cursos");
+ const courses = res.data;
+
container.innerHTML = `
Mis Cursos
@@ -388,12 +391,8 @@ function loadProfessorCourses(container) {
(course) => `
${course.nombre} |
- ${
- course.descripcion || "-"
- } |
- ${course.tipo} |
+ ${course.descripcion || "-"} |
+ ${formatCourseType(course.tipo)} |
|
-
-
+
+
|
@@ -425,14 +420,18 @@ function loadProfessorCourses(container) {
`;
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'
+ pildora: "Píldora",
+ inyeccion: "Inyección",
+ tratamiento: "Tratamiento"
};
return types[type] || type;
}
@@ -445,7 +444,7 @@ function setupCourseForm() {
: null;
if (courseTypeSelect && competenciasInput) {
- courseTypeSelect.addEventListener('change', function() {
+ courseTypeSelect.addEventListener('change', function () {
const isTratamiento = this.value === 'tratamiento';
competencesField.classList.toggle('oculto', !isTratamiento);
competenciasInput.required = isTratamiento;
@@ -458,7 +457,7 @@ function setupCourseForm() {
competencesField.classList.toggle('oculto', !isTratamiento);
competenciasInput.required = isTratamiento;
}
-
+
const form = document.getElementById("courseForm");
if (!form) return;
@@ -482,7 +481,7 @@ function setupCourseForm() {
descripcion: formData.get("descripcion"),
competencias: formData.get("competencias"),
tipo: formData.get("tipo"),
- estado: formData.get("estado"),
+ estado: formData.get("estado"),
profesor_id: getProfesorId(),
};
@@ -532,8 +531,8 @@ window.updateCourse = function (id, data) {
window.editCourse = function (id) {
fetch(`api/cursos.php?profesor_id=${getProfesorId()}`)
.then((response) => response.json())
- .then((courses) => {
- const course = courses.find((c) => c.id == id);
+ .then((res) => {
+ const course = res.data.find((c) => c.id == id);
if (!course) return;
const form = document.getElementById("courseForm");
@@ -562,6 +561,7 @@ window.editCourse = function (id) {
});
};
+
window.deleteCourse = function (id) {
if (!confirm("¿Estás seguro de eliminar este curso?")) return;
@@ -613,48 +613,104 @@ function loadStudentsManagement(container) {
});
}
+
function renderStudentForm() {
return `
-
-
Gestión de Alumnos
-
-
`;
+
+
+
+
`;
}
+
function setupStudentForm() {
const form = document.getElementById("studentForm");
if (!form) return;
- form.addEventListener("submit", function (e) {
- e.preventDefault();
- submitStudentForm();
+ // 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 = '';
+ });
});
- // Configurar búsqueda
+ // 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 () {
@@ -662,6 +718,7 @@ function setupStudentForm() {
});
}
}
+
function submitStudentForm() {
const form = document.getElementById("studentForm");
const submitBtn = form.querySelector('button[type="submit"]');
@@ -678,12 +735,12 @@ function submitStudentForm() {
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" + (isEdit ? "" : "");
+ const url = "api/alumnos.php";
const method = isEdit ? "PUT" : "POST";
if (isEdit) {
@@ -772,6 +829,24 @@ window.editStudent = function (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) => {
@@ -780,6 +855,11 @@ window.editStudent = function (id) {
};
window.deleteStudent = function (id) {
+ if (!id) {
+ showToast("error", "ID de alumno no proporcionado");
+ return;
+ }
+
fetch(`api/alumnos.php?id=${id}`, {
method: "DELETE",
})
@@ -796,6 +876,8 @@ window.deleteStudent = function (id) {
showToast("error", error.message || "Error al eliminar alumno");
});
};
+
+
window.confirmDeleteStudent = function (id) {
showModal(
"Confirmar eliminación",
@@ -809,11 +891,12 @@ window.confirmDeleteStudent = function (id) {
{
text: "Eliminar",
class: "btn-danger",
- handler: () => deleteStudent(id),
+ handler: "deleteStudent(" + id + ")"
},
]
);
};
+
window.resetStudentForm = function () {
const form = document.getElementById("studentForm");
form.reset();
@@ -870,13 +953,13 @@ function renderStudentsTable(alumnos) {
-