Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 7x 6x 6x 6x 6x 7x 9x 9x 9x 9x 9x 6x 6x 6x 9x 7x 8x 8x 8x 8x 9x 9x 8x | import { Box, Typography } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import React, { memo } from "react";
import TinyMCETextEditorReadOnly from "@/utils/components/TinyMCETextEditorReadOnly";
import {
inlineSelectBlankColors,
questionCardSurfaceBg,
questionItemNumberSx,
questionStemTypographySx,
} from "@/utils/components/question-bank/question-display/utils/questionCardStyles";
import {
extractAnswerContent,
htmlContentEquals,
} from "@/utils/components/question-bank/question-display/utils/questionAnswerUtils";
const unwrapBlock = (html) => {
const el = document.createElement("div");
el.innerHTML = html;
Eif (el.children.length === 1 && el.children[0].tagName === "P") {
return el.children[0].innerHTML;
}
return html;
};
const buildSelectHTML = (index, showAnswers, blank, choices, theme) => {
const answerContent = extractAnswerContent(blank);
const isAnswer = showAnswers && answerContent;
const colors = inlineSelectBlankColors(theme, isAnswer);
let displayContent = "Select...";
if (isAnswer) {
const items = choices?.[index]?.items || [];
const matched = items.find((item) => htmlContentEquals(item, answerContent));
displayContent = matched ? unwrapBlock(matched) : unwrapBlock(answerContent);
}
return (
`<span style="display:inline-block;padding:2px 8px;` +
`border:1px solid ${colors.borderColor};border-radius:4px;background-color:${colors.backgroundColor};` +
`vertical-align:middle;margin:0 4px;color:${colors.color};` +
`white-space:nowrap;line-height:normal;">` +
`${displayContent}</span>`
);
};
const DropDownMenuViewOnly = ({ question, showAnswers, itemNumber }) => {
const theme = useTheme();
const cardBg = questionCardSurfaceBg(theme);
let blankIndex = 0;
// Modified by Allan Ninal — optional chaining here; the identical unguarded
// dereference its twin DragDropViewOnly had. A question saved with no correct
// answer threw on `.answers` and took the whole rendered LIST with it. The
// choices side was already guarded (`choices?.[index]?.items`) — only the
// answers side was not.
const content = question.question.replace(/__blank__/g, () => {
const idx = blankIndex++;
return buildSelectHTML(idx, showAnswers, question.correctAnswer?.answers?.[idx], question.choices, theme);
});
return (
<Box sx={{ display: "flex", flexDirection: "column", gap: 2, width: "100%" }}>
<Box sx={{ display: "flex", alignItems: "flex-start", gap: 1 }}>
{itemNumber != null && itemNumber !== false && (
<Typography component="span" sx={{ ...questionItemNumberSx, flexShrink: 0 }}>
{itemNumber}.
</Typography>
)}
<Box sx={{ flex: 1, ...questionStemTypographySx }}>
<TinyMCETextEditorReadOnly content={content} backgroundColor={cardBg} />
</Box>
</Box>
</Box>
);
};
export default memo(DropDownMenuViewOnly);
|