@elice/material-quiz 1.220803.0

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 (160) hide show
  1. package/README.md +3 -0
  2. package/cjs/components/eb-sortable/EbDraggable.d.ts +18 -0
  3. package/cjs/components/eb-sortable/EbDraggable.js +112 -0
  4. package/cjs/components/eb-sortable/EbDroppable.d.ts +13 -0
  5. package/cjs/components/eb-sortable/EbDroppable.js +60 -0
  6. package/cjs/components/eb-sortable/EbSortable.d.ts +17 -0
  7. package/cjs/components/material-quiz/MaterialQuiz.d.ts +4 -0
  8. package/cjs/components/material-quiz/MaterialQuiz.i18n.d.ts +25 -0
  9. package/cjs/components/material-quiz/MaterialQuiz.i18n.js +55 -0
  10. package/cjs/components/material-quiz/MaterialQuiz.js +114 -0
  11. package/cjs/components/material-quiz/MaterialQuizAnswerExplanation.d.ts +3 -0
  12. package/cjs/components/material-quiz/MaterialQuizAnswerExplanation.js +55 -0
  13. package/cjs/components/material-quiz/MaterialQuizError.d.ts +3 -0
  14. package/cjs/components/material-quiz/MaterialQuizInfo.d.ts +3 -0
  15. package/cjs/components/material-quiz/MaterialQuizInfo.js +74 -0
  16. package/cjs/components/material-quiz/MaterialQuizSelectMultiple.d.ts +3 -0
  17. package/cjs/components/material-quiz/MaterialQuizSelectMultiple.js +203 -0
  18. package/cjs/components/material-quiz/MaterialQuizSelectMultipleOrder.d.ts +3 -0
  19. package/cjs/components/material-quiz/MaterialQuizSelectMultipleOrder.js +468 -0
  20. package/cjs/components/material-quiz/MaterialQuizSelectOne.d.ts +3 -0
  21. package/cjs/components/material-quiz/MaterialQuizSelectOne.js +191 -0
  22. package/cjs/components/material-quiz/MaterialQuizShimmer.d.ts +3 -0
  23. package/cjs/components/material-quiz/MaterialQuizShimmer.js +61 -0
  24. package/cjs/components/material-quiz/MaterialQuizText.d.ts +3 -0
  25. package/cjs/components/material-quiz/MaterialQuizText.js +181 -0
  26. package/cjs/components/material-quiz/QuizResultBadge.d.ts +7 -0
  27. package/cjs/components/material-quiz/QuizResultBadge.js +48 -0
  28. package/cjs/components/material-quiz/QuizSubmitStatusText.d.ts +7 -0
  29. package/cjs/components/material-quiz/QuizSubmitStatusText.js +38 -0
  30. package/cjs/components/material-quiz/context/MaterialQuizContext.d.ts +31 -0
  31. package/cjs/components/material-quiz/context/MaterialQuizContext.js +134 -0
  32. package/cjs/components/material-quiz/index.d.ts +3 -0
  33. package/cjs/components/material-quiz-edit/MaterialQuizEdit.d.ts +25 -0
  34. package/cjs/components/material-quiz-edit/MaterialQuizEdit.js +91 -0
  35. package/cjs/components/material-quiz-edit/MaterialQuizEditContent.d.ts +3 -0
  36. package/cjs/components/material-quiz-edit/MaterialQuizEditContent.js +463 -0
  37. package/cjs/components/material-quiz-edit/context.d.ts +6 -0
  38. package/cjs/components/material-quiz-edit/context.js +15 -0
  39. package/cjs/components/material-quiz-edit/index.d.ts +2 -0
  40. package/cjs/components/material-quiz-edit/locales.d.ts +34 -0
  41. package/cjs/components/material-quiz-edit/locales.js +73 -0
  42. package/cjs/components/material-quiz-edit/options/OptionSelectMultiple.d.ts +3 -0
  43. package/cjs/components/material-quiz-edit/options/OptionSelectMultiple.js +204 -0
  44. package/cjs/components/material-quiz-edit/options/OptionSelectMultipleOrder.d.ts +3 -0
  45. package/cjs/components/material-quiz-edit/options/OptionSelectMultipleOrder.js +205 -0
  46. package/cjs/components/material-quiz-edit/options/OptionSelectOne.d.ts +3 -0
  47. package/cjs/components/material-quiz-edit/options/OptionSelectOne.js +207 -0
  48. package/cjs/components/material-quiz-edit/options/OptionText.d.ts +3 -0
  49. package/cjs/components/material-quiz-edit/options/OptionText.js +99 -0
  50. package/cjs/components/material-quiz-edit/utils/editValue.d.ts +15 -0
  51. package/cjs/components/material-quiz-edit/utils/editValue.js +37 -0
  52. package/cjs/components/material-quiz-edit/utils/randomId.d.ts +4 -0
  53. package/cjs/components/material-quiz-edit/utils/randomId.js +12 -0
  54. package/cjs/components/shared/QuestionBox.d.ts +16 -0
  55. package/cjs/components/shared/QuestionBox.js +111 -0
  56. package/cjs/components/shared/QuizDraggbleDroppedOption.d.ts +12 -0
  57. package/cjs/components/shared/QuizDraggbleDroppedOption.js +31 -0
  58. package/cjs/components/shared/QuizDraggbleDummyOption.d.ts +8 -0
  59. package/cjs/components/shared/QuizDraggbleDummyOption.js +36 -0
  60. package/cjs/components/shared/QuizDraggbleOption.d.ts +14 -0
  61. package/cjs/components/shared/QuizDraggbleOption.js +191 -0
  62. package/cjs/components/shared/StyledMarkdown.d.ts +3 -0
  63. package/cjs/components/shared/StyledMarkdown.js +14 -0
  64. package/cjs/components/shared/index.d.ts +7 -0
  65. package/cjs/components/shared/question-checkbox/QuestionCheckbox.d.ts +8 -0
  66. package/cjs/components/shared/question-checkbox/QuestionCheckbox.js +26 -0
  67. package/cjs/components/shared/question-checkbox/QuestionCheckboxContext.d.ts +9 -0
  68. package/cjs/components/shared/question-checkbox/QuestionCheckboxContext.js +42 -0
  69. package/cjs/components/shared/question-checkbox/QuestionCheckboxOption.d.ts +9 -0
  70. package/cjs/components/shared/question-checkbox/QuestionCheckboxOption.js +188 -0
  71. package/cjs/components/shared/question-radio/QuestionRadio.d.ts +8 -0
  72. package/cjs/components/shared/question-radio/QuestionRadio.js +26 -0
  73. package/cjs/components/shared/question-radio/QuestionRadioContext.d.ts +9 -0
  74. package/cjs/components/shared/question-radio/QuestionRadioContext.js +42 -0
  75. package/cjs/components/shared/question-radio/QuestionRadioOption.d.ts +9 -0
  76. package/cjs/components/shared/question-radio/QuestionRadioOption.js +156 -0
  77. package/cjs/helpers/index.d.ts +50 -0
  78. package/cjs/helpers/index.js +86 -0
  79. package/cjs/index.d.ts +3 -0
  80. package/cjs/index.js +27 -0
  81. package/es/components/eb-sortable/EbDraggable.d.ts +18 -0
  82. package/es/components/eb-sortable/EbDraggable.js +105 -0
  83. package/es/components/eb-sortable/EbDroppable.d.ts +13 -0
  84. package/es/components/eb-sortable/EbDroppable.js +53 -0
  85. package/es/components/eb-sortable/EbSortable.d.ts +17 -0
  86. package/es/components/material-quiz/MaterialQuiz.d.ts +4 -0
  87. package/es/components/material-quiz/MaterialQuiz.i18n.d.ts +25 -0
  88. package/es/components/material-quiz/MaterialQuiz.i18n.js +50 -0
  89. package/es/components/material-quiz/MaterialQuiz.js +106 -0
  90. package/es/components/material-quiz/MaterialQuizAnswerExplanation.d.ts +3 -0
  91. package/es/components/material-quiz/MaterialQuizAnswerExplanation.js +48 -0
  92. package/es/components/material-quiz/MaterialQuizError.d.ts +3 -0
  93. package/es/components/material-quiz/MaterialQuizInfo.d.ts +3 -0
  94. package/es/components/material-quiz/MaterialQuizInfo.js +68 -0
  95. package/es/components/material-quiz/MaterialQuizSelectMultiple.d.ts +3 -0
  96. package/es/components/material-quiz/MaterialQuizSelectMultiple.js +197 -0
  97. package/es/components/material-quiz/MaterialQuizSelectMultipleOrder.d.ts +3 -0
  98. package/es/components/material-quiz/MaterialQuizSelectMultipleOrder.js +461 -0
  99. package/es/components/material-quiz/MaterialQuizSelectOne.d.ts +3 -0
  100. package/es/components/material-quiz/MaterialQuizSelectOne.js +185 -0
  101. package/es/components/material-quiz/MaterialQuizShimmer.d.ts +3 -0
  102. package/es/components/material-quiz/MaterialQuizShimmer.js +54 -0
  103. package/es/components/material-quiz/MaterialQuizText.d.ts +3 -0
  104. package/es/components/material-quiz/MaterialQuizText.js +174 -0
  105. package/es/components/material-quiz/QuizResultBadge.d.ts +7 -0
  106. package/es/components/material-quiz/QuizResultBadge.js +42 -0
  107. package/es/components/material-quiz/QuizSubmitStatusText.d.ts +7 -0
  108. package/es/components/material-quiz/QuizSubmitStatusText.js +32 -0
  109. package/es/components/material-quiz/context/MaterialQuizContext.d.ts +31 -0
  110. package/es/components/material-quiz/context/MaterialQuizContext.js +124 -0
  111. package/es/components/material-quiz/index.d.ts +3 -0
  112. package/es/components/material-quiz-edit/MaterialQuizEdit.d.ts +25 -0
  113. package/es/components/material-quiz-edit/MaterialQuizEdit.js +86 -0
  114. package/es/components/material-quiz-edit/MaterialQuizEditContent.d.ts +3 -0
  115. package/es/components/material-quiz-edit/MaterialQuizEditContent.js +456 -0
  116. package/es/components/material-quiz-edit/context.d.ts +6 -0
  117. package/es/components/material-quiz-edit/context.js +6 -0
  118. package/es/components/material-quiz-edit/index.d.ts +2 -0
  119. package/es/components/material-quiz-edit/locales.d.ts +34 -0
  120. package/es/components/material-quiz-edit/locales.js +68 -0
  121. package/es/components/material-quiz-edit/options/OptionSelectMultiple.d.ts +3 -0
  122. package/es/components/material-quiz-edit/options/OptionSelectMultiple.js +197 -0
  123. package/es/components/material-quiz-edit/options/OptionSelectMultipleOrder.d.ts +3 -0
  124. package/es/components/material-quiz-edit/options/OptionSelectMultipleOrder.js +198 -0
  125. package/es/components/material-quiz-edit/options/OptionSelectOne.d.ts +3 -0
  126. package/es/components/material-quiz-edit/options/OptionSelectOne.js +200 -0
  127. package/es/components/material-quiz-edit/options/OptionText.d.ts +3 -0
  128. package/es/components/material-quiz-edit/options/OptionText.js +93 -0
  129. package/es/components/material-quiz-edit/utils/editValue.d.ts +15 -0
  130. package/es/components/material-quiz-edit/utils/editValue.js +32 -0
  131. package/es/components/material-quiz-edit/utils/randomId.d.ts +4 -0
  132. package/es/components/material-quiz-edit/utils/randomId.js +8 -0
  133. package/es/components/shared/QuestionBox.d.ts +16 -0
  134. package/es/components/shared/QuestionBox.js +101 -0
  135. package/es/components/shared/QuizDraggbleDroppedOption.d.ts +12 -0
  136. package/es/components/shared/QuizDraggbleDroppedOption.js +25 -0
  137. package/es/components/shared/QuizDraggbleDummyOption.d.ts +8 -0
  138. package/es/components/shared/QuizDraggbleDummyOption.js +29 -0
  139. package/es/components/shared/QuizDraggbleOption.d.ts +14 -0
  140. package/es/components/shared/QuizDraggbleOption.js +184 -0
  141. package/es/components/shared/StyledMarkdown.d.ts +3 -0
  142. package/es/components/shared/StyledMarkdown.js +8 -0
  143. package/es/components/shared/index.d.ts +7 -0
  144. package/es/components/shared/question-checkbox/QuestionCheckbox.d.ts +8 -0
  145. package/es/components/shared/question-checkbox/QuestionCheckbox.js +19 -0
  146. package/es/components/shared/question-checkbox/QuestionCheckboxContext.d.ts +9 -0
  147. package/es/components/shared/question-checkbox/QuestionCheckboxContext.js +33 -0
  148. package/es/components/shared/question-checkbox/QuestionCheckboxOption.d.ts +9 -0
  149. package/es/components/shared/question-checkbox/QuestionCheckboxOption.js +181 -0
  150. package/es/components/shared/question-radio/QuestionRadio.d.ts +8 -0
  151. package/es/components/shared/question-radio/QuestionRadio.js +19 -0
  152. package/es/components/shared/question-radio/QuestionRadioContext.d.ts +9 -0
  153. package/es/components/shared/question-radio/QuestionRadioContext.js +33 -0
  154. package/es/components/shared/question-radio/QuestionRadioOption.d.ts +9 -0
  155. package/es/components/shared/question-radio/QuestionRadioOption.js +149 -0
  156. package/es/helpers/index.d.ts +50 -0
  157. package/es/helpers/index.js +78 -0
  158. package/es/index.d.ts +3 -0
  159. package/es/index.js +10 -0
  160. package/package.json +75 -0
@@ -0,0 +1,185 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { getOrgMaterialQuizResponseGet, getOrgMaterialQuizResponseList, postOrgMaterialQuizResponseAdd } from '@elice/api-client';
4
+ import { checkUserLectureTestEnded, getOptionStatus, getQuizResult } from '../../helpers/index.js';
5
+ import '../shared/QuizDraggbleOption.js';
6
+ import '../shared/QuizDraggbleDummyOption.js';
7
+ import QuestionRadio from '../shared/question-radio/QuestionRadio.js';
8
+ import QuestionRadioOption from '../shared/question-radio/QuestionRadioOption.js';
9
+ import '../shared/question-checkbox/QuestionCheckbox.js';
10
+ import '../shared/question-checkbox/QuestionCheckboxOption.js';
11
+ import QuestionBox from '../shared/QuestionBox.js';
12
+ import StyledMarkdown from '../shared/StyledMarkdown.js';
13
+ import { useMaterialQuizState, useMaterialQuizDispatch } from './context/MaterialQuizContext.js';
14
+ import QuizResultBadge from './QuizResultBadge.js';
15
+ import QuizSubmitStatusText from './QuizSubmitStatusText.js';
16
+
17
+ const MaterialQuizSelectOne = () => {
18
+ // context
19
+ const {
20
+ course,
21
+ lecture,
22
+ materialQuiz,
23
+ userId
24
+ } = useMaterialQuizState();
25
+ const {
26
+ onSubmit,
27
+ onNext,
28
+ refreshOrgMaterialQuiz
29
+ } = useMaterialQuizDispatch(); // state
30
+
31
+ const intl = useIntl();
32
+ const [selectedAnswer, setSelectedAnswer] = React.useState();
33
+ const [materialQuizResponse, setMaterialQuizResponse] = React.useState();
34
+ const [submitStatus, setSubmitStatus] = React.useState('idle'); // Whether user has clicked any options
35
+
36
+ const [isActive, setIsActive] = React.useState(false);
37
+ const [hasSubmitted, setHasSubmitted] = React.useState(false); // quiz response fetcher
38
+
39
+ React.useEffect(() => {
40
+ if (!userId && (materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.lastQuizResponseId)) {
41
+ const controller = new AbortController();
42
+ const {
43
+ signal
44
+ } = controller;
45
+ getOrgMaterialQuizResponseGet({
46
+ quizResponseId: materialQuiz.lastQuizResponseId
47
+ }, {
48
+ signal
49
+ }).then(response => {
50
+ setMaterialQuizResponse(response.quizResponse);
51
+ setSelectedAnswer(typeof response.quizResponse.answer === 'string' ? undefined : response.quizResponse.answer[0]);
52
+ }).catch(error => {
53
+ console.error(error);
54
+ });
55
+ return () => controller.abort();
56
+ }
57
+ }, [materialQuiz, userId]); // quiz response fetcher
58
+
59
+ React.useEffect(() => {
60
+ if (userId && materialQuiz) {
61
+ const controller = new AbortController();
62
+ const {
63
+ signal
64
+ } = controller;
65
+ getOrgMaterialQuizResponseList({
66
+ materialQuizId: materialQuiz.id,
67
+ filterUserIds: [userId],
68
+ isContainOnlyLast: true,
69
+ isIncludeAnswer: true,
70
+ offset: 0,
71
+ count: 1
72
+ }, {
73
+ signal
74
+ }).then(response => {
75
+ const quizResponse = response.quizResponses[0];
76
+ setMaterialQuizResponse(quizResponse);
77
+ setSelectedAnswer(typeof quizResponse.answer === 'string' ? undefined : quizResponse.answer[0]);
78
+ }).catch(error => {
79
+ console.error(error);
80
+ });
81
+ return () => controller.abort();
82
+ }
83
+ }, [materialQuiz, userId]); // submit handler
84
+
85
+ const handleSubmit = async () => {
86
+ if (!materialQuiz) {
87
+ return;
88
+ }
89
+
90
+ setSubmitStatus('pending');
91
+
92
+ try {
93
+ const {
94
+ quizResponseId
95
+ } = await postOrgMaterialQuizResponseAdd({
96
+ materialQuizId: materialQuiz.id,
97
+ answer: [selectedAnswer]
98
+ });
99
+ const {
100
+ quizResponse
101
+ } = await getOrgMaterialQuizResponseGet({
102
+ quizResponseId
103
+ });
104
+ setIsActive(false);
105
+ setMaterialQuizResponse(quizResponse);
106
+ void refreshOrgMaterialQuiz();
107
+ onSubmit(true, getQuizResult(quizResponse));
108
+ setSubmitStatus('resolved');
109
+ setHasSubmitted(true);
110
+ } catch (error) {
111
+ console.error(error);
112
+ onSubmit(false);
113
+ setSubmitStatus('rejected');
114
+ }
115
+ };
116
+
117
+ return React.createElement(QuestionBox, {
118
+ title: intl.formatMessage({
119
+ id: 'materialQuiz.myAnswer'
120
+ }),
121
+ onNext: onNext,
122
+ isNextActive: hasSubmitted && typeof onNext === 'function',
123
+ submitStatus: React.createElement(QuizSubmitStatusText, {
124
+ status: submitStatus
125
+ }),
126
+ submitResult: React.createElement(QuizResultBadge, {
127
+ materialQuizResponse: materialQuizResponse
128
+ }),
129
+ footerActions: [{
130
+ border: true,
131
+ disabled: selectedAnswer === undefined || checkUserLectureTestEnded(lecture) || !!userId,
132
+ loading: submitStatus === 'pending',
133
+ tabIndex: 0,
134
+ transparent: false,
135
+ role: 'primary',
136
+ onClick: handleSubmit,
137
+ children: intl.formatMessage({
138
+ id: 'materialQuiz.submit'
139
+ })
140
+ }]
141
+ }, materialQuiz ? React.createElement(QuestionRadio, {
142
+ selectedValue: selectedAnswer,
143
+ onSelect: index => {
144
+ if (checkUserLectureTestEnded(lecture) || !!userId) {
145
+ return;
146
+ }
147
+
148
+ setHasSubmitted(false);
149
+ setIsActive(true);
150
+ setSelectedAnswer(index);
151
+ },
152
+ disabled: submitStatus === 'pending' || checkUserLectureTestEnded(lecture) || !!userId
153
+ }, materialQuiz.optionInfo ? materialQuiz.optionInfo.map((option, index) => {
154
+ var _a;
155
+
156
+ const getIsSelected = (index, materialQuizResponse) => {
157
+ var _a;
158
+
159
+ if (!materialQuizResponse || typeof materialQuizResponse.answer === 'string') {
160
+ return false;
161
+ }
162
+
163
+ return (_a = materialQuizResponse.answer.includes(index)) !== null && _a !== void 0 ? _a : false;
164
+ };
165
+
166
+ const status = getOptionStatus({
167
+ materialQuizResponse,
168
+ isSelected: getIsSelected(index, materialQuizResponse),
169
+ isActive
170
+ });
171
+ return React.createElement(QuestionRadioOption, {
172
+ key: index,
173
+ value: index,
174
+ status: status,
175
+ isAnswer: (_a = !!userId && Array.isArray(materialQuiz.answerInfo) && materialQuiz.answerInfo.includes(index)) !== null && _a !== void 0 ? _a : false
176
+ }, (course === null || course === void 0 ? void 0 : course.preference.renderMarkdownInQuizOptions) ? React.createElement(StyledMarkdown, {
177
+ children: option,
178
+ paddingx: 0,
179
+ paddingy: 0,
180
+ dark: false
181
+ }) : option);
182
+ }) : null) : null);
183
+ };
184
+
185
+ export { MaterialQuizSelectOne as default };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const MaterialQuizShimmer: React.FC;
3
+ export default MaterialQuizShimmer;
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { Shimmer, Vspace } from '@elice/blocks';
3
+ import { base } from '@elice/design-tokens';
4
+ import styled from 'styled-components';
5
+ import { useMaterialQuizState } from './context/MaterialQuizContext.js';
6
+
7
+ const StyledShimmer = styled.div.withConfig({
8
+ componentId: "sc-10uz5tw-0"
9
+ })(["display:flex;flex-direction:column;border-radius:", ";overflow:hidden;width:100%;"], ({
10
+ vertical
11
+ }) => vertical ? '0' : '8px');
12
+ const StyledShimmerHeader = styled.div.withConfig({
13
+ componentId: "sc-10uz5tw-1"
14
+ })(["display:flex;justify-content:space-between;background-color:", ";padding:1rem 1.5rem;height:3.5rem;"], base.color.navy6);
15
+ const StyledShimmerBody = styled.div.withConfig({
16
+ componentId: "sc-10uz5tw-2"
17
+ })(["padding:1.5rem;background-color:", ";overflow-y:auto;height:100%;"], base.color.navy7);
18
+
19
+ const MaterialQuizShimmer = () => {
20
+ const {
21
+ vertical
22
+ } = useMaterialQuizState();
23
+ return React.createElement(StyledShimmer, {
24
+ vertical: vertical
25
+ }, React.createElement(StyledShimmerHeader, null), React.createElement(StyledShimmerBody, null, React.createElement(Shimmer, {
26
+ dark: true,
27
+ borderRadius: '4px',
28
+ width: "80%",
29
+ height: '40px'
30
+ }), React.createElement(Vspace, {
31
+ height: 1
32
+ }), React.createElement(Shimmer, {
33
+ dark: true,
34
+ borderRadius: '4px',
35
+ width: "100%",
36
+ height: '40px'
37
+ }), React.createElement(Vspace, {
38
+ height: 1
39
+ }), React.createElement(Shimmer, {
40
+ dark: true,
41
+ borderRadius: '4px',
42
+ width: "100%",
43
+ height: '40px'
44
+ }), React.createElement(Vspace, {
45
+ height: 1
46
+ }), React.createElement(Shimmer, {
47
+ dark: true,
48
+ borderRadius: '4px',
49
+ width: "100%",
50
+ height: '40px'
51
+ })));
52
+ };
53
+
54
+ export { MaterialQuizShimmer as default };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const MaterialQuizText: React.FC;
3
+ export default MaterialQuizText;
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { getOrgMaterialQuizResponseGet, getOrgMaterialQuizResponseList, postOrgMaterialQuizResponseAdd } from '@elice/api-client';
4
+ import { Flex } from '@elice/blocks';
5
+ import { base } from '@elice/design-tokens';
6
+ import styled from 'styled-components';
7
+ import { checkUserLectureTestEnded, getQuizResult } from '../../helpers/index.js';
8
+ import QuestionBox from '../shared/QuestionBox.js';
9
+ import { useMaterialQuizState, useMaterialQuizDispatch } from './context/MaterialQuizContext.js';
10
+ import QuizResultBadge from './QuizResultBadge.js';
11
+ import QuizSubmitStatusText from './QuizSubmitStatusText.js';
12
+
13
+ const StyledTextarea = styled.textarea.withConfig({
14
+ componentId: "sc-186cnpj-0"
15
+ })(["min-height:12rem;width:100%;padding:1rem 1.375rem;font-size:1rem;color:", ";border-radius:4px;resize:vertical;line-height:1.5rem;outline:none;background-color:", ";&::placeholder{color:", ";}&:hover{cursor:", ";}"], base.color.navy2, base.color.navy5, base.color.navy2, ({
16
+ disabled
17
+ }) => disabled ? 'not-allowed' : 'text');
18
+ const StyledLabel = styled.label.withConfig({
19
+ componentId: "sc-186cnpj-1"
20
+ })(["font-size:0.875rem;margin-bottom:0.5rem;color:", ";"], base.color.navy1);
21
+
22
+ const MaterialQuizText = () => {
23
+ // context
24
+ const {
25
+ lecture,
26
+ materialQuiz,
27
+ userId
28
+ } = useMaterialQuizState();
29
+ const {
30
+ onSubmit,
31
+ onNext,
32
+ refreshOrgMaterialQuiz
33
+ } = useMaterialQuizDispatch(); // state
34
+
35
+ const intl = useIntl();
36
+ const [materialQuizResponse, setMaterialQuizResponse] = React.useState();
37
+ const [submitStatus, setSubmitStatus] = React.useState('idle');
38
+ const [answer, setAnswer] = React.useState('');
39
+ const [hasSubmitted, setHasSubmitted] = React.useState(false); // quiz response fetcher
40
+
41
+ React.useEffect(() => {
42
+ if (!userId && (materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.lastQuizResponseId)) {
43
+ const controller = new AbortController();
44
+ const {
45
+ signal
46
+ } = controller;
47
+ getOrgMaterialQuizResponseGet({
48
+ quizResponseId: materialQuiz.lastQuizResponseId
49
+ }, {
50
+ signal
51
+ }).then(response => {
52
+ setMaterialQuizResponse(response.quizResponse);
53
+ setAnswer(response.quizResponse.answer);
54
+ }).catch(error => {
55
+ console.error(error);
56
+ });
57
+ return () => controller.abort();
58
+ }
59
+ }, [materialQuiz, userId]); // quiz response fetcher
60
+
61
+ React.useEffect(() => {
62
+ if (userId && materialQuiz) {
63
+ const controller = new AbortController();
64
+ const {
65
+ signal
66
+ } = controller;
67
+ getOrgMaterialQuizResponseList({
68
+ materialQuizId: materialQuiz.id,
69
+ filterUserIds: [userId],
70
+ isContainOnlyLast: true,
71
+ isIncludeAnswer: true,
72
+ offset: 0,
73
+ count: 1
74
+ }, {
75
+ signal
76
+ }).then(response => {
77
+ const quizResponse = response.quizResponses[0];
78
+ setMaterialQuizResponse(quizResponse);
79
+ setAnswer(typeof (quizResponse === null || quizResponse === void 0 ? void 0 : quizResponse.answer) === 'string' ? quizResponse.answer : '');
80
+ }).catch(error => {
81
+ console.error(error);
82
+ });
83
+ return () => controller.abort();
84
+ }
85
+ }, [materialQuiz, userId]); // submit handler
86
+
87
+ const handleSubmit = async () => {
88
+ if (!materialQuiz) {
89
+ return;
90
+ }
91
+
92
+ setSubmitStatus('pending');
93
+
94
+ try {
95
+ const {
96
+ quizResponseId
97
+ } = await postOrgMaterialQuizResponseAdd({
98
+ materialQuizId: materialQuiz.id,
99
+ answer: JSON.stringify(answer)
100
+ });
101
+ const {
102
+ quizResponse
103
+ } = await getOrgMaterialQuizResponseGet({
104
+ quizResponseId
105
+ });
106
+ setHasSubmitted(true);
107
+ setMaterialQuizResponse(quizResponse);
108
+ void refreshOrgMaterialQuiz();
109
+ onSubmit(true, getQuizResult(quizResponse));
110
+ setSubmitStatus('resolved');
111
+ } catch (error) {
112
+ console.error(error);
113
+ onSubmit(false);
114
+ setSubmitStatus('rejected');
115
+ }
116
+ };
117
+
118
+ const commonProps = {
119
+ type: 'text',
120
+ autoFocus: answer.length === 0,
121
+ disabled: submitStatus === 'pending' || checkUserLectureTestEnded(lecture) || !!userId,
122
+ placeholder: (materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.answerHint) || intl.formatMessage({
123
+ id: 'materialQuiz.text.placeholder'
124
+ }),
125
+ value: answer,
126
+ onChange: e => {
127
+ setHasSubmitted(false);
128
+ setAnswer(e.target.value);
129
+ }
130
+ };
131
+ return React.createElement(QuestionBox, {
132
+ onNext: onNext,
133
+ submitResult: React.createElement(QuizResultBadge, {
134
+ materialQuizResponse: materialQuizResponse
135
+ }),
136
+ submitStatus: React.createElement(QuizSubmitStatusText, {
137
+ status: submitStatus
138
+ }),
139
+ isNextActive: hasSubmitted && typeof onNext === 'function',
140
+ footerActions: [{
141
+ border: true,
142
+ children: intl.formatMessage({
143
+ id: 'materialQuiz.submit'
144
+ }),
145
+ disabled: answer.length === 0 || checkUserLectureTestEnded(lecture) || !!userId,
146
+ loading: submitStatus === 'pending',
147
+ tabIndex: 0,
148
+ transparent: false,
149
+ role: 'primary',
150
+ onClick: handleSubmit
151
+ }]
152
+ }, React.createElement(Flex, {
153
+ column: true
154
+ }, userId ? React.createElement(StyledLabel, {
155
+ htmlFor: "quiz-text-answer"
156
+ }, intl.formatMessage({
157
+ id: 'materialQuiz.submittedAnswer'
158
+ })) : null, React.createElement(StyledTextarea, Object.assign({
159
+ id: "quiz-text-answer"
160
+ }, commonProps))), userId ? React.createElement(Flex, {
161
+ column: true,
162
+ margintop: "1rem"
163
+ }, React.createElement(StyledLabel, {
164
+ htmlFor: "quiz-text-submitted-answer"
165
+ }, intl.formatMessage({
166
+ id: 'materialQuiz.answer'
167
+ })), React.createElement(StyledTextarea, {
168
+ id: "quiz-text-submitted-answer",
169
+ disabled: true,
170
+ value: typeof (materialQuiz === null || materialQuiz === void 0 ? void 0 : materialQuiz.answerInfo) === 'string' ? materialQuiz.answerInfo : ''
171
+ })) : null);
172
+ };
173
+
174
+ export { MaterialQuizText as default };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { GetOrgMaterialQuizResponseGetResponses } from '@elice/types';
3
+ interface QuizResultStatusProps {
4
+ materialQuizResponse?: GetOrgMaterialQuizResponseGetResponses['quizResponse'];
5
+ }
6
+ declare const QuizResultBadge: React.FC<QuizResultStatusProps>;
7
+ export default QuizResultBadge;
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { BadgeNext } from '@elice/blocks';
4
+ import { getQuizResultStatus, QuizResultStatus } from '../../helpers/index.js';
5
+
6
+ const QuizResultBadge = ({
7
+ materialQuizResponse
8
+ }) => {
9
+ const intl = useIntl();
10
+ const status = React.useMemo(() => getQuizResultStatus(materialQuizResponse), [materialQuizResponse]);
11
+
12
+ switch (status) {
13
+ case QuizResultStatus.Correct:
14
+ return React.createElement(BadgeNext, {
15
+ type: "quiet",
16
+ role: "green"
17
+ }, intl.formatMessage({
18
+ id: 'materialQuiz.resultStatus.correct'
19
+ }));
20
+
21
+ case QuizResultStatus.Wrong:
22
+ return React.createElement(BadgeNext, {
23
+ type: "quiet",
24
+ role: "red"
25
+ }, intl.formatMessage({
26
+ id: 'materialQuiz.resultStatus.wrong'
27
+ }));
28
+
29
+ case QuizResultStatus.Submitted:
30
+ return React.createElement(BadgeNext, {
31
+ type: "quiet",
32
+ role: "primary"
33
+ }, intl.formatMessage({
34
+ id: 'materialQuiz.resultStatus.submitted'
35
+ }));
36
+
37
+ default:
38
+ return null;
39
+ }
40
+ };
41
+
42
+ export { QuizResultBadge as default };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { APIStatus } from '@elice/material-shared-types';
3
+ interface QuizSubmitStatusTextProps {
4
+ status: APIStatus;
5
+ }
6
+ declare const QuizSubmitStatusText: React.FC<QuizSubmitStatusTextProps>;
7
+ export default QuizSubmitStatusText;
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { StatusText } from '@elice/blocks';
4
+
5
+ const QuizSubmitStatusText = ({
6
+ status
7
+ }) => {
8
+ const intl = useIntl();
9
+
10
+ switch (status) {
11
+ case 'resolved':
12
+ return React.createElement(StatusText, {
13
+ role: "success",
14
+ size: "small"
15
+ }, intl.formatMessage({
16
+ id: 'materialQuiz.submitStatus.success'
17
+ }));
18
+
19
+ case 'rejected':
20
+ return React.createElement(StatusText, {
21
+ role: "danger",
22
+ size: "small"
23
+ }, intl.formatMessage({
24
+ id: 'materialQuiz.submitStatus.failure'
25
+ }));
26
+
27
+ default:
28
+ return null;
29
+ }
30
+ };
31
+
32
+ export { QuizSubmitStatusText as default };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import type { APIStatus } from '@elice/material-shared-types';
3
+ import type { GetOrgCourseGetResponses, GetOrgLectureGetResponses, GetOrgMaterialQuizGetResponses } from '@elice/types';
4
+ export interface State {
5
+ course?: GetOrgCourseGetResponses['course'];
6
+ lecture?: GetOrgLectureGetResponses['lecture'];
7
+ materialQuiz?: GetOrgMaterialQuizGetResponses['materialQuiz'];
8
+ vertical: boolean;
9
+ userId?: number;
10
+ initStatus: APIStatus;
11
+ }
12
+ export declare type MaterialQuizProps = {
13
+ materialQuizId: number;
14
+ userId?: number;
15
+ locale?: string;
16
+ onSubmit?: (isSucceeded: boolean, isCorrect?: boolean) => void;
17
+ onNext?: () => void;
18
+ };
19
+ interface MaterialQuizProviderProps extends Omit<MaterialQuizProps, 'locale'> {
20
+ children: React.ReactNode;
21
+ }
22
+ interface DispatchContextType {
23
+ onSubmit: (isSucceeded: boolean, isCorrect?: boolean) => void;
24
+ refreshOrgMaterialQuiz: (signal?: AbortSignal | undefined) => Promise<void>;
25
+ setVertical: React.Dispatch<React.SetStateAction<boolean>>;
26
+ onNext?: () => void;
27
+ }
28
+ declare function MaterialQuizProvider({ materialQuizId, userId, onSubmit, onNext, children, }: MaterialQuizProviderProps): JSX.Element;
29
+ declare function useMaterialQuizState(): State;
30
+ declare function useMaterialQuizDispatch(): DispatchContextType;
31
+ export { MaterialQuizProvider, useMaterialQuizState, useMaterialQuizDispatch };
@@ -0,0 +1,124 @@
1
+ import React from 'react';
2
+ import { config, getOrgMaterialQuizGet, getOrgCourseGet, getOrgLectureGet } from '@elice/api-client';
3
+ import { useMaterialConfigApiClientUpdate } from '@elice/material-shared-utils';
4
+
5
+ const StateContext = React.createContext(undefined);
6
+ const DispatchContext = React.createContext(undefined);
7
+ StateContext.displayName = 'MaterialQuizStateContext';
8
+ DispatchContext.displayName = 'MaterialQuizDispatchContext';
9
+
10
+ function MaterialQuizProvider({
11
+ materialQuizId,
12
+ userId,
13
+ onSubmit = () => void 0,
14
+ onNext,
15
+ children
16
+ }) {
17
+ const [course, setCourse] = React.useState();
18
+ const [lecture, setLecture] = React.useState();
19
+ const [materialQuiz, setMaterialQuiz] = React.useState();
20
+ const [initStatus, setInitStatus] = React.useState('idle');
21
+ const [vertical, setVertical] = React.useState(false);
22
+ const canInit = useMaterialConfigApiClientUpdate(config.init);
23
+ const init = React.useCallback(async () => {
24
+ const controller = new AbortController();
25
+ const {
26
+ signal
27
+ } = controller;
28
+
29
+ try {
30
+ setInitStatus('pending'); // fetch materialQuiz
31
+
32
+ const {
33
+ materialQuiz
34
+ } = await getOrgMaterialQuizGet({
35
+ materialQuizId
36
+ }, {
37
+ signal
38
+ }); // fetch course
39
+
40
+ const {
41
+ course
42
+ } = await getOrgCourseGet({
43
+ courseId: materialQuiz.courseId
44
+ }, {
45
+ signal
46
+ }); // fetch lecture
47
+
48
+ const {
49
+ lecture
50
+ } = await getOrgLectureGet({
51
+ lectureId: materialQuiz.lectureId
52
+ }, {
53
+ signal
54
+ });
55
+ setMaterialQuiz(materialQuiz);
56
+ setCourse(course);
57
+ setLecture(lecture);
58
+ setInitStatus('resolved');
59
+ } catch (error) {
60
+ console.error(error);
61
+ setInitStatus('rejected');
62
+ }
63
+
64
+ return () => controller.abort();
65
+ }, [materialQuizId]);
66
+ React.useEffect(() => {
67
+ if (canInit) {
68
+ void init();
69
+ }
70
+ }, [canInit, init]); //
71
+ //
72
+ // materialQuiz refresher
73
+
74
+ const refreshOrgMaterialQuiz = React.useCallback(signal => {
75
+ return getOrgMaterialQuizGet({
76
+ materialQuizId
77
+ }, {
78
+ signal
79
+ }).then(response => {
80
+ setMaterialQuiz(response.materialQuiz);
81
+ }).catch(error => {
82
+ console.error(error);
83
+ });
84
+ }, [materialQuizId]);
85
+ return React.createElement(StateContext.Provider, {
86
+ value: {
87
+ course,
88
+ lecture,
89
+ materialQuiz,
90
+ userId,
91
+ vertical,
92
+ initStatus
93
+ }
94
+ }, React.createElement(DispatchContext.Provider, {
95
+ value: {
96
+ onSubmit,
97
+ onNext,
98
+ refreshOrgMaterialQuiz,
99
+ setVertical
100
+ }
101
+ }, children));
102
+ }
103
+
104
+ function useMaterialQuizState() {
105
+ const context = React.useContext(StateContext);
106
+
107
+ if (context === undefined) {
108
+ throw new Error('useMaterialQuizState must be used within a MaterialQuizProvider');
109
+ }
110
+
111
+ return context;
112
+ }
113
+
114
+ function useMaterialQuizDispatch() {
115
+ const context = React.useContext(DispatchContext);
116
+
117
+ if (context === undefined) {
118
+ throw new Error('useMaterialQuizDispatch must be used within a MaterialQuizProvider');
119
+ }
120
+
121
+ return context;
122
+ }
123
+
124
+ export { MaterialQuizProvider, useMaterialQuizDispatch, useMaterialQuizState };
@@ -0,0 +1,3 @@
1
+ export { default as MaterialQuiz } from './MaterialQuiz';
2
+ export { default as MaterialQuizInfo } from './MaterialQuizInfo';
3
+ export type { MaterialQuizProps } from './context/MaterialQuizContext';