catchup-library-web 1.20.30 → 1.20.32
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 +306 -288
- package/dist/index.mjs +246 -228
- package/package.json +1 -1
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +189 -183
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent2.tsx +306 -0
package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { InlineMath } from "react-katex";
|
|
2
|
-
import
|
|
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";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
8
3
|
import BaseImage from "../../images/BaseImage";
|
|
9
4
|
import { shuffleArray } from "../../../utilization/AppUtilization";
|
|
10
|
-
import DraggableItem from "../../dnds/DraggableItem";
|
|
11
|
-
import DroppableItem from "../../dnds/DroppableItem";
|
|
12
5
|
import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
|
|
13
6
|
import DividerLine from "../../dividers/DividerLine";
|
|
14
7
|
import { IFillInTheBlanksActivityMaterialProps } from "../../../properties/ActivityProperties";
|
|
15
8
|
import InputWithSpecialExpression from "../../texts/InputWithSpecialExpression";
|
|
9
|
+
import i18n from "../../../language/i18n";
|
|
10
|
+
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
16
11
|
|
|
17
12
|
const FillInTheBlanksActivityMaterialContent = ({
|
|
18
13
|
uniqueValue,
|
|
@@ -27,15 +22,8 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
27
22
|
}: IFillInTheBlanksActivityMaterialProps) => {
|
|
28
23
|
const [shuffleOptionList, setShuffleOptionList] = useState([]);
|
|
29
24
|
const [selectedOption, setSelectedOption] = useState(null);
|
|
30
|
-
const [
|
|
31
|
-
const [
|
|
32
|
-
accept: "FILL_IN_THE_BLANKS",
|
|
33
|
-
drop: () => {},
|
|
34
|
-
collect: (monitor) => ({
|
|
35
|
-
isOver: monitor.isOver(),
|
|
36
|
-
canDrop: monitor.canDrop(),
|
|
37
|
-
}),
|
|
38
|
-
});
|
|
25
|
+
const [draggedOption, setDraggedOption] = useState(null);
|
|
26
|
+
const [dropTargetIndex, setDropTargetIndex] = useState(null);
|
|
39
27
|
|
|
40
28
|
useEffect(() => {
|
|
41
29
|
setShuffleOptionList(shuffleArray(optionList));
|
|
@@ -82,17 +70,39 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
82
70
|
|
|
83
71
|
const handleSelectOption = (option: any) => {
|
|
84
72
|
setSelectedOption(option);
|
|
85
|
-
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleDragStart = (option: any) => {
|
|
76
|
+
setDraggedOption(option);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleDragEnd = () => {
|
|
80
|
+
if (dropTargetIndex !== null && draggedOption !== null) {
|
|
81
|
+
onChange(answer, dropTargetIndex, draggedOption);
|
|
82
|
+
}
|
|
83
|
+
setDraggedOption(null);
|
|
84
|
+
setDropTargetIndex(null);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const handleDropZoneEnter = (index: any) => {
|
|
88
|
+
setDropTargetIndex(index);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const handleDropZoneDrop = (index: any) => {
|
|
92
|
+
if (selectedOption !== null) {
|
|
93
|
+
onChange(answer, index, selectedOption);
|
|
94
|
+
setSelectedOption(null);
|
|
95
|
+
} else if (draggedOption !== null) {
|
|
96
|
+
onChange(answer, index, draggedOption);
|
|
97
|
+
setDraggedOption(null);
|
|
98
|
+
}
|
|
99
|
+
setDropTargetIndex(null);
|
|
86
100
|
};
|
|
87
101
|
|
|
88
102
|
const answerMap = retrieveAnswerMap();
|
|
89
103
|
|
|
90
104
|
return (
|
|
91
|
-
<div
|
|
92
|
-
className="flex flex-row flex-wrap items-center"
|
|
93
|
-
// onMouseUp={() => {}}
|
|
94
|
-
// onTouchStart={() => {}}
|
|
95
|
-
>
|
|
105
|
+
<div className="flex flex-row flex-wrap items-center">
|
|
96
106
|
<div className="hidden md:block">
|
|
97
107
|
<span className="font-semibold text-xl opacity-60">
|
|
98
108
|
{i18n.t("please_select_fill_in_the_blanks_text")}
|
|
@@ -114,57 +124,43 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
114
124
|
/>
|
|
115
125
|
</div>
|
|
116
126
|
) : (
|
|
117
|
-
<
|
|
127
|
+
<div
|
|
118
128
|
key={index}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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}
|
|
129
|
+
draggable
|
|
130
|
+
onDragStart={() => handleDragStart(option)}
|
|
131
|
+
onDragEnd={handleDragEnd}
|
|
132
|
+
className={`${
|
|
133
|
+
draggedOption === option ? "opacity-40" : "opacity-100"
|
|
134
|
+
} transition-opacity duration-200`}
|
|
135
|
+
>
|
|
136
|
+
{contentMap.type === "TEXT" ? (
|
|
137
|
+
<div
|
|
138
|
+
className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge cursor-pointer select-none touch-none"
|
|
139
|
+
onClick={() => handleSelectOption(option)}
|
|
140
|
+
onTouchEnd={() => handleSelectOption(option)}
|
|
141
|
+
>
|
|
142
|
+
<p className="italic whitespace-pre-wrap">
|
|
143
|
+
<InputWithSpecialExpression
|
|
144
|
+
value={option}
|
|
145
|
+
showSpecialOnly={false}
|
|
160
146
|
/>
|
|
161
|
-
</
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
147
|
+
</p>
|
|
148
|
+
</div>
|
|
149
|
+
) : (
|
|
150
|
+
<div
|
|
151
|
+
className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge cursor-pointer select-none touch-none"
|
|
152
|
+
onClick={() => handleSelectOption(option)}
|
|
153
|
+
onTouchEnd={() => handleSelectOption(option)}
|
|
154
|
+
>
|
|
155
|
+
<ShowMaterialMediaByContentType
|
|
156
|
+
key={`${uniqueValue}-${index}`}
|
|
157
|
+
contentType={contentMap.type}
|
|
158
|
+
src={option}
|
|
159
|
+
canFullScreen={true}
|
|
160
|
+
/>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
168
164
|
)
|
|
169
165
|
)}
|
|
170
166
|
</div>
|
|
@@ -177,123 +173,133 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
177
173
|
return (
|
|
178
174
|
<div key={index} className="w-full md:w-1/2">
|
|
179
175
|
<div className="mx-2">
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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"
|
|
176
|
+
<div
|
|
177
|
+
onDragOver={(e) => {
|
|
178
|
+
e.preventDefault();
|
|
179
|
+
handleDropZoneEnter(materialKey);
|
|
180
|
+
}}
|
|
181
|
+
onDragLeave={() => setDropTargetIndex(null)}
|
|
182
|
+
onDrop={(e) => {
|
|
183
|
+
e.preventDefault();
|
|
184
|
+
handleDropZoneDrop(materialKey);
|
|
185
|
+
}}
|
|
186
|
+
onClick={() => {
|
|
187
|
+
if (selectedOption !== null) {
|
|
188
|
+
handleDropZoneDrop(materialKey);
|
|
189
|
+
}
|
|
190
|
+
}}
|
|
191
|
+
className={`${
|
|
192
|
+
dropTargetIndex === materialKey
|
|
193
|
+
? "ring-2 ring-blue-400"
|
|
194
|
+
: ""
|
|
195
|
+
}`}
|
|
196
|
+
>
|
|
197
|
+
<div className="w-full flex flex-row my-2 gap-x-2">
|
|
198
|
+
<div className="my-auto">
|
|
199
|
+
<p className="text-xl">{parseFloat(materialKey) + 1}.</p>
|
|
200
|
+
</div>
|
|
201
|
+
<div className="flex-1">
|
|
202
|
+
{checkCanAnswerQuestion() ? (
|
|
203
|
+
contentMap.type === "TEXT" ? (
|
|
204
|
+
<div className="relative">
|
|
205
|
+
<div className="flex-1">
|
|
206
|
+
<div
|
|
207
|
+
className={`w-full min-h-[44px] border rounded-lg ${
|
|
208
|
+
answerMap[materialKey]
|
|
209
|
+
? "border-catchup-blue-400 px-2"
|
|
210
|
+
: "bg-catchup-gray-50 border-catchup-gray-200 border-dashed py-2 px-4"
|
|
211
|
+
}`}
|
|
212
|
+
onClick={() => {
|
|
213
|
+
if (answerMap[materialKey]) {
|
|
214
|
+
onChange(answer, materialKey, "");
|
|
215
|
+
}
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{answerMap[materialKey] ? (
|
|
219
|
+
<InputWithSpecialExpression
|
|
220
|
+
value={answerMap[materialKey]}
|
|
221
|
+
showSpecialOnly={false}
|
|
236
222
|
/>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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>
|
|
223
|
+
) : (
|
|
224
|
+
<p className="text-gray-400 italic"></p>
|
|
225
|
+
)}
|
|
254
226
|
</div>
|
|
255
227
|
</div>
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
className="
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
228
|
+
|
|
229
|
+
{learnerAnswerState === "CORRECT" ? (
|
|
230
|
+
<div className="absolute -top-[10px] right-4 bg-catchup-white">
|
|
231
|
+
<BaseImage
|
|
232
|
+
src="/icons/checkbox.webp"
|
|
233
|
+
alt="checkbox"
|
|
234
|
+
size="small"
|
|
235
|
+
/>
|
|
236
|
+
</div>
|
|
237
|
+
) : learnerAnswerState === "INCORRECT" ? (
|
|
238
|
+
<div className="absolute -top-[10px] right-4 bg-catchup-white">
|
|
239
|
+
<BaseImage
|
|
240
|
+
src="/icons/cross-red.webp"
|
|
241
|
+
alt="cross-red"
|
|
242
|
+
size="small"
|
|
243
|
+
/>
|
|
244
|
+
</div>
|
|
245
|
+
) : null}
|
|
246
|
+
</div>
|
|
247
|
+
) : answerMap[materialKey] === "" ? (
|
|
248
|
+
<div
|
|
249
|
+
className={`w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed ${
|
|
250
|
+
learnerAnswerState === "CORRECT"
|
|
251
|
+
? "border-catchup-green"
|
|
252
|
+
: learnerAnswerState === "INCORRECT"
|
|
253
|
+
? "border-catchup-red"
|
|
254
|
+
: "border-catchup-blue"
|
|
255
|
+
}`}
|
|
256
|
+
>
|
|
257
|
+
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
258
|
+
<span className="italic">
|
|
259
|
+
{i18n.t("please_drop_here")}
|
|
260
|
+
</span>
|
|
269
261
|
</div>
|
|
270
|
-
|
|
262
|
+
</div>
|
|
271
263
|
) : (
|
|
272
|
-
<
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
264
|
+
<div
|
|
265
|
+
className="flex-1 cursor-pointer"
|
|
266
|
+
onClick={() => {
|
|
267
|
+
onChange(answer, materialKey, "");
|
|
268
|
+
}}
|
|
269
|
+
>
|
|
270
|
+
<ShowMaterialMediaByContentType
|
|
271
|
+
key={`${uniqueValue}-${index}`}
|
|
272
|
+
contentType={contentMap.type}
|
|
273
|
+
src={answerMap[materialKey]}
|
|
274
|
+
canFullScreen={true}
|
|
275
|
+
/>
|
|
276
|
+
</div>
|
|
277
|
+
)
|
|
278
|
+
) : (
|
|
279
|
+
<p key={materialKey} className="text-xl">
|
|
280
|
+
{constructInputWithSpecialExpressionList(
|
|
281
|
+
answerMap[materialKey]
|
|
282
|
+
).map((inputPart, index) => (
|
|
283
|
+
<span
|
|
284
|
+
key={index}
|
|
285
|
+
className={`${
|
|
286
|
+
inputPart.isBold ? "font-bold" : ""
|
|
287
|
+
} ${inputPart.isUnderline ? "underline" : ""}`}
|
|
288
|
+
>
|
|
289
|
+
{inputPart.isEquation ? (
|
|
290
|
+
<span className="text-xl">
|
|
291
|
+
<InlineMath math={inputPart.value} />
|
|
292
|
+
</span>
|
|
293
|
+
) : (
|
|
294
|
+
inputPart.value
|
|
295
|
+
)}
|
|
296
|
+
</span>
|
|
297
|
+
))}
|
|
298
|
+
</p>
|
|
299
|
+
)}
|
|
294
300
|
</div>
|
|
295
|
-
|
|
296
|
-
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
297
303
|
</div>
|
|
298
304
|
</div>
|
|
299
305
|
);
|