From 535434421a5954aa15664c02a6036ec93a5933c2 Mon Sep 17 00:00:00 2001 From: LaurensBartelds Date: Tue, 21 Apr 2026 21:38:58 +0200 Subject: [PATCH] feat: add MultipleChoice and MultipleSelect renderers --- .../components/questions/MultipleChoice.tsx | 40 +++++++++++++++++++ .../components/questions/MultipleSelect.tsx | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 frontend/src/components/questions/MultipleChoice.tsx create mode 100644 frontend/src/components/questions/MultipleSelect.tsx diff --git a/frontend/src/components/questions/MultipleChoice.tsx b/frontend/src/components/questions/MultipleChoice.tsx new file mode 100644 index 0000000..39d7c66 --- /dev/null +++ b/frontend/src/components/questions/MultipleChoice.tsx @@ -0,0 +1,40 @@ +import Tex from '../Tex' +import type { Question } from '../../types' + +interface Props { + q: Question + value: string | null | undefined + onChange: (val: string) => void + locked?: boolean + graded?: boolean +} + +export default function MultipleChoice({ q, value, onChange, locked, graded }: Props) { + return ( +
+ {(q.choices ?? []).map((c, i) => { + const isSelected = value === c.id + let cls = 'choice' + if (isSelected) cls += ' selected' + if (graded) { + if (c.id === q.answer) cls += ' correct' + else if (isSelected) cls += ' wrong' + } + return ( + + ) + })} +
+ ) +} diff --git a/frontend/src/components/questions/MultipleSelect.tsx b/frontend/src/components/questions/MultipleSelect.tsx new file mode 100644 index 0000000..d9046f8 --- /dev/null +++ b/frontend/src/components/questions/MultipleSelect.tsx @@ -0,0 +1,40 @@ +import Tex from '../Tex' +import type { Question } from '../../types' + +interface Props { + q: Question + value: string[] | null | undefined + onChange: (val: string[]) => void + locked?: boolean + graded?: boolean +} + +export default function MultipleSelect({ q, value, onChange, locked, graded }: Props) { + const current = value ?? [] + const toggle = (id: string) => { + if (locked) return + onChange(current.includes(id) ? current.filter((v) => v !== id) : [...current, id]) + } + const answerSet = new Set((q.answer as string[]) ?? []) + + return ( +
+ {(q.choices ?? []).map((c, i) => { + const isSelected = current.includes(c.id) + let cls = 'choice' + if (isSelected) cls += ' selected' + if (graded) { + if (answerSet.has(c.id)) cls += ' correct' + else if (isSelected) cls += ' wrong' + } + return ( + + ) + })} +
+ ) +}