From 60bfe3ca4a3bc0ec08cef4592ab5820aa36f54c4 Mon Sep 17 00:00:00 2001 From: Nate Emmert Date: Sat, 1 Aug 2026 16:57:52 -0400 Subject: [PATCH] Add instructions field to quiz and matching item types Instructions are optional free text shown to the student above the questions/word bank. Admin enters them in the item editor; stored in items.body for quiz and matching types. Co-Authored-By: Claude Sonnet 4.6 --- public/admin.html | 10 ++++++++-- public/admin.js | 14 ++++++++++++-- public/app.js | 6 ++++++ public/index.html | 1 + public/styles.css | 8 ++++++++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/public/admin.html b/public/admin.html index d955908..639ce23 100644 --- a/public/admin.html +++ b/public/admin.html @@ -226,7 +226,10 @@
-
+ +
@@ -236,7 +239,10 @@
-

Enter word-clue pairs. Words are shown as A, B, C… (alphabetical order) in the word bank.

+ +

Enter word-clue pairs. Words are shown as A, B, C… (alphabetical order) in the word bank.

diff --git a/public/admin.js b/public/admin.js index ae459f3..d0b3daa 100644 --- a/public/admin.js +++ b/public/admin.js @@ -406,8 +406,12 @@ async function openItemEditor(unitId, itemId) { $('#ie-retake-policy').value = item.retake_policy || 'latest'; if (item.type === 'spelling_practice' || item.type === 'spelling_test') $('#ie-list').value = item.ref_id; if (item.type === 'flashcards') $('#ie-deck').value = item.ref_id; - if (item.type === 'quiz') (item.questions || []).forEach(addQuestionRow); + if (item.type === 'quiz') { + $('#ie-quiz-instructions').value = item.body || ''; + (item.questions || []).forEach(addQuestionRow); + } if (item.type === 'matching') { + $('#ie-matching-instructions').value = item.body || ''; $('#ie-pairs').innerHTML = ''; pairCount = 0; (item.questions || []).forEach(addMatchingRow); @@ -425,6 +429,8 @@ async function openItemEditor(unitId, itemId) { $('#ie-title').value = ''; $('#ie-body-lesson').innerHTML = ''; $('#ie-body-assignment').innerHTML = ''; + $('#ie-quiz-instructions').value = ''; + $('#ie-matching-instructions').value = ''; $('#ie-points').value = 10; $('#ie-due-date').value = ''; $('#ie-allow-retakes').checked = false; @@ -713,7 +719,11 @@ $('#item-form').addEventListener('submit', async (e) => { unitId: Number($('#ie-unit-id').value), type, title, - body: type === 'lesson' ? getLessonBody() : type === 'assignment' ? getAssignmentBody() : '', + body: type === 'lesson' ? getLessonBody() + : type === 'assignment' ? getAssignmentBody() + : type === 'quiz' ? $('#ie-quiz-instructions').value.trim() + : type === 'matching' ? $('#ie-matching-instructions').value.trim() + : '', points: type === 'assignment' ? Number($('#ie-points').value) || 0 : 0, refId: type === 'spelling_practice' || type === 'spelling_test' ? Number($('#ie-list').value) : type === 'flashcards' ? Number($('#ie-deck').value) : null, diff --git a/public/app.js b/public/app.js index f1a1556..b121a05 100644 --- a/public/app.js +++ b/public/app.js @@ -771,6 +771,9 @@ async function openQuiz(itemId, forceRetake = false) { const item = await api(`/api/items/${itemId}?studentId=${currentStudent.id}`); $('#quiz-kicker').textContent = `${item.course_name} · ${item.unit_name}`; $('#quiz-title').textContent = item.title; + const instrEl = $('#quiz-instructions'); + if (item.body) { instrEl.textContent = item.body; instrEl.hidden = false; } + else instrEl.hidden = true; const graded = !forceRetake && item.submission && item.submission.status === 'graded'; const result = $('#quiz-result'); @@ -865,6 +868,9 @@ async function openMatching(itemId, forceRetake = false) { const item = await api(`/api/items/${itemId}?studentId=${currentStudent.id}`); $('#quiz-kicker').textContent = `${item.course_name} · ${item.unit_name}`; $('#quiz-title').textContent = item.title; + const instrEl = $('#quiz-instructions'); + if (item.body) { instrEl.textContent = item.body; instrEl.hidden = false; } + else instrEl.hidden = true; const graded = !forceRetake && item.submission && item.submission.status === 'graded'; const result = $('#quiz-result'); diff --git a/public/index.html b/public/index.html index dd208f4..0e7f359 100644 --- a/public/index.html +++ b/public/index.html @@ -135,6 +135,7 @@

+
diff --git a/public/styles.css b/public/styles.css index e86b34a..8df9577 100644 --- a/public/styles.css +++ b/public/styles.css @@ -830,6 +830,14 @@ body.theme-indigo { --accent: #5b6abf; --accent-dark: #4a57a0; --bg: #f4f5ff; } font-size: 1.05rem; } +/* ---------- quiz / matching instructions ---------- */ +.quiz-instructions { + background: var(--bg); border-left: 3px solid var(--accent); + border-radius: 6px; padding: 0.55rem 0.9rem; + font-size: 0.95rem; color: var(--ink); + margin-bottom: 1rem; text-align: left; +} + /* ---------- matching quiz ---------- */ .match-word-bank { background: var(--bg); border: 2px solid var(--accent);