@tinyweb_dev/oe-exam-sdk 0.1.1 → 0.1.3

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 (514) hide show
  1. package/dist/api/exam-create.js +1 -179
  2. package/dist/api/exam-create.types.js +1 -1
  3. package/dist/api/exam-questions.d.ts +1 -1
  4. package/dist/api/exam-questions.js +1 -98
  5. package/dist/api/exam-questions.types.d.ts +45 -1
  6. package/dist/api/exam-questions.types.js +1 -1
  7. package/dist/api/exam-taking.js +1 -73
  8. package/dist/api/exam-taking.types.js +1 -1
  9. package/dist/api/index.js +1 -6
  10. package/dist/api/result-review.js +1 -50
  11. package/dist/api/result-review.types.js +1 -1
  12. package/dist/components/CueCardEditor.js +1 -58
  13. package/dist/components/common/ResolvedImage.js +1 -15
  14. package/dist/components/exams/CompletionDialog.d.ts +8 -0
  15. package/dist/components/exams/CompletionDialog.js +1 -0
  16. package/dist/components/exams/CreateExamInfoForm.d.ts +4 -1
  17. package/dist/components/exams/CreateExamInfoForm.js +1 -35
  18. package/dist/components/exams/CreateExamPageContainer.d.ts +3 -0
  19. package/dist/components/exams/CreateExamPageContainer.js +1 -103
  20. package/dist/components/exams/ExamCreator.d.ts +9 -3
  21. package/dist/components/exams/ExamCreator.js +1 -89
  22. package/dist/components/exams/ExamPartTabs.d.ts +1 -1
  23. package/dist/components/exams/ExamPartTabs.js +1 -40
  24. package/dist/components/exams/ExamPreviewDialog.d.ts +20 -0
  25. package/dist/components/exams/ExamPreviewDialog.js +1 -0
  26. package/dist/components/exams/ExamQuestionGrid.d.ts +1 -1
  27. package/dist/components/exams/ExamQuestionGrid.js +1 -18
  28. package/dist/components/exams/ExamQuestionsPageContainer.d.ts +3 -0
  29. package/dist/components/exams/ExamQuestionsPageContainer.js +1 -90
  30. package/dist/components/exams/ExamViewDialog.d.ts +24 -0
  31. package/dist/components/exams/ExamViewDialog.js +1 -0
  32. package/dist/components/exams/PartAudioUploader.js +1 -9
  33. package/dist/components/exams/TemplateSelector.js +1 -66
  34. package/dist/components/exams/UnsavedChangesDialog.d.ts +8 -0
  35. package/dist/components/exams/UnsavedChangesDialog.js +1 -0
  36. package/dist/components/exams/api.d.ts +1 -1
  37. package/dist/components/exams/api.js +1 -3
  38. package/dist/components/exams/create-exam.texts.d.ts +58 -0
  39. package/dist/components/exams/create-exam.texts.js +1 -0
  40. package/dist/components/exams/create-exam.validation.js +1 -18
  41. package/dist/components/exams/exam-question-status.d.ts +9 -0
  42. package/dist/components/exams/exam-question-status.js +1 -0
  43. package/dist/components/exams/exam-template.utils.js +1 -18
  44. package/dist/components/exams/index.d.ts +11 -1
  45. package/dist/components/exams/index.js +1 -10
  46. package/dist/components/exams/take/ExamTakingPageContainer.js +1 -153
  47. package/dist/components/exams/take/GenericQuestionRenderer.js +1 -14
  48. package/dist/components/exams/take/exam-taking.utils.js +1 -88
  49. package/dist/components/exams/take/hooks/useSpeakingRecorder.js +1 -24
  50. package/dist/components/exams/take/index.js +1 -2
  51. package/dist/components/exams/take/types.js +1 -1
  52. package/dist/components/index.js +1 -42
  53. package/dist/components/questions/_shared/config/question-types.config.js +1 -333
  54. package/dist/components/questions/_shared/constants/color-palette.js +1 -21
  55. package/dist/components/questions/_shared/hooks/useAnswerGroupQuestionGroup.js +1 -105
  56. package/dist/components/questions/_shared/hooks/useBasicQuestionGroup.js +1 -222
  57. package/dist/components/questions/_shared/hooks/useCompareImagesGroup.js +1 -140
  58. package/dist/components/questions/_shared/hooks/useImageQuestionGroup.js +1 -123
  59. package/dist/components/questions/_shared/hooks/useInfoExchangeGroup.js +1 -50
  60. package/dist/components/questions/_shared/hooks/useQuestionFormState.js +1 -54
  61. package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +1 -123
  62. package/dist/components/questions/_shared/hooks/useQuestionListGroup.js +1 -121
  63. package/dist/components/questions/_shared/hooks/useQuestionOnChange.js +1 -70
  64. package/dist/components/questions/_shared/hooks/useSceneQuestionGroup.js +1 -194
  65. package/dist/components/questions/_shared/index.js +1 -7
  66. package/dist/components/questions/_shared/types/answer-the-question.type.js +1 -1
  67. package/dist/components/questions/_shared/types/arrange-letters-into-words.type.js +1 -1
  68. package/dist/components/questions/_shared/types/choose-correct-adjective.type.js +1 -3
  69. package/dist/components/questions/_shared/types/color-region.config.js +1 -1
  70. package/dist/components/questions/_shared/types/fill-in-blank.type.js +1 -1
  71. package/dist/components/questions/_shared/types/fill-missing-words-in-grid.type.js +1 -1
  72. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +1 -1
  73. package/dist/components/questions/_shared/types/index.js +1 -12
  74. package/dist/components/questions/_shared/types/label-the-picture.type.js +1 -1
  75. package/dist/components/questions/_shared/types/listen-and-choose-from-answer-group.type.js +1 -1
  76. package/dist/components/questions/_shared/types/listen-and-choose-objects-in-scene.type.js +1 -1
  77. package/dist/components/questions/_shared/types/listen-and-drag-objects-into-scene.type.js +1 -1
  78. package/dist/components/questions/_shared/types/listen-and-speak-answer.type.js +1 -1
  79. package/dist/components/questions/_shared/types/listen-and-speak-compare-images.type.js +1 -1
  80. package/dist/components/questions/_shared/types/listen-and-speak-image-group.type.js +1 -1
  81. package/dist/components/questions/_shared/types/listen-and-speak-info-exchange.type.js +1 -1
  82. package/dist/components/questions/_shared/types/listen-and-speak-odd-one-out.type.js +1 -3
  83. package/dist/components/questions/_shared/types/listen-and-speak-question-list.type.js +1 -1
  84. package/dist/components/questions/_shared/types/listen-and-speak-with-story-images.type.js +1 -3
  85. package/dist/components/questions/_shared/types/listen-and-tick-answer.type.js +1 -1
  86. package/dist/components/questions/_shared/types/listening-drawline.type.js +1 -1
  87. package/dist/components/questions/_shared/types/look-and-choose-answer.type.js +1 -1
  88. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +1 -1
  89. package/dist/components/questions/_shared/types/match-by-writing-answer.type.js +1 -1
  90. package/dist/components/questions/_shared/types/multiple-choice.type.js +1 -1
  91. package/dist/components/questions/_shared/types/question-group.type.js +1 -11
  92. package/dist/components/questions/_shared/types/read-and-color-objects.type.js +1 -1
  93. package/dist/components/questions/_shared/types/read-displayed-content.type.js +1 -1
  94. package/dist/components/questions/_shared/types/read-passage-and-answer-questions.type.js +1 -1
  95. package/dist/components/questions/_shared/types/speaking-describe-image.type.js +1 -1
  96. package/dist/components/questions/_shared/types/spontaneous-qa.type.js +1 -1
  97. package/dist/components/questions/_shared/types/word-fill-paragraph-with-options.type.js +1 -1
  98. package/dist/components/questions/_shared/types/word-fill-paragraph.type.js +1 -1
  99. package/dist/components/questions/_shared/types/word-fill-structured-form.type.js +1 -1
  100. package/dist/components/questions/_shared/types/word-ordering.type.js +1 -1
  101. package/dist/components/questions/_shared/types/write-a-short-letter.type.js +1 -1
  102. package/dist/components/questions/_shared/types/write-correct-verb-form.type.js +1 -3
  103. package/dist/components/questions/_shared/types/write-sentences.type.js +1 -1
  104. package/dist/components/questions/_shared/types/write-short-paragraph.type.js +1 -1
  105. package/dist/components/questions/_shared/utils/answer-builder.js +1 -79
  106. package/dist/components/questions/_shared/utils/createColorRegionRegistration.js +1 -39
  107. package/dist/components/questions/_shared/utils/id-generator.js +1 -3
  108. package/dist/components/questions/_shared/utils/question-validation.js +1 -21
  109. package/dist/components/questions/components/ColorNode.js +1 -85
  110. package/dist/components/questions/components/ColorRegionClient.js +1 -545
  111. package/dist/components/questions/components/ColorRegionCreator.js +1 -420
  112. package/dist/components/questions/components/ColorRegionNode.js +1 -59
  113. package/dist/components/questions/components/CreatorGuide.js +1 -103
  114. package/dist/components/questions/components/NameNode.js +1 -26
  115. package/dist/components/questions/components/QuestionBankOption.js +1 -46
  116. package/dist/components/questions/components/QuestionBasicInfoForm.js +1 -9
  117. package/dist/components/questions/components/QuestionCommonFields.js +1 -33
  118. package/dist/components/questions/components/QuestionSearchDropdown.js +1 -258
  119. package/dist/components/questions/components/QuestionTypeSelector.js +1 -32
  120. package/dist/components/questions/components/QuestionTypeSpecificForms.js +1 -6
  121. package/dist/components/questions/components/RegionNode.js +1 -94
  122. package/dist/components/questions/components/index.js +1 -14
  123. package/dist/components/questions/creator/QuestionCreator.js +1 -90
  124. package/dist/components/questions/creator/QuestionGroupCreator.js +1 -119
  125. package/dist/components/questions/creator/dedicated-component-router.js +1 -79
  126. package/dist/components/questions/creator/index.js +1 -3
  127. package/dist/components/questions/creator/question-type-registry.js +1 -80
  128. package/dist/components/questions/groups/ArticlesGroupCard.js +1 -121
  129. package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -50
  130. package/dist/components/questions/groups/DocumentGroupCard.js +1 -114
  131. package/dist/components/questions/groups/MatchAnswerGroupCard.js +1 -25
  132. package/dist/components/questions/index.js +1 -10
  133. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +1 -37
  134. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +1 -351
  135. package/dist/components/questions/types/answer-the-question/register.js +1 -67
  136. package/dist/components/questions/types/answer-the-question/transform.js +1 -36
  137. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +1 -141
  138. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +1 -118
  139. package/dist/components/questions/types/arrange-letters-into-words/index.js +1 -2
  140. package/dist/components/questions/types/arrange-letters-into-words/register.js +1 -4
  141. package/dist/components/questions/types/arrange-letters-into-words/transform.js +1 -24
  142. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -64
  143. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +1 -169
  144. package/dist/components/questions/types/choose-correct-adjective/index.js +1 -2
  145. package/dist/components/questions/types/choose-correct-adjective/register.js +1 -55
  146. package/dist/components/questions/types/choose-correct-adjective/transform.js +1 -16
  147. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +1 -131
  148. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +1 -581
  149. package/dist/components/questions/types/choose-the-correct-answer/index.js +1 -2
  150. package/dist/components/questions/types/choose-the-correct-answer/register.js +1 -101
  151. package/dist/components/questions/types/choose-the-correct-answer/transform.js +1 -43
  152. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +1 -275
  153. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +1 -448
  154. package/dist/components/questions/types/fill-in-blank/index.js +1 -2
  155. package/dist/components/questions/types/fill-in-blank/register.js +1 -138
  156. package/dist/components/questions/types/fill-in-blank/transform.js +1 -59
  157. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +1 -117
  158. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +1 -671
  159. package/dist/components/questions/types/fill-missing-words-in-grid/index.js +1 -2
  160. package/dist/components/questions/types/fill-missing-words-in-grid/register.js +1 -37
  161. package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +1 -15
  162. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +1 -262
  163. package/dist/components/questions/types/gn-speaking-interview/register.js +1 -121
  164. package/dist/components/questions/types/gn-speaking-interview/transform.js +1 -48
  165. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +1 -16
  166. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +1 -27
  167. package/dist/components/questions/types/image-object-matching/index.js +1 -2
  168. package/dist/components/questions/types/image-object-matching/register.js +1 -3
  169. package/dist/components/questions/types/image-object-matching/transform.js +1 -2
  170. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +1 -102
  171. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +1 -344
  172. package/dist/components/questions/types/label-the-picture/index.js +1 -2
  173. package/dist/components/questions/types/label-the-picture/register.js +1 -54
  174. package/dist/components/questions/types/label-the-picture/transform.js +1 -28
  175. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +1 -78
  176. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +1 -232
  177. package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +1 -2
  178. package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +1 -82
  179. package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +1 -27
  180. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +1 -70
  181. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +1 -386
  182. package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +1 -2
  183. package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +1 -100
  184. package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +1 -33
  185. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +1 -106
  186. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +1 -457
  187. package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +1 -2
  188. package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +1 -110
  189. package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +1 -35
  190. package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +1 -8
  191. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -22
  192. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +1 -291
  193. package/dist/components/questions/types/listen-and-speak-answer/index.js +1 -2
  194. package/dist/components/questions/types/listen-and-speak-answer/register.js +1 -84
  195. package/dist/components/questions/types/listen-and-speak-answer/transform.js +1 -27
  196. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -32
  197. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +1 -295
  198. package/dist/components/questions/types/listen-and-speak-compare-images/register.js +1 -79
  199. package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +1 -27
  200. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -34
  201. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +1 -285
  202. package/dist/components/questions/types/listen-and-speak-image-group/register.js +1 -81
  203. package/dist/components/questions/types/listen-and-speak-image-group/transform.js +1 -26
  204. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -38
  205. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +1 -385
  206. package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +1 -87
  207. package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +1 -32
  208. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -26
  209. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +1 -247
  210. package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +1 -59
  211. package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +1 -18
  212. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -26
  213. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +1 -256
  214. package/dist/components/questions/types/listen-and-speak-question-list/register.js +1 -81
  215. package/dist/components/questions/types/listen-and-speak-question-list/transform.js +1 -26
  216. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -26
  217. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +1 -230
  218. package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +1 -56
  219. package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +1 -16
  220. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +1 -72
  221. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +1 -230
  222. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
  223. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +1 -66
  224. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +1 -42
  225. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +1 -96
  226. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +1 -238
  227. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +1 -2
  228. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +1 -76
  229. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +1 -19
  230. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +1 -134
  231. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +1 -617
  232. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +1 -2
  233. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +1 -82
  234. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +1 -29
  235. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +1 -38
  236. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +1 -359
  237. package/dist/components/questions/types/match-by-writing-answer/index.js +1 -3
  238. package/dist/components/questions/types/match-by-writing-answer/register.js +1 -58
  239. package/dist/components/questions/types/match-by-writing-answer/transform.js +1 -61
  240. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +1 -16
  241. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +1 -23
  242. package/dist/components/questions/types/read-and-color-objects/index.js +1 -2
  243. package/dist/components/questions/types/read-and-color-objects/register.js +1 -3
  244. package/dist/components/questions/types/read-and-color-objects/transform.js +1 -36
  245. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +1 -125
  246. package/dist/components/questions/types/read-displayed-content/register.js +1 -64
  247. package/dist/components/questions/types/read-displayed-content/transform.js +1 -12
  248. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -64
  249. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +1 -511
  250. package/dist/components/questions/types/read-passage-and-answer-questions/index.js +1 -2
  251. package/dist/components/questions/types/read-passage-and-answer-questions/register.js +1 -58
  252. package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +1 -28
  253. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +1 -373
  254. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +1 -41
  255. package/dist/components/questions/types/speaking-conversation/register.js +1 -110
  256. package/dist/components/questions/types/speaking-conversation/transform.js +1 -34
  257. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +1 -74
  258. package/dist/components/questions/types/speaking-cue-card/register.js +1 -52
  259. package/dist/components/questions/types/speaking-cue-card/transform.js +1 -12
  260. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -10
  261. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +1 -161
  262. package/dist/components/questions/types/speaking-describe-image/index.js +1 -2
  263. package/dist/components/questions/types/speaking-describe-image/register.js +1 -69
  264. package/dist/components/questions/types/speaking-describe-image/transform.js +1 -16
  265. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +1 -234
  266. package/dist/components/questions/types/spontaneous-qa/register.js +1 -93
  267. package/dist/components/questions/types/spontaneous-qa/transform.js +1 -34
  268. package/dist/components/questions/types/true-false/TrueFalseClient.js +1 -75
  269. package/dist/components/questions/types/true-false/TrueFalseCreator.js +1 -244
  270. package/dist/components/questions/types/true-false/index.js +1 -2
  271. package/dist/components/questions/types/true-false/register.js +1 -77
  272. package/dist/components/questions/types/true-false/transform.js +1 -32
  273. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +1 -233
  274. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +1 -631
  275. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +1 -28
  276. package/dist/components/questions/types/word-fill-paragraph/index.js +1 -2
  277. package/dist/components/questions/types/word-fill-paragraph/register.js +1 -136
  278. package/dist/components/questions/types/word-fill-paragraph/transform.js +1 -56
  279. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -138
  280. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +1 -261
  281. package/dist/components/questions/types/word-fill-structured-form/index.js +1 -2
  282. package/dist/components/questions/types/word-fill-structured-form/register.js +1 -67
  283. package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -40
  284. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -84
  285. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +1 -192
  286. package/dist/components/questions/types/word-ordering/index.js +1 -2
  287. package/dist/components/questions/types/word-ordering/register.js +1 -46
  288. package/dist/components/questions/types/word-ordering/transform.js +1 -24
  289. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +1 -98
  290. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +1 -320
  291. package/dist/components/questions/types/write-a-short-letter/index.js +1 -2
  292. package/dist/components/questions/types/write-a-short-letter/register.js +1 -68
  293. package/dist/components/questions/types/write-a-short-letter/transform.js +1 -25
  294. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +1 -61
  295. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +1 -196
  296. package/dist/components/questions/types/write-correct-verb-form/index.js +1 -2
  297. package/dist/components/questions/types/write-correct-verb-form/register.js +1 -62
  298. package/dist/components/questions/types/write-correct-verb-form/transform.js +1 -17
  299. package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +1 -22
  300. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +1 -174
  301. package/dist/components/questions/types/write-sentences/index.js +1 -2
  302. package/dist/components/questions/types/write-sentences/register.js +1 -58
  303. package/dist/components/questions/types/write-sentences/transform.js +1 -28
  304. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -96
  305. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +1 -161
  306. package/dist/components/questions/types/write-short-paragraph/index.js +1 -2
  307. package/dist/components/questions/types/write-short-paragraph/register.js +1 -4
  308. package/dist/components/questions/types/write-short-paragraph/transform.js +1 -21
  309. package/dist/components/questions/viewer/QuestionGroupViewer.js +1 -36
  310. package/dist/components/questions/viewer/QuestionViewer.js +1 -446
  311. package/dist/components/questions/viewer/index.js +1 -2
  312. package/dist/components/results/ResultReviewPageContainer.js +1 -98
  313. package/dist/components/results/ReviewQuestionRenderer.js +1 -72
  314. package/dist/components/results/index.js +1 -2
  315. package/dist/components/results/result-review.utils.js +1 -6
  316. package/dist/components/results/review-data.js +1 -150
  317. package/dist/components/results/review-renderer.utils.js +1 -97
  318. package/dist/components/results/review-types.js +1 -1
  319. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +1 -138
  320. package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +1 -12
  321. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +1 -18
  322. package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +1 -11
  323. package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +1 -11
  324. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +1 -9
  325. package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +1 -13
  326. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +1 -8
  327. package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +1 -6
  328. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +1 -5
  329. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +1 -9
  330. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +1 -41
  331. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +1 -25
  332. package/dist/components/themes/cambridge-yle/index.js +1 -13
  333. package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +1 -24
  334. package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +1 -88
  335. package/dist/components/themes/english-certification/EcWordFillParagraph.js +1 -55
  336. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -156
  337. package/dist/components/themes/english-certification/EcWritingTask.js +1 -34
  338. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +1 -114
  339. package/dist/components/themes/english-certification/EnglishCertificationBrand.js +1 -11
  340. package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +1 -21
  341. package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +1 -15
  342. package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +1 -19
  343. package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +1 -148
  344. package/dist/components/themes/english-certification/EnglishCertificationHeader.js +1 -31
  345. package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +1 -71
  346. package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +1 -33
  347. package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +1 -16
  348. package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +1 -22
  349. package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +1 -37
  350. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +1 -72
  351. package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +1 -90
  352. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +1 -18
  353. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +1 -29
  354. package/dist/components/themes/english-certification/english-certification-theme.js +1 -58
  355. package/dist/components/themes/english-certification/grouped-question-utils.js +1 -218
  356. package/dist/components/themes/english-certification/index.js +1 -21
  357. package/dist/components/themes/index.js +1 -6
  358. package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +1 -170
  359. package/dist/components/themes/summer-sky/SummerSkyLayout.js +1 -221
  360. package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +1 -18
  361. package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +1 -194
  362. package/dist/components/themes/types.js +1 -1
  363. package/dist/components/ui/alert-dialog.js +1 -26
  364. package/dist/components/ui/alert.js +1 -22
  365. package/dist/components/ui/avatar.js +1 -12
  366. package/dist/components/ui/badge.js +1 -38
  367. package/dist/components/ui/button.js +1 -35
  368. package/dist/components/ui/calendar.js +1 -76
  369. package/dist/components/ui/card.js +1 -16
  370. package/dist/components/ui/carousel.js +1 -91
  371. package/dist/components/ui/checkbox.js +1 -9
  372. package/dist/components/ui/collapsible.js +1 -13
  373. package/dist/components/ui/command.js +1 -34
  374. package/dist/components/ui/confirm-dialog.js +1 -49
  375. package/dist/components/ui/dialog.js +1 -23
  376. package/dist/components/ui/drawer.js +1 -35
  377. package/dist/components/ui/dropdown-menu.js +1 -33
  378. package/dist/components/ui/file-upload.js +1 -155
  379. package/dist/components/ui/form.js +1 -62
  380. package/dist/components/ui/hover-card.js +1 -10
  381. package/dist/components/ui/image-preview.js +1 -29
  382. package/dist/components/ui/input.js +1 -8
  383. package/dist/components/ui/label.js +1 -9
  384. package/dist/components/ui/language-switcher.js +1 -15
  385. package/dist/components/ui/multi-select.js +1 -90
  386. package/dist/components/ui/points-input.js +1 -33
  387. package/dist/components/ui/popover.js +1 -26
  388. package/dist/components/ui/progress.js +1 -16
  389. package/dist/components/ui/radio-group.js +1 -12
  390. package/dist/components/ui/scroll-area.js +1 -11
  391. package/dist/components/ui/select.js +1 -38
  392. package/dist/components/ui/separator.js +1 -8
  393. package/dist/components/ui/sheet.js +1 -40
  394. package/dist/components/ui/single-select.js +1 -76
  395. package/dist/components/ui/skeleton.js +1 -6
  396. package/dist/components/ui/switch.js +1 -8
  397. package/dist/components/ui/table.js +1 -20
  398. package/dist/components/ui/tabs.js +1 -17
  399. package/dist/components/ui/textarea.js +1 -8
  400. package/dist/components/ui/tooltip.js +1 -11
  401. package/dist/index.d.ts +3 -3
  402. package/dist/index.js +1 -19
  403. package/dist/mcp/config.js +1 -32
  404. package/dist/mcp/http-client.js +1 -48
  405. package/dist/mcp/index.js +1 -29
  406. package/dist/mcp/tools/_helpers.js +1 -25
  407. package/dist/mcp/tools/exams.js +1 -439
  408. package/dist/mcp/tools/index.js +1 -6
  409. package/dist/mcp/tools/results.js +1 -19
  410. package/dist/shared/constants/ApiConstant.js +1 -276
  411. package/dist/shared/constants/QueryKeyConstant.js +1 -112
  412. package/dist/shared/constants/exam-level.enum.js +1 -41
  413. package/dist/shared/constants/landings/placement-test.constants.js +1 -431
  414. package/dist/shared/constants/question-skills.js +1 -267
  415. package/dist/shared/constants/routes.js +1 -81
  416. package/dist/shared/index.d.ts +3 -0
  417. package/dist/shared/index.js +1 -7
  418. package/dist/shared/lib/hooks/index.js +1 -10
  419. package/dist/shared/lib/hooks/useAlertDialog.js +1 -57
  420. package/dist/shared/lib/hooks/useAudioPlayCounter.js +1 -30
  421. package/dist/shared/lib/hooks/useAudioPreview.js +1 -81
  422. package/dist/shared/lib/hooks/useAudioUpload.js +1 -24
  423. package/dist/shared/lib/hooks/useConfirmDialog.js +1 -89
  424. package/dist/shared/lib/hooks/useDebouncedCallback.js +1 -32
  425. package/dist/shared/lib/hooks/useDelayedAutoPlay.js +1 -12
  426. package/dist/shared/lib/hooks/useFileUpload.js +1 -24
  427. package/dist/shared/lib/hooks/useImageUrl.js +1 -5
  428. package/dist/shared/lib/hooks/usePresignedFileUrl.js +1 -10
  429. package/dist/shared/lib/hooks/useReactHookForm.js +1 -31
  430. package/dist/shared/lib/hooks/useToast.js +1 -62
  431. package/dist/shared/lib/i18n/index.js +1 -54
  432. package/dist/shared/lib/i18n/messages/en/admin.js +1 -2104
  433. package/dist/shared/lib/i18n/messages/en/auth.js +1 -86
  434. package/dist/shared/lib/i18n/messages/en/common.js +1 -140
  435. package/dist/shared/lib/i18n/messages/en/file-upload.js +1 -18
  436. package/dist/shared/lib/i18n/messages/en/student.js +1 -133
  437. package/dist/shared/lib/i18n/messages/en/terms.js +1 -37
  438. package/dist/shared/lib/i18n/messages/en.js +1 -15
  439. package/dist/shared/lib/i18n/messages/vi/admin.js +1 -2104
  440. package/dist/shared/lib/i18n/messages/vi/auth.js +1 -86
  441. package/dist/shared/lib/i18n/messages/vi/common.js +1 -140
  442. package/dist/shared/lib/i18n/messages/vi/file-upload.js +1 -18
  443. package/dist/shared/lib/i18n/messages/vi/student.js +1 -133
  444. package/dist/shared/lib/i18n/messages/vi/terms.js +1 -37
  445. package/dist/shared/lib/i18n/messages/vi.js +1 -15
  446. package/dist/shared/lib/i18n/types.js +1 -1
  447. package/dist/shared/lib/stores/examQuestionStore.js +1 -212
  448. package/dist/shared/lib/stores/localeStore.js +1 -10
  449. package/dist/shared/lib/utils/public-page.js +1 -44
  450. package/dist/shared/lib/utils/question-reverse-transform.d.ts +6 -0
  451. package/dist/shared/lib/utils/question-reverse-transform.js +1 -0
  452. package/dist/shared/lib/utils/question-transform-types.js +1 -1
  453. package/dist/shared/lib/utils/question-transform-validation.d.ts +6 -0
  454. package/dist/shared/lib/utils/question-transform-validation.js +1 -0
  455. package/dist/shared/lib/utils/question-transform.d.ts +6 -2
  456. package/dist/shared/lib/utils/question-transform.js +1 -174
  457. package/dist/shared/lib/utils.js +1 -168
  458. package/dist/shared/lib/validation/choose-correct-answer.validation.js +1 -111
  459. package/dist/shared/lib/validation/label-the-picture.validation.js +1 -19
  460. package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +1 -46
  461. package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +1 -21
  462. package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +1 -34
  463. package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +1 -40
  464. package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +1 -45
  465. package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +1 -19
  466. package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +1 -39
  467. package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +1 -32
  468. package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +1 -19
  469. package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +1 -28
  470. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +1 -12
  471. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +1 -47
  472. package/dist/shared/lib/validation/read-and-color-objects.validation.js +1 -29
  473. package/dist/shared/lib/validation/read-displayed-content.validation.js +1 -28
  474. package/dist/shared/lib/validation/speaking-conversation.validation.js +1 -75
  475. package/dist/shared/lib/validation/speaking-describe-image.validation.js +1 -31
  476. package/dist/shared/lib/validation/spontaneous-qa.validation.js +1 -48
  477. package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +1 -38
  478. package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +1 -39
  479. package/dist/shared/lib/validation/word-fill-paragraph.validation.js +1 -43
  480. package/dist/shared/lib/validation/word-ordering.validation.js +1 -33
  481. package/dist/shared/types/branch.types.js +1 -6
  482. package/dist/shared/types/common.types.js +1 -50
  483. package/dist/shared/types/entities/exam-schedule.types.js +1 -5
  484. package/dist/shared/types/entities/exam.types.js +1 -1
  485. package/dist/shared/types/entities/question.types.js +1 -4
  486. package/dist/shared/types/entities/result.types.js +1 -4
  487. package/dist/shared/types/entities/user.types.js +1 -4
  488. package/dist/shared/types/exam-taking.types.js +1 -2
  489. package/dist/shared/types/history.types.js +1 -34
  490. package/dist/shared/types/index.js +1 -1
  491. package/dist/shared/types/questions/choose-correct-adjective.js +1 -4
  492. package/dist/shared/types/questions/choose-the-correct-answer.js +1 -9
  493. package/dist/shared/types/questions/fill-missing-words-in-grid.js +1 -11
  494. package/dist/shared/types/questions/index.js +1 -40
  495. package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
  496. package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
  497. package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
  498. package/dist/shared/types/questions/listen-and-speak-info-exchange.js +1 -3
  499. package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +1 -3
  500. package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
  501. package/dist/shared/types/questions/listen-and-speak-with-story-images.js +1 -3
  502. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +1 -5
  503. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +1 -9
  504. package/dist/shared/types/questions/look-picture-fill-word-hint.js +1 -7
  505. package/dist/shared/types/questions/read-displayed-content.js +1 -1
  506. package/dist/shared/types/questions/speaking-conversation.js +1 -7
  507. package/dist/shared/types/questions/speaking-describe-image.js +1 -1
  508. package/dist/shared/types/questions/spontaneous-qa.js +1 -1
  509. package/dist/shared/types/questions/write-correct-verb-form.js +1 -12
  510. package/dist/shared/types/role.types.js +1 -1
  511. package/dist/shared/types/structure-management.js +1 -28
  512. package/dist/shared/types/student.types.js +1 -54
  513. package/dist/shared/types/teacher-dashboard-rooms.js +1 -2
  514. package/package.json +12 -3
@@ -1,58 +1 @@
1
- import { MatchByWritingAnswerCreator } from './MatchByWritingAnswerCreator';
2
- export const matchByWritingAnswerRegistration = {
3
- component: MatchByWritingAnswerCreator,
4
- transformInitialData: (initialData) => {
5
- const content = initialData?.content;
6
- const answer = initialData?.answer;
7
- const questionGroup = initialData?.questionGroup;
8
- const groupPayload = questionGroup?.payload || {};
9
- const groupNumber = questionGroup?.groupNumber || 1;
10
- // Extract shared options from group payload
11
- const options = groupPayload?.options || answer?.options || [];
12
- const groupImageUrl = groupPayload?.groupImageUrl || answer?.groupImageUrl || '';
13
- const groupTitle = groupPayload?.groupTitle || answer?.groupTitle || '';
14
- return {
15
- question: content?.question || answer?.question || '',
16
- imageUrl: content?.imageUrl || answer?.imageUrl || '',
17
- correctAnswer: answer?.answer || answer?.correctAnswer || '',
18
- points: initialData?.points || 1,
19
- groupNumber: answer?.groupNumber || groupNumber,
20
- isExample: initialData?.isExample || answer?.isExample || false,
21
- askerName: content?.askerName || answer?.askerName || '',
22
- answererName: content?.answererName || answer?.answererName || '',
23
- options,
24
- groupImageUrl,
25
- groupTitle,
26
- explanation: initialData?.explanation || answer?.explanation || '',
27
- };
28
- },
29
- getExtraProps: (ctx) => ({
30
- groups: ctx.groups,
31
- groupConfig: ctx.groupConfig,
32
- questionConfig: ctx.questionConfig,
33
- viewMode: ctx.viewMode,
34
- questionIndexInPart: ctx.questionIndexInPart,
35
- partId: ctx.partId,
36
- validationRef: ctx.validationRef,
37
- }),
38
- wrapOnSave: (data, ctx) => ({
39
- type: ctx.questionType,
40
- content: ctx.state.content,
41
- points: data?.points ?? ctx.state.points ?? 1,
42
- level: ctx.state.level,
43
- difficulty: ctx.state.difficulty,
44
- skill: ctx.state.skill,
45
- answer: data,
46
- explanation: data?.explanation || '',
47
- }),
48
- wrapOnChange: (data, ctx) => ({
49
- type: ctx.questionType,
50
- content: ctx.state.content,
51
- points: data?.points ?? ctx.state.points ?? 1,
52
- level: ctx.state.level,
53
- difficulty: ctx.state.difficulty,
54
- skill: ctx.state.skill,
55
- answer: data,
56
- explanation: data?.explanation || '',
57
- }),
58
- };
1
+ import{MatchByWritingAnswerCreator as e}from"./MatchByWritingAnswerCreator";export const matchByWritingAnswerRegistration={component:e,transformInitialData:e=>{const t=e?.content,n=e?.answer,a=e?.questionGroup,o=a?.payload||{},i=a?.groupNumber||1,r=o?.options||n?.options||[],s=o?.groupImageUrl||n?.groupImageUrl||"",p=o?.groupTitle||n?.groupTitle||"";return{question:t?.question||n?.question||"",imageUrl:t?.imageUrl||n?.imageUrl||"",correctAnswer:n?.answer||n?.correctAnswer||"",points:e?.points||1,groupNumber:n?.groupNumber||i,isExample:e?.isExample||n?.isExample||!1,askerName:t?.askerName||n?.askerName||"",answererName:t?.answererName||n?.answererName||"",options:r,groupImageUrl:s,groupTitle:p,explanation:e?.explanation||n?.explanation||""}},getExtraProps:e=>({groups:e.groups,groupConfig:e.groupConfig,questionConfig:e.questionConfig,viewMode:e.viewMode,questionIndexInPart:e.questionIndexInPart,partId:e.partId,validationRef:e.validationRef}),wrapOnSave:(e,t)=>({type:t.questionType,content:t.state.content,points:e?.points??t.state.points??1,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:e,explanation:e?.explanation||""}),wrapOnChange:(e,t)=>({type:t.questionType,content:t.state.content,points:e?.points??t.state.points??1,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:e,explanation:e?.explanation||""})};
@@ -1,61 +1 @@
1
- function normalizeMatchByWritingAnswerOptions(options) {
2
- if (!Array.isArray(options)) {
3
- return [];
4
- }
5
- return options.map((option) => ({
6
- answer: typeof option?.answer === 'string' ? option.answer : '',
7
- content: typeof option?.content === 'string' ? option.content : '',
8
- imageUrl: typeof option?.imageUrl === 'string' ? option.imageUrl : '',
9
- }));
10
- }
11
- /**
12
- * Transform MATCH_BY_WRITING_ANSWER creator data → API format
13
- *
14
- * API format:
15
- * content: { question, imageUrl }
16
- * correctAnswer: { answer }
17
- * questionGroup.payload: { options: [{ answer, imageUrl }] }
18
- */
19
- export function transformMatchByWritingAnswer(question) {
20
- const answerData = question.answer;
21
- if (!answerData) {
22
- return { apiContent: {}, apiCorrectAnswer: {} };
23
- }
24
- const apiContent = {
25
- question: answerData.question || '',
26
- };
27
- // Add question image if present
28
- if (answerData.imageUrl) {
29
- apiContent.imageUrl = answerData.imageUrl;
30
- }
31
- // Add conversation names if present (viewMode = conversation)
32
- if (answerData.askerName) {
33
- apiContent.askerName = answerData.askerName;
34
- }
35
- if (answerData.answererName) {
36
- apiContent.answererName = answerData.answererName;
37
- }
38
- const apiCorrectAnswer = {
39
- answer: answerData.correctAnswer || '',
40
- };
41
- const normalizedOptions = normalizeMatchByWritingAnswerOptions(answerData.options);
42
- // Build imageData to store shared options and group metadata in questionGroup.payload
43
- const imageData = {};
44
- if (normalizedOptions.length > 0) {
45
- imageData.options = normalizedOptions;
46
- }
47
- if (answerData.groupImageUrl) {
48
- imageData.groupImageUrl = answerData.groupImageUrl;
49
- }
50
- if (answerData.groupTitle) {
51
- imageData.groupTitle = answerData.groupTitle;
52
- }
53
- return {
54
- apiContent,
55
- apiCorrectAnswer,
56
- totalPoints: answerData.points || 1,
57
- imageData: imageData,
58
- groupNumber: answerData.groupNumber || 1,
59
- isExample: answerData.isExample || false,
60
- };
61
- }
1
+ export function transformMatchByWritingAnswer(r){const e=r.answer;if(!e)return{apiContent:{},apiCorrectAnswer:{}};const t={question:e.question||""};e.imageUrl&&(t.imageUrl=e.imageUrl),e.askerName&&(t.askerName=e.askerName),e.answererName&&(t.answererName=e.answererName);const a={answer:e.correctAnswer||""},n=(o=e.options,Array.isArray(o)?o.map(r=>({answer:"string"==typeof r?.answer?r.answer:"",content:"string"==typeof r?.content?r.content:"",imageUrl:"string"==typeof r?.imageUrl?r.imageUrl:""})):[]);var o;const s={};return n.length>0&&(s.options=n),e.groupImageUrl&&(s.groupImageUrl=e.groupImageUrl),e.groupTitle&&(s.groupTitle=e.groupTitle),{apiContent:t,apiCorrectAnswer:a,totalPoints:e.points||1,imageData:s,groupNumber:e.groupNumber||1,isExample:e.isExample||!1}}
@@ -1,16 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { ColorRegionClient } from '../../components/ColorRegionClient';
4
- const readAndColorObjectsConfig = {
5
- creatorTitle: 'Đọc và tô màu',
6
- creatorSubtitle: 'Tạo câu hỏi tô màu với hình ảnh và vùng màu',
7
- instructionsLabel: 'Hướng dẫn tô màu',
8
- instructionsTips: [],
9
- instructionPlaceholder: '',
10
- previewTitle: 'Read and Color Objects (Preview)',
11
- clientTitle: 'Read and Color',
12
- clientSubtitle: 'Đọc hướng dẫn và tô màu các vật thể trong hình',
13
- };
14
- export function ReadAndColorObjectsClient(props) {
15
- return _jsx(ColorRegionClient, { ...props, config: readAndColorObjectsConfig });
16
- }
1
+ "use client";import{jsx as t}from"react/jsx-runtime";import{ColorRegionClient as n}from"../../components/ColorRegionClient";const e={creatorTitle:"Đọc và tô màu",creatorSubtitle:"Tạo câu hỏi tô màu với hình ảnh và vùng màu",instructionsLabel:"Hướng dẫn tô màu",instructionsTips:[],instructionPlaceholder:"",previewTitle:"Read and Color Objects (Preview)",clientTitle:"Read and Color",clientSubtitle:"Đọc hướng dẫn và tô màu các vật thể trong hình"};export function ReadAndColorObjectsClient(i){return t(n,{...i,config:e})}
@@ -1,23 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { ColorRegionCreator } from '../../components/ColorRegionCreator';
4
- import { ReadAndColorObjectsClient } from './ReadAndColorObjectsClient';
5
- const readAndColorObjectsConfig = {
6
- creatorTitle: 'Đọc và tô màu',
7
- creatorSubtitle: 'Tạo câu hỏi tô màu với hình ảnh và vùng màu',
8
- instructionsLabel: 'Hướng dẫn tô màu',
9
- instructionsRequired: false,
10
- instructionsTips: [
11
- 'Upload hình ảnh nền cần tô màu',
12
- 'Thêm các màu sắc và tạo vùng tương ứng trên hình ảnh',
13
- 'Kéo thả các vùng để điều chỉnh vị trí',
14
- 'Thêm hướng dẫn tô màu cho mỗi câu lệnh (ví dụ: "Colour the sun yellow")',
15
- ],
16
- instructionPlaceholder: 'Colour the sun yellow',
17
- previewTitle: 'Read and Color Objects (Preview)',
18
- clientTitle: 'Read and Color',
19
- clientSubtitle: 'Đọc hướng dẫn và tô màu các vật thể trong hình',
20
- };
21
- export function ReadAndColorObjectsCreator(props) {
22
- return (_jsx(ColorRegionCreator, { ...props, config: readAndColorObjectsConfig, ClientComponent: ReadAndColorObjectsClient }));
23
- }
1
+ "use client";import{jsx as n}from"react/jsx-runtime";import{ColorRegionCreator as t}from"../../components/ColorRegionCreator";import{ReadAndColorObjectsClient as o}from"./ReadAndColorObjectsClient";const e={creatorTitle:"Đọc và tô màu",creatorSubtitle:"Tạo câu hỏi tô màu với hình ảnh và vùng màu",instructionsLabel:"Hướng dẫn tô màu",instructionsRequired:!1,instructionsTips:["Upload hình ảnh nền cần tô màu","Thêm các màu sắc và tạo vùng tương ứng trên hình ảnh","Kéo thả các vùng để điều chỉnh vị trí",'Thêm hướng dẫn tô màu cho mỗi câu lệnh (ví dụ: "Colour the sun yellow")'],instructionPlaceholder:"Colour the sun yellow",previewTitle:"Read and Color Objects (Preview)",clientTitle:"Read and Color",clientSubtitle:"Đọc hướng dẫn và tô màu các vật thể trong hình"};export function ReadAndColorObjectsCreator(r){return n(t,{...r,config:e,ClientComponent:o})}
@@ -1,2 +1 @@
1
- export * from './ReadAndColorObjectsCreator';
2
- export * from './ReadAndColorObjectsClient';
1
+ export*from"./ReadAndColorObjectsCreator";export*from"./ReadAndColorObjectsClient";
@@ -1,3 +1 @@
1
- import { ReadAndColorObjectsCreator } from './ReadAndColorObjectsCreator';
2
- import { createColorRegionRegistration } from '../../_shared/utils/createColorRegionRegistration';
3
- export const readAndColorObjectsRegistration = createColorRegionRegistration(ReadAndColorObjectsCreator);
1
+ import{ReadAndColorObjectsCreator as o}from"./ReadAndColorObjectsCreator";import{createColorRegionRegistration as r}from"../../_shared/utils/createColorRegionRegistration";export const readAndColorObjectsRegistration=r(o);
@@ -1,36 +1 @@
1
- export const transformReadAndColorObjects = (question) => {
2
- const answerData = question.answer;
3
- if (!answerData?.backgroundImageUrl) {
4
- return { apiContent: {}, apiCorrectAnswer: {} };
5
- }
6
- const apiContent = {
7
- backgroundImageUrl: answerData.backgroundImageUrl,
8
- colorNodes: (answerData.colorNodes || []).map((node) => ({
9
- id: node.id,
10
- color: node.color,
11
- ...(node.label ? { label: node.label } : {}),
12
- })),
13
- regionNodes: (answerData.regionNodes || []).map((region) => ({
14
- id: region.id,
15
- x: region.x,
16
- y: region.y,
17
- width: region.width,
18
- height: region.height,
19
- color: region.color,
20
- linkedColorNodeId: region.linkedColorNodeId,
21
- })),
22
- instructions: answerData.instructions || [],
23
- };
24
- const answers = (answerData.regionNodes || []).reduce((acc, region) => {
25
- if (region.id && region.color) {
26
- acc[region.id] = region.color;
27
- }
28
- return acc;
29
- }, {});
30
- return {
31
- apiContent,
32
- apiCorrectAnswer: {
33
- answers,
34
- },
35
- };
36
- };
1
+ export const transformReadAndColorObjects=o=>{const r=o.answer;if(!r?.backgroundImageUrl)return{apiContent:{},apiCorrectAnswer:{}};return{apiContent:{backgroundImageUrl:r.backgroundImageUrl,colorNodes:(r.colorNodes||[]).map(o=>({id:o.id,color:o.color,...o.label?{label:o.label}:{}})),regionNodes:(r.regionNodes||[]).map(o=>({id:o.id,x:o.x,y:o.y,width:o.width,height:o.height,color:o.color,linkedColorNodeId:o.linkedColorNodeId})),instructions:r.instructions||[]},apiCorrectAnswer:{answers:(r.regionNodes||[]).reduce((o,r)=>(r.id&&r.color&&(o[r.id]=r.color),o),{})}}};
@@ -1,125 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useRef, useEffect } from 'react';
4
- import { Label } from '../../../../components/ui/label';
5
- import { Textarea } from '../../../../components/ui/textarea';
6
- import { PointsInput } from '../../../../components/ui/points-input';
7
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
8
- import { useDebouncedCallback } from '../../../../shared/lib/hooks';
9
- import { useReactHookForm } from '../../../../shared/lib/hooks/useReactHookForm';
10
- import { BookOpen, FileText, Info, MessageSquare } from 'lucide-react';
11
- import { CreatorGuide } from '../../components/CreatorGuide';
12
- import { readDisplayedContentFormSchema, } from '../../../../shared/lib/validation/read-displayed-content.validation';
13
- export function ReadDisplayedContentCreator({ initialData, onSave, onChange, externalErrors, validationRef, }) {
14
- const apiData = initialData;
15
- const form = useReactHookForm({
16
- defaultValues: {
17
- referenceText: apiData?.referenceText || apiData?.content?.referenceText || apiData?.correctAnswer?.expectedAnswers || '',
18
- explanation: apiData?.explanation || '',
19
- points: apiData?.points ?? 5,
20
- },
21
- zodSchema: readDisplayedContentFormSchema,
22
- mode: 'onBlur',
23
- });
24
- const previousInitialDataRef = useRef(initialData);
25
- const isInitializingRef = useRef(false);
26
- const onChangeRef = useRef(onChange);
27
- const previousPayloadRef = useRef('');
28
- useEffect(() => {
29
- onChangeRef.current = onChange;
30
- }, [onChange]);
31
- const debouncedOnChange = useDebouncedCallback((data) => {
32
- onChangeRef.current?.(data);
33
- }, 300);
34
- const watchedReferenceText = form.watch('referenceText');
35
- const watchedExplanation = form.watch('explanation');
36
- const watchedPoints = form.watch('points');
37
- // Expose validation ref for external trigger
38
- useEffect(() => {
39
- if (validationRef) {
40
- validationRef.current = {
41
- triggerValidation: async () => {
42
- return await form.trigger();
43
- },
44
- getFormData: () => ({
45
- referenceText: watchedReferenceText,
46
- explanation: watchedExplanation,
47
- points: watchedPoints,
48
- }),
49
- };
50
- }
51
- }, [validationRef, form, watchedReferenceText, watchedExplanation, watchedPoints]);
52
- // Reset form when initialData changes externally
53
- useEffect(() => {
54
- const apiD = initialData;
55
- const normalizedInitialData = {
56
- referenceText: apiD?.referenceText || apiD?.content?.referenceText || apiD?.correctAnswer?.expectedAnswers || '',
57
- explanation: apiD?.explanation || '',
58
- points: apiD?.points ?? 5,
59
- };
60
- const initialDataChanged = JSON.stringify(previousInitialDataRef.current) !== JSON.stringify(initialData);
61
- if (!initialDataChanged) {
62
- return;
63
- }
64
- previousInitialDataRef.current = initialData;
65
- const currentFormData = {
66
- referenceText: watchedReferenceText,
67
- explanation: watchedExplanation,
68
- points: watchedPoints,
69
- };
70
- const isEchoFromOnChange = currentFormData.points === normalizedInitialData.points &&
71
- currentFormData.explanation === normalizedInitialData.explanation &&
72
- currentFormData.referenceText === normalizedInitialData.referenceText;
73
- const wasJustSaved = initialData?.isCompleted === true;
74
- if (isEchoFromOnChange && wasJustSaved) {
75
- return;
76
- }
77
- const shouldReset = !isEchoFromOnChange;
78
- if (shouldReset) {
79
- isInitializingRef.current = true;
80
- form.reset(normalizedInitialData);
81
- setTimeout(() => {
82
- isInitializingRef.current = false;
83
- }, 150);
84
- }
85
- }, [initialData, form, watchedReferenceText, watchedExplanation, watchedPoints]);
86
- // Debounced onChange
87
- useEffect(() => {
88
- if (isInitializingRef.current) {
89
- const currentPayload = JSON.stringify({
90
- referenceText: watchedReferenceText,
91
- explanation: watchedExplanation,
92
- points: watchedPoints,
93
- });
94
- previousPayloadRef.current = currentPayload;
95
- return;
96
- }
97
- const payload = {
98
- referenceText: watchedReferenceText,
99
- explanation: watchedExplanation,
100
- points: watchedPoints,
101
- };
102
- const payloadString = JSON.stringify(payload);
103
- if (previousPayloadRef.current !== payloadString) {
104
- previousPayloadRef.current = payloadString;
105
- debouncedOnChange(payload);
106
- }
107
- }, [
108
- watchedReferenceText,
109
- watchedExplanation,
110
- watchedPoints,
111
- debouncedOnChange,
112
- ]);
113
- const handleSave = form.handleSubmit((data) => {
114
- onSave?.({
115
- ...data,
116
- });
117
- });
118
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(CreatorGuide, { colorScheme: "blue", steps: [
119
- { text: 'Nhập đoạn văn bản mà học sinh sẽ đọc to (reference text)', highlight: true },
120
- { text: 'Thêm giải thích (tùy chọn)' },
121
- ], tips: [
122
- 'Học sinh sẽ nhìn thấy đoạn văn trên màn hình và đọc to.',
123
- 'AI sẽ so sánh giọng đọc của học sinh với văn bản gốc (Phonetic Distance).',
124
- ] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white", children: [_jsx(CardHeader, { className: "px-4 py-3", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100", children: _jsx(FileText, { className: "h-4 w-4 text-gray-600" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-base font-bold text-gray-900", children: "\u0110o\u1EA1n v\u0103n b\u1EA3n c\u1EA7n \u0111\u1ECDc" }), _jsx("p", { className: "text-xs text-gray-500", children: "T\u1EA1o c\u00E2u h\u1ECFi \u0111\u1ECDc \u0111o\u1EA1n v\u0103n" })] })] }) }) }), _jsxs(CardContent, { className: "space-y-3 px-4 pb-4", children: [_jsx("div", { className: "flex items-center gap-6", children: _jsx(PointsInput, { ...form.register('points', { valueAsNumber: true }), error: form.hasError('points') ? form.getFieldError('points') : undefined }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "referenceText", className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-indigo-500" }), _jsx("span", { className: "flex items-center gap-1", children: "\u0110o\u1EA1n v\u0103n b\u1EA3n" }), _jsx("span", { className: "text-sm font-normal text-red-500", children: "*" })] }), _jsx(Textarea, { id: "referenceText", ...form.register('referenceText'), placeholder: "VD: The fat cat sat on a red mat. It has a small bell on its neck. The bell rings when the cat jumps.", rows: 4, className: `min-h-[120px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 resize-none ${form.hasError('referenceText') ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), form.hasError('referenceText') && (_jsx("p", { className: "text-sm text-red-600", children: form.getFieldError('referenceText') })), _jsxs("div", { className: "mt-2 flex items-start gap-3 rounded-xl border border-blue-100 bg-gradient-to-r from-blue-50 to-indigo-50 p-4 text-sm text-blue-800", children: [_jsx(Info, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-indigo-500" }), _jsx("p", { children: "\u0110\u00E2y l\u00E0 \u0111o\u1EA1n v\u0103n s\u1EBD hi\u1EC3n th\u1ECB tr\u00EAn m\u00E0n h\u00ECnh cho h\u1ECDc sinh \u0111\u1ECDc to. AI s\u1EBD so s\u00E1nh ph\u00E1t \u00E2m c\u1EE7a h\u1ECDc sinh v\u1EDBi \u0111o\u1EA1n v\u0103n n\u00E0y." })] })] }), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100", children: _jsx("span", { className: "text-lg", children: "\u274C" }) }), _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] })] }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white", children: [_jsx(CardHeader, { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm", children: _jsx(BookOpen, { className: "h-3.5 w-3.5 text-white" }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-base font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx("span", { className: "inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600", children: "Kh\u00F4ng b\u1EAFt bu\u1ED9c" })] }), _jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng \u2014 hi\u1EC3n th\u1ECB sau khi h\u1ECDc sinh ho\u00E0n th\u00E0nh c\u00E2u h\u1ECFi" })] })] }) }), _jsx(CardContent, { className: "px-4 pb-4", children: _jsx(Textarea, { value: watchedExplanation || '', onChange: (e) => form.setValue('explanation', e.target.value, { shouldValidate: true }), placeholder: "VD: \u0110o\u1EA1n v\u0103n t\u1EADp trung v\u00E0o c\u00E1c \u00E2m ng\u1EAFn /\u00E6/, /e/, /\u026A/...", rows: 3, className: "min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none" }) })] })] }));
125
- }
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useRef as t,useEffect as n}from"react";import{Label as i}from"../../../../components/ui/label";import{Textarea as s}from"../../../../components/ui/textarea";import{PointsInput as a}from"../../../../components/ui/points-input";import{Card as c,CardContent as o,CardHeader as l,CardTitle as d}from"../../../../components/ui/card";import{useDebouncedCallback as h}from"../../../../shared/lib/hooks";import{useReactHookForm as m}from"../../../../shared/lib/hooks/useReactHookForm";import{BookOpen as x,FileText as p,Info as f,MessageSquare as g}from"lucide-react";import{CreatorGuide as u}from"../../components/CreatorGuide";import{readDisplayedContentFormSchema as b}from"../../../../shared/lib/validation/read-displayed-content.validation";export function ReadDisplayedContentCreator({initialData:N,onSave:v,onChange:y,externalErrors:w,validationRef:T}){const j=N,S=m({defaultValues:{referenceText:j?.referenceText||j?.content?.referenceText||j?.correctAnswer?.expectedAnswers||"",explanation:j?.explanation||"",points:j?.points??5},zodSchema:b,mode:"onBlur"}),k=t(N),A=t(!1),C=t(y),D=t("");n(()=>{C.current=y},[y]);const E=h(e=>{C.current?.(e)},300),V=S.watch("referenceText"),F=S.watch("explanation"),J=S.watch("points");n(()=>{T&&(T.current={triggerValidation:async()=>await S.trigger(),getFormData:()=>({referenceText:V,explanation:F,points:J})})},[T,S,V,F,J]),n(()=>{const e=N,r={referenceText:e?.referenceText||e?.content?.referenceText||e?.correctAnswer?.expectedAnswers||"",explanation:e?.explanation||"",points:e?.points??5};if(!(JSON.stringify(k.current)!==JSON.stringify(N)))return;k.current=N;const t=J===r.points&&F===r.explanation&&V===r.referenceText;if(t&&!0===N?.isCompleted)return;!t&&(A.current=!0,S.reset(r),setTimeout(()=>{A.current=!1},150))},[N,S,V,F,J]),n(()=>{if(A.current){const e=JSON.stringify({referenceText:V,explanation:F,points:J});return void(D.current=e)}const e={referenceText:V,explanation:F,points:J},r=JSON.stringify(e);D.current!==r&&(D.current=r,E(e))},[V,F,J,E]);S.handleSubmit(e=>{v?.({...e})});return r("div",{className:"space-y-4",children:[e(u,{colorScheme:"blue",steps:[{text:"Nhập đoạn văn bản mà học sinh sẽ đọc to (reference text)",highlight:!0},{text:"Thêm giải thích (tùy chọn)"}],tips:["Học sinh sẽ nhìn thấy đoạn văn trên màn hình và đọc to.","AI sẽ so sánh giọng đọc của học sinh với văn bản gốc (Phonetic Distance)."]}),r(c,{className:"overflow-hidden border-0 bg-white",children:[e(l,{className:"px-4 py-3",children:e("div",{className:"flex items-center justify-between",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100",children:e(p,{className:"h-4 w-4 text-gray-600"})}),r("div",{children:[e(d,{className:"text-base font-bold text-gray-900",children:"Đoạn văn bản cần đọc"}),e("p",{className:"text-xs text-gray-500",children:"Tạo câu hỏi đọc đoạn văn"})]})]})})}),r(o,{className:"space-y-3 px-4 pb-4",children:[e("div",{className:"flex items-center gap-6",children:e(a,{...S.register("points",{valueAsNumber:!0}),error:S.hasError("points")?S.getFieldError("points"):void 0})}),r("div",{className:"space-y-2",children:[r(i,{htmlFor:"referenceText",className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(g,{className:"h-4 w-4 text-indigo-500"}),e("span",{className:"flex items-center gap-1",children:"Đoạn văn bản"}),e("span",{className:"text-sm font-normal text-red-500",children:"*"})]}),e(s,{id:"referenceText",...S.register("referenceText"),placeholder:"VD: The fat cat sat on a red mat. It has a small bell on its neck. The bell rings when the cat jumps.",rows:4,className:"min-h-[120px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 resize-none "+(S.hasError("referenceText")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),S.hasError("referenceText")&&e("p",{className:"text-sm text-red-600",children:S.getFieldError("referenceText")}),r("div",{className:"mt-2 flex items-start gap-3 rounded-xl border border-blue-100 bg-gradient-to-r from-blue-50 to-indigo-50 p-4 text-sm text-blue-800",children:[e(f,{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-indigo-500"}),e("p",{children:"Đây là đoạn văn sẽ hiển thị trên màn hình cho học sinh đọc to. AI sẽ so sánh phát âm của học sinh với đoạn văn này."})]})]}),w&&w.length>0&&r("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100",children:e("span",{className:"text-lg",children:"❌"})}),r("div",{className:"text-sm",children:[e("p",{className:"font-semibold text-red-800",children:"Lỗi:"}),e("ul",{className:"mt-1 list-inside list-disc text-red-700",children:w.map((r,t)=>e("li",{children:r},t))})]})]})]})]}),r(c,{className:"overflow-hidden border-0 bg-white",children:[e(l,{className:"px-4 py-3",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm",children:e(x,{className:"h-3.5 w-3.5 text-white"})}),r("div",{children:[r("div",{className:"flex items-center gap-2",children:[e(d,{className:"text-base font-semibold text-gray-800",children:"Giải thích"}),e("span",{className:"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600",children:"Không bắt buộc"})]}),e("p",{className:"text-xs text-gray-500 mt-0.5",children:"Giải thích cho đáp án đúng — hiển thị sau khi học sinh hoàn thành câu hỏi"})]})]})}),e(o,{className:"px-4 pb-4",children:e(s,{value:F||"",onChange:e=>S.setValue("explanation",e.target.value,{shouldValidate:!0}),placeholder:"VD: Đoạn văn tập trung vào các âm ngắn /æ/, /e/, /ɪ/...",rows:3,className:"min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none"})})]})]})}
@@ -1,64 +1 @@
1
- import { ReadDisplayedContentCreator } from './ReadDisplayedContentCreator';
2
- export const readDisplayedContentRegistration = {
3
- component: ReadDisplayedContentCreator,
4
- transformInitialData: (initialData) => {
5
- let creatorData = initialData?.answer;
6
- const content = initialData?.content;
7
- const answer = initialData?.answer || initialData?.correctAnswer || initialData?.correct_answer;
8
- const referenceTextValue = answer?.referenceText || answer?.expectedAnswers || content?.referenceText || '';
9
- const points = initialData?.total_points
10
- ? parseFloat(initialData.total_points)
11
- : (initialData?.points || content?.points || answer?.points || 5);
12
- const explanation = initialData?.explanation || content?.explanation || answer?.explanation || '';
13
- if (content && typeof content === 'object' && (content.referenceText !== undefined || answer?.expectedAnswers !== undefined)) {
14
- creatorData = {
15
- referenceText: referenceTextValue,
16
- explanation,
17
- points,
18
- };
19
- }
20
- else if (answer && typeof answer === 'object') {
21
- creatorData = {
22
- ...answer,
23
- referenceText: referenceTextValue,
24
- explanation,
25
- points,
26
- };
27
- }
28
- return creatorData;
29
- },
30
- getExtraProps: (ctx) => ({
31
- onUnsavedChangesChange: ctx.onUnsavedChangesChange,
32
- validationRef: ctx.validationRef,
33
- }),
34
- wrapOnSave: (data, ctx) => ({
35
- type: ctx.questionType,
36
- content: {
37
- ...(typeof ctx.state.content === 'object' && ctx.state.content !== null ? ctx.state.content : {}),
38
- referenceText: data.referenceText,
39
- },
40
- points: data?.points ?? ctx.state.points ?? 5,
41
- level: ctx.state.level,
42
- difficulty: ctx.state.difficulty,
43
- skill: ctx.state.skill,
44
- answer: {
45
- expectedAnswers: data.referenceText,
46
- },
47
- explanation: data?.explanation || '',
48
- }),
49
- wrapOnChange: (data, ctx) => ({
50
- type: ctx.questionType,
51
- content: {
52
- ...(typeof ctx.state.content === 'object' && ctx.state.content !== null ? ctx.state.content : {}),
53
- referenceText: data.referenceText,
54
- },
55
- points: data?.points ?? ctx.state.points ?? 5,
56
- level: ctx.state.level,
57
- difficulty: ctx.state.difficulty,
58
- skill: ctx.state.skill,
59
- answer: {
60
- expectedAnswers: data.referenceText,
61
- },
62
- explanation: data?.explanation || '',
63
- }),
64
- };
1
+ import{ReadDisplayedContentCreator as e}from"./ReadDisplayedContentCreator";export const readDisplayedContentRegistration={component:e,transformInitialData:e=>{let t=e?.answer;const n=e?.content,a=e?.answer||e?.correctAnswer||e?.correct_answer,o=a?.referenceText||a?.expectedAnswers||n?.referenceText||"",s=e?.total_points?parseFloat(e.total_points):e?.points||n?.points||a?.points||5,r=e?.explanation||n?.explanation||a?.explanation||"";return!n||"object"!=typeof n||void 0===n.referenceText&&void 0===a?.expectedAnswers?a&&"object"==typeof a&&(t={...a,referenceText:o,explanation:r,points:s}):t={referenceText:o,explanation:r,points:s},t},getExtraProps:e=>({onUnsavedChangesChange:e.onUnsavedChangesChange,validationRef:e.validationRef}),wrapOnSave:(e,t)=>({type:t.questionType,content:{..."object"==typeof t.state.content&&null!==t.state.content?t.state.content:{},referenceText:e.referenceText},points:e?.points??t.state.points??5,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:{expectedAnswers:e.referenceText},explanation:e?.explanation||""}),wrapOnChange:(e,t)=>({type:t.questionType,content:{..."object"==typeof t.state.content&&null!==t.state.content?t.state.content:{},referenceText:e.referenceText},points:e?.points??t.state.points??5,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:{expectedAnswers:e.referenceText},explanation:e?.explanation||""})};
@@ -1,12 +1 @@
1
- export const transformReadDisplayedContent = (question) => {
2
- const contentData = question.content;
3
- const answerData = question.answer;
4
- const referenceText = contentData?.referenceText || answerData?.referenceText || answerData?.expectedAnswers || '';
5
- const apiContent = {
6
- referenceText,
7
- };
8
- return {
9
- apiContent,
10
- apiCorrectAnswer: {},
11
- };
12
- };
1
+ export const transformReadDisplayedContent=e=>{const n=e.content,r=e.answer;return{apiContent:{referenceText:n?.referenceText||r?.referenceText||r?.expectedAnswers||""},apiCorrectAnswer:{}}};
@@ -1,64 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useEffect, useRef } from 'react';
4
- import { cn } from '../../../../shared/lib/utils';
5
- import { Check, X, BookOpen, FileText, ClipboardList, Lightbulb } from 'lucide-react';
6
- export function ReadPassageAndAnswerQuestionsClient({ questionData, userAnswer, isReviewMode = false, onSubmit, autoFillCorrectAnswers = false, explanation: explanationProp, }) {
7
- const { passage, passageTitle, instructions, singleQuestion, explanation: dataExplanation } = questionData;
8
- const explanation = explanationProp || dataExplanation;
9
- // Single answer state
10
- const [selectedAnswer, setSelectedAnswer] = useState(() => {
11
- if (autoFillCorrectAnswers && singleQuestion) {
12
- return singleQuestion.correctAnswer;
13
- }
14
- return typeof userAnswer === 'number' ? userAnswer : -1;
15
- });
16
- const previousUserAnswerRef = useRef(JSON.stringify(userAnswer));
17
- // Sync userAnswer when it changes
18
- useEffect(() => {
19
- if (autoFillCorrectAnswers)
20
- return;
21
- const currentUserAnswerStr = JSON.stringify(userAnswer);
22
- if (previousUserAnswerRef.current !== currentUserAnswerStr) {
23
- previousUserAnswerRef.current = currentUserAnswerStr;
24
- setSelectedAnswer(typeof userAnswer === 'number' ? userAnswer : -1);
25
- }
26
- }, [userAnswer, autoFillCorrectAnswers]);
27
- // Handle answer change
28
- const handleAnswerChange = (value) => {
29
- if (isReviewMode)
30
- return;
31
- setSelectedAnswer(value);
32
- onSubmit?.(value);
33
- };
34
- // If no singleQuestion data, show empty state
35
- if (!singleQuestion) {
36
- return (_jsx("div", { className: "text-center text-gray-500 py-8", children: "Kh\u00F4ng c\u00F3 c\u00E2u h\u1ECFi n\u00E0o" }));
37
- }
38
- const isCorrect = isReviewMode && selectedAnswer === singleQuestion.correctAnswer;
39
- const isWrong = isReviewMode && selectedAnswer >= 0 && selectedAnswer !== singleQuestion.correctAnswer;
40
- const hasAnswered = selectedAnswer >= 0;
41
- return (_jsxs("div", { className: "space-y-5", children: [instructions && (_jsx("div", { className: "overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 shadow-sm", children: _jsxs("div", { className: "flex items-center gap-3 px-5 py-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm", children: _jsx(FileText, { className: "h-4 w-4" }) }), _jsx("p", { className: "text-sm font-medium text-blue-900", children: instructions })] }) })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-sm", children: _jsx(BookOpen, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "\u0110o\u1EA1n v\u0103n \u0111\u1ECDc hi\u1EC3u" })] }), _jsxs("div", { className: "p-5 space-y-4", children: [passageTitle && (_jsx("h3", { className: "text-center text-lg font-bold text-gray-900 border-b border-gray-100 pb-3", children: passageTitle })), _jsx("div", { className: "rounded-lg bg-gradient-to-br from-slate-50 to-gray-50 p-5 border border-gray-100", children: _jsx("p", { className: "whitespace-pre-wrap text-base leading-relaxed text-gray-700", children: passage }) })] })] }), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: cn('flex items-center justify-between border-b px-5 py-3', isReviewMode && isCorrect && 'border-green-200 bg-gradient-to-r from-green-50 to-emerald-50', isReviewMode && isWrong && 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50', !isReviewMode && 'border-gray-100 bg-gradient-to-r from-gray-50 to-white'), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-8 w-8 items-center justify-center rounded-lg text-sm font-bold text-white shadow-sm', isReviewMode && isCorrect && 'bg-gradient-to-br from-green-500 to-emerald-600', isReviewMode && isWrong && 'bg-gradient-to-br from-red-500 to-rose-600', !isReviewMode && 'bg-gradient-to-br from-indigo-500 to-purple-600'), children: _jsx(ClipboardList, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-800", children: singleQuestion.question })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold', isCorrect ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'), children: [isCorrect ? _jsx(Check, { className: "h-3.5 w-3.5" }) : _jsx(X, { className: "h-3.5 w-3.5" }), isCorrect ? 'Đúng' : 'Sai'] }))] }), _jsxs("div", { className: "p-5 space-y-2.5", children: [singleQuestion.options.map((option, optIndex) => {
42
- const isSelected = selectedAnswer === optIndex;
43
- const isCorrectOption = optIndex === singleQuestion.correctAnswer;
44
- const letter = String.fromCharCode(65 + optIndex);
45
- return (_jsxs("button", { type: "button", onClick: () => handleAnswerChange(optIndex), disabled: isReviewMode, className: cn('group flex w-full items-center gap-3 rounded-lg border-2 p-3.5 text-left transition-all', isReviewMode
46
- ? isCorrectOption
47
- ? 'border-green-400 bg-green-50'
48
- : isSelected
49
- ? 'border-red-400 bg-red-50'
50
- : 'border-gray-200 bg-gray-50'
51
- : isSelected
52
- ? 'border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100'
53
- : 'border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm'), children: [_jsx("div", { className: cn('flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all', isReviewMode
54
- ? isCorrectOption
55
- ? 'bg-green-500 text-white'
56
- : isSelected
57
- ? 'bg-red-500 text-white'
58
- : 'bg-gray-200 text-gray-600'
59
- : isSelected
60
- ? 'bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm'
61
- : 'bg-gray-100 text-gray-600 group-hover:bg-gray-200'), children: letter }), _jsx("span", { className: cn('flex-1 text-sm font-medium', isReviewMode && isCorrectOption ? 'text-green-800' :
62
- isReviewMode && isSelected && !isCorrectOption ? 'text-red-800' : 'text-gray-700'), children: option }), isReviewMode && (isCorrectOption || isSelected) && (_jsx("div", { className: cn('flex h-6 w-6 items-center justify-center rounded-full', isCorrectOption ? 'bg-green-500' : 'bg-red-500'), children: isCorrectOption ? _jsx(Check, { className: "h-4 w-4 text-white" }) : _jsx(X, { className: "h-4 w-4 text-white" }) }))] }, optIndex));
63
- }), !isReviewMode && !hasAnswered && (_jsxs("div", { className: "rounded-lg border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-3 flex items-center gap-2 mt-3", children: [_jsx("div", { className: "flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-amber-400 text-white", children: _jsx("span", { className: "text-xs font-bold", children: "!" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng ch\u1ECDn m\u1ED9t \u0111\u00E1p \u00E1n" })] })), isReviewMode && isWrong && (_jsx("div", { className: "rounded-lg bg-gradient-to-r from-green-50 to-emerald-50 p-4 border border-green-200 mt-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Check, { className: "h-4 w-4 text-green-600" }), _jsxs("span", { className: "text-sm text-green-700", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", _jsxs("strong", { children: [String.fromCharCode(65 + singleQuestion.correctAnswer), ". ", singleQuestion.options[singleQuestion.correctAnswer]] })] })] }) }))] })] }), isReviewMode && explanation && (_jsxs("div", { className: "overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-br from-blue-50 to-indigo-50 shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-blue-100 bg-white/50 px-4 py-3", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm", children: _jsx(Lightbulb, { className: "h-4 w-4" }) }), _jsx("h4", { className: "text-sm font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-sm text-gray-700 leading-relaxed", children: explanation }) })] }))] }));
64
- }
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t,useEffect as s,useRef as a}from"react";import{cn as n}from"../../../../shared/lib/utils";import{Check as d,X as i,BookOpen as o,FileText as l,ClipboardList as c,Lightbulb as g}from"lucide-react";export function ReadPassageAndAnswerQuestionsClient({questionData:m,userAnswer:b,isReviewMode:h=!1,onSubmit:x,autoFillCorrectAnswers:f=!1,explanation:u}){const{passage:p,passageTitle:w,instructions:y,singleQuestion:N,explanation:v}=m,j=u||v,[A,C]=t(()=>f&&N?N.correctAnswer:"number"==typeof b?b:-1),S=a(JSON.stringify(b));s(()=>{if(f)return;const e=JSON.stringify(b);S.current!==e&&(S.current=e,C("number"==typeof b?b:-1))},[b,f]);if(!N)return e("div",{className:"text-center text-gray-500 py-8",children:"Không có câu hỏi nào"});const k=h&&A===N.correctAnswer,q=h&&A>=0&&A!==N.correctAnswer,J=A>=0;return r("div",{className:"space-y-5",children:[y&&e("div",{className:"overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 shadow-sm",children:r("div",{className:"flex items-center gap-3 px-5 py-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm",children:e(l,{className:"h-4 w-4"})}),e("p",{className:"text-sm font-medium text-blue-900",children:y})]})}),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Đoạn văn đọc hiểu"})]}),r("div",{className:"p-5 space-y-4",children:[w&&e("h3",{className:"text-center text-lg font-bold text-gray-900 border-b border-gray-100 pb-3",children:w}),e("div",{className:"rounded-lg bg-gradient-to-br from-slate-50 to-gray-50 p-5 border border-gray-100",children:e("p",{className:"whitespace-pre-wrap text-base leading-relaxed text-gray-700",children:p})})]})]}),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:n("flex items-center justify-between border-b px-5 py-3",h&&k&&"border-green-200 bg-gradient-to-r from-green-50 to-emerald-50",h&&q&&"border-red-200 bg-gradient-to-r from-red-50 to-rose-50",!h&&"border-gray-100 bg-gradient-to-r from-gray-50 to-white"),children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-8 w-8 items-center justify-center rounded-lg text-sm font-bold text-white shadow-sm",h&&k&&"bg-gradient-to-br from-green-500 to-emerald-600",h&&q&&"bg-gradient-to-br from-red-500 to-rose-600",!h&&"bg-gradient-to-br from-indigo-500 to-purple-600"),children:e(c,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-800",children:N.question})]}),h&&J&&r("div",{className:n("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",k?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(k?d:i,{className:"h-3.5 w-3.5"}),k?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-2.5",children:[N.options.map((t,s)=>{const a=A===s,o=s===N.correctAnswer,l=String.fromCharCode(65+s);return r("button",{type:"button",onClick:()=>{return e=s,void(h||(C(e),x?.(e)));var e},disabled:h,className:n("group flex w-full items-center gap-3 rounded-lg border-2 p-3.5 text-left transition-all",h?o?"border-green-400 bg-green-50":a?"border-red-400 bg-red-50":"border-gray-200 bg-gray-50":a?"border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100":"border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm"),children:[e("div",{className:n("flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all",h?o?"bg-green-500 text-white":a?"bg-red-500 text-white":"bg-gray-200 text-gray-600":a?"bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm":"bg-gray-100 text-gray-600 group-hover:bg-gray-200"),children:l}),e("span",{className:n("flex-1 text-sm font-medium",h&&o?"text-green-800":h&&a&&!o?"text-red-800":"text-gray-700"),children:t}),h&&(o||a)&&e("div",{className:n("flex h-6 w-6 items-center justify-center rounded-full",o?"bg-green-500":"bg-red-500"),children:e(o?d:i,{className:"h-4 w-4 text-white"})})]},s)}),!h&&!J&&r("div",{className:"rounded-lg border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-3 flex items-center gap-2 mt-3",children:[e("div",{className:"flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-amber-400 text-white",children:e("span",{className:"text-xs font-bold",children:"!"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng chọn một đáp án"})]}),h&&q&&e("div",{className:"rounded-lg bg-gradient-to-r from-green-50 to-emerald-50 p-4 border border-green-200 mt-3",children:r("div",{className:"flex items-center gap-2",children:[e(d,{className:"h-4 w-4 text-green-600"}),r("span",{className:"text-sm text-green-700",children:["Đáp án đúng: ",r("strong",{children:[String.fromCharCode(65+N.correctAnswer),". ",N.options[N.correctAnswer]]})]})]})})]})]}),h&&j&&r("div",{className:"overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-br from-blue-50 to-indigo-50 shadow-sm",children:[r("div",{className:"flex items-center gap-2 border-b border-blue-100 bg-white/50 px-4 py-3",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",children:e(g,{className:"h-4 w-4"})}),e("h4",{className:"text-sm font-semibold text-gray-800",children:"Giải thích"})]}),e("div",{className:"p-4",children:e("p",{className:"text-sm text-gray-700 leading-relaxed",children:j})})]})]})}