vault backup: 2025-12-22 13:19:11
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m27s
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m27s
This commit is contained in:
@@ -1,49 +1,19 @@
|
||||
{% if show_answer %}
|
||||
<div class="answer-feedback {% if is_correct %}correct{% else %}incorrect{% endif %}">
|
||||
{% if is_correct %}
|
||||
✓ Rätt svar!
|
||||
{% else %}
|
||||
✗ Fel svar. Rätt svar är: {{ question.correct_answer }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% csrf_token %}
|
||||
<input type="hidden" id="current-question-id" value="{{ question.id }}">
|
||||
|
||||
<div class="question-text">{{ question.text }}</div>
|
||||
|
||||
<div class="options-container">
|
||||
{% for option in question.options.all %}
|
||||
<div class="option-item" id="option-{{ option.letter }}"
|
||||
onclick="selectOption('{{ option.letter }}', {{ question.id }}, {{ session.id }})">
|
||||
<div class="option-item" id="option-{{ option.letter }}" onclick="toggleOption('{{ option.letter }}')">
|
||||
<input type="checkbox" id="checkbox-{{ option.letter }}\" value="{{ option.letter }}"
|
||||
style="margin-right: 0.5rem; width: 1.2rem; height: 1.2rem; cursor: pointer;">
|
||||
<span class="option-letter">{{ option.letter }}</span>
|
||||
<span>{{ option.text }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if show_answer %}
|
||||
<div class="difficulty-section">
|
||||
<div class="difficulty-label">Hur svårt var detta?</div>
|
||||
<div class="difficulty-buttons">
|
||||
<button class="difficulty-btn again" onclick="submitDifficulty('again', {{ question.id }}, {{ session.id }})">
|
||||
<div>Igen</div>
|
||||
<small style="font-size: 0.75rem; font-weight: 400;"><1m</small>
|
||||
</button>
|
||||
<button class="difficulty-btn hard" onclick="submitDifficulty('hard', {{ question.id }}, {{ session.id }})">
|
||||
<div>Svårt</div>
|
||||
<small style="font-size: 0.75rem; font-weight: 400;"><6m</small>
|
||||
</button>
|
||||
<button class="difficulty-btn good" onclick="submitDifficulty('good', {{ question.id }}, {{ session.id }})">
|
||||
<div>Bra</div>
|
||||
<small style="font-size: 0.75rem; font-weight: 400;"><10m</small>
|
||||
</button>
|
||||
<button class="difficulty-btn easy" onclick="submitDifficulty('easy', {{ question.id }}, {{ session.id }})">
|
||||
<div>Lätt</div>
|
||||
<small style="font-size: 0.75rem; font-weight: 400;">4d</small>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="nav-buttons">
|
||||
<button class="nav-btn" {% if not has_previous %}disabled{% endif %}
|
||||
onclick="navigateQuestion('previous', {{ session.id }})">
|
||||
@@ -53,55 +23,4 @@
|
||||
onclick="navigateQuestion('next', {{ session.id }})">
|
||||
Nästa →
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let selectedAnswer = null;
|
||||
|
||||
function selectOption(letter, questionId, sessionId) {
|
||||
{% if show_answer %}
|
||||
return; // Don't allow changing answer after submission
|
||||
{% endif %}
|
||||
|
||||
selectedAnswer = letter;
|
||||
|
||||
// Visual feedback
|
||||
document.querySelectorAll('.option-item').forEach(opt => {
|
||||
opt.style.borderColor = 'var(--border)';
|
||||
opt.style.background = 'white';
|
||||
});
|
||||
|
||||
const selected = document.getElementById('option-' + letter);
|
||||
selected.style.borderColor = 'var(--primary)';
|
||||
selected.style.background = '#f0f4ff';
|
||||
|
||||
// Submit answer
|
||||
htmx.ajax('POST', `/submit/${sessionId}/`, {
|
||||
target: '#quiz-content',
|
||||
values: {
|
||||
question_id: questionId,
|
||||
answer: letter
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function submitDifficulty(difficulty, questionId, sessionId) {
|
||||
htmx.ajax('POST', `/difficulty/${sessionId}/`, {
|
||||
values: {
|
||||
question_id: questionId,
|
||||
difficulty: difficulty
|
||||
}
|
||||
});
|
||||
|
||||
// Move to next question after a brief delay
|
||||
setTimeout(() => {
|
||||
navigateQuestion('next', sessionId);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function navigateQuestion(direction, sessionId) {
|
||||
htmx.ajax('GET', `/quiz/${sessionId}/${direction}/`, {
|
||||
target: '#quiz-content'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
@@ -52,6 +52,8 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option-item:hover {
|
||||
@@ -70,78 +72,7 @@
|
||||
text-align: center;
|
||||
line-height: 2rem;
|
||||
font-weight: 700;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.difficulty-section {
|
||||
margin-top: 2rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.difficulty-label {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.difficulty-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.difficulty-btn {
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 2px solid var(--border);
|
||||
background: white;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.difficulty-btn.again {
|
||||
border-color: #ef4444;
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.difficulty-btn.again:hover {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.difficulty-btn.hard {
|
||||
border-color: #f59e0b;
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.difficulty-btn.hard:hover {
|
||||
background: #f59e0b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.difficulty-btn.good {
|
||||
border-color: #10b981;
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.difficulty-btn.good:hover {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.difficulty-btn.easy {
|
||||
border-color: #6366f1;
|
||||
color: #6366f1;
|
||||
}
|
||||
|
||||
.difficulty-btn.easy:hover {
|
||||
background: #6366f1;
|
||||
color: white;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-buttons {
|
||||
@@ -169,25 +100,6 @@
|
||||
background: #cbd5e1;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.answer-feedback {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.answer-feedback.correct {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
border: 2px solid #10b981;
|
||||
}
|
||||
|
||||
.answer-feedback.incorrect {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
border: 2px solid #ef4444;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="quiz-mode-container">
|
||||
@@ -202,9 +114,82 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Load first question on page load
|
||||
const SESSION_ID = parseInt("{{ session.id }}");
|
||||
|
||||
function saveAnswer(questionId, selectedLetters) {
|
||||
const key = 'quiz_' + SESSION_ID + '_answers';
|
||||
const answers = JSON.parse(localStorage.getItem(key) || '{}');
|
||||
answers[questionId] = selectedLetters;
|
||||
localStorage.setItem(key, JSON.stringify(answers));
|
||||
}
|
||||
|
||||
function loadAnswer(questionId) {
|
||||
const key = 'quiz_' + SESSION_ID + '_answers';
|
||||
const answers = JSON.parse(localStorage.getItem(key) || '{}');
|
||||
return answers[questionId] || [];
|
||||
}
|
||||
|
||||
function toggleOption(letter) {
|
||||
const checkbox = document.getElementById('checkbox-' + letter);
|
||||
const optionDiv = document.getElementById('option-' + letter);
|
||||
|
||||
if (!checkbox || !optionDiv) return;
|
||||
|
||||
checkbox.checked = !checkbox.checked;
|
||||
|
||||
if (checkbox.checked) {
|
||||
optionDiv.style.borderColor = 'var(--primary)';
|
||||
optionDiv.style.background = '#f0f4ff';
|
||||
} else {
|
||||
optionDiv.style.borderColor = 'var(--border)';
|
||||
optionDiv.style.background = 'white';
|
||||
}
|
||||
|
||||
const questionId = document.getElementById('current-question-id').value;
|
||||
const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked');
|
||||
const selectedLetters = Array.from(checkboxes).map(cb => cb.value).sort();
|
||||
saveAnswer(questionId, selectedLetters);
|
||||
}
|
||||
|
||||
function restoreAnswers() {
|
||||
const questionId = document.getElementById('current-question-id')?.value;
|
||||
if (!questionId) return;
|
||||
|
||||
const saved = loadAnswer(questionId);
|
||||
saved.forEach(letter => {
|
||||
const checkbox = document.getElementById('checkbox-' + letter);
|
||||
const optionDiv = document.getElementById('option-' + letter);
|
||||
if (checkbox && optionDiv) {
|
||||
checkbox.checked = true;
|
||||
optionDiv.style.borderColor = 'var(--primary)';
|
||||
optionDiv.style.background = '#f0f4ff';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function navigateQuestion(direction, sessionId) {
|
||||
const currentQInput = document.getElementById('current-question-id');
|
||||
const currentQ = currentQInput ? currentQInput.value : null;
|
||||
const url = currentQ
|
||||
? '/quiz/' + sessionId + '/' + direction + '/?q=' + currentQ
|
||||
: '/quiz/' + sessionId + '/' + direction + '/';
|
||||
|
||||
htmx.ajax('GET', url, {
|
||||
target: '#quiz-content'
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
restoreAnswers();
|
||||
});
|
||||
observer.observe(document.getElementById('quiz-content'), {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
htmx.ajax('GET', '{% url 'quiz_question' session.id %}', { target: '#quiz-content' });
|
||||
setTimeout(restoreAnswers, 100);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user