catchup-library-web 1.20.36 → 1.21.0
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.js +448 -243
- package/dist/index.mjs +448 -243
- package/package.json +2 -6
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +62 -2
- package/src/components/activities/material-contents/GroupingActivityMaterialContent.tsx +74 -2
- package/src/components/activities/material-contents/MatchingActivityMaterialContent.tsx +74 -2
- package/src/components/activities/material-contents/OrderingActivityMaterialContent.tsx +76 -2
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent2.tsx +0 -306
- package/src/components/activities/material-contents/GroupingActivityMaterialContent2.tsx +0 -362
- package/src/components/activities/material-contents/MatchingActivityMaterialContent2.tsx +0 -350
- package/src/components/activities/material-contents/OrderingActivityMaterialContent2.tsx +0 -231
- package/src/components/dnds/DraggableDroppableItem.tsx +0 -60
- package/src/components/dnds/DraggableItem.tsx +0 -39
- package/src/components/dnds/DroppableItem.tsx +0 -33
package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent2.tsx
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { InlineMath } from "react-katex";
|
|
2
|
-
import InputGroup from "../../groups/InputGroup";
|
|
3
|
-
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
4
|
-
import i18n from "../../../language/i18n";
|
|
5
|
-
import { useState } from "react";
|
|
6
|
-
import { useEffect } from "react";
|
|
7
|
-
import { useDrop } from "react-dnd";
|
|
8
|
-
import BaseImage from "../../images/BaseImage";
|
|
9
|
-
import { shuffleArray } from "../../../utilization/AppUtilization";
|
|
10
|
-
import DraggableItem from "../../dnds/DraggableItem";
|
|
11
|
-
import DroppableItem from "../../dnds/DroppableItem";
|
|
12
|
-
import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
|
|
13
|
-
import DividerLine from "../../dividers/DividerLine";
|
|
14
|
-
import { IFillInTheBlanksActivityMaterialProps } from "../../../properties/ActivityProperties";
|
|
15
|
-
import InputWithSpecialExpression from "../../texts/InputWithSpecialExpression";
|
|
16
|
-
|
|
17
|
-
const FillInTheBlanksActivityMaterialContent = ({
|
|
18
|
-
uniqueValue,
|
|
19
|
-
answer,
|
|
20
|
-
optionList,
|
|
21
|
-
materialMap,
|
|
22
|
-
contentMap,
|
|
23
|
-
checkCanAnswerQuestion,
|
|
24
|
-
onChange,
|
|
25
|
-
isPreview,
|
|
26
|
-
showCorrectAnswer,
|
|
27
|
-
}: IFillInTheBlanksActivityMaterialProps) => {
|
|
28
|
-
const [shuffleOptionList, setShuffleOptionList] = useState([]);
|
|
29
|
-
const [selectedOption, setSelectedOption] = useState(null);
|
|
30
|
-
const [pasteOptionIndex, setPasteOptionIndex] = useState(null);
|
|
31
|
-
const [{ isOver, canDrop }, drop] = useDrop({
|
|
32
|
-
accept: "FILL_IN_THE_BLANKS",
|
|
33
|
-
drop: () => {},
|
|
34
|
-
collect: (monitor) => ({
|
|
35
|
-
isOver: monitor.isOver(),
|
|
36
|
-
canDrop: monitor.canDrop(),
|
|
37
|
-
}),
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
setShuffleOptionList(shuffleArray(optionList));
|
|
42
|
-
}, []);
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (!showCorrectAnswer) return;
|
|
46
|
-
const foundAnswer = answer.data.find(
|
|
47
|
-
(answerData: any) => answerData.type === "FILL_IN_THE_BLANKS"
|
|
48
|
-
);
|
|
49
|
-
if (foundAnswer.answerMap.length === 0) return;
|
|
50
|
-
if (Object.keys(materialMap).length === 0) return;
|
|
51
|
-
foundAnswer.answerMap = Object.keys(materialMap).map(
|
|
52
|
-
(materialMapKey) => JSON.parse(materialMap[materialMapKey])[0]
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
onChange(answer, 0, JSON.parse(materialMap[0])[0]);
|
|
56
|
-
}, [showCorrectAnswer]);
|
|
57
|
-
|
|
58
|
-
const retrieveAnswerMap = () => {
|
|
59
|
-
const foundIndex = answer.data.findIndex(
|
|
60
|
-
(answerData: any) => answerData.type === "FILL_IN_THE_BLANKS"
|
|
61
|
-
);
|
|
62
|
-
return answer.data[foundIndex].answerMap;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const checkAnswerState = (correctAnswerList: any, learnerAnswer: string) => {
|
|
66
|
-
if (!isPreview) return null;
|
|
67
|
-
const foundIndex = correctAnswerList.findIndex(
|
|
68
|
-
(correctAnswer: string) => correctAnswer === learnerAnswer
|
|
69
|
-
);
|
|
70
|
-
if (foundIndex !== -1) {
|
|
71
|
-
return "CORRECT";
|
|
72
|
-
}
|
|
73
|
-
return "INCORRECT";
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const checkAnswerProvided = (answerMap: any, option: string) => {
|
|
77
|
-
return (
|
|
78
|
-
Object.keys(answerMap).findIndex((key) => answerMap[key] === option) !==
|
|
79
|
-
-1
|
|
80
|
-
);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const handleSelectOption = (option: any) => {
|
|
84
|
-
setSelectedOption(option);
|
|
85
|
-
setPasteOptionIndex(null);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const answerMap = retrieveAnswerMap();
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<div
|
|
92
|
-
className="flex flex-row flex-wrap items-center"
|
|
93
|
-
// onMouseUp={() => {}}
|
|
94
|
-
// onTouchStart={() => {}}
|
|
95
|
-
>
|
|
96
|
-
<div className="hidden md:block">
|
|
97
|
-
<span className="font-semibold text-xl opacity-60">
|
|
98
|
-
{i18n.t("please_select_fill_in_the_blanks_text")}
|
|
99
|
-
</span>
|
|
100
|
-
</div>
|
|
101
|
-
<div className="hidden md:contents">
|
|
102
|
-
<DividerLine />
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
<div className="w-full flex flex-row flex-wrap gap-x-2 gap-y-2 my-2">
|
|
106
|
-
{shuffleOptionList.map((option, index) =>
|
|
107
|
-
checkAnswerProvided(answerMap, option) ? (
|
|
108
|
-
<div className="opacity-30" key={index}>
|
|
109
|
-
<ShowMaterialMediaByContentType
|
|
110
|
-
key={`${uniqueValue}-${index}`}
|
|
111
|
-
contentType={contentMap.type}
|
|
112
|
-
src={option}
|
|
113
|
-
canFullScreen={true}
|
|
114
|
-
/>
|
|
115
|
-
</div>
|
|
116
|
-
) : (
|
|
117
|
-
<DraggableItem
|
|
118
|
-
key={index}
|
|
119
|
-
item={{ index: option }}
|
|
120
|
-
type={"FILL_IN_THE_BLANKS"}
|
|
121
|
-
component={
|
|
122
|
-
contentMap.type === "TEXT" ? (
|
|
123
|
-
<div
|
|
124
|
-
className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge cursor-pointer select-none"
|
|
125
|
-
onClick={() => handleSelectOption(option)}
|
|
126
|
-
onMouseDown={() => {
|
|
127
|
-
setSelectedOption(option);
|
|
128
|
-
setPasteOptionIndex(null);
|
|
129
|
-
}}
|
|
130
|
-
onTouchEnd={() => {
|
|
131
|
-
setSelectedOption(option);
|
|
132
|
-
setPasteOptionIndex(null);
|
|
133
|
-
}}
|
|
134
|
-
>
|
|
135
|
-
<p className="italic whitespace-pre-wrap">
|
|
136
|
-
<InputWithSpecialExpression
|
|
137
|
-
value={option}
|
|
138
|
-
showSpecialOnly={false}
|
|
139
|
-
/>
|
|
140
|
-
</p>
|
|
141
|
-
</div>
|
|
142
|
-
) : (
|
|
143
|
-
<div
|
|
144
|
-
className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge cursor-pointer select-none"
|
|
145
|
-
onClick={() => handleSelectOption(option)}
|
|
146
|
-
onMouseDown={() => {
|
|
147
|
-
setSelectedOption(option);
|
|
148
|
-
setPasteOptionIndex(null);
|
|
149
|
-
}}
|
|
150
|
-
onTouchEnd={() => {
|
|
151
|
-
setSelectedOption(option);
|
|
152
|
-
setPasteOptionIndex(null);
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
<ShowMaterialMediaByContentType
|
|
156
|
-
key={`${uniqueValue}-${index}`}
|
|
157
|
-
contentType={contentMap.type}
|
|
158
|
-
src={option}
|
|
159
|
-
canFullScreen={true}
|
|
160
|
-
/>
|
|
161
|
-
</div>
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
moveCardHandler={() => {
|
|
165
|
-
onChange(answer, pasteOptionIndex, selectedOption);
|
|
166
|
-
}}
|
|
167
|
-
/>
|
|
168
|
-
)
|
|
169
|
-
)}
|
|
170
|
-
</div>
|
|
171
|
-
<div className="w-full flex flex-row flex-wrap">
|
|
172
|
-
{Object.keys(answerMap).map((materialKey, index) => {
|
|
173
|
-
const learnerAnswerState = checkAnswerState(
|
|
174
|
-
JSON.parse(materialMap[materialKey]),
|
|
175
|
-
answerMap[materialKey]
|
|
176
|
-
);
|
|
177
|
-
return (
|
|
178
|
-
<div key={index} className="w-full md:w-1/2">
|
|
179
|
-
<div className="mx-2">
|
|
180
|
-
<DroppableItem
|
|
181
|
-
key={index}
|
|
182
|
-
item={{ index }}
|
|
183
|
-
type={"FILL_IN_THE_BLANKS"}
|
|
184
|
-
target={pasteOptionIndex}
|
|
185
|
-
setTarget={setPasteOptionIndex}
|
|
186
|
-
dropRef={drop}
|
|
187
|
-
component={
|
|
188
|
-
<div className="w-full flex flex-row my-2 gap-x-2">
|
|
189
|
-
<div className="my-auto">
|
|
190
|
-
<p className="text-xl">
|
|
191
|
-
{parseFloat(materialKey) + 1}.
|
|
192
|
-
</p>
|
|
193
|
-
</div>
|
|
194
|
-
<div className="flex-1">
|
|
195
|
-
{checkCanAnswerQuestion() ? (
|
|
196
|
-
contentMap.type === "TEXT" ? (
|
|
197
|
-
<div className="relative">
|
|
198
|
-
<div className="flex-1">
|
|
199
|
-
<div
|
|
200
|
-
className={`w-full min-h-[44px] border rounded-lg ${
|
|
201
|
-
answerMap[materialKey]
|
|
202
|
-
? "border-catchup-blue-400 px-2"
|
|
203
|
-
: "bg-catchup-gray-50 border-catchup-gray-200 border-dashed py-2 px-4"
|
|
204
|
-
}`}
|
|
205
|
-
onClick={() => {
|
|
206
|
-
if (answerMap[materialKey]) {
|
|
207
|
-
onChange(answer, materialKey, "");
|
|
208
|
-
}
|
|
209
|
-
}}
|
|
210
|
-
>
|
|
211
|
-
{answerMap[materialKey] ? (
|
|
212
|
-
<InputWithSpecialExpression
|
|
213
|
-
value={answerMap[materialKey]}
|
|
214
|
-
showSpecialOnly={false}
|
|
215
|
-
/>
|
|
216
|
-
) : (
|
|
217
|
-
<p className="text-gray-400 italic"></p>
|
|
218
|
-
)}
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
|
|
222
|
-
{learnerAnswerState === "CORRECT" ? (
|
|
223
|
-
<div className="absolute -top-[10px] right-4 bg-catchup-white">
|
|
224
|
-
<BaseImage
|
|
225
|
-
src="/icons/checkbox.webp"
|
|
226
|
-
alt="checkbox"
|
|
227
|
-
size="small"
|
|
228
|
-
/>
|
|
229
|
-
</div>
|
|
230
|
-
) : learnerAnswerState === "INCORRECT" ? (
|
|
231
|
-
<div className="absolute -top-[10px] right-4 bg-catchup-white">
|
|
232
|
-
<BaseImage
|
|
233
|
-
src="/icons/cross-red.webp"
|
|
234
|
-
alt="cross-red"
|
|
235
|
-
size="small"
|
|
236
|
-
/>
|
|
237
|
-
</div>
|
|
238
|
-
) : null}
|
|
239
|
-
</div>
|
|
240
|
-
) : answerMap[materialKey] === "" ? (
|
|
241
|
-
<div
|
|
242
|
-
className={`w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed ${
|
|
243
|
-
learnerAnswerState === "CORRECT"
|
|
244
|
-
? "border-catchup-green"
|
|
245
|
-
: learnerAnswerState === "INCORRECT"
|
|
246
|
-
? "border-catchup-red"
|
|
247
|
-
: "border-catchup-blue"
|
|
248
|
-
}`}
|
|
249
|
-
>
|
|
250
|
-
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
251
|
-
<span className="italic">
|
|
252
|
-
{i18n.t("please_drop_here")}
|
|
253
|
-
</span>
|
|
254
|
-
</div>
|
|
255
|
-
</div>
|
|
256
|
-
) : (
|
|
257
|
-
<div
|
|
258
|
-
className="flex-1 cursor-pointer"
|
|
259
|
-
onClick={() => {
|
|
260
|
-
onChange(answer, materialKey, "");
|
|
261
|
-
}}
|
|
262
|
-
>
|
|
263
|
-
<ShowMaterialMediaByContentType
|
|
264
|
-
key={`${uniqueValue}-${index}`}
|
|
265
|
-
contentType={contentMap.type}
|
|
266
|
-
src={answerMap[materialKey]}
|
|
267
|
-
canFullScreen={true}
|
|
268
|
-
/>
|
|
269
|
-
</div>
|
|
270
|
-
)
|
|
271
|
-
) : (
|
|
272
|
-
<p key={materialKey} className="text-xl">
|
|
273
|
-
{constructInputWithSpecialExpressionList(
|
|
274
|
-
answerMap[materialKey]
|
|
275
|
-
).map((inputPart, index) => (
|
|
276
|
-
<span
|
|
277
|
-
key={index}
|
|
278
|
-
className={`${
|
|
279
|
-
inputPart.isBold ? "font-bold" : ""
|
|
280
|
-
} ${inputPart.isUnderline ? "underline" : ""}`}
|
|
281
|
-
>
|
|
282
|
-
{inputPart.isEquation ? (
|
|
283
|
-
<span className="text-xl">
|
|
284
|
-
<InlineMath math={inputPart.value} />
|
|
285
|
-
</span>
|
|
286
|
-
) : (
|
|
287
|
-
inputPart.value
|
|
288
|
-
)}
|
|
289
|
-
</span>
|
|
290
|
-
))}
|
|
291
|
-
</p>
|
|
292
|
-
)}
|
|
293
|
-
</div>
|
|
294
|
-
</div>
|
|
295
|
-
}
|
|
296
|
-
/>
|
|
297
|
-
</div>
|
|
298
|
-
</div>
|
|
299
|
-
);
|
|
300
|
-
})}
|
|
301
|
-
</div>
|
|
302
|
-
</div>
|
|
303
|
-
);
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
export default FillInTheBlanksActivityMaterialContent;
|
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
import { useDrop } from "react-dnd";
|
|
3
|
-
import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
|
|
4
|
-
import { InlineMath } from "react-katex";
|
|
5
|
-
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
6
|
-
import DividerLine from "../../dividers/DividerLine";
|
|
7
|
-
import { IGroupingActivityMaterialProps } from "../../../properties/ActivityProperties";
|
|
8
|
-
import DraggableItem from "../../dnds/DraggableItem";
|
|
9
|
-
import DroppableItem from "../../dnds/DroppableItem";
|
|
10
|
-
|
|
11
|
-
const GroupingActivityMaterialContent = ({
|
|
12
|
-
uniqueValue,
|
|
13
|
-
answer,
|
|
14
|
-
materialMap,
|
|
15
|
-
contentMap,
|
|
16
|
-
checkCanAnswerQuestion,
|
|
17
|
-
onChange,
|
|
18
|
-
isPreview,
|
|
19
|
-
showCorrectAnswer,
|
|
20
|
-
}: IGroupingActivityMaterialProps) => {
|
|
21
|
-
const [selectedValue, setSelectedValue] = useState(null);
|
|
22
|
-
const [selectedTargetKey, setSelectedTargetKey] = useState(null);
|
|
23
|
-
const [isShuffled, setIsShuffled] = useState(false);
|
|
24
|
-
const [shuffledMaterialList, setShuffledMaterialList] = useState([]);
|
|
25
|
-
const [{ isOver, canDrop }, drop] = useDrop({
|
|
26
|
-
accept: "GROUPING",
|
|
27
|
-
drop: () => {},
|
|
28
|
-
collect: (monitor: any) => ({
|
|
29
|
-
isOver: monitor.isOver(),
|
|
30
|
-
canDrop: monitor.canDrop(),
|
|
31
|
-
}),
|
|
32
|
-
});
|
|
33
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
const shuffleArray = (array: any) => {
|
|
37
|
-
if (!isShuffled) {
|
|
38
|
-
const copyArray = JSON.parse(JSON.stringify(array));
|
|
39
|
-
for (let i = copyArray.length - 1; i > 0; i--) {
|
|
40
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
41
|
-
[copyArray[i], copyArray[j]] = [copyArray[j], copyArray[i]];
|
|
42
|
-
}
|
|
43
|
-
setIsShuffled(true);
|
|
44
|
-
return copyArray;
|
|
45
|
-
}
|
|
46
|
-
return array;
|
|
47
|
-
};
|
|
48
|
-
const materialList: any = [];
|
|
49
|
-
Object.keys(materialMap).forEach((materialKey) => {
|
|
50
|
-
for (const materialValue of materialMap[materialKey]) {
|
|
51
|
-
materialList.push(materialValue);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
setShuffledMaterialList(shuffleArray(materialList));
|
|
55
|
-
}, []);
|
|
56
|
-
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
if (!showCorrectAnswer) return;
|
|
59
|
-
answer.data.find(
|
|
60
|
-
(answerData: any) => answerData.type === "GROUPING"
|
|
61
|
-
).answerMap = materialMap;
|
|
62
|
-
}, [showCorrectAnswer]);
|
|
63
|
-
|
|
64
|
-
const retrieveAnswerMap = () => {
|
|
65
|
-
const foundIndex = answer.data.findIndex(
|
|
66
|
-
(answerData: any) => answerData.type === "GROUPING"
|
|
67
|
-
);
|
|
68
|
-
const answerMap = answer.data[foundIndex].answerMap;
|
|
69
|
-
return answerMap;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const retrieveFilteredMaterialList = (answerMap: any) => {
|
|
73
|
-
const selectedValueList: any = [];
|
|
74
|
-
Object.keys(answerMap).forEach((key) => {
|
|
75
|
-
answerMap[key].forEach((value: string) => {
|
|
76
|
-
selectedValueList.push(value);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
return shuffledMaterialList.filter(
|
|
80
|
-
(material) =>
|
|
81
|
-
selectedValueList.findIndex((value: string) => material === value) ===
|
|
82
|
-
-1
|
|
83
|
-
);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const checkAnswerState = (correctAnswerList: any, learnerAnswer: string) => {
|
|
87
|
-
if (!isPreview) return null;
|
|
88
|
-
if (!learnerAnswer) return "EMPTY";
|
|
89
|
-
if (!correctAnswerList) return "EMPTY";
|
|
90
|
-
const foundIndex = correctAnswerList.findIndex(
|
|
91
|
-
(correctAnswer: string) => correctAnswer === learnerAnswer
|
|
92
|
-
);
|
|
93
|
-
if (foundIndex !== -1) {
|
|
94
|
-
return "CORRECT";
|
|
95
|
-
}
|
|
96
|
-
return "INCORRECT";
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const handleGroupingActivityItemOnChange = (
|
|
100
|
-
selectedTargetKey: string,
|
|
101
|
-
selectedValue: string
|
|
102
|
-
) => {
|
|
103
|
-
if (checkCanAnswerQuestion()) {
|
|
104
|
-
onChange(answer, selectedTargetKey, selectedValue, null);
|
|
105
|
-
setSelectedValue(null);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const answerMap = retrieveAnswerMap();
|
|
110
|
-
const filteredMaterialList = retrieveFilteredMaterialList(answerMap);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<>
|
|
114
|
-
{filteredMaterialList.length > 0 ? (
|
|
115
|
-
<>
|
|
116
|
-
<div className="flex-1 flex flex-row gap-x-4 overflow-x-auto py-2">
|
|
117
|
-
{filteredMaterialList.map((materialValue, index) => {
|
|
118
|
-
return (
|
|
119
|
-
<DraggableItem
|
|
120
|
-
key={index}
|
|
121
|
-
item={{ index: materialValue }}
|
|
122
|
-
type={"GROUPING"}
|
|
123
|
-
component={
|
|
124
|
-
<div
|
|
125
|
-
className={`${
|
|
126
|
-
selectedValue === materialValue
|
|
127
|
-
? "border-catchup-blue"
|
|
128
|
-
: "border-catchup-lighter-gray"
|
|
129
|
-
} ${
|
|
130
|
-
contentMap.type === "TEXT"
|
|
131
|
-
? "h-catchup-activity-text-box-item"
|
|
132
|
-
: "h-catchup-activity-media-box-item"
|
|
133
|
-
} flex flex-col items-center justify-center border-2 rounded-catchup-xlarge cursor-pointer transition-all duration-300`}
|
|
134
|
-
onMouseDown={() => {
|
|
135
|
-
if (checkCanAnswerQuestion()) {
|
|
136
|
-
setSelectedValue(materialValue);
|
|
137
|
-
}
|
|
138
|
-
}}
|
|
139
|
-
onTouchEnd={() => {
|
|
140
|
-
if (checkCanAnswerQuestion()) {
|
|
141
|
-
setSelectedValue(materialValue);
|
|
142
|
-
}
|
|
143
|
-
}}
|
|
144
|
-
onMouseUp={() => {
|
|
145
|
-
if (checkCanAnswerQuestion()) {
|
|
146
|
-
setSelectedValue(null);
|
|
147
|
-
}
|
|
148
|
-
}}
|
|
149
|
-
onTouchStart={() => {
|
|
150
|
-
if (checkCanAnswerQuestion()) {
|
|
151
|
-
setSelectedValue(null);
|
|
152
|
-
}
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
{contentMap.type === "TEXT" ? (
|
|
156
|
-
<div className="flex flex-col items-center justify-center m-2 min-w-[200px] overflow-y-auto">
|
|
157
|
-
<p className="text-xl text-center whitespace-pre-wrap">
|
|
158
|
-
{constructInputWithSpecialExpressionList(
|
|
159
|
-
materialValue
|
|
160
|
-
).map((inputPart, index) => (
|
|
161
|
-
<span
|
|
162
|
-
key={index}
|
|
163
|
-
className={`${
|
|
164
|
-
inputPart.isBold ? "font-bold" : ""
|
|
165
|
-
} ${inputPart.isUnderline ? "underline" : ""}`}
|
|
166
|
-
>
|
|
167
|
-
{inputPart.isEquation ? (
|
|
168
|
-
<span className="text-2xl">
|
|
169
|
-
<InlineMath math={inputPart.value} />
|
|
170
|
-
</span>
|
|
171
|
-
) : (
|
|
172
|
-
inputPart.value
|
|
173
|
-
)}
|
|
174
|
-
</span>
|
|
175
|
-
))}
|
|
176
|
-
</p>
|
|
177
|
-
</div>
|
|
178
|
-
) : (
|
|
179
|
-
<ShowMaterialMediaByContentType
|
|
180
|
-
key={`${uniqueValue}-${index}`}
|
|
181
|
-
contentType={contentMap.type}
|
|
182
|
-
src={materialValue}
|
|
183
|
-
canFullScreen={true}
|
|
184
|
-
/>
|
|
185
|
-
)}
|
|
186
|
-
</div>
|
|
187
|
-
}
|
|
188
|
-
moveCardHandler={() => {
|
|
189
|
-
if (!selectedTargetKey) return;
|
|
190
|
-
if (!selectedValue) return;
|
|
191
|
-
handleGroupingActivityItemOnChange(
|
|
192
|
-
selectedTargetKey,
|
|
193
|
-
selectedValue
|
|
194
|
-
);
|
|
195
|
-
}}
|
|
196
|
-
/>
|
|
197
|
-
);
|
|
198
|
-
})}
|
|
199
|
-
</div>
|
|
200
|
-
<DividerLine />
|
|
201
|
-
</>
|
|
202
|
-
) : null}
|
|
203
|
-
<div className="overflow-y-auto max-h-[500px]">
|
|
204
|
-
{Object.keys(answerMap).map((answerMapKey, index) => (
|
|
205
|
-
<div key={index} className="flex flex-row w-full">
|
|
206
|
-
<div className="w-1/3">
|
|
207
|
-
<div
|
|
208
|
-
className={`border-catchup-blue ${
|
|
209
|
-
contentMap.type === "TEXT"
|
|
210
|
-
? "h-catchup-activity-text-outer-box-item"
|
|
211
|
-
: "h-catchup-activity-media-outer-box-item"
|
|
212
|
-
} flex flex-col items-center justify-center border-2 rounded-catchup-xlarge transition-all duration-300 my-3`}
|
|
213
|
-
>
|
|
214
|
-
<div className="flex flex-col items-center justify-center transition-all duration-300 px-4 text-center">
|
|
215
|
-
<p className="text-lg whitespace-pre-wrap">
|
|
216
|
-
{constructInputWithSpecialExpressionList(answerMapKey).map(
|
|
217
|
-
(inputPart, index) => (
|
|
218
|
-
<span
|
|
219
|
-
key={index}
|
|
220
|
-
className={`${inputPart.isBold ? "font-bold" : ""} ${
|
|
221
|
-
inputPart.isUnderline ? "underline" : ""
|
|
222
|
-
}`}
|
|
223
|
-
>
|
|
224
|
-
{inputPart.isEquation ? (
|
|
225
|
-
<span className="text-2xl">
|
|
226
|
-
<InlineMath math={inputPart.value} />
|
|
227
|
-
</span>
|
|
228
|
-
) : (
|
|
229
|
-
inputPart.value
|
|
230
|
-
)}
|
|
231
|
-
</span>
|
|
232
|
-
)
|
|
233
|
-
)}
|
|
234
|
-
</p>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
</div>
|
|
238
|
-
<div className="mx-4 w-[2px] bg-catchup-lighter-gray"></div>
|
|
239
|
-
<div className="flex-1 min-w-0" ref={ref}>
|
|
240
|
-
<div className="h-full py-3">
|
|
241
|
-
<div
|
|
242
|
-
className={`${
|
|
243
|
-
canDrop
|
|
244
|
-
? selectedTargetKey === answerMapKey
|
|
245
|
-
? "bg-catchup-light-blue"
|
|
246
|
-
: "bg-catchup-light-blue opacity-40"
|
|
247
|
-
: ""
|
|
248
|
-
} flex-1 border-catchup-blue rounded-catchup-xlarge border-2 h-full p-1`}
|
|
249
|
-
>
|
|
250
|
-
<DroppableItem
|
|
251
|
-
key={index}
|
|
252
|
-
item={{ index: answerMapKey }}
|
|
253
|
-
type={"GROUPING"}
|
|
254
|
-
target={selectedTargetKey}
|
|
255
|
-
setTarget={setSelectedTargetKey}
|
|
256
|
-
dropRef={drop}
|
|
257
|
-
component={
|
|
258
|
-
<div className="h-full w-full overflow-x-auto">
|
|
259
|
-
<div className="flex flex-row items-center gap-2 w-max h-full">
|
|
260
|
-
{answerMap[answerMapKey].map(
|
|
261
|
-
(
|
|
262
|
-
answerMapValue: string,
|
|
263
|
-
answerMapIndex: number
|
|
264
|
-
) => {
|
|
265
|
-
const learnerAnswerState = checkAnswerState(
|
|
266
|
-
materialMap[answerMapKey],
|
|
267
|
-
answerMapValue
|
|
268
|
-
);
|
|
269
|
-
return (
|
|
270
|
-
<div key={answerMapIndex} className="p-1">
|
|
271
|
-
<div
|
|
272
|
-
className={`${
|
|
273
|
-
contentMap.type === "TEXT"
|
|
274
|
-
? "h-catchup-activity-text-box-item"
|
|
275
|
-
: "h-catchup-activity-media-box-item"
|
|
276
|
-
}`}
|
|
277
|
-
>
|
|
278
|
-
<div
|
|
279
|
-
className={`${
|
|
280
|
-
learnerAnswerState === "EMPTY"
|
|
281
|
-
? "border-catchup-lighter-gray"
|
|
282
|
-
: learnerAnswerState === "CORRECT"
|
|
283
|
-
? "border-catchup-green"
|
|
284
|
-
: learnerAnswerState === "INCORRECT"
|
|
285
|
-
? "border-catchup-red"
|
|
286
|
-
: "border-catchup-blue"
|
|
287
|
-
} border-2 rounded-catchup-xlarge h-full flex flex-col items-center justify-center transition-all duration-300 cursor-pointer`}
|
|
288
|
-
onClick={(e) => {
|
|
289
|
-
e.preventDefault();
|
|
290
|
-
if (checkCanAnswerQuestion()) {
|
|
291
|
-
onChange(
|
|
292
|
-
answer,
|
|
293
|
-
answerMapKey,
|
|
294
|
-
null,
|
|
295
|
-
answerMapIndex
|
|
296
|
-
);
|
|
297
|
-
setSelectedValue(null);
|
|
298
|
-
}
|
|
299
|
-
}}
|
|
300
|
-
>
|
|
301
|
-
{contentMap.type === "TEXT" ? (
|
|
302
|
-
<div className="flex flex-col items-center justify-center transition-all duration-300 min-w-[200px] overflow-y-auto">
|
|
303
|
-
<div className="m-2">
|
|
304
|
-
<p className="text-xl text-center whitespace-pre-wrap">
|
|
305
|
-
{constructInputWithSpecialExpressionList(
|
|
306
|
-
answerMapValue
|
|
307
|
-
).map((inputPart, index) => (
|
|
308
|
-
<span
|
|
309
|
-
key={index}
|
|
310
|
-
className={`${
|
|
311
|
-
inputPart.isBold
|
|
312
|
-
? "font-bold"
|
|
313
|
-
: ""
|
|
314
|
-
} ${
|
|
315
|
-
inputPart.isUnderline
|
|
316
|
-
? "underline"
|
|
317
|
-
: ""
|
|
318
|
-
}`}
|
|
319
|
-
>
|
|
320
|
-
{inputPart.isEquation ? (
|
|
321
|
-
<span className="text-2xl">
|
|
322
|
-
<InlineMath
|
|
323
|
-
math={inputPart.value}
|
|
324
|
-
/>
|
|
325
|
-
</span>
|
|
326
|
-
) : (
|
|
327
|
-
inputPart.value
|
|
328
|
-
)}
|
|
329
|
-
</span>
|
|
330
|
-
))}
|
|
331
|
-
</p>
|
|
332
|
-
</div>
|
|
333
|
-
</div>
|
|
334
|
-
) : (
|
|
335
|
-
<ShowMaterialMediaByContentType
|
|
336
|
-
key={`${uniqueValue}-${answerMapIndex}`}
|
|
337
|
-
contentType={contentMap.type}
|
|
338
|
-
src={answerMapValue}
|
|
339
|
-
canFullScreen={false}
|
|
340
|
-
/>
|
|
341
|
-
)}
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
)}
|
|
348
|
-
</div>
|
|
349
|
-
</div>
|
|
350
|
-
}
|
|
351
|
-
/>
|
|
352
|
-
</div>
|
|
353
|
-
</div>
|
|
354
|
-
</div>
|
|
355
|
-
</div>
|
|
356
|
-
))}
|
|
357
|
-
</div>
|
|
358
|
-
</>
|
|
359
|
-
);
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
export default GroupingActivityMaterialContent;
|