import { fetchSubjectsMock as fetchSubjects, fetchProgressMock as fetchProgress, } from "./mock.js"; import { GraduationChange, fetchGraduation, submitGraduationChange } from "./graduation-ENV.js"; import { Student, fetchStudents } from "./student-ENV.js"; import { isTeacher as getIsTeacher } from "../../utils-ENV.js"; let isTeacher; let firstname; let lastname; let student; function initCurrentName() { const autoNameDiv = document.getElementById("auto-name"); firstname = autoNameDiv.children[0].innerHTML; lastname = autoNameDiv.children[1].innerHTML; autoNameDiv.remove(); } async function loadNewStudent(name, group) { student = new Student(0, name, group); await loadStudent(student); } async function loadStudent(studentToLoad) { student = studentToLoad; fetchAndUpdateStudentInfo(); updateStudentCalendar(); updateStudentProgress(); updateStudentGraduation(); } async function initStudentSelection() { const sel = document.getElementById("student-selection"); const list = document.getElementById('student-selection-list'); const noResults = document.getElementById('student-selection-noresults'); const clearBtn = document.getElementById('student-selection-clear'); const students = await fetchStudents(); let items = []; let currentFocus = -1; let visibleItems = []; function setActive() { visibleItems.forEach(item => item.classList.remove("active")); if (currentFocus >= 0 && visibleItems[currentFocus]) { visibleItems[currentFocus].classList.add("active"); } } for (const student of students) { let item = document.createElement("li"); item.student = student; item.innerHTML = `${student.name} ${student.group}`; item.style.display = 'none'; item.addEventListener('click', function() { sel.value = ""; sel.dispatchEvent(new Event('keyup')); loadStudent(student); }); list.appendChild(item); items.push(item); } sel.addEventListener('keyup', function(e) { if ((["ArrowDown", "ArrowUp", "Enter"]).includes(e.key)) return; const filter = sel.value.toLowerCase(); visibleItems = []; for (const item of items) { const itemText = item.textContent.trim().toLowerCase(); if (itemText.indexOf(filter) > -1 && filter !== "") { item.style.display = ""; visibleItems.push(item); // Highlight matched text const regex = new RegExp(`(${filter})`, 'gi'); item.innerHTML = item.textContent.replace( regex, "$1" ); } else { item.style.display = "none"; } } // Show the clear button if there is an input clearBtn.style.display = sel.value ? "block" : "none"; // Select the first or none if there are no items visible currentFocus = visibleItems.length ? 0 : -1; setActive(visibleItems); noResults.style.display = visibleItems.length || filter === "" ? "none" : "block"; }); clearBtn.addEventListener('click', function() { sel.value = ""; sel.dispatchEvent(new Event('keyup')); // reset list sel.focus(); }); sel.addEventListener('keydown', function(e) { if (e.key === "ArrowDown" || e.key === "ArrowUp") { if(e.key === "ArrowDown") currentFocus = (currentFocus + 1) % visibleItems.length; else currentFocus = (currentFocus - 1 + visibleItems.length) % visibleItems.length; setActive(); e.preventDefault(); } else if (e.key === "Enter") { if (currentFocus > -1 && visibleItems[currentFocus]) { const visibleItem = visibleItems[currentFocus]; sel.value = ""; sel.dispatchEvent(new Event('keyup')); loadStudent(visibleItem.student); } e.preventDefault(); } }); } function pointClickHandler(color) { const textareaDiv = document.getElementById("student-info-point-reason-container"); const textarea = document.getElementById("student-info-point-reason"); const submitBtn = document.getElementById("student-info-point-reason-submit"); // TODO(muhq): Prefill the textarea with common reasons switch (color) { case "green": textarea.style.background = "rgb(from green r g b / 20%)" textarea.value = ""; break; case "orange": textarea.style.background = "rgb(from orange r g b / 20%)" textarea.value = ""; break; case "red": textarea.style.background = "rgb(from red r g b / 20%)" textarea.value = ""; break; } textareaDiv.style.display = "block"; textarea.focus(); // Can not use string interpolation because of Moodle's firstname filter. const coach = firstname + " " + lastname; let submit = function() { let change; switch (color) { case "green": change = GraduationChange.newGreenPointChange(student, textarea.value, coach); break; case "orange": change = GraduationChange.newOrangePointChange(student, textarea.value, coach); break; case "red": change = GraduationChange.newRedPointChange(student, textarea.value, coach); break; default: alert("Invalid color"); break; } submitGraduationChange(student, change); textareaDiv.style.display = "none"; updateStudentInfo(); } // Use onEVENT to override any previous handler textarea.onkeydown = function(e) { if (e.shiftKey && e.key === "Enter") { submit(); } if (e.key === "Escape") { textareaDiv.style.display = "none"; } }; submitBtn.onclick = submit; } async function fetchAndUpdateStudentInfo() { student.graduation = await fetchGraduation(student); updateStudentInfo(); } let DEFAULT_STUDENT_ICON; function updateStudentInfo() { // Reset the student icon document.getElementById("student-info-icon").src = DEFAULT_STUDENT_ICON; // Try to replace the generic icon with the user's icon var img = document.createElement('img'); img.onload = function() { document.getElementById("student-info-icon").src = img.src; img = img.onload = null; }; student.getIconUrl().then( (url) => img.src = url ); document.getElementById("student-info-name").innerHTML = `${student.name}`; if (student.graduation) { const tag = document.getElementById("student-info-tag"); tag.innerHTML = student.graduation.level; tag.style.display = "block"; document.getElementById("student-info-green").addEventListener('click', () => pointClickHandler("green")); document.getElementById("student-info-points-green").innerHTML = student.graduation.green; document.getElementById("student-info-orange").addEventListener('click', () => pointClickHandler("orange")); document.getElementById("student-info-points-orange").innerHTML = student.graduation.orange; document.getElementById("student-info-red").addEventListener('click', () => pointClickHandler("red")); document.getElementById("student-info-points-red").innerHTML = student.graduation.red; renderGraduationLevel(student.graduation, document.getElementById("student-info-level")); renderGraduationStickers(student.graduation, document.getElementById("student-info-stickers")); renderGraduationBonus(student.graduation, document.getElementById("student-info-stickers")); } document.getElementById("student-content").style.display = "block"; } function renderGraduationLevel(graduation, node) { node.innerHTML = graduation.level; } function renderGraduationStickers(graduation, node) { } function renderGraduationBonus(graduation, node) { } function newProgressBar(subject) { let bar = document.createElement("div"); fetchProgress(subject).then((progress) => { bar.progress = progress; }); let s1 = document.createElement("div"); s1.onhover bar.appendChild(s1); let s2 = document.createElement("div"); bar.appendChild(s2); let s3 = document.createElement("div"); bar.appendChild(s3); return bar; } let selectedSubjects; async function updateStudentProgress() { selectedSubjects = await fetchSubjects(student); let prog = document.getElementById("progress"); for(const subj of selectedSubjects) { let subjDiv = document.createElement("div"); subjDiv.innerHTML = subj; subjDiv.appendChild(newProgressBar(subj)) prog.appendChild(subjDiv); } } async function updateStudentCalendar() { let cal = document.getElementById("calendar"); } async function updateStudentGraduation() { let graduation = document.getElementById("graduation"); } async function initCockpit() { if (isTeacher) { await initStudentSelection(); } else { loadNewStudent(`${firstname} ${lastname}`); } return; } window.onload = function() { isTeacher = getIsTeacher(); DEFAULT_STUDENT_ICON = document.getElementById("student-info-icon").src; initCurrentName(); initCockpit(isTeacher); }