const API_URL = "https://creditos-api.adrian-camelot32.workers.dev";
// Variables globales para la matriz
let globalEstudiantes = [];
let globalActividades = [];
// Elementos UI
const loginForm = document.getElementById('login-form');
const loginSection = document.getElementById('login-section');
const dashboardSection = document.getElementById('dashboard-section');
const loginError = document.getElementById('login-error');
const welcomeMsg = document.getElementById('welcome-msg');
const logoutBtn = document.getElementById('logout-btn');
const adminPanel = document.getElementById('admin-panel');
const tutorPanel = document.getElementById('tutor-panel');
const studentPanel = document.getElementById('student-panel');
const changePasswordPanel = document.getElementById('change-password-panel');
// Elementos Admin & Estudiante
const createUserForm = document.getElementById('create-user-form');
const createUserMsg = document.getElementById('create-user-msg');
const adminResetForm = document.getElementById('admin-reset-form');
const userChangePasswordForm = document.getElementById('user-change-password-form');
const creditosObtenidosEl = document.getElementById('creditos-obtenidos');
const creditosMetaEl = document.getElementById('creditos-meta');
// Elementos Tutor
const createActivityForm = document.getElementById('create-activity-form');
const setGoalForm = document.getElementById('set-goal-form');
const assignForm = document.getElementById('assign-activity-form');
const gruposBotones = document.getElementById('grupos-botones');
const matrizContainer = document.getElementById('matriz-container');
const matrizHeader = document.getElementById('matriz-header');
const matrizBody = document.getElementById('matriz-body');
const matrizTitulo = document.getElementById('matriz-titulo');
const btnGuardarMatriz = document.getElementById('btn-guardar-matriz');
const matrizMsg = document.getElementById('matriz-msg');
document.addEventListener("DOMContentLoaded", () => {
const token = localStorage.getItem('token');
const user = JSON.parse(localStorage.getItem('user'));
if (token && user) showDashboard(user);
});
document.getElementById('new-role').addEventListener('change', (e) => {
const s = document.getElementById('new-grupo'); s.innerHTML = '';
if (e.target.value === 'tutor') s.innerHTML = ``;
else if (e.target.value === 'student') s.innerHTML = ``;
});
async function loadTutorData(grado) {
let grupos = [];
if(grado === '4') grupos = ['4A','4B','4C'];
if(grado === '5') grupos = ['5A','5B','5C'];
if(grado === '6') grupos = ['6A','6B','6C','6D'];
document.getElementById('goal-grupo').innerHTML = '';
grupos.forEach(g => document.getElementById('goal-grupo').innerHTML += ``);
// Botones de Grupos para la Matriz
gruposBotones.innerHTML = '';
grupos.forEach(g => {
const btn = document.createElement('button');
btn.textContent = `Lista ${g}`;
btn.type = "button";
btn.style.padding = "0.6rem"; btn.style.background = "#17a2b8";
btn.onclick = () => renderMatriz(g);
gruposBotones.appendChild(btn);
});
try {
const resEst = await fetch(`${API_URL}/api/usuarios?grado=${grado}`);
globalEstudiantes = await resEst.json();
const estSelect = document.getElementById('assign-student');
estSelect.innerHTML = '';
globalEstudiantes.forEach(est => estSelect.innerHTML += ``);
const resAct = await fetch(`${API_URL}/api/actividades`);
globalActividades = await resAct.json();
const actSelect = document.getElementById('assign-activity');
actSelect.innerHTML = '';
globalActividades.forEach(act => actSelect.innerHTML += ``);
// Si la matriz está abierta, refrescarla
if (!matrizContainer.classList.contains('hidden')) {
const grupoActual = matrizTitulo.textContent.split(': ')[1];
if(grupoActual) renderMatriz(grupoActual);
}
} catch(e) { console.error(e); }
}
// ---------------- LÓGICA DE LA MATRIZ MASIVA ----------------
function renderMatriz(grupo) {
matrizContainer.classList.remove('hidden');
matrizTitulo.textContent = `Alumnos del Grupo: ${grupo}`;
// Generar Cabeceras (Las Actividades + Checkbox "Seleccionar Todo")
matrizHeader.innerHTML = '
Alumno | ';
globalActividades.forEach(act => {
matrizHeader.innerHTML += `
|
`;
});
// Generar Filas (Los Alumnos)
matrizBody.innerHTML = '';
const alumnosGrupo = globalEstudiantes.filter(e => e.grupo === grupo);
if(alumnosGrupo.length === 0) {
matrizBody.innerHTML = `| No hay alumnos. |
`;
return;
}
alumnosGrupo.forEach((alum, index) => {
const bg = index % 2 === 0 ? '#fff' : '#f9f9f9';
let tr = `
| ${alum.username} | `;
globalActividades.forEach(act => {
tr += `
| `;
});
tr += `
`;
matrizBody.innerHTML += tr;
});
}
// Función mágica para seleccionar/deseleccionar toda una columna
window.toggleColumna = function(checkboxCentral, actId) {
const checkboxesAlumnos = document.querySelectorAll(`.act-${actId}`);
checkboxesAlumnos.forEach(c => c.checked = checkboxCentral.checked);
};
// Guardar lo que esté chequeado en la Matriz
btnGuardarMatriz.addEventListener('click', async () => {
const checked = document.querySelectorAll('.chk-matriz:checked');
if (checked.length === 0) {
matrizMsg.textContent = "No has seleccionado ninguna casilla."; matrizMsg.className = "msg error";
return;
}
matrizMsg.textContent = "Enviando lote de asignaciones..."; matrizMsg.className = "msg";
const asignaciones = Array.from(checked).map(c => ({
student_id: parseInt(c.getAttribute('data-student')),
activity_id: parseInt(c.getAttribute('data-activity'))
}));
try {
const res = await fetch(`${API_URL}/api/asignaciones`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ asignaciones })
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || "Error al asignar");
matrizMsg.textContent = `¡Excelente! ${asignaciones.length} créditos asignados a los alumnos.`;
matrizMsg.classList.add('success');
// Limpiar todas las casillas tras guardar
document.querySelectorAll('input[type="checkbox"]').forEach(c => c.checked = false);
setTimeout(() => { matrizMsg.textContent = ""; }, 4000);
} catch (error) { matrizMsg.textContent = error.message; matrizMsg.classList.add('error'); }
});
// -------------------------------------------------------------
// FORMULARIOS CLÁSICOS RESTANTES
loginForm.addEventListener('submit', async (e) => {
e.preventDefault(); loginError.textContent = "Conectando...";
try {
const res = await fetch(`${API_URL}/api/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: document.getElementById('username').value.trim(), password: document.getElementById('password').value }) });
const data = await res.json(); if (!res.ok) throw new Error(data.error || "Error");
localStorage.setItem('token', data.token); localStorage.setItem('user', JSON.stringify(data.usuario));
showDashboard(data.usuario); loginForm.reset(); loginError.textContent = "";
} catch (error) { loginError.textContent = error.message; }
});
createActivityForm.addEventListener('submit', async (e) => {
e.preventDefault(); const user = JSON.parse(localStorage.getItem('user'));
try {
await fetch(`${API_URL}/api/actividades`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nombre_actividad: document.getElementById('actividad-nombre').value.trim(), creditos: parseInt(document.getElementById('actividad-creditos').value), created_by: user.id }) });
createActivityForm.reset(); loadTutorData(user.grupo);
document.getElementById('create-activity-msg').textContent = "¡Actividad registrada!"; setTimeout(() => { document.getElementById('create-activity-msg').textContent = ""; }, 3000);
} catch (error) {}
});
setGoalForm.addEventListener('submit', async (e) => {
e.preventDefault(); const user = JSON.parse(localStorage.getItem('user'));
try {
await fetch(`${API_URL}/api/metas`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grupo: document.getElementById('goal-grupo').value, creditos_objetivo: parseInt(document.getElementById('goal-creditos').value), set_by: user.id }) });
setGoalForm.reset(); document.getElementById('set-goal-msg').textContent = "¡Meta fijada!"; setTimeout(() => { document.getElementById('set-goal-msg').textContent = ""; }, 3000);
} catch (error) {}
});
assignForm.addEventListener('submit', async (e) => {
e.preventDefault();
try {
await fetch(`${API_URL}/api/asignaciones`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ student_id: document.getElementById('assign-student').value, activity_id: document.getElementById('assign-activity').value }) });
assignForm.reset(); document.getElementById('assign-msg').textContent = "¡Créditos asignados!"; setTimeout(() => { document.getElementById('assign-msg').textContent = ""; }, 3000);
} catch (error) {}
});
logoutBtn.addEventListener('click', () => {
localStorage.clear(); window.location.reload();
});
async function loadStudentData(user) {
document.getElementById('student-grupo-info').textContent = `Grupo: ${user.grupo}`;
try {
const data = await (await fetch(`${API_URL}/api/progreso?student_id=${user.id}&grupo=${user.grupo}`)).json();
creditosObtenidosEl.textContent = data.obtenidos; creditosMetaEl.textContent = data.meta;
document.getElementById('progress-bar').style.width = `${Math.min(data.meta > 0 ? (data.obtenidos / data.meta) * 100 : 0, 100)}%`;
const list = document.getElementById('historial-lista'); list.innerHTML = '';
if(data.historial.length === 0) list.innerHTML = 'No hay actividades registradas.';
else data.historial.forEach(i => list.innerHTML += `${i.nombre_actividad}+${i.creditos} pts`);
} catch(e) {}
}
function showDashboard(user) {
loginSection.classList.add('hidden'); dashboardSection.classList.remove('hidden');
welcomeMsg.textContent = `¡Hola, ${user.username}!`;
[adminPanel, tutorPanel, studentPanel, changePasswordPanel].forEach(p => p.classList.add('hidden'));
if (user.requires_password_change) changePasswordPanel.classList.remove('hidden');
if (user.role === 'admin') adminPanel.classList.remove('hidden');
else if (user.role === 'tutor') { tutorPanel.classList.remove('hidden'); document.getElementById('tutor-info').textContent = `Titular del Grado ${user.grupo}`; loadTutorData(user.grupo); }
else { studentPanel.classList.remove('hidden'); loadStudentData(user); }
}