catchup-library-web 2.5.8 → 2.5.10
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 +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +158 -218
- package/dist/index.mjs +177 -237
- package/package.json +1 -1
- package/src/components/activities/MatchingActivityContent.tsx +28 -17
- package/src/components/activities/OrderingActivityContent.tsx +28 -17
- package/src/components/activities/body-contents/ActivityBodyContent.tsx +1 -1
- package/src/components/activities/body-contents/ShowBodyMediaByContentType.tsx +2 -6
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +19 -19
- package/src/components/activities/material-contents/GroupingActivityMaterialContent.tsx +24 -24
- package/src/components/activities/material-contents/MatchingActivityMaterialContent.tsx +25 -25
- package/src/components/activities/material-contents/OrderingActivityMaterialContent.tsx +16 -55
- package/src/components/activities/material-contents/ShowMaterialMediaByContentType.tsx +1 -1
- package/src/components/groups/InputGroup.tsx +2 -2
- package/src/components/groups/PageTravelGroup.tsx +46 -86
- package/src/properties/ActivityProperties.ts +2 -0
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
parseMaterialMapFromData,
|
|
6
6
|
} from "../../utilization/CatchtivityUtilization";
|
|
7
7
|
import DividerLine from "../dividers/DividerLine";
|
|
8
|
+
import VerticalDividerLine from "../dividers/VerticalDividerLine";
|
|
8
9
|
import ActivityBodyContent from "./body-contents/ActivityBodyContent";
|
|
9
10
|
import MatchingActivityMaterialContent from "./material-contents/MatchingActivityMaterialContent";
|
|
10
11
|
|
|
@@ -15,6 +16,7 @@ const MatchingActivityContent = ({
|
|
|
15
16
|
changeAnswer,
|
|
16
17
|
isPreview,
|
|
17
18
|
showCorrectAnswer,
|
|
19
|
+
isFullScreen,
|
|
18
20
|
}: IMatchingActivityProps) => {
|
|
19
21
|
const contentMap = parseContentMapFromData(data);
|
|
20
22
|
const matchingBodyMap = parseBodyMapFromData(data, "MATCHING");
|
|
@@ -31,23 +33,32 @@ const MatchingActivityContent = ({
|
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
return (
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
<div className="flex flex-row flex-wrap">
|
|
37
|
+
<div className={`${isFullScreen ? "w-full" : "w-full md:w-[40%]"}`}>
|
|
38
|
+
<ActivityBodyContent
|
|
39
|
+
bodyMap={matchingBodyMap}
|
|
40
|
+
templateType={"MATCHING"}
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
<div className={`${isFullScreen ? "contents" : "contents md:hidden"}`}>
|
|
44
|
+
<DividerLine />
|
|
45
|
+
</div>
|
|
46
|
+
<div className={`${isFullScreen ? "hidden" : "hidden md:block"}`}>
|
|
47
|
+
<VerticalDividerLine />
|
|
48
|
+
</div>
|
|
49
|
+
<div className={`${isFullScreen ? "w-full" : "w-full md:flex-1"}`}>
|
|
50
|
+
<MatchingActivityMaterialContent
|
|
51
|
+
uniqueValue={JSON.stringify(data.contentMap)}
|
|
52
|
+
answerMap={answerMap}
|
|
53
|
+
materialMap={matchingMaterialMap}
|
|
54
|
+
contentMap={contentMap}
|
|
55
|
+
checkCanAnswerQuestion={canAnswerQuestion}
|
|
56
|
+
onChange={handleMatchingAnswerOnChange}
|
|
57
|
+
isPreview={isPreview}
|
|
58
|
+
showCorrectAnswer={showCorrectAnswer}
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
51
62
|
);
|
|
52
63
|
};
|
|
53
64
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
parseMaterialMapFromData,
|
|
6
6
|
} from "../../utilization/CatchtivityUtilization";
|
|
7
7
|
import DividerLine from "../dividers/DividerLine";
|
|
8
|
+
import VerticalDividerLine from "../dividers/VerticalDividerLine";
|
|
8
9
|
import ActivityBodyContent from "./body-contents/ActivityBodyContent";
|
|
9
10
|
import OrderingActivityMaterialContent from "./material-contents/OrderingActivityMaterialContent";
|
|
10
11
|
|
|
@@ -15,6 +16,7 @@ const OrderingActivityContent = ({
|
|
|
15
16
|
changeAnswer,
|
|
16
17
|
isPreview,
|
|
17
18
|
showCorrectAnswer,
|
|
19
|
+
isFullScreen,
|
|
18
20
|
}: IOrderingActivityProps) => {
|
|
19
21
|
const contentMap = parseContentMapFromData(data);
|
|
20
22
|
const orderingBodyMap = parseBodyMapFromData(data, "ORDERING");
|
|
@@ -33,23 +35,32 @@ const OrderingActivityContent = ({
|
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
return (
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
<div className="flex flex-row flex-wrap">
|
|
39
|
+
<div className={`${isFullScreen ? "w-full" : "w-full md:w-[40%]"}`}>
|
|
40
|
+
<ActivityBodyContent
|
|
41
|
+
bodyMap={orderingBodyMap}
|
|
42
|
+
templateType={"ORDERING"}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
<div className={`${isFullScreen ? "contents" : "contents md:hidden"}`}>
|
|
46
|
+
<DividerLine />
|
|
47
|
+
</div>
|
|
48
|
+
<div className={`${isFullScreen ? "hidden" : "hidden md:block"}`}>
|
|
49
|
+
<VerticalDividerLine />
|
|
50
|
+
</div>
|
|
51
|
+
<div className={`${isFullScreen ? "w-full" : "w-full md:flex-1"}`}>
|
|
52
|
+
<OrderingActivityMaterialContent
|
|
53
|
+
uniqueValue={JSON.stringify(data.contentMap)}
|
|
54
|
+
answerMap={answerMap}
|
|
55
|
+
materialMap={orderingMaterialMap}
|
|
56
|
+
contentMap={contentMap}
|
|
57
|
+
checkCanAnswerQuestion={canAnswerQuestion}
|
|
58
|
+
onChange={handleOrderingAnswerOnChange}
|
|
59
|
+
isPreview={isPreview}
|
|
60
|
+
showCorrectAnswer={showCorrectAnswer}
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
53
64
|
);
|
|
54
65
|
};
|
|
55
66
|
|
|
@@ -107,7 +107,7 @@ const ActivityBodyContent = ({
|
|
|
107
107
|
.filter(Boolean);
|
|
108
108
|
|
|
109
109
|
return (
|
|
110
|
-
<div className="flex flex-col justify-center items-center">
|
|
110
|
+
<div className="flex flex-col justify-center items-center max-h-[40vh] overflow-y-auto">
|
|
111
111
|
{processedBodies.map((body, index) => (
|
|
112
112
|
<ShowBodyMediaByContentType
|
|
113
113
|
key={`body-${body.key}-${index}`}
|
|
@@ -356,16 +356,12 @@ const ShowBodyMediaByContentType = ({
|
|
|
356
356
|
case "IMAGE":
|
|
357
357
|
return (
|
|
358
358
|
<div className="mb-1 flex flex-col items-center relative">
|
|
359
|
-
<div
|
|
360
|
-
className={`${convertToPercentage(
|
|
361
|
-
size
|
|
362
|
-
)} rounded-catchup-xlarge relative`}
|
|
363
|
-
>
|
|
359
|
+
<div className="relative">
|
|
364
360
|
<BaseImage
|
|
365
361
|
src={value}
|
|
366
362
|
alt="body-image"
|
|
367
363
|
size="custom"
|
|
368
|
-
className="w-full rounded-catchup-xlarge"
|
|
364
|
+
className="max-h-[50vh] max-w-full object-contain rounded-catchup-xlarge"
|
|
369
365
|
/>
|
|
370
366
|
<div
|
|
371
367
|
className="absolute flex items-center justify-center top-2 right-2 h-6 w-6 cursor-pointer border rounded-catchup-xlarge border-catchup-blue p-1"
|
package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx
CHANGED
|
@@ -25,7 +25,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
25
25
|
const [draggedOption, setDraggedOption] = useState<any>(null);
|
|
26
26
|
const [dropTargetIndex, setDropTargetIndex] = useState<string | null>(null);
|
|
27
27
|
const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
|
|
28
|
-
null
|
|
28
|
+
null,
|
|
29
29
|
);
|
|
30
30
|
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
31
31
|
const dragElementRef = useRef<HTMLDivElement>(null);
|
|
@@ -48,7 +48,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
48
48
|
const correctAnswerMap: any = {};
|
|
49
49
|
Object.keys(materialMap).forEach((materialMapKey) => {
|
|
50
50
|
correctAnswerMap[materialMapKey] = JSON.parse(
|
|
51
|
-
materialMap[materialMapKey]
|
|
51
|
+
materialMap[materialMapKey],
|
|
52
52
|
)[0];
|
|
53
53
|
});
|
|
54
54
|
setDisplayAnswerMap(correctAnswerMap);
|
|
@@ -59,11 +59,11 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
59
59
|
|
|
60
60
|
const checkAnswerState = (
|
|
61
61
|
correctAnswerList: any[],
|
|
62
|
-
learnerAnswer: string
|
|
62
|
+
learnerAnswer: string,
|
|
63
63
|
): string | null => {
|
|
64
64
|
if (!isPreview) return null;
|
|
65
65
|
const foundIndex = correctAnswerList.findIndex(
|
|
66
|
-
(correctAnswer: string) => correctAnswer === learnerAnswer
|
|
66
|
+
(correctAnswer: string) => correctAnswer === learnerAnswer,
|
|
67
67
|
);
|
|
68
68
|
if (foundIndex !== -1) {
|
|
69
69
|
return "CORRECT";
|
|
@@ -73,11 +73,11 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
73
73
|
|
|
74
74
|
const checkAnswerProvided = (
|
|
75
75
|
currentAnswerMap: Record<string, any>,
|
|
76
|
-
option: string
|
|
76
|
+
option: string,
|
|
77
77
|
): boolean => {
|
|
78
78
|
return (
|
|
79
79
|
Object.keys(currentAnswerMap).findIndex(
|
|
80
|
-
(key) => currentAnswerMap[key] === option
|
|
80
|
+
(key) => currentAnswerMap[key] === option,
|
|
81
81
|
) !== -1
|
|
82
82
|
);
|
|
83
83
|
};
|
|
@@ -120,7 +120,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
120
120
|
const handleTouchStart = (
|
|
121
121
|
e: React.TouchEvent,
|
|
122
122
|
option: any,
|
|
123
|
-
element: HTMLElement
|
|
123
|
+
element: HTMLElement,
|
|
124
124
|
): void => {
|
|
125
125
|
const touch = e.touches[0];
|
|
126
126
|
setDraggedOption(option);
|
|
@@ -138,7 +138,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
138
138
|
// Find the element under the touch point
|
|
139
139
|
const elementUnder = document.elementFromPoint(
|
|
140
140
|
touch.clientX,
|
|
141
|
-
touch.clientY
|
|
141
|
+
touch.clientY,
|
|
142
142
|
);
|
|
143
143
|
const dropZone = elementUnder?.closest("[data-drop-zone]");
|
|
144
144
|
|
|
@@ -199,7 +199,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
199
199
|
}}
|
|
200
200
|
>
|
|
201
201
|
{contentMap.type === "TEXT" ? (
|
|
202
|
-
<div className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
202
|
+
<div className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
203
203
|
<p className="italic whitespace-pre-wrap">
|
|
204
204
|
<InputWithSpecialExpression
|
|
205
205
|
value={draggedOption}
|
|
@@ -208,7 +208,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
208
208
|
</p>
|
|
209
209
|
</div>
|
|
210
210
|
) : (
|
|
211
|
-
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-white shadow-lg">
|
|
211
|
+
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
212
212
|
<ShowMaterialMediaByContentType
|
|
213
213
|
key={uniqueValue}
|
|
214
214
|
contentType={contentMap.type}
|
|
@@ -231,7 +231,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
231
231
|
}}
|
|
232
232
|
>
|
|
233
233
|
{contentMap.type === "TEXT" ? (
|
|
234
|
-
<div className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
234
|
+
<div className="border-catchup-blue border-2 px-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
235
235
|
<p className="italic whitespace-pre-wrap">
|
|
236
236
|
<InputWithSpecialExpression
|
|
237
237
|
value={draggedOption}
|
|
@@ -240,7 +240,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
240
240
|
</p>
|
|
241
241
|
</div>
|
|
242
242
|
) : (
|
|
243
|
-
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-white shadow-lg">
|
|
243
|
+
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
244
244
|
<ShowMaterialMediaByContentType
|
|
245
245
|
key={uniqueValue}
|
|
246
246
|
contentType={contentMap.type}
|
|
@@ -269,8 +269,8 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
269
269
|
draggedOption === option
|
|
270
270
|
? "opacity-40"
|
|
271
271
|
: selectedOption === option
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
? "ring-2 ring-blue-500"
|
|
273
|
+
: "opacity-100"
|
|
274
274
|
} transition-all duration-200`}
|
|
275
275
|
onMouseDown={(e) => handleMouseDown(e, option)}
|
|
276
276
|
onTouchStart={(e) => handleTouchStart(e, option, e.currentTarget)}
|
|
@@ -303,14 +303,14 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
303
303
|
</div>
|
|
304
304
|
)}
|
|
305
305
|
</div>
|
|
306
|
-
)
|
|
306
|
+
),
|
|
307
307
|
)}
|
|
308
308
|
</div>
|
|
309
309
|
<div className="w-full flex flex-row flex-wrap">
|
|
310
310
|
{Object.keys(displayAnswerMap).map((materialKey, index) => {
|
|
311
311
|
const learnerAnswerState = checkAnswerState(
|
|
312
312
|
JSON.parse(materialMap[materialKey]),
|
|
313
|
-
displayAnswerMap[materialKey]
|
|
313
|
+
displayAnswerMap[materialKey],
|
|
314
314
|
);
|
|
315
315
|
return (
|
|
316
316
|
<div key={index} className="w-full md:w-1/2">
|
|
@@ -383,8 +383,8 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
383
383
|
learnerAnswerState === "CORRECT"
|
|
384
384
|
? "border-catchup-green"
|
|
385
385
|
: learnerAnswerState === "INCORRECT"
|
|
386
|
-
|
|
387
|
-
|
|
386
|
+
? "border-catchup-red"
|
|
387
|
+
: "border-catchup-blue"
|
|
388
388
|
}`}
|
|
389
389
|
>
|
|
390
390
|
<div className="h-full flex flex-col items-center justify-center px-4 py-2">
|
|
@@ -412,7 +412,7 @@ const FillInTheBlanksActivityMaterialContent = ({
|
|
|
412
412
|
) : (
|
|
413
413
|
<p key={materialKey} className="text-xl">
|
|
414
414
|
{constructInputWithSpecialExpressionList(
|
|
415
|
-
displayAnswerMap[materialKey]
|
|
415
|
+
displayAnswerMap[materialKey],
|
|
416
416
|
).map((inputPart, index) => (
|
|
417
417
|
<span
|
|
418
418
|
key={index}
|
|
@@ -19,7 +19,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
19
19
|
const [draggedValue, setDraggedValue] = useState<string | null>(null);
|
|
20
20
|
const [dropTargetKey, setDropTargetKey] = useState<string | null>(null);
|
|
21
21
|
const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
|
|
22
|
-
null
|
|
22
|
+
null,
|
|
23
23
|
);
|
|
24
24
|
const [shuffledMaterialList, setShuffledMaterialList] = useState<any[]>([]);
|
|
25
25
|
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
@@ -142,7 +142,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
142
142
|
return shuffledMaterialList.filter(
|
|
143
143
|
(material) =>
|
|
144
144
|
selectedValueList.findIndex((value: string) => material === value) ===
|
|
145
|
-
-1
|
|
145
|
+
-1,
|
|
146
146
|
);
|
|
147
147
|
};
|
|
148
148
|
|
|
@@ -151,7 +151,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
151
151
|
if (!learnerAnswer) return "EMPTY";
|
|
152
152
|
if (!correctAnswerList) return "EMPTY";
|
|
153
153
|
const foundIndex = correctAnswerList.findIndex(
|
|
154
|
-
(correctAnswer: string) => correctAnswer === learnerAnswer
|
|
154
|
+
(correctAnswer: string) => correctAnswer === learnerAnswer,
|
|
155
155
|
);
|
|
156
156
|
if (foundIndex !== -1) {
|
|
157
157
|
return "CORRECT";
|
|
@@ -161,7 +161,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
161
161
|
|
|
162
162
|
const handleMouseDown = (
|
|
163
163
|
e: React.MouseEvent,
|
|
164
|
-
materialValue: string
|
|
164
|
+
materialValue: string,
|
|
165
165
|
): void => {
|
|
166
166
|
if (!checkCanAnswerQuestion()) return;
|
|
167
167
|
e.preventDefault();
|
|
@@ -198,7 +198,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
198
198
|
const handleTouchStart = (
|
|
199
199
|
e: React.TouchEvent,
|
|
200
200
|
materialValue: string,
|
|
201
|
-
element: HTMLElement
|
|
201
|
+
element: HTMLElement,
|
|
202
202
|
): void => {
|
|
203
203
|
if (!checkCanAnswerQuestion()) return;
|
|
204
204
|
const touch = e.touches[0];
|
|
@@ -216,7 +216,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
216
216
|
|
|
217
217
|
const elementUnder = document.elementFromPoint(
|
|
218
218
|
touch.clientX,
|
|
219
|
-
touch.clientY
|
|
219
|
+
touch.clientY,
|
|
220
220
|
);
|
|
221
221
|
const dropZone = elementUnder?.closest("[data-grouping-drop-zone]");
|
|
222
222
|
|
|
@@ -266,7 +266,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
266
266
|
}}
|
|
267
267
|
>
|
|
268
268
|
{contentMap.type === "TEXT" ? (
|
|
269
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
269
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
270
270
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px]">
|
|
271
271
|
<p className="text-xl text-center whitespace-pre-wrap">
|
|
272
272
|
{constructInputWithSpecialExpressionList(draggedValue).map(
|
|
@@ -285,13 +285,13 @@ const GroupingActivityMaterialContent = ({
|
|
|
285
285
|
inputPart.value
|
|
286
286
|
)}
|
|
287
287
|
</span>
|
|
288
|
-
)
|
|
288
|
+
),
|
|
289
289
|
)}
|
|
290
290
|
</p>
|
|
291
291
|
</div>
|
|
292
292
|
</div>
|
|
293
293
|
) : (
|
|
294
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
294
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
295
295
|
<ShowMaterialMediaByContentType
|
|
296
296
|
key={`${uniqueValue}-drag-mouse`}
|
|
297
297
|
contentType={contentMap.type}
|
|
@@ -314,7 +314,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
314
314
|
}}
|
|
315
315
|
>
|
|
316
316
|
{contentMap.type === "TEXT" ? (
|
|
317
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
317
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
318
318
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px]">
|
|
319
319
|
<p className="text-xl text-center whitespace-pre-wrap">
|
|
320
320
|
{constructInputWithSpecialExpressionList(draggedValue).map(
|
|
@@ -333,13 +333,13 @@ const GroupingActivityMaterialContent = ({
|
|
|
333
333
|
inputPart.value
|
|
334
334
|
)}
|
|
335
335
|
</span>
|
|
336
|
-
)
|
|
336
|
+
),
|
|
337
337
|
)}
|
|
338
338
|
</p>
|
|
339
339
|
</div>
|
|
340
340
|
</div>
|
|
341
341
|
) : (
|
|
342
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
342
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
343
343
|
<ShowMaterialMediaByContentType
|
|
344
344
|
key={`${uniqueValue}-drag-touch`}
|
|
345
345
|
contentType={contentMap.type}
|
|
@@ -363,8 +363,8 @@ const GroupingActivityMaterialContent = ({
|
|
|
363
363
|
draggedValue === materialValue
|
|
364
364
|
? "opacity-40"
|
|
365
365
|
: selectedValue === materialValue
|
|
366
|
-
|
|
367
|
-
|
|
366
|
+
? "ring-2 ring-blue-500"
|
|
367
|
+
: "opacity-100"
|
|
368
368
|
} transition-all duration-200`}
|
|
369
369
|
onMouseDown={(e) => handleMouseDown(e, materialValue)}
|
|
370
370
|
onTouchStart={(e) =>
|
|
@@ -389,7 +389,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
389
389
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px] overflow-y-auto">
|
|
390
390
|
<p className="text-xl text-center whitespace-pre-wrap">
|
|
391
391
|
{constructInputWithSpecialExpressionList(
|
|
392
|
-
materialValue
|
|
392
|
+
materialValue,
|
|
393
393
|
).map((inputPart, index) => (
|
|
394
394
|
<span
|
|
395
395
|
key={index}
|
|
@@ -452,7 +452,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
452
452
|
inputPart.value
|
|
453
453
|
)}
|
|
454
454
|
</span>
|
|
455
|
-
)
|
|
455
|
+
),
|
|
456
456
|
)}
|
|
457
457
|
</p>
|
|
458
458
|
</div>
|
|
@@ -481,7 +481,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
481
481
|
(answerMapValue: string, answerMapIndex: number) => {
|
|
482
482
|
const learnerAnswerState = checkAnswerState(
|
|
483
483
|
materialMap[answerMapKey],
|
|
484
|
-
answerMapValue
|
|
484
|
+
answerMapValue,
|
|
485
485
|
);
|
|
486
486
|
return (
|
|
487
487
|
<div key={answerMapIndex} className="p-1">
|
|
@@ -497,10 +497,10 @@ const GroupingActivityMaterialContent = ({
|
|
|
497
497
|
learnerAnswerState === "EMPTY"
|
|
498
498
|
? "border-catchup-lighter-gray"
|
|
499
499
|
: learnerAnswerState === "CORRECT"
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
500
|
+
? "border-catchup-green"
|
|
501
|
+
: learnerAnswerState === "INCORRECT"
|
|
502
|
+
? "border-catchup-red"
|
|
503
|
+
: "border-catchup-blue"
|
|
504
504
|
} border-2 rounded-catchup-xlarge h-full flex flex-col items-center justify-center transition-all duration-300 cursor-pointer`}
|
|
505
505
|
onClick={(e) => {
|
|
506
506
|
e.stopPropagation();
|
|
@@ -509,7 +509,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
509
509
|
answerMap,
|
|
510
510
|
answerMapKey,
|
|
511
511
|
null,
|
|
512
|
-
answerMapIndex
|
|
512
|
+
answerMapIndex,
|
|
513
513
|
);
|
|
514
514
|
setSelectedValue(null);
|
|
515
515
|
}
|
|
@@ -520,7 +520,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
520
520
|
<div className="m-2">
|
|
521
521
|
<p className="text-xl text-center whitespace-pre-wrap">
|
|
522
522
|
{constructInputWithSpecialExpressionList(
|
|
523
|
-
answerMapValue
|
|
523
|
+
answerMapValue,
|
|
524
524
|
).map((inputPart, index) => (
|
|
525
525
|
<span
|
|
526
526
|
key={index}
|
|
@@ -560,7 +560,7 @@ const GroupingActivityMaterialContent = ({
|
|
|
560
560
|
</div>
|
|
561
561
|
</div>
|
|
562
562
|
);
|
|
563
|
-
}
|
|
563
|
+
},
|
|
564
564
|
)}
|
|
565
565
|
</div>
|
|
566
566
|
</div>
|
|
@@ -19,7 +19,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
19
19
|
const [draggedValue, setDraggedValue] = useState<string | null>(null);
|
|
20
20
|
const [dropTargetKey, setDropTargetKey] = useState<string | null>(null);
|
|
21
21
|
const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
|
|
22
|
-
null
|
|
22
|
+
null,
|
|
23
23
|
);
|
|
24
24
|
const [shuffledMaterialList, setShuffledMaterialList] = useState<any[]>([]);
|
|
25
25
|
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
@@ -140,7 +140,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
140
140
|
return shuffledMaterialList.filter(
|
|
141
141
|
(material) =>
|
|
142
142
|
selectedValueList.findIndex((value: string) => material === value) ===
|
|
143
|
-
-1
|
|
143
|
+
-1,
|
|
144
144
|
);
|
|
145
145
|
};
|
|
146
146
|
|
|
@@ -156,7 +156,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
156
156
|
// Mouse drag handlers
|
|
157
157
|
const handleMouseDown = (
|
|
158
158
|
e: React.MouseEvent,
|
|
159
|
-
materialValue: string
|
|
159
|
+
materialValue: string,
|
|
160
160
|
): void => {
|
|
161
161
|
if (!checkCanAnswerQuestion()) return;
|
|
162
162
|
e.preventDefault();
|
|
@@ -195,7 +195,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
195
195
|
const handleTouchStart = (
|
|
196
196
|
e: React.TouchEvent,
|
|
197
197
|
materialValue: string,
|
|
198
|
-
element: HTMLElement
|
|
198
|
+
element: HTMLElement,
|
|
199
199
|
): void => {
|
|
200
200
|
if (!checkCanAnswerQuestion()) return;
|
|
201
201
|
const touch = e.touches[0];
|
|
@@ -214,7 +214,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
214
214
|
// Find the element under the touch point
|
|
215
215
|
const elementUnder = document.elementFromPoint(
|
|
216
216
|
touch.clientX,
|
|
217
|
-
touch.clientY
|
|
217
|
+
touch.clientY,
|
|
218
218
|
);
|
|
219
219
|
const dropZone = elementUnder?.closest("[data-matching-drop-zone]");
|
|
220
220
|
|
|
@@ -264,7 +264,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
264
264
|
}}
|
|
265
265
|
>
|
|
266
266
|
{contentMap.type === "TEXT" ? (
|
|
267
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
267
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
268
268
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px] px-4">
|
|
269
269
|
<p className="text-lg whitespace-pre-wrap">
|
|
270
270
|
{constructInputWithSpecialExpressionList(draggedValue).map(
|
|
@@ -283,13 +283,13 @@ const MatchingActivityMaterialContent = ({
|
|
|
283
283
|
inputPart.value
|
|
284
284
|
)}
|
|
285
285
|
</span>
|
|
286
|
-
)
|
|
286
|
+
),
|
|
287
287
|
)}
|
|
288
288
|
</p>
|
|
289
289
|
</div>
|
|
290
290
|
</div>
|
|
291
291
|
) : (
|
|
292
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
292
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
293
293
|
<ShowMaterialMediaByContentType
|
|
294
294
|
key={`${uniqueValue}-drag-mouse`}
|
|
295
295
|
contentType={contentMap.type}
|
|
@@ -311,7 +311,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
311
311
|
}}
|
|
312
312
|
>
|
|
313
313
|
{contentMap.type === "TEXT" ? (
|
|
314
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
314
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
315
315
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px] px-4">
|
|
316
316
|
<p className="text-lg whitespace-pre-wrap">
|
|
317
317
|
{constructInputWithSpecialExpressionList(draggedValue).map(
|
|
@@ -330,13 +330,13 @@ const MatchingActivityMaterialContent = ({
|
|
|
330
330
|
inputPart.value
|
|
331
331
|
)}
|
|
332
332
|
</span>
|
|
333
|
-
)
|
|
333
|
+
),
|
|
334
334
|
)}
|
|
335
335
|
</p>
|
|
336
336
|
</div>
|
|
337
337
|
</div>
|
|
338
338
|
) : (
|
|
339
|
-
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
339
|
+
<div className="border-catchup-blue border-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
340
340
|
<ShowMaterialMediaByContentType
|
|
341
341
|
key={`${uniqueValue}-drag-touch`}
|
|
342
342
|
contentType={contentMap.type}
|
|
@@ -362,8 +362,8 @@ const MatchingActivityMaterialContent = ({
|
|
|
362
362
|
draggedValue === materialValue
|
|
363
363
|
? "opacity-40"
|
|
364
364
|
: selectedValue === materialValue
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
? "ring-2 ring-blue-500"
|
|
366
|
+
: "opacity-100"
|
|
367
367
|
} transition-all duration-200`}
|
|
368
368
|
onMouseDown={(e) => handleMouseDown(e, materialValue)}
|
|
369
369
|
onTouchStart={(e) =>
|
|
@@ -388,7 +388,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
388
388
|
<div className="flex flex-col items-center justify-center m-2 min-w-[200px] overflow-y-auto px-4">
|
|
389
389
|
<p className="text-lg whitespace-pre-wrap">
|
|
390
390
|
{constructInputWithSpecialExpressionList(
|
|
391
|
-
materialValue
|
|
391
|
+
materialValue,
|
|
392
392
|
).map((inputPart, index) => (
|
|
393
393
|
<span
|
|
394
394
|
key={index}
|
|
@@ -428,7 +428,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
428
428
|
{Object.keys(displayAnswerMap).map((answerMapKey, index) => {
|
|
429
429
|
const learnerAnswerState = checkAnswerState(
|
|
430
430
|
materialMap[answerMapKey],
|
|
431
|
-
displayAnswerMap[answerMapKey]
|
|
431
|
+
displayAnswerMap[answerMapKey],
|
|
432
432
|
);
|
|
433
433
|
|
|
434
434
|
return (
|
|
@@ -443,10 +443,10 @@ const MatchingActivityMaterialContent = ({
|
|
|
443
443
|
learnerAnswerState === "EMPTY"
|
|
444
444
|
? "border-catchup-blue"
|
|
445
445
|
: learnerAnswerState === "CORRECT"
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
446
|
+
? "border-catchup-green"
|
|
447
|
+
: learnerAnswerState === "INCORRECT"
|
|
448
|
+
? "border-catchup-red"
|
|
449
|
+
: "border-catchup-blue"
|
|
450
450
|
}`}
|
|
451
451
|
>
|
|
452
452
|
<div className="flex flex-col items-center justify-center transition-all duration-300 px-4 text-center">
|
|
@@ -467,7 +467,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
467
467
|
inputPart.value
|
|
468
468
|
)}
|
|
469
469
|
</span>
|
|
470
|
-
)
|
|
470
|
+
),
|
|
471
471
|
)}
|
|
472
472
|
</p>
|
|
473
473
|
</div>
|
|
@@ -495,10 +495,10 @@ const MatchingActivityMaterialContent = ({
|
|
|
495
495
|
learnerAnswerState === "EMPTY"
|
|
496
496
|
? "border-catchup-blue"
|
|
497
497
|
: learnerAnswerState === "CORRECT"
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
498
|
+
? "border-catchup-green"
|
|
499
|
+
: learnerAnswerState === "INCORRECT"
|
|
500
|
+
? "border-catchup-red"
|
|
501
|
+
: "border-catchup-blue"
|
|
502
502
|
}`}
|
|
503
503
|
>
|
|
504
504
|
<div
|
|
@@ -518,7 +518,7 @@ const MatchingActivityMaterialContent = ({
|
|
|
518
518
|
contentMap.type === "TEXT" ? (
|
|
519
519
|
<p className="text-lg whitespace-pre-wrap">
|
|
520
520
|
{constructInputWithSpecialExpressionList(
|
|
521
|
-
displayAnswerMap[answerMapKey]
|
|
521
|
+
displayAnswerMap[answerMapKey],
|
|
522
522
|
).map((inputPart, index) => (
|
|
523
523
|
<span
|
|
524
524
|
key={index}
|