import { MaterialIcon } from "@/components/ui/MaterialIcon"; import { MCQ_FORMATS } from "@/lib/question-formats"; interface McqOptionItem { key: string; text: string; } interface MatchingOptionItem { left: string; right?: string; } interface OptionDisplayProps { format: string; options: unknown; correctAnswer: string; userAnswer: string; } export function OptionDisplay({ format, options, correctAnswer, userAnswer }: OptionDisplayProps) { if (!Array.isArray(options) || options.length === 0) return null; if (format === "matching_pairs") { return ; } if (format === "true_false_not_given") { return ; } if (format === "author_view") { return ; } if ((MCQ_FORMATS as readonly string[]).includes(format)) { return ; } return null; } function McqOptions({ options, correctAnswer, userAnswer }: { options: { key: string; text: string }[]; correctAnswer: string; userAnswer: string }) { const normUser = userAnswer?.trim().toUpperCase() || ""; const normCorrect = correctAnswer?.trim().toUpperCase() || ""; const hasAnswer = !!userAnswer && userAnswer !== "Tidak dijawab"; return (
{options.map((opt) => { const key = opt.key.trim().toUpperCase(); const isCorrectOption = key === normCorrect; const isChosen = key === normUser && hasAnswer; const isWrongChoice = isChosen && !isCorrectOption; let bg = "bg-[var(--oat-light)]"; let keyBg = "bg-[var(--oat-light)] text-[var(--clay-black)]"; let border = "border-[var(--oat-border)]"; let icon = null; if (isWrongChoice) { bg = "bg-[var(--pomegranate-100)]"; keyBg = "bg-[var(--pomegranate-400)] text-[var(--pure-white)]"; border = "border-[var(--pomegranate-400)]"; icon = ; } else if (isCorrectOption) { bg = "bg-[var(--matcha-300)]/20"; keyBg = "bg-[var(--matcha-600)] text-[var(--pure-white)]"; border = "border-[var(--matcha-400)]"; icon = ; } return (
{key || "?"} {opt.text} {icon}
); })}
); } function TriStateOptions({ choices, labels, correctAnswer, userAnswer }: { choices: string[]; labels: Record; correctAnswer: string; userAnswer: string }) { const normUser = userAnswer?.trim().toUpperCase().replace(/\s+/g, "_") || ""; const normCorrect = correctAnswer?.trim().toUpperCase() || ""; const hasAnswer = !!userAnswer && userAnswer !== "Tidak dijawab"; return (
{choices.map((c) => { const isCorrectOption = c === normCorrect; const isChosen = c === normUser && hasAnswer; const isWrongChoice = isChosen && !isCorrectOption; let bg = "bg-[var(--oat-light)]"; let dot = "border-[var(--oat-border)]"; let textColor = "text-[var(--warm-charcoal)]"; if (isWrongChoice) { bg = "bg-[var(--pomegranate-100)]"; dot = "border-[var(--pomegranate-400)] bg-[var(--pomegranate-400)]"; textColor = "text-[var(--pomegranate-600)]"; } else if (isCorrectOption) { bg = "bg-[var(--matcha-300)]/20"; dot = "border-[var(--matcha-600)] bg-[var(--matcha-600)]"; textColor = "text-[var(--matcha-800)]"; } return (
{isChosen || isCorrectOption ? : null} {labels[c]}
); })}
); } function MatchingPairsOptions({ options, correctAnswer, userAnswer }: { options: MatchingOptionItem[]; correctAnswer: string; userAnswer: string }) { const parseMapping = (s: string): Map => { const map = new Map(); if (!s) return map; s.split(",").forEach((pair) => { const [k, v] = pair.split(":").map((x) => x.trim()); if (k && v) map.set(k, v); }); return map; }; const correctMap = parseMapping(correctAnswer); const userMap = parseMapping(userAnswer); return (
{options.map((opt) => { const matchedCorrect = correctMap.get(opt.left) || ""; const matchedUser = userMap.get(opt.left) || ""; const isMatchCorrect = matchedUser === matchedCorrect; const hasUserAnswer = !!matchedUser; return (
{opt.left.charAt(0).toUpperCase()} {opt.left} {hasUserAnswer && ( {matchedUser} )} {!isMatchCorrect && matchedCorrect && ( {matchedCorrect} )}
); })}
); }