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.
@@ -1,18 +1,13 @@
1
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";
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 [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
- });
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
- setPasteOptionIndex(null);
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
- <DraggableItem
127
+ <div
118
128
  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}
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
- </div>
162
- )
163
- }
164
- moveCardHandler={() => {
165
- onChange(answer, pasteOptionIndex, selectedOption);
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
- <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"
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
- </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>
223
+ ) : (
224
+ <p className="text-gray-400 italic"></p>
225
+ )}
254
226
  </div>
255
227
  </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
- />
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
- <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>
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
  );