catchup-library-web 2.2.2 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +235 -184
- package/dist/index.mjs +234 -183
- package/package.json +1 -1
- package/src/components/activities/ActivityPreviewByData.tsx +2 -0
- package/src/components/activities/MCMAActivityContent.tsx +2 -0
- package/src/components/activities/MCSAActivityContent.tsx +2 -0
- package/src/components/activities/material-contents/DropdownActivityMaterialContent.tsx +146 -142
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +28 -19
- package/src/components/activities/material-contents/GroupingActivityMaterialContent.tsx +12 -8
- package/src/components/activities/material-contents/MCMAActivityMaterialContent.tsx +21 -3
- package/src/components/activities/material-contents/MCSAActivityMaterialContent.tsx +20 -3
- package/src/components/activities/material-contents/MatchingActivityMaterialContent.tsx +20 -13
- package/src/properties/ActivityProperties.ts +2 -0
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ const MCMAActivityContent = ({
|
|
|
15
15
|
canAnswerQuestion,
|
|
16
16
|
changeAnswer,
|
|
17
17
|
isPreview,
|
|
18
|
+
showCorrectAnswer,
|
|
18
19
|
isFullScreen,
|
|
19
20
|
}: IMCMAActivityProps) => {
|
|
20
21
|
const contentMap = parseContentMapFromData(data);
|
|
@@ -58,6 +59,7 @@ const MCMAActivityContent = ({
|
|
|
58
59
|
checkCanAnswerQuestion={canAnswerQuestion}
|
|
59
60
|
onChange={handleMCMAAnswerOnChange}
|
|
60
61
|
isPreview={isPreview}
|
|
62
|
+
showCorrectAnswer={showCorrectAnswer}
|
|
61
63
|
/>
|
|
62
64
|
</div>
|
|
63
65
|
</div>
|
|
@@ -15,6 +15,7 @@ const MCSAActivityContent = ({
|
|
|
15
15
|
canAnswerQuestion,
|
|
16
16
|
changeAnswer,
|
|
17
17
|
isPreview,
|
|
18
|
+
showCorrectAnswer,
|
|
18
19
|
isFullScreen,
|
|
19
20
|
}: IMCSAActivityProps) => {
|
|
20
21
|
const contentMap = parseContentMapFromData(data);
|
|
@@ -50,6 +51,7 @@ const MCSAActivityContent = ({
|
|
|
50
51
|
contentMap={contentMap}
|
|
51
52
|
checkCanAnswerQuestion={canAnswerQuestion}
|
|
52
53
|
onChange={handleMCSAAnswerOnChange}
|
|
54
|
+
showCorrectAnswer={showCorrectAnswer}
|
|
53
55
|
isPreview={isPreview}
|
|
54
56
|
/>
|
|
55
57
|
</div>
|
|
@@ -21,21 +21,22 @@ const DropdownActivityMaterialContent = ({
|
|
|
21
21
|
isPreview,
|
|
22
22
|
showCorrectAnswer,
|
|
23
23
|
}: IDropdownActivityMaterialProps) => {
|
|
24
|
-
const [
|
|
24
|
+
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
25
25
|
|
|
26
26
|
useEffect(() => {
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
if (showCorrectAnswer) {
|
|
28
|
+
// Create correct answer map where each key maps to the correct answer (first key in materialMap)
|
|
29
|
+
const correctAnswerMap: any = {};
|
|
30
|
+
Object.keys(materialMap).forEach((materialMapKey) => {
|
|
31
|
+
correctAnswerMap[materialMapKey] = Object.keys(
|
|
32
|
+
materialMap[materialMapKey]
|
|
33
|
+
)[0];
|
|
34
|
+
});
|
|
35
|
+
setDisplayAnswerMap(correctAnswerMap);
|
|
36
|
+
} else {
|
|
37
|
+
setDisplayAnswerMap(answerMap);
|
|
38
|
+
}
|
|
39
|
+
}, [showCorrectAnswer, answerMap, materialMap]);
|
|
39
40
|
|
|
40
41
|
const checkAnswerState = (correctAnswer: string, learnerAnswer: string) => {
|
|
41
42
|
if (!isPreview) return null;
|
|
@@ -56,92 +57,95 @@ const DropdownActivityMaterialContent = ({
|
|
|
56
57
|
<DividerLine />
|
|
57
58
|
</div>
|
|
58
59
|
<div className="w-full flex flex-row flex-wrap">
|
|
59
|
-
{Object.keys(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<div className="
|
|
68
|
-
<div className="
|
|
69
|
-
<div className="my-
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<div className="
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
),
|
|
111
|
-
value: materialOption,
|
|
112
|
-
}))}
|
|
113
|
-
onChange={(e) => {
|
|
114
|
-
onChange(
|
|
115
|
-
answerMap,
|
|
116
|
-
materialKey,
|
|
117
|
-
e.target.value
|
|
118
|
-
);
|
|
119
|
-
}}
|
|
120
|
-
/>
|
|
121
|
-
</div>
|
|
122
|
-
) : (
|
|
123
|
-
<MediaDropdown
|
|
124
|
-
id={materialKey}
|
|
125
|
-
answer={
|
|
126
|
-
answerMap[materialKey] === "DEFAULT_OPTION" ? (
|
|
127
|
-
<div className="w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed border-catchup-blue">
|
|
128
|
-
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
129
|
-
<span className="italic">
|
|
130
|
-
{i18n.t("please_select")}
|
|
60
|
+
{Object.keys(displayAnswerMap).map(
|
|
61
|
+
(materialKey: string, index: number) => {
|
|
62
|
+
const answerKey = Object.keys(materialMap[materialKey])[0];
|
|
63
|
+
const learnerAnswerState = checkAnswerState(
|
|
64
|
+
answerKey,
|
|
65
|
+
displayAnswerMap[materialKey]
|
|
66
|
+
);
|
|
67
|
+
return (
|
|
68
|
+
<div key={index} className="w-full md:w-1/2">
|
|
69
|
+
<div className="mx-2">
|
|
70
|
+
<div className="w-full flex flex-row my-2 gap-x-2">
|
|
71
|
+
<div className="my-auto">
|
|
72
|
+
<p className="text-xl">{parseFloat(materialKey) + 1}.</p>
|
|
73
|
+
</div>
|
|
74
|
+
<div className="w-full relative">
|
|
75
|
+
<div className="flex-1">
|
|
76
|
+
{checkCanAnswerQuestion() ? (
|
|
77
|
+
contentMap.type === "TEXT" ? (
|
|
78
|
+
<div className="flex-1">
|
|
79
|
+
<InputGroup
|
|
80
|
+
type="select"
|
|
81
|
+
value={displayAnswerMap[materialKey]}
|
|
82
|
+
optionList={shuffleArray(
|
|
83
|
+
materialMap[materialKey][answerKey]
|
|
84
|
+
).map((materialOption: any) => ({
|
|
85
|
+
text: (
|
|
86
|
+
<span className="text-xl whitespace-pre-wrap">
|
|
87
|
+
{constructInputWithSpecialExpressionList(
|
|
88
|
+
materialOption
|
|
89
|
+
).map((inputPart, index) => (
|
|
90
|
+
<span
|
|
91
|
+
key={index}
|
|
92
|
+
className={`${
|
|
93
|
+
inputPart.isBold ? "font-bold" : ""
|
|
94
|
+
} ${
|
|
95
|
+
inputPart.isUnderline
|
|
96
|
+
? "underline"
|
|
97
|
+
: ""
|
|
98
|
+
}`}
|
|
99
|
+
>
|
|
100
|
+
{inputPart.isEquation ? (
|
|
101
|
+
<span className="text-xl">
|
|
102
|
+
<InlineMath
|
|
103
|
+
math={inputPart.value}
|
|
104
|
+
/>
|
|
105
|
+
</span>
|
|
106
|
+
) : (
|
|
107
|
+
inputPart.value
|
|
108
|
+
)}
|
|
109
|
+
</span>
|
|
110
|
+
))}
|
|
131
111
|
</span>
|
|
112
|
+
),
|
|
113
|
+
value: materialOption,
|
|
114
|
+
}))}
|
|
115
|
+
onChange={(e) => {
|
|
116
|
+
onChange(
|
|
117
|
+
answerMap,
|
|
118
|
+
materialKey,
|
|
119
|
+
e.target.value
|
|
120
|
+
);
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
) : (
|
|
125
|
+
<MediaDropdown
|
|
126
|
+
id={materialKey}
|
|
127
|
+
answer={
|
|
128
|
+
displayAnswerMap[materialKey] ===
|
|
129
|
+
"DEFAULT_OPTION" ? (
|
|
130
|
+
<div className="w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed border-catchup-blue">
|
|
131
|
+
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
132
|
+
<span className="italic">
|
|
133
|
+
{i18n.t("please_select")}
|
|
134
|
+
</span>
|
|
135
|
+
</div>
|
|
132
136
|
</div>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
(materialOption: any, index: number) => ({
|
|
137
|
+
) : (
|
|
138
|
+
<ShowMaterialMediaByContentType
|
|
139
|
+
key={`${uniqueValue}-${index}`}
|
|
140
|
+
contentType={contentMap.type}
|
|
141
|
+
src={displayAnswerMap[materialKey]}
|
|
142
|
+
canFullScreen={false}
|
|
143
|
+
/>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
optionList={materialMap[materialKey][
|
|
147
|
+
answerKey
|
|
148
|
+
].map((materialOption: any, index: number) => ({
|
|
145
149
|
id: index,
|
|
146
150
|
media: (
|
|
147
151
|
<div key={index}>
|
|
@@ -160,56 +164,56 @@ const DropdownActivityMaterialContent = ({
|
|
|
160
164
|
e.target.currentSrc
|
|
161
165
|
);
|
|
162
166
|
},
|
|
163
|
-
})
|
|
164
|
-
|
|
167
|
+
}))}
|
|
168
|
+
/>
|
|
169
|
+
)
|
|
170
|
+
) : (
|
|
171
|
+
<p className="text-xl whitespace-pre-wrap">
|
|
172
|
+
{constructInputWithSpecialExpressionList(
|
|
173
|
+
displayAnswerMap[materialKey]
|
|
174
|
+
).map((inputPart, index) => (
|
|
175
|
+
<span
|
|
176
|
+
key={index}
|
|
177
|
+
className={`${
|
|
178
|
+
inputPart.isBold ? "font-bold" : ""
|
|
179
|
+
} ${inputPart.isUnderline ? "underline" : ""}`}
|
|
180
|
+
>
|
|
181
|
+
{inputPart.isEquation ? (
|
|
182
|
+
<span className="text-xl">
|
|
183
|
+
<InlineMath math={inputPart.value} />
|
|
184
|
+
</span>
|
|
185
|
+
) : (
|
|
186
|
+
inputPart.value
|
|
187
|
+
)}
|
|
188
|
+
</span>
|
|
189
|
+
))}
|
|
190
|
+
</p>
|
|
191
|
+
)}
|
|
192
|
+
</div>
|
|
193
|
+
{learnerAnswerState === "CORRECT" ? (
|
|
194
|
+
<div className="absolute -top-2 right-3 bg-catchup-white">
|
|
195
|
+
<BaseImage
|
|
196
|
+
src="/icons/checkbox.webp"
|
|
197
|
+
alt="chekbbox"
|
|
198
|
+
size="small"
|
|
165
199
|
/>
|
|
166
|
-
|
|
167
|
-
) : (
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
} ${inputPart.isUnderline ? "underline" : ""}`}
|
|
177
|
-
>
|
|
178
|
-
{inputPart.isEquation ? (
|
|
179
|
-
<span className="text-xl">
|
|
180
|
-
<InlineMath math={inputPart.value} />
|
|
181
|
-
</span>
|
|
182
|
-
) : (
|
|
183
|
-
inputPart.value
|
|
184
|
-
)}
|
|
185
|
-
</span>
|
|
186
|
-
))}
|
|
187
|
-
</p>
|
|
188
|
-
)}
|
|
200
|
+
</div>
|
|
201
|
+
) : learnerAnswerState === "INCORRECT" ? (
|
|
202
|
+
<div className="absolute -top-2 right-3 bg-catchup-white">
|
|
203
|
+
<BaseImage
|
|
204
|
+
src="/icons/cross-red.webp"
|
|
205
|
+
alt="cross-red"
|
|
206
|
+
size="small"
|
|
207
|
+
/>
|
|
208
|
+
</div>
|
|
209
|
+
) : null}
|
|
189
210
|
</div>
|
|
190
|
-
{learnerAnswerState === "CORRECT" ? (
|
|
191
|
-
<div className="absolute -top-2 right-3 bg-catchup-white">
|
|
192
|
-
<BaseImage
|
|
193
|
-
src="/icons/checkbox.webp"
|
|
194
|
-
alt="chekbbox"
|
|
195
|
-
size="small"
|
|
196
|
-
/>
|
|
197
|
-
</div>
|
|
198
|
-
) : learnerAnswerState === "INCORRECT" ? (
|
|
199
|
-
<div className="absolute -top-2 right-3 bg-catchup-white">
|
|
200
|
-
<BaseImage
|
|
201
|
-
src="/icons/cross-red.webp"
|
|
202
|
-
alt="cross-red"
|
|
203
|
-
size="small"
|
|
204
|
-
/>
|
|
205
|
-
</div>
|
|
206
|
-
) : null}
|
|
207
211
|
</div>
|
|
208
212
|
</div>
|
|
209
213
|
</div>
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
)}
|
|
213
217
|
</div>
|
|
214
218
|
</div>
|
|
215
219
|
);
|
package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx
CHANGED
|
@@ -27,6 +27,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
27
27
|
const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
|
|
28
28
|
null
|
|
29
29
|
);
|
|
30
|
+
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
30
31
|
const dragElementRef = useRef<HTMLDivElement>(null);
|
|
31
32
|
const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>({
|
|
32
33
|
x: 0,
|
|
@@ -42,12 +43,19 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
42
43
|
}, [optionList]);
|
|
43
44
|
|
|
44
45
|
useEffect(() => {
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
if (showCorrectAnswer) {
|
|
47
|
+
// Create correct answer map where each key maps to the first correct answer
|
|
48
|
+
const correctAnswerMap: any = {};
|
|
49
|
+
Object.keys(materialMap).forEach((materialMapKey) => {
|
|
50
|
+
correctAnswerMap[materialMapKey] = JSON.parse(
|
|
51
|
+
materialMap[materialMapKey]
|
|
52
|
+
)[0];
|
|
53
|
+
});
|
|
54
|
+
setDisplayAnswerMap(correctAnswerMap);
|
|
55
|
+
} else {
|
|
56
|
+
setDisplayAnswerMap(answerMap);
|
|
57
|
+
}
|
|
58
|
+
}, [showCorrectAnswer, answerMap, materialMap]);
|
|
51
59
|
|
|
52
60
|
const checkAnswerState = (
|
|
53
61
|
correctAnswerList: any[],
|
|
@@ -64,12 +72,13 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
64
72
|
};
|
|
65
73
|
|
|
66
74
|
const checkAnswerProvided = (
|
|
67
|
-
|
|
75
|
+
currentAnswerMap: Record<string, any>,
|
|
68
76
|
option: string
|
|
69
77
|
): boolean => {
|
|
70
78
|
return (
|
|
71
|
-
Object.keys(
|
|
72
|
-
|
|
79
|
+
Object.keys(currentAnswerMap).findIndex(
|
|
80
|
+
(key) => currentAnswerMap[key] === option
|
|
81
|
+
) !== -1
|
|
73
82
|
);
|
|
74
83
|
};
|
|
75
84
|
|
|
@@ -245,7 +254,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
245
254
|
|
|
246
255
|
<div className="w-full flex flex-row flex-wrap gap-x-2 gap-y-2 my-2">
|
|
247
256
|
{shuffleOptionList.map((option, index) =>
|
|
248
|
-
checkAnswerProvided(
|
|
257
|
+
checkAnswerProvided(displayAnswerMap, option) ? (
|
|
249
258
|
<ShowMaterialMediaByContentType
|
|
250
259
|
key={`${uniqueValue}-${index}`}
|
|
251
260
|
contentType={contentMap.type}
|
|
@@ -298,10 +307,10 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
298
307
|
)}
|
|
299
308
|
</div>
|
|
300
309
|
<div className="w-full flex flex-row flex-wrap">
|
|
301
|
-
{Object.keys(
|
|
310
|
+
{Object.keys(displayAnswerMap).map((materialKey, index) => {
|
|
302
311
|
const learnerAnswerState = checkAnswerState(
|
|
303
312
|
JSON.parse(materialMap[materialKey]),
|
|
304
|
-
|
|
313
|
+
displayAnswerMap[materialKey]
|
|
305
314
|
);
|
|
306
315
|
return (
|
|
307
316
|
<div key={index} className="w-full md:w-1/2">
|
|
@@ -330,20 +339,20 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
330
339
|
<div className="flex-1">
|
|
331
340
|
<div
|
|
332
341
|
className={`w-full min-h-[44px] border rounded-lg ${
|
|
333
|
-
|
|
342
|
+
displayAnswerMap[materialKey]
|
|
334
343
|
? "border-catchup-blue-400 px-2 cursor-pointer"
|
|
335
344
|
: "bg-catchup-gray-50 border-catchup-gray-200 border-dashed py-2 px-4"
|
|
336
345
|
}`}
|
|
337
346
|
onClick={(e) => {
|
|
338
|
-
if (
|
|
347
|
+
if (displayAnswerMap[materialKey]) {
|
|
339
348
|
e.stopPropagation();
|
|
340
349
|
onChange(answerMap, materialKey, "");
|
|
341
350
|
}
|
|
342
351
|
}}
|
|
343
352
|
>
|
|
344
|
-
{
|
|
353
|
+
{displayAnswerMap[materialKey] ? (
|
|
345
354
|
<InputWithSpecialExpression
|
|
346
|
-
value={
|
|
355
|
+
value={displayAnswerMap[materialKey]}
|
|
347
356
|
showSpecialOnly={false}
|
|
348
357
|
/>
|
|
349
358
|
) : null}
|
|
@@ -368,7 +377,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
368
377
|
</div>
|
|
369
378
|
) : null}
|
|
370
379
|
</div>
|
|
371
|
-
) :
|
|
380
|
+
) : displayAnswerMap[materialKey] === "" ? (
|
|
372
381
|
<div
|
|
373
382
|
className={`w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed ${
|
|
374
383
|
learnerAnswerState === "CORRECT"
|
|
@@ -395,7 +404,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
395
404
|
<ShowMaterialMediaByContentType
|
|
396
405
|
key={`${uniqueValue}-${index}`}
|
|
397
406
|
contentType={contentMap.type}
|
|
398
|
-
src={
|
|
407
|
+
src={displayAnswerMap[materialKey]}
|
|
399
408
|
canFullScreen={true}
|
|
400
409
|
/>
|
|
401
410
|
</div>
|
|
@@ -403,7 +412,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
403
412
|
) : (
|
|
404
413
|
<p key={materialKey} className="text-xl">
|
|
405
414
|
{constructInputWithSpecialExpressionList(
|
|
406
|
-
|
|
415
|
+
displayAnswerMap[materialKey]
|
|
407
416
|
).map((inputPart, index) => (
|
|
408
417
|
<span
|
|
409
418
|
key={index}
|
|
@@ -22,6 +22,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
22
22
|
null
|
|
23
23
|
);
|
|
24
24
|
const [shuffledMaterialList, setShuffledMaterialList] = useState<any[]>([]);
|
|
25
|
+
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
25
26
|
const dragElementRef = useRef<HTMLDivElement>(null);
|
|
26
27
|
const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>({
|
|
27
28
|
x: 0,
|
|
@@ -59,8 +60,11 @@ const GroupingActivityMaterialContent = ({
|
|
|
59
60
|
}, [materialMap]);
|
|
60
61
|
|
|
61
62
|
useEffect(() => {
|
|
62
|
-
if (
|
|
63
|
-
|
|
63
|
+
if (showCorrectAnswer) {
|
|
64
|
+
setDisplayAnswerMap(materialMap);
|
|
65
|
+
} else {
|
|
66
|
+
setDisplayAnswerMap(answerMap);
|
|
67
|
+
}
|
|
64
68
|
}, [showCorrectAnswer, answerMap, materialMap]);
|
|
65
69
|
|
|
66
70
|
useEffect(() => {
|
|
@@ -128,10 +132,10 @@ const GroupingActivityMaterialContent = ({
|
|
|
128
132
|
requestAnimationFrame(animate);
|
|
129
133
|
}, [dropTargetKey]);
|
|
130
134
|
|
|
131
|
-
const retrieveFilteredMaterialList = (
|
|
135
|
+
const retrieveFilteredMaterialList = (currentAnswerMap: any) => {
|
|
132
136
|
const selectedValueList: any = [];
|
|
133
|
-
Object.keys(
|
|
134
|
-
|
|
137
|
+
Object.keys(currentAnswerMap).forEach((key) => {
|
|
138
|
+
currentAnswerMap[key].forEach((value: string) => {
|
|
135
139
|
selectedValueList.push(value);
|
|
136
140
|
});
|
|
137
141
|
});
|
|
@@ -247,7 +251,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
247
251
|
}
|
|
248
252
|
};
|
|
249
253
|
|
|
250
|
-
const filteredMaterialList = retrieveFilteredMaterialList(
|
|
254
|
+
const filteredMaterialList = retrieveFilteredMaterialList(displayAnswerMap);
|
|
251
255
|
|
|
252
256
|
return (
|
|
253
257
|
<div onMouseMove={handleMouseMove} onMouseUp={handleMouseUp}>
|
|
@@ -420,7 +424,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
420
424
|
<DividerLine />
|
|
421
425
|
</>
|
|
422
426
|
) : null}
|
|
423
|
-
{Object.keys(
|
|
427
|
+
{Object.keys(displayAnswerMap).map((answerMapKey, index) => (
|
|
424
428
|
<div key={index} className="flex flex-row w-full">
|
|
425
429
|
<div className="w-1/3">
|
|
426
430
|
<div
|
|
@@ -473,7 +477,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
473
477
|
>
|
|
474
478
|
<div className="h-full w-full overflow-x-auto">
|
|
475
479
|
<div className="flex flex-row items-center gap-2 w-max h-full">
|
|
476
|
-
{
|
|
480
|
+
{displayAnswerMap[answerMapKey].map(
|
|
477
481
|
(answerMapValue: string, answerMapIndex: number) => {
|
|
478
482
|
const learnerAnswerState = checkAnswerState(
|
|
479
483
|
materialMap[answerMapKey],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
1
2
|
import { InlineMath } from "react-katex";
|
|
2
3
|
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
3
4
|
import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
|
|
@@ -14,7 +15,24 @@ const MCMAActivityMaterialContent = ({
|
|
|
14
15
|
checkCanAnswerQuestion,
|
|
15
16
|
onChange,
|
|
16
17
|
isPreview,
|
|
18
|
+
showCorrectAnswer,
|
|
17
19
|
}: IMCMAActivityMaterialProps) => {
|
|
20
|
+
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (showCorrectAnswer) {
|
|
24
|
+
// Create correct answer map where each key maps to the correct answer list
|
|
25
|
+
const correctAnswerMap: any = {};
|
|
26
|
+
Object.keys(materialMap).forEach((materialKey) => {
|
|
27
|
+
// The correct answers are stored as a JSON string in the first key
|
|
28
|
+
correctAnswerMap[materialKey] = JSON.parse(materialKey);
|
|
29
|
+
});
|
|
30
|
+
setDisplayAnswerMap(correctAnswerMap);
|
|
31
|
+
} else {
|
|
32
|
+
setDisplayAnswerMap(answerMap);
|
|
33
|
+
}
|
|
34
|
+
}, [showCorrectAnswer, answerMap, materialMap]);
|
|
35
|
+
|
|
18
36
|
const retrieveCorrectAnswerList = () => {
|
|
19
37
|
return JSON.parse(Object.keys(materialMap)[0]);
|
|
20
38
|
};
|
|
@@ -53,7 +71,7 @@ const MCMAActivityMaterialContent = ({
|
|
|
53
71
|
<div className="flex flex-row w-full flex-wrap ">
|
|
54
72
|
{materialMap[materialKey].map(
|
|
55
73
|
(materialSubKey: string, index: number) => {
|
|
56
|
-
const foundAnswer =
|
|
74
|
+
const foundAnswer = displayAnswerMap[materialKey].find(
|
|
57
75
|
(learnerAnswer: string) => learnerAnswer === materialSubKey
|
|
58
76
|
);
|
|
59
77
|
const learnerAnswerState = checkAnswerState(
|
|
@@ -81,7 +99,7 @@ const MCMAActivityMaterialContent = ({
|
|
|
81
99
|
>
|
|
82
100
|
<BaseImage
|
|
83
101
|
src={
|
|
84
|
-
|
|
102
|
+
displayAnswerMap[materialKey].includes(materialSubKey)
|
|
85
103
|
? "/icons/checkbox.webp"
|
|
86
104
|
: "/icons/checkbox-empty.webp"
|
|
87
105
|
}
|
|
@@ -128,7 +146,7 @@ const MCMAActivityMaterialContent = ({
|
|
|
128
146
|
) : (
|
|
129
147
|
<p key={materialKey} className="text-xl">
|
|
130
148
|
{constructInputWithSpecialExpressionList(
|
|
131
|
-
|
|
149
|
+
displayAnswerMap[materialKey]
|
|
132
150
|
).map((inputPart, index) => (
|
|
133
151
|
<span
|
|
134
152
|
key={index}
|