Arreglo en cursos y alumnos

This commit is contained in:
Christopher Alessandro Rodriguez Salazar 2025-06-19 16:29:00 -06:00
parent ed9bd3dd85
commit 703794f542
3 changed files with 117 additions and 43 deletions

View File

@ -122,31 +122,7 @@ switch ($method) {
$data['id']
]);
// Verificar si el estado nuevo es "completado" y generar diplomas
if ($data['estado'] === 'completado') {
// 1. Obtener todos los alumnos_cursos para ese curso
$stmtAC = $pdo->prepare("SELECT id FROM alumnos_cursos WHERE curso_id = ? AND estado IN ('cursando','aprobado')");
$stmtAC->execute([$data['id']]);
$alumnosCursos = $stmtAC->fetchAll(PDO::FETCH_ASSOC);
// 2. Preparar inserción si no existe diploma para ese alumno_curso
$stmtInsert = $pdo->prepare("
INSERT IGNORE INTO diplomas (alumno_curso_id, codigo_unico, fecha_emision)
VALUES (?, ?, NOW())
");
file_put_contents("debug_diplomas.log", "Curso completado: {$data['id']}\n", FILE_APPEND);
file_put_contents("debug_diplomas.log", print_r($alumnosCursos, true), FILE_APPEND);
foreach ($alumnosCursos as $ac) {
$codigo = substr(md5(uniqid($ac['id'], true)), 0, 12);
$stmtInsert->execute([$ac['id'], $codigo]);
}
}
echo json_encode(['success' => true]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Error al actualizar curso']);

View File

@ -998,3 +998,18 @@ textarea {
cursor: pointer;
}
/* Espaciado entre el título "Mis Cursos" y el formulario */
#courses-content h2 + form,
#courses-content h2 + #courseForm {
margin-top: 1.5rem;
}
/* Reducir el tamaño de letra del textarea de descripción */
#courses-content textarea[name="descripcion"] {
font-size: 0.95rem;
}
textarea[name="descripcion"] {
resize: none;
overflow-y: hidden;
}

View File

@ -381,18 +381,17 @@ function loadProfessorCourses(container) {
<label>Estado</label>
<select name="estado">
<option value="activo">Activo</option>
<option value="completado">Completado</option>
<option value="archivado">Archivado</option>
</select>
<div class="form-actions">
<button type="button" class="btn btn-outline" id="cancelCourseBtn" style="display:none;">
Cancelar
</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>
<button type="button" class="btn btn-outline" id="cancelCourseBtn" style="display:none;">
Cancelar
</button>
</div>
</form>
@ -557,19 +556,64 @@ function setupCourseForm() {
const submitText = document.getElementById("submitCourseText");
const spinner = document.getElementById("submitCourseSpinner");
if (cancelBtn) {
cancelBtn.addEventListener("click", function () {
form.reset();
competencesField.classList.add("oculto");
form.dataset.editing = "false";
delete form.dataset.courseId;
submitText.textContent = "Guardar";
spinner.style.display = "none";
submitBtn.disabled = false;
cancelBtn.style.display = "none";
// Cargar dinámicamente opciones del select de estado
const estadoSelect = form.querySelector('select[name="estado"]');
if (estadoSelect) {
estadoSelect.innerHTML = "";
const opcionesBase = [
{ value: "activo", label: "Activo" },
{ value: "archivado", label: "Archivado" }
];
const isEdit = form.dataset.editing === "true";
if (isEdit) {
opcionesBase.push({ value: "completado", label: "Completado" });
}
opcionesBase.forEach(opt => {
const option = document.createElement("option");
option.value = opt.value;
option.textContent = opt.label;
estadoSelect.appendChild(option);
});
}
// ✅ Botón Cancelar: volver a modo "Crear"
if (cancelBtn) {
cancelBtn.addEventListener("click", function () {
form.reset();
form.dataset.editing = "false";
delete form.dataset.courseId;
submitText.textContent = "Guardar";
spinner.style.display = "none";
submitBtn.disabled = false;
cancelBtn.style.display = "none";
// Restaurar opciones del select estado
if (estadoSelect) {
estadoSelect.innerHTML = "";
["activo", "archivado"].forEach(val => {
const opt = document.createElement("option");
opt.value = val;
opt.textContent = val.charAt(0).toUpperCase() + val.slice(1);
estadoSelect.appendChild(opt);
});
}
// 🔄 Forzar reactivación lógica por cambio de tipo de curso
const tipoCurso = document.getElementById("courseType");
if (tipoCurso) {
tipoCurso.value = "inyeccion"; // por defecto
tipoCurso.dispatchEvent(new Event("change")); // 👈 esto ejecuta tu lógica oculta
}
// Restaurar orden visual de los botones
const actions = form.querySelector(".form-actions");
if (actions) actions.appendChild(cancelBtn);
});
}
// Envío del formulario
form.addEventListener("submit", function (e) {
e.preventDefault();
@ -597,7 +641,7 @@ function setupCourseForm() {
} else {
showToast("error", message);
}
submitText.textContent = isEdit ? "Actualizar Curso" : "Guardar";
submitText.textContent = "Guardar";
spinner.style.display = "none";
submitBtn.disabled = false;
};
@ -608,6 +652,17 @@ function setupCourseForm() {
createCourse(jsonData, callback);
}
});
// Autoajuste dinámico del campo Descripción
const descripcionTextarea = form.querySelector('textarea[name="descripcion"]');
if (descripcionTextarea) {
const autoResize = () => {
descripcionTextarea.style.height = "auto";
descripcionTextarea.style.height = descripcionTextarea.scrollHeight + "px";
};
descripcionTextarea.addEventListener("input", autoResize);
autoResize();
}
}
window.editCourse = function (id) {
@ -621,8 +676,8 @@ window.editCourse = function (id) {
form.nombre.value = course.nombre;
form.descripcion.value = course.descripcion || "";
form.tipo.value = course.tipo;
form.estado.value = course.estado || "activo";
// 🟦 Mostrar/ocultar campo de competencias según tipo
const competencesField = document.getElementById("competencesField");
const competenciasInput = competencesField.querySelector('input[name="competencias"]');
if (course.tipo === "tratamiento") {
@ -635,15 +690,43 @@ window.editCourse = function (id) {
competenciasInput.required = false;
}
// 🟦 Cargar opciones de estado incluyendo "completado"
const estadoSelect = form.querySelector('select[name="estado"]');
if (estadoSelect) {
estadoSelect.innerHTML = "";
const opciones = [
{ value: "activo", label: "Activo" },
{ value: "archivado", label: "Archivado" },
{ value: "completado", label: "Completado" }
];
opciones.forEach(opt => {
const option = document.createElement("option");
option.value = opt.value;
option.textContent = opt.label;
estadoSelect.appendChild(option);
});
estadoSelect.value = course.estado || "activo";
}
// 🟦 Marcar modo edición
form.dataset.editing = "true";
form.dataset.courseId = id;
form.querySelector("button[type='submit']").textContent = "Actualizar Curso";
document.getElementById("cancelCourseBtn").style.display = "inline-block";
// ✅ Solo actualizamos el texto del span, no todo el botón
const submitText = document.getElementById("submitCourseText");
if (submitText) submitText.textContent = "Actualizar";
// ✅ Mostrar el botón de cancelar
const cancelBtn = document.getElementById("cancelCourseBtn");
if (cancelBtn) cancelBtn.style.display = "inline-block";
form.scrollIntoView({ behavior: "smooth" });
});
};
window.confirmDeleteCourse = function (id) {
showModal(
"Confirmar eliminación",