100 lines
3.8 KiB
JavaScript
100 lines
3.8 KiB
JavaScript
import { sendJson } from './api.js';
|
|
import { renderQuizQuestions, renderQuizResultExplanations } from './quizRenderer.js';
|
|
|
|
export function createQuizController(deps) {
|
|
function renderQuiz(questions) {
|
|
var container = document.getElementById('lh-quiz-questions');
|
|
var countEl = document.getElementById('lh-quiz-count');
|
|
if (!container) return;
|
|
if (countEl) countEl.textContent = questions.length + ' question' + (questions.length !== 1 ? 's' : '');
|
|
|
|
container.innerHTML = renderQuizQuestions(questions);
|
|
}
|
|
|
|
function submitQuiz() {
|
|
var currentContent = deps.getCurrentContent();
|
|
if (!currentContent || !currentContent.questions) return;
|
|
|
|
var answers = buildQuizAnswers(currentContent.questions);
|
|
deps.showLoading('Submitting quiz...');
|
|
|
|
sendJson('/api/learning/submit-quiz', 'POST', { contentId: currentContent.id, answers: answers })
|
|
.then(function(data) {
|
|
deps.hideLoading();
|
|
if (!data.success) { deps.showToast(data.error || 'Submit failed', 'error'); return; }
|
|
showQuizResults(data);
|
|
})
|
|
.catch(function() { deps.hideLoading(); deps.showToast('Submit failed', 'error'); });
|
|
}
|
|
|
|
function showQuizResults(data) {
|
|
var resultsEl = document.getElementById('lh-quiz-results');
|
|
var scoreEl = document.getElementById('lh-quiz-score');
|
|
var explEl = document.getElementById('lh-quiz-explanations');
|
|
if (!resultsEl) return;
|
|
|
|
resultsEl.classList.remove('hidden');
|
|
var pct = data.percentage;
|
|
var color = pct >= 80 ? 'var(--green)' : pct >= 50 ? 'var(--amber)' : 'var(--red)';
|
|
if (scoreEl) {
|
|
scoreEl.textContent = data.score + '/' + data.total + ' (' + pct + '%)';
|
|
scoreEl.style.background = color;
|
|
scoreEl.style.color = 'white';
|
|
}
|
|
|
|
if (explEl) explEl.innerHTML = renderQuizResultExplanations(data.results);
|
|
applyQuizResultHighlights(data.results || []);
|
|
|
|
var submitBtn = document.getElementById('lh-submit-quiz');
|
|
if (submitBtn) { submitBtn.disabled = true; submitBtn.innerHTML = '<i class="fas fa-check"></i> Submitted'; }
|
|
|
|
resultsEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
}
|
|
|
|
return {
|
|
renderQuiz: renderQuiz,
|
|
submitQuiz: submitQuiz
|
|
};
|
|
}
|
|
|
|
export function buildQuizAnswers(questions, root) {
|
|
root = root || document;
|
|
var answers = [];
|
|
|
|
(questions || []).forEach(function(q) {
|
|
if (q.question_type === 'multi') {
|
|
var checkedEls = root.querySelectorAll('input[name="lh-qm-' + q.id + '"]:checked');
|
|
var optionIds = [];
|
|
checkedEls.forEach(function(el) { optionIds.push(parseInt(el.value)); });
|
|
answers.push({ questionId: q.id, optionIds: optionIds });
|
|
} else {
|
|
var selected = root.querySelector('input[name="lh-q-' + q.id + '"]:checked');
|
|
answers.push({ questionId: q.id, optionId: selected ? parseInt(selected.value) : null });
|
|
}
|
|
});
|
|
|
|
return answers;
|
|
}
|
|
|
|
function applyQuizResultHighlights(results) {
|
|
results.forEach(function(r) {
|
|
var qDiv = document.querySelector('.lh-quiz-q[data-qid="' + r.questionId + '"]');
|
|
if (!qDiv) return;
|
|
var isMulti = r.questionType === 'multi';
|
|
qDiv.querySelectorAll('.lh-quiz-option').forEach(function(label) {
|
|
var input = label.querySelector('input');
|
|
if (!input) return;
|
|
var optId = parseInt(input.value);
|
|
if (isMulti) {
|
|
var correctIds = r.correctOptionIds || [];
|
|
var selectedIds = r.selectedOptionIds || [];
|
|
if (correctIds.indexOf(optId) !== -1) label.classList.add('lh-opt-correct');
|
|
if (selectedIds.indexOf(optId) !== -1 && correctIds.indexOf(optId) === -1) label.classList.add('lh-opt-wrong');
|
|
} else {
|
|
if (optId === r.correctOptionId) label.classList.add('lh-opt-correct');
|
|
if (optId === r.selectedOptionId && !r.isCorrect) label.classList.add('lh-opt-wrong');
|
|
}
|
|
input.disabled = true;
|
|
});
|
|
});
|
|
}
|