catchup-library-web 1.0.0 → 1.0.2

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.
Files changed (51) hide show
  1. package/dist/index.d.mts +239 -2
  2. package/dist/index.d.ts +239 -2
  3. package/dist/index.js +4686 -2
  4. package/dist/index.mjs +4621 -1
  5. package/package.json +10 -2
  6. package/src/components/activities/DropdownActivityContent.tsx +73 -0
  7. package/src/components/activities/FillInTheBlanksActivityContent.tsx +102 -0
  8. package/src/components/activities/GroupingActivityContent.tsx +62 -0
  9. package/src/components/activities/MCMAActivityContent.tsx +65 -0
  10. package/src/components/activities/MCSAActivityContent.tsx +58 -0
  11. package/src/components/activities/MatchingActivityContent.tsx +57 -0
  12. package/src/components/activities/OpenEndedActivityContent.tsx +92 -0
  13. package/src/components/activities/OrderingActivityContent.tsx +59 -0
  14. package/src/components/activities/TrueFalseActivityContent.tsx +98 -0
  15. package/src/components/activities/body-content/ActivityBodyContent.tsx +108 -0
  16. package/src/components/activities/body-content/ShowBodyMediaByContentType.tsx +404 -0
  17. package/src/components/activities/empty-content/ActivityEmptyContent.tsx +15 -0
  18. package/src/components/activities/material-content/DropdownActivityMaterialContent.tsx +227 -0
  19. package/src/components/activities/material-content/FillInTheBlanksActivityMaterialContent.tsx +270 -0
  20. package/src/components/activities/material-content/GroupingActivityMaterialContent.tsx +359 -0
  21. package/src/components/activities/material-content/MCMAActivityMaterialContent.tsx +166 -0
  22. package/src/components/activities/material-content/MCSAActivityMaterialContent.tsx +165 -0
  23. package/src/components/activities/material-content/MatchingActivityMaterialContent.tsx +332 -0
  24. package/src/components/activities/material-content/OpenEndedActivityMaterialContent.tsx +818 -0
  25. package/src/components/activities/material-content/OrderingActivityMaterialContent.tsx +216 -0
  26. package/src/components/activities/material-content/ShowMaterialMediaByContentType.tsx +172 -0
  27. package/src/components/activities/material-content/TrueFalseActivityMaterialContent.tsx +217 -0
  28. package/src/components/activities/solution-content/ActivitySolutionContent.tsx +86 -0
  29. package/src/components/dividers/BlueVerticalDividerLine.tsx +13 -0
  30. package/src/components/dividers/DividerLine.tsx +5 -0
  31. package/src/components/dividers/VerticalDividerLine.tsx +5 -0
  32. package/src/components/dnds/DraggableDroppableItem.tsx +62 -0
  33. package/src/components/dnds/DraggableItem.tsx +41 -0
  34. package/src/components/dnds/DroppableItem.tsx +38 -0
  35. package/src/components/dropdowns/MediaDropdown.tsx +51 -0
  36. package/src/components/groups/InputGroup.tsx +330 -0
  37. package/src/hooks/useScreenSize.ts +40 -0
  38. package/src/index.ts +24 -0
  39. package/src/language/i18n.ts +10 -0
  40. package/src/properties/ActivityProperties.ts +204 -0
  41. package/src/properties/ButtonProperties.ts +1 -1
  42. package/src/properties/CommonProperties.ts +1 -1
  43. package/src/properties/DividerLineProperties.ts +3 -0
  44. package/src/properties/DnDProperties.ts +28 -0
  45. package/src/properties/DropdownProperties.ts +5 -0
  46. package/src/properties/EnumProperties.ts +11 -0
  47. package/src/properties/GroupProperties.ts +19 -0
  48. package/src/utilization/AppUtilization.ts +56 -0
  49. package/src/utilization/CatchtivityUtilization.ts +1566 -0
  50. package/src/utilization/StorageUtilization.ts +35 -0
  51. package/tsconfig.json +2 -1
@@ -0,0 +1,216 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useDrop } from "react-dnd";
3
+ import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
4
+ import { InlineMath } from "react-katex";
5
+ import useScreenSize from "../../../hooks/useScreenSize";
6
+ import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
7
+ import { IOrderingActivityMaterialProps } from "../../../properties/ActivityProperties";
8
+ import DraggableDroppableItem from "../../dnds/DraggableDroppableItem";
9
+
10
+ const OrderingActivityMaterialContent = ({
11
+ uniqueValue,
12
+ answer,
13
+ materialMap,
14
+ contentMap,
15
+ checkCanAnswerQuestion,
16
+ onChange,
17
+ isPreview,
18
+ showCorrectAnswer,
19
+ }: IOrderingActivityMaterialProps) => {
20
+ const [selectedTargetKey, setSelectedTargetKey] = useState(null);
21
+ const [selectedKey, setSelectedKey] = useState<string | null>(null);
22
+ const { screenSize } = useScreenSize();
23
+ const [view, setView] = useState("PC");
24
+ const [{ isOver, canDrop }, drop] = useDrop({
25
+ accept: "ORDERING",
26
+ drop: () => {},
27
+ collect: (monitor) => ({
28
+ isOver: monitor.isOver(),
29
+ canDrop: monitor.canDrop(),
30
+ }),
31
+ });
32
+
33
+ useEffect(() => {
34
+ if (!screenSize) return;
35
+ if (screenSize.width <= 768) {
36
+ setView("TABLET");
37
+ } else {
38
+ setView("PC");
39
+ }
40
+ }, [screenSize]);
41
+
42
+ useEffect(() => {
43
+ if (!showCorrectAnswer) return;
44
+ const answerMap = answer.data.find(
45
+ (answerData: any) => answerData.type === "ORDERING"
46
+ ).answerMap;
47
+ Object.keys(answerMap).forEach((answerKey, index) => {
48
+ answerMap[answerKey] = index;
49
+ });
50
+ }, [showCorrectAnswer]);
51
+
52
+ const retrieveAnswerMap = () => {
53
+ const foundIndex = answer.data.findIndex(
54
+ (answerData: any) => answerData.type === "ORDERING"
55
+ );
56
+ return answer.data[foundIndex].answerMap;
57
+ };
58
+
59
+ const checkAnswerState = (correctAnswer: string, learnerAnswer: string) => {
60
+ if (!isPreview) return "HIDDEN";
61
+ if (correctAnswer === learnerAnswer) {
62
+ return "CORRECT";
63
+ }
64
+ return "INCORRECT";
65
+ };
66
+
67
+ const handleOrderingActivityItemChange = (
68
+ selectedKey: string,
69
+ materialKey: string
70
+ ) => {
71
+ if (checkCanAnswerQuestion()) {
72
+ if (selectedKey) {
73
+ onChange(answer, selectedKey, materialKey);
74
+ setSelectedKey(null);
75
+ } else {
76
+ setSelectedKey(materialKey);
77
+ }
78
+ }
79
+ };
80
+
81
+ const calculateMarginTop = (index: number) => {
82
+ if (index === 0) {
83
+ return 0;
84
+ } else if (index === 1) {
85
+ return 150;
86
+ } else if (index % 2 === 0) {
87
+ return -150;
88
+ } else if (index % 2 === 1) {
89
+ return 0;
90
+ }
91
+ return 0;
92
+ };
93
+
94
+ const answerMap = retrieveAnswerMap();
95
+
96
+ return (
97
+ <div className="flex flex-row flex-wrap">
98
+ {Object.keys(answerMap).map((materialKey, index) => {
99
+ const learnerAnswerState = checkAnswerState(
100
+ answerMap[materialKey] + "",
101
+ index + ""
102
+ );
103
+ return (
104
+ <div className="w-full lg:w-1/2" key={index}>
105
+ <div
106
+ className={`flex flex-row items-center my-4 mx-2`}
107
+ style={{
108
+ marginTop:
109
+ view === "PC"
110
+ ? calculateMarginTop(parseFloat(materialKey))
111
+ : 0,
112
+ }}
113
+ >
114
+ <div className="mr-3">
115
+ <div
116
+ className={`${
117
+ learnerAnswerState === "CORRECT"
118
+ ? "border-catchup-green"
119
+ : learnerAnswerState === "INCORRECT"
120
+ ? "border-catchup-red"
121
+ : selectedKey === materialKey
122
+ ? "border-catchup-blue"
123
+ : "border-catchup-lighter-gray"
124
+ } min-h-catchup-activity-outer-box-item w-catchup-activity-box-item flex flex-col items-center justify-center border-2 rounded-catchup-xlarge cursor-pointer transition-all duration-300`}
125
+ >
126
+ <div
127
+ className={`${
128
+ selectedKey === materialKey
129
+ ? "border-2 border-catchup-light-gray"
130
+ : "border-2 border-catchup-blue"
131
+ } flex flex-col items-center justify-center transition-all duration-300 rounded-catchup-full w-[50px] h-[50px]`}
132
+ >
133
+ <p className="">{parseFloat(materialKey) + 1}</p>
134
+ </div>
135
+ </div>
136
+ </div>
137
+
138
+ <DraggableDroppableItem
139
+ key={index}
140
+ item={{ index: materialKey }}
141
+ type={"ORDERING"}
142
+ dropRef={drop}
143
+ component={
144
+ <div
145
+ className={`${
146
+ canDrop
147
+ ? selectedKey !== materialKey
148
+ ? selectedTargetKey === materialKey
149
+ ? "bg-catchup-light-blue rounded-catchup-xlarge"
150
+ : "bg-catchup-light-blue rounded-catchup-xlarge opacity-40"
151
+ : ""
152
+ : ""
153
+ } flex-1 min-h-catchup-activity-outer-box-item flex flex-col items-center justify-center border-2 rounded-catchup-xlarge cursor-pointer p-3 ${
154
+ learnerAnswerState === "CORRECT"
155
+ ? "border-catchup-green"
156
+ : learnerAnswerState === "INCORRECT"
157
+ ? "border-catchup-red"
158
+ : "border-catchup-blue"
159
+ }`}
160
+ onMouseDown={() => {
161
+ if (checkCanAnswerQuestion()) {
162
+ setSelectedKey(materialKey);
163
+ }
164
+ }}
165
+ >
166
+ {contentMap.type === "TEXT" ? (
167
+ <p className="text-xl whitespace-pre-wrap">
168
+ {constructInputWithSpecialExpressionList(
169
+ materialMap[answerMap[materialKey]]
170
+ ).map((inputPart, index) => (
171
+ <span
172
+ key={index}
173
+ className={`${
174
+ inputPart.isBold ? "font-bold" : ""
175
+ } ${inputPart.isUnderline ? "underline" : ""}`}
176
+ >
177
+ {inputPart.isEquation ? (
178
+ <span className="text-2xl">
179
+ <InlineMath math={inputPart.value} />
180
+ </span>
181
+ ) : (
182
+ inputPart.value
183
+ )}
184
+ </span>
185
+ ))}
186
+ </p>
187
+ ) : (
188
+ <ShowMaterialMediaByContentType
189
+ key={`${uniqueValue}-${index}`}
190
+ contentType={contentMap.type}
191
+ src={materialMap[answerMap[materialKey]]}
192
+ canFullScreen={true}
193
+ />
194
+ )}
195
+ </div>
196
+ }
197
+ target={selectedTargetKey}
198
+ setTarget={setSelectedTargetKey}
199
+ moveCardHandler={() => {
200
+ if (!selectedKey) return;
201
+ if (!selectedTargetKey) return;
202
+ handleOrderingActivityItemChange(
203
+ selectedKey,
204
+ selectedTargetKey
205
+ );
206
+ }}
207
+ />
208
+ </div>
209
+ </div>
210
+ );
211
+ })}
212
+ </div>
213
+ );
214
+ };
215
+
216
+ export default OrderingActivityMaterialContent;
@@ -0,0 +1,172 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import Modal from "react-modal";
3
+ import BaseImage from "../../images/BaseImage";
4
+ import { IShowMaterialMediaByContentTypeProps } from "../../../properties/ActivityProperties";
5
+
6
+ const ShowMaterialMediaByContentType = ({
7
+ key,
8
+ contentType,
9
+ src,
10
+ canFullScreen,
11
+ }: IShowMaterialMediaByContentTypeProps) => {
12
+ const [showFullScreen, setShowFullScreen] = useState<boolean>(false);
13
+ const [selectedFullScreenItem, setSelectedFullScreenItem] = useState<
14
+ any | null
15
+ >(null);
16
+ const [isLoaded, setIsLoaded] = useState<boolean>(false);
17
+ const [isFullHeight, setIsFullHeight] = useState<boolean>(false);
18
+ const imageRef = useRef<HTMLImageElement>(null);
19
+
20
+ useEffect(() => {
21
+ setIsLoaded(false);
22
+ }, []);
23
+
24
+ useEffect(() => {
25
+ if (!isLoaded) return;
26
+ if (!imageRef) return;
27
+ if (!imageRef.current) return;
28
+ const w = imageRef.current.naturalWidth;
29
+ const h = imageRef.current.naturalHeight;
30
+ if (w >= h) {
31
+ setIsFullHeight(false);
32
+ } else {
33
+ setIsFullHeight(true);
34
+ }
35
+ }, [isLoaded, key]);
36
+
37
+ const RenderShowFullScreenItem = () => {
38
+ return (
39
+ <Modal
40
+ isOpen={showFullScreen}
41
+ onAfterOpen={() => {}}
42
+ onRequestClose={() => {
43
+ setShowFullScreen(false);
44
+ setSelectedFullScreenItem(null);
45
+ }}
46
+ style={{
47
+ content: {
48
+ top: "50%",
49
+ left: "50%",
50
+ right: "auto",
51
+ bottom: "auto",
52
+ marginRight: "-50%",
53
+ transform: "translate(-50%, -50%)",
54
+ padding: 0,
55
+ borderRadius: 20,
56
+ background: "",
57
+ border: "",
58
+ width: "900px",
59
+ maxHeight: "70%",
60
+ overflow: "auto",
61
+ },
62
+ overlay: {
63
+ background: "rgba(0, 0, 0, 0.6)",
64
+ },
65
+ }}
66
+ contentLabel=""
67
+ >
68
+ <div className="flex-1 flex flex-col">
69
+ {/* <div className="m-4"> */}
70
+ <div className="ml-auto px-5 py-3">
71
+ <BaseImage
72
+ src="/icons/cross-red.png"
73
+ alt="cross-red"
74
+ size="medium"
75
+ onClick={() => {
76
+ setShowFullScreen(false);
77
+ setSelectedFullScreenItem(null);
78
+ }}
79
+ />
80
+ </div>
81
+ <div className="flex items-center justify-center h-[500px]">
82
+ <BaseImage
83
+ src={selectedFullScreenItem}
84
+ alt="selected-fullscreen-item"
85
+ size="custom"
86
+ className="w-full"
87
+ />
88
+ </div>
89
+ </div>
90
+ </Modal>
91
+ );
92
+ };
93
+
94
+ return contentType === "IMAGE" ? (
95
+ <div key={key}>
96
+ {RenderShowFullScreenItem()}
97
+ <div className="my-2">
98
+ <div className="h-full flex flex-row flex-wrap items-center">
99
+ <div
100
+ className={`${
101
+ isFullHeight
102
+ ? "h-catchup-activity-box-item"
103
+ : "max-w-catchup-activity-box-item"
104
+ } flex flex-col justify-center items-center relative`}
105
+ >
106
+ <BaseImage
107
+ src={src}
108
+ alt="image"
109
+ ref={imageRef}
110
+ size="custom"
111
+ className="h-full rounded-catchup-xlarge"
112
+ onLoad={() => {
113
+ setIsLoaded(true);
114
+ }}
115
+ />
116
+ {src !== null &&
117
+ src !== "" &&
118
+ src !== "DEFAULT_OPTION" &&
119
+ canFullScreen ? (
120
+ <div
121
+ 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"
122
+ onMouseEnter={(e) => {
123
+ e.preventDefault();
124
+ }}
125
+ onClick={(e) => {
126
+ e.preventDefault();
127
+ setShowFullScreen(true);
128
+ setSelectedFullScreenItem(src);
129
+ }}
130
+ >
131
+ <BaseImage
132
+ src="/icons/arrow-up.png"
133
+ alt="arrow-up"
134
+ size="custom"
135
+ className="w-full"
136
+ />
137
+ </div>
138
+ ) : null}
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ ) : contentType === "VIDEO" ? (
144
+ <div className="my-2">
145
+ <div className="h-full flex flex-row flex-wrap items-center">
146
+ <div className="h-full flex flex-col justify-center items-center">
147
+ <video
148
+ className="h-catchup-activity-box-item rounded-catchup-xlarge"
149
+ src={src}
150
+ controls
151
+ onClick={() => {}}
152
+ />
153
+ </div>
154
+ </div>
155
+ </div>
156
+ ) : contentType === "AUDIO" ? (
157
+ <div className="my-2">
158
+ <div className="h-full flex flex-row flex-wrap items-center">
159
+ <div className="h-full flex flex-col justify-center items-center">
160
+ <audio
161
+ className="h-catchup-activity-box-item rounded-catchup-xlarge"
162
+ src={src}
163
+ controls
164
+ onClick={() => {}}
165
+ />
166
+ </div>
167
+ </div>
168
+ </div>
169
+ ) : null;
170
+ };
171
+
172
+ export default ShowMaterialMediaByContentType;
@@ -0,0 +1,217 @@
1
+ import { useEffect, useState } from "react";
2
+ import useScreenSize from "../../../hooks/useScreenSize";
3
+ import i18n from "../../../language/i18n";
4
+ import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
5
+ import { InlineMath } from "react-katex";
6
+ import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
7
+ import BaseImage from "../../images/BaseImage";
8
+ import { ITrueFalseActivityMaterialProps } from "../../../properties/ActivityProperties";
9
+ import DividerLine from "../../dividers/DividerLine";
10
+ import { shuffleArray } from "../../../utilization/AppUtilization";
11
+
12
+ const TrueFalseActivityMaterialContent = ({
13
+ uniqueValue,
14
+ answer,
15
+ materialMap,
16
+ contentMap,
17
+ checkCanAnswerQuestion,
18
+ onChange,
19
+ isPreview,
20
+ showCorrectAnswer,
21
+ }: ITrueFalseActivityMaterialProps) => {
22
+ const { screenSize } = useScreenSize();
23
+ const [shuffleOptionList, setShuffleOptionList] = useState<any[]>([]);
24
+
25
+ useEffect(() => {
26
+ const optionList = [];
27
+ optionList.push(...materialMap.trueList);
28
+ optionList.push(...materialMap.falseList);
29
+ if (isPreview) {
30
+ setShuffleOptionList(optionList);
31
+ } else {
32
+ setShuffleOptionList(shuffleArray(optionList));
33
+ }
34
+ }, []);
35
+
36
+ useEffect(() => {
37
+ if (!showCorrectAnswer) return;
38
+ answer.data.find(
39
+ (answerData: any) => answerData.type === "TRUE_FALSE"
40
+ ).answerMap = materialMap;
41
+ }, [showCorrectAnswer]);
42
+
43
+ const retrieveAnswer = () => {
44
+ if (!answer)
45
+ return {
46
+ answerMap: {
47
+ trueList: [],
48
+ falseList: [],
49
+ },
50
+ };
51
+ return answer.data.find(
52
+ (answerData: any) => answerData.type === "TRUE_FALSE"
53
+ );
54
+ };
55
+
56
+ const retrieveAnswerMap = () => {
57
+ const { answerMap } = retrieveAnswer();
58
+ return answerMap;
59
+ };
60
+
61
+ const checkAnswerState = (correctAnswer: string, learnerAnswer: string) => {
62
+ if (!isPreview) return "HIDDEN";
63
+ if (correctAnswer === learnerAnswer) {
64
+ return "CORRECT";
65
+ }
66
+ return "INCORRECT";
67
+ };
68
+
69
+ const answerMap = retrieveAnswerMap();
70
+ return (
71
+ <div className="">
72
+ <div className="hidden md:block">
73
+ <span className="font-semibold text-xl opacity-60">
74
+ {i18n.t("please_select_true_false_text")}
75
+ </span>
76
+ </div>
77
+ <div className="hidden md:contents">
78
+ <DividerLine />
79
+ </div>
80
+ <div className="flex flex-row justify-end items-center gap-x-2">
81
+ <div className="w-[50px]">
82
+ <p className="font-bold text-lg">{i18n.t("true")}</p>
83
+ </div>
84
+ <div className="w-[50px]">
85
+ <p className="font-bold text-lg">{i18n.t("false")}</p>
86
+ </div>
87
+ </div>
88
+ {checkCanAnswerQuestion() ? (
89
+ <div className={`flex flex-row w-full justify-center flex-wrap`}>
90
+ {shuffleOptionList.map((shuffleOption, index) => {
91
+ const correctAnswer =
92
+ materialMap.trueList.find(
93
+ (trueItem: string) => trueItem === shuffleOption
94
+ ) !== undefined
95
+ ? "TRUE"
96
+ : "FALSE";
97
+ const learnerAnswer =
98
+ answerMap.trueList.find(
99
+ (trueItem: string) => trueItem === shuffleOption
100
+ ) !== undefined
101
+ ? "TRUE"
102
+ : "FALSE";
103
+
104
+ const learnerAnswerState = checkAnswerState(
105
+ correctAnswer,
106
+ learnerAnswer
107
+ );
108
+
109
+ return (
110
+ <div
111
+ key={index}
112
+ className={`w-full flex flex-row items-center justify-center cursor-pointer my-2 ${
113
+ learnerAnswerState === "CORRECT"
114
+ ? "border-2 border-catchup-green rounded-catchup-xlarge"
115
+ : learnerAnswerState === "INCORRECT"
116
+ ? "border-2 border-catchup-red rounded-catchup-xlarge"
117
+ : ""
118
+ }`}
119
+ >
120
+ <div className="flex-1">
121
+ {contentMap.type === "TEXT" ? (
122
+ <p className="text-xl p-2 whitespace-pre-wrap">
123
+ {constructInputWithSpecialExpressionList(
124
+ shuffleOption
125
+ ).map((inputPart, index) => (
126
+ <span
127
+ key={index}
128
+ className={`${inputPart.isBold ? "font-bold" : ""} ${
129
+ inputPart.isUnderline ? "underline" : ""
130
+ }`}
131
+ >
132
+ {inputPart.isEquation ? (
133
+ <span className="text-2xl">
134
+ <InlineMath math={inputPart.value} />
135
+ </span>
136
+ ) : (
137
+ inputPart.value
138
+ )}
139
+ </span>
140
+ ))}
141
+ </p>
142
+ ) : (
143
+ <ShowMaterialMediaByContentType
144
+ key={`${uniqueValue}-${index}`}
145
+ contentType={contentMap.type}
146
+ src={shuffleOption}
147
+ canFullScreen={true}
148
+ />
149
+ )}
150
+ </div>
151
+ <div className="flex flex-row items-center gap-x-2">
152
+ <div className="w-[50px]">
153
+ <div className="flex flex-col items-center justify-center">
154
+ <BaseImage
155
+ src={
156
+ answerMap.trueList.includes(shuffleOption)
157
+ ? "/icons/checkbox.png"
158
+ : "/icons/empty-checkbox.png"
159
+ }
160
+ alt="checkbox-empty-checkbox"
161
+ size="small"
162
+ onClick={() => {
163
+ onChange(answer, "TRUE", shuffleOption);
164
+ }}
165
+ />
166
+ </div>
167
+ </div>
168
+ <div className="w-[50px]">
169
+ <div className="flex flex-col items-center justify-center">
170
+ <BaseImage
171
+ src={
172
+ answerMap.falseList.includes(shuffleOption)
173
+ ? "/icons/checkbox.png"
174
+ : "/icons/empty-checkbox.png"
175
+ }
176
+ alt="checkbox-empty-checkbox"
177
+ size="small"
178
+ onClick={() => {
179
+ onChange(answer, "FALSE", shuffleOption);
180
+ }}
181
+ />
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ );
187
+ })}
188
+ </div>
189
+ ) : (
190
+ <>
191
+ {answerMap.trueList.map((item: string) => (
192
+ <div className="flex flex-row items-center gap-x-2">
193
+ <div className="flex-1">
194
+ <p>{item}</p>
195
+ </div>
196
+ <div className="w-[50px]">
197
+ <p className="underline">{i18n.t("true")}</p>
198
+ </div>
199
+ </div>
200
+ ))}
201
+ {answerMap.falseList.map((item: string) => (
202
+ <div className="flex flex-row items-center gap-x-2">
203
+ <div className="flex-1">
204
+ <p>{item}</p>
205
+ </div>
206
+ <div className="w-[50px]">
207
+ <p className="underline">{i18n.t("false")}</p>
208
+ </div>
209
+ </div>
210
+ ))}
211
+ </>
212
+ )}
213
+ </div>
214
+ );
215
+ };
216
+
217
+ export default TrueFalseActivityMaterialContent;
@@ -0,0 +1,86 @@
1
+ import { InlineMath } from "react-katex";
2
+ import i18n from "../../../language/i18n";
3
+ import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
4
+ import { IActivitySolutionProps } from "../../../properties/ActivityProperties";
5
+
6
+ const ActivitySolutionContent = ({
7
+ activityTemplateType,
8
+ data,
9
+ }: IActivitySolutionProps) => {
10
+ if (!activityTemplateType) return;
11
+
12
+ let solutionMapString;
13
+ if (activityTemplateType === "ORDERING") {
14
+ if (data["orderingSolutionMap"])
15
+ solutionMapString = data["orderingSolutionMap"];
16
+ } else if (activityTemplateType === "DROPDOWN") {
17
+ if (data["dropdownSolutionMap"])
18
+ solutionMapString = data["dropdownSolutionMap"];
19
+ } else if (activityTemplateType === "MCSA") {
20
+ if (data["MCSASolutionMap"]) solutionMapString = data["MCSASolutionMap"];
21
+ } else if (activityTemplateType === "MCMA") {
22
+ if (data["MCMASolutionMap"]) solutionMapString = data["MCMASolutionMap"];
23
+ } else if (activityTemplateType === "MATCHING") {
24
+ if (data["matchingSolutionMap"])
25
+ solutionMapString = data["matchingSolutionMap"];
26
+ } else if (activityTemplateType === "GROUPING") {
27
+ if (data["groupingSolutionMap"])
28
+ solutionMapString = data["groupingSolutionMap"];
29
+ } else if (activityTemplateType === "FILL_IN_THE_BLANKS") {
30
+ if (data["fillInTheBlanksSolutionMap"])
31
+ solutionMapString = data["fillInTheBlanksSolutionMap"];
32
+ } else if (activityTemplateType === "OPEN_ENDED") {
33
+ if (data["openEndedSolutionMap"])
34
+ solutionMapString = data["openEndedSolutionMap"];
35
+ } else if (activityTemplateType === "TRUE_FALSE") {
36
+ if (data["trueFalseSolutionMap"])
37
+ solutionMapString = data["trueFalseSolutionMap"];
38
+ }
39
+ if (!solutionMapString.includes("[ONAYLI CEVAP]")) return;
40
+ const solutionMap = JSON.parse(solutionMapString);
41
+ if (!solutionMap) return;
42
+
43
+ if (Object.keys(solutionMap).length === 0) return;
44
+ return (
45
+ <div className="mx-2">
46
+ <div className="p-4 border-catchup-blue border-2 rounded-catchup-xlarge">
47
+ <p className="text-xl font-bold text-center mb-3">
48
+ {i18n.t("solution")}
49
+ </p>
50
+ {Object.keys(solutionMap).map((key, index) => {
51
+ const currentItem = JSON.parse(solutionMap[key]);
52
+ const { value } = currentItem;
53
+ return (
54
+ <p className="my-3">
55
+ <span
56
+ key={`${key}_${index}`}
57
+ className="text-xl whitespace-pre-wrap"
58
+ >
59
+ {constructInputWithSpecialExpressionList(value).map(
60
+ (inputPart, index) => (
61
+ <span
62
+ key={index}
63
+ className={`${inputPart.isBold ? "font-bold" : ""} ${
64
+ inputPart.isUnderline ? "underline" : ""
65
+ }`}
66
+ >
67
+ {inputPart.isEquation ? (
68
+ <span className="text-2xl">
69
+ <InlineMath math={inputPart.value} />
70
+ </span>
71
+ ) : (
72
+ inputPart.value
73
+ )}
74
+ </span>
75
+ )
76
+ )}
77
+ </span>
78
+ </p>
79
+ );
80
+ })}
81
+ </div>
82
+ </div>
83
+ );
84
+ };
85
+
86
+ export default ActivitySolutionContent;