catchup-library-web 1.20.29 → 1.20.31
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 +308 -304
- package/dist/index.mjs +248 -244
- package/package.json +1 -1
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +193 -180
- 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));
|
|
@@ -80,14 +68,41 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
80
68
|
);
|
|
81
69
|
};
|
|
82
70
|
|
|
71
|
+
const handleSelectOption = (option: any) => {
|
|
72
|
+
setSelectedOption(option);
|
|
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);
|
|
100
|
+
};
|
|
101
|
+
|
|
83
102
|
const answerMap = retrieveAnswerMap();
|
|
84
103
|
|
|
85
104
|
return (
|
|
86
|
-
<div
|
|
87
|
-
className="flex flex-row flex-wrap items-center"
|
|
88
|
-
onMouseUp={() => {}}
|
|
89
|
-
onTouchStart={() => {}}
|
|
90
|
-
>
|
|
105
|
+
<div className="flex flex-row flex-wrap items-center">
|
|
91
106
|
<div className="hidden md:block">
|
|
92
107
|
<span className="font-semibold text-xl opacity-60">
|
|
93
108
|
{i18n.t("please_select_fill_in_the_blanks_text")}
|
|
@@ -109,55 +124,43 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
109
124
|
/>
|
|
110
125
|
</div>
|
|
111
126
|
) : (
|
|
112
|
-
<
|
|
127
|
+
<div
|
|
113
128
|
key={index}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
value={option}
|
|
132
|
-
showSpecialOnly={false}
|
|
133
|
-
/>
|
|
134
|
-
</p>
|
|
135
|
-
</div>
|
|
136
|
-
) : (
|
|
137
|
-
<div
|
|
138
|
-
className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge cursor-pointer"
|
|
139
|
-
onMouseDown={() => {
|
|
140
|
-
setSelectedOption(option);
|
|
141
|
-
setPasteOptionIndex(null);
|
|
142
|
-
}}
|
|
143
|
-
onTouchEnd={() => {
|
|
144
|
-
setSelectedOption(option);
|
|
145
|
-
setPasteOptionIndex(null);
|
|
146
|
-
}}
|
|
147
|
-
>
|
|
148
|
-
<ShowMaterialMediaByContentType
|
|
149
|
-
key={`${uniqueValue}-${index}`}
|
|
150
|
-
contentType={contentMap.type}
|
|
151
|
-
src={option}
|
|
152
|
-
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}
|
|
153
146
|
/>
|
|
154
|
-
</
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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>
|
|
161
164
|
)
|
|
162
165
|
)}
|
|
163
166
|
</div>
|
|
@@ -170,123 +173,133 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
170
173
|
return (
|
|
171
174
|
<div key={index} className="w-full md:w-1/2">
|
|
172
175
|
<div className="mx-2">
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
alt="checkbox"
|
|
220
|
-
size="small"
|
|
221
|
-
/>
|
|
222
|
-
</div>
|
|
223
|
-
) : learnerAnswerState === "INCORRECT" ? (
|
|
224
|
-
<div className="absolute -top-[10px] right-4 bg-catchup-white">
|
|
225
|
-
<BaseImage
|
|
226
|
-
src="/icons/cross-red.webp"
|
|
227
|
-
alt="cross-red"
|
|
228
|
-
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}
|
|
229
222
|
/>
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
) : answerMap[materialKey] === "" ? (
|
|
234
|
-
<div
|
|
235
|
-
className={`w-catchup-activity-media-box-item h-catchup-activity-media-box-item border rounded-catchup-xlarge border-dashed ${
|
|
236
|
-
learnerAnswerState === "CORRECT"
|
|
237
|
-
? "border-catchup-green"
|
|
238
|
-
: learnerAnswerState === "INCORRECT"
|
|
239
|
-
? "border-catchup-red"
|
|
240
|
-
: "border-catchup-blue"
|
|
241
|
-
}`}
|
|
242
|
-
>
|
|
243
|
-
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
244
|
-
<span className="italic">
|
|
245
|
-
{i18n.t("please_drop_here")}
|
|
246
|
-
</span>
|
|
223
|
+
) : (
|
|
224
|
+
<p className="text-gray-400 italic"></p>
|
|
225
|
+
)}
|
|
247
226
|
</div>
|
|
248
227
|
</div>
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
className="
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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>
|
|
262
261
|
</div>
|
|
263
|
-
|
|
262
|
+
</div>
|
|
264
263
|
) : (
|
|
265
|
-
<
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
)}
|
|
287
300
|
</div>
|
|
288
|
-
|
|
289
|
-
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
290
303
|
</div>
|
|
291
304
|
</div>
|
|
292
305
|
);
|