Verificación de caracteres en gestión de cursos

This commit is contained in:
carlos.bonilla 2025-06-19 15:57:05 -06:00
parent 29ed4d7847
commit 272026f236
2 changed files with 122 additions and 54 deletions

View File

@ -7,38 +7,48 @@ if (!is_logged_in()) {
echo json_encode(['error' => 'No autenticado']); echo json_encode(['error' => 'No autenticado']);
exit; exit;
} }
try { try {
$profesorId = $_GET['profesor_id'] ?? null; $profesorId = $_GET['profesor_id'] ?? null;
$query = " $query = "
SELECT d.*, a.nombre AS alumno_nombre, c.nombre AS curso_nombre SELECT
d.codigo_unico,
d.fecha_emision,
a.nombre AS alumno_nombre,
a.email AS alumno_email,
c.nombre AS curso_nombre,
c.tipo AS curso_tipo
FROM diplomas d FROM diplomas d
JOIN alumnos_cursos ac ON d.alumno_curso_id = ac.id JOIN alumnos_cursos ac ON d.alumno_curso_id = ac.id
JOIN alumnos a ON ac.alumno_id = a.id JOIN alumnos a ON ac.alumno_id = a.id
JOIN cursos c ON ac.curso_id = c.id JOIN cursos c ON ac.curso_id = c.id
"; ";
$params = []; $params = [];
if ($profesorId) { if ($profesorId) {
$query .= " WHERE c.profesor_id = ?"; $query .= " WHERE c.profesor_id = ?";
$params[] = $profesorId; $params[] = $profesorId;
} }
$query .= " ORDER BY d.fecha_emision DESC"; $query .= " ORDER BY d.fecha_emision DESC";
$stmt = $pdo->prepare($query); $stmt = $pdo->prepare($query);
$stmt->execute($params); $stmt->execute($params);
$diplomas = $stmt->fetchAll(); $diplomas = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$row['fecha_formateada'] = date("d/m/Y", strtotime($row['fecha_emision']));
$diplomas[] = $row;
}
echo json_encode([ echo json_encode([
'success' => true, 'success' => true,
'data' => $diplomas, 'data' => $diplomas,
'count' => count($diplomas) 'count' => count($diplomas)
]); ]);
} catch (Exception $e) { } catch (Exception $e) {
http_response_code(500); http_response_code(500);
echo json_encode(['success' => false, 'error' => $e->getMessage()]); echo json_encode(['success' => false, 'error' => $e->getMessage()]);
} }
?>

View File

@ -385,12 +385,16 @@ function loadProfessorCourses(container) {
<option value="archivado">Archivado</option> <option value="archivado">Archivado</option>
</select> </select>
<div class="action-buttons"> <div class="form-actions">
<button class="btn btn-success" type="submit">Guardar</button> <button type="button" class="btn btn-outline" id="cancelCourseBtn" style="display:none;">
<button class="btn btn-outline" type="button" id="cancelCourseBtn" style="display:none; margin-left:8px; background-color: #f44336;">
Cancelar Cancelar
</button> </button>
<button type="submit" class="btn">
<span id="submitCourseText">Guardar</span>
<span class="spinner-border spinner-border-sm" id="submitCourseSpinner" style="display:none;"></span>
</button>
</div> </div>
</form> </form>
</div> </div>
<div class="card"> <div class="card">
@ -435,7 +439,7 @@ function loadProfessorCourses(container) {
<td> <td>
<div class="action-buttons"> <div class="action-buttons">
<button class="btn btn-sm" onclick="editCourse(${course.id})">Editar</button> <button class="btn btn-sm" onclick="editCourse(${course.id})">Editar</button>
<button class="btn btn-sm btn-danger" onclick="deleteCourse(${course.id})">Eliminar</button> <button class="btn btn-sm btn-danger" onclick="confirmDeleteCourse(${course.id})">Eliminar</button>
</div> </div>
</td> </td>
</tr>`; </tr>`;
@ -483,6 +487,46 @@ function formatCourseType(type) {
return types[type] || type; return types[type] || type;
} }
window.createCourse = function (data, callback) {
fetch("api/cursos.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((res) => {
if (res.success) {
callback(true, "Curso creado correctamente");
} else {
callback(false, res.error || "Error al crear curso");
}
})
.catch(() => {
callback(false, "No se pudo conectar con el servidor");
});
};
window.updateCourse = function (id, data, callback) {
data.id = id;
fetch("api/cursos.php", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((res) => {
if (res.success) {
callback(true, "Curso actualizado correctamente");
} else {
callback(false, res.error || "Error al actualizar curso");
}
})
.catch(() => {
callback(false, "No se pudo conectar con el servidor");
});
};
function setupCourseForm() { function setupCourseForm() {
const courseTypeSelect = document.getElementById('courseType'); const courseTypeSelect = document.getElementById('courseType');
const competencesField = document.getElementById('competencesField'); const competencesField = document.getElementById('competencesField');
@ -509,19 +553,30 @@ function setupCourseForm() {
if (!form) return; if (!form) return;
const cancelBtn = document.getElementById("cancelCourseBtn"); const cancelBtn = document.getElementById("cancelCourseBtn");
const submitBtn = form.querySelector("button[type='submit']");
const submitText = document.getElementById("submitCourseText");
const spinner = document.getElementById("submitCourseSpinner");
if (cancelBtn) { if (cancelBtn) {
cancelBtn.addEventListener("click", function () { cancelBtn.addEventListener("click", function () {
form.reset(); form.reset();
competencesField.classList.add("oculto"); competencesField.classList.add("oculto");
form.dataset.editing = "false"; form.dataset.editing = "false";
delete form.dataset.courseId; delete form.dataset.courseId;
form.querySelector("button[type='submit']").textContent = "Guardar"; submitText.textContent = "Guardar";
spinner.style.display = "none";
submitBtn.disabled = false;
cancelBtn.style.display = "none"; cancelBtn.style.display = "none";
}); });
} }
form.addEventListener("submit", function (e) { form.addEventListener("submit", function (e) {
e.preventDefault(); e.preventDefault();
submitText.textContent = "Procesando...";
spinner.style.display = "inline-block";
submitBtn.disabled = true;
const formData = new FormData(this); const formData = new FormData(this);
const jsonData = { const jsonData = {
nombre: formData.get("nombre"), nombre: formData.get("nombre"),
@ -535,46 +590,26 @@ function setupCourseForm() {
const isEdit = form.dataset.editing === "true"; const isEdit = form.dataset.editing === "true";
const courseId = form.dataset.courseId; const courseId = form.dataset.courseId;
const callback = (success, message) => {
if (success) {
showToast("success", message);
showSection("courses");
} else {
showToast("error", message);
}
submitText.textContent = isEdit ? "Actualizar Curso" : "Guardar";
spinner.style.display = "none";
submitBtn.disabled = false;
};
if (isEdit) { if (isEdit) {
updateCourse(courseId, jsonData); updateCourse(courseId, jsonData, callback);
} else { } else {
createCourse(jsonData); createCourse(jsonData, callback);
} }
}); });
} }
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) { window.editCourse = function (id) {
fetch(`api/cursos.php?profesor_id=${getProfesorId()}`) fetch(`api/cursos.php?profesor_id=${getProfesorId()}`)
.then((response) => response.json()) .then((response) => response.json())
@ -609,19 +644,42 @@ window.editCourse = function (id) {
}; };
window.deleteCourse = function (id) { window.confirmDeleteCourse = function (id) {
if (!confirm("¿Estás seguro de eliminar este curso?")) return; showModal(
"Confirmar eliminación",
"¿Estás seguro de eliminar este curso? Esta acción no se puede deshacer.",
[
{
text: "Cancelar",
class: "btn-outline",
handler: "closeModal",
},
{
text: "Eliminar",
class: "btn-danger",
handler: `deleteCourse(${id})`,
},
]
);
};
window.deleteCourse = function (id) {
fetch(`api/cursos.php?id=${id}`, { fetch(`api/cursos.php?id=${id}`, {
method: "DELETE", method: "DELETE",
}) })
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
if (data.success) { if (data.success) {
showSection("courses"); showToast("success", "Curso eliminado correctamente");
closeModal();
loadProfessorCourses(document.querySelector("#courses-content"));
} else {
showToast("error", data.error || "No se pudo eliminar el curso");
} }
}) })
.catch((error) => console.error("Error:", error)); .catch((error) => {
showToast("error", "Error al eliminar el curso");
});
}; };
// Gestión de alumnos // Gestión de alumnos
@ -1240,7 +1298,7 @@ window.unassignStudent = async function (alumnoId, cursoId) {
function loadDiplomasSection(container) { function loadDiplomasSection(container) {
container.innerHTML = '<div class="loader">Cargando diplomas...</div>'; container.innerHTML = '<div class="loader">Cargando diplomas...</div>';
fetch(`api/diplomas.php?profesor_id=${getProfesorId()}`) fetch(`api/diploma.php?profesor_id=${getProfesorId()}`)
.then((response) => { .then((response) => {
if (!response.ok) throw new Error("Error en la respuesta del servidor"); if (!response.ok) throw new Error("Error en la respuesta del servidor");
return response.json(); return response.json();