@tinyweb_dev/oe-exam-sdk 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) 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.js +1 -98
  4. package/dist/api/exam-questions.types.js +1 -1
  5. package/dist/api/exam-taking.js +1 -73
  6. package/dist/api/exam-taking.types.js +1 -1
  7. package/dist/api/index.js +1 -6
  8. package/dist/api/result-review.js +1 -50
  9. package/dist/api/result-review.types.js +1 -1
  10. package/dist/components/CueCardEditor.js +1 -58
  11. package/dist/components/common/ResolvedImage.js +1 -15
  12. package/dist/components/exams/CreateExamInfoForm.js +1 -35
  13. package/dist/components/exams/CreateExamPageContainer.js +1 -103
  14. package/dist/components/exams/ExamCreator.js +1 -89
  15. package/dist/components/exams/ExamPartTabs.js +1 -40
  16. package/dist/components/exams/ExamQuestionGrid.js +1 -18
  17. package/dist/components/exams/ExamQuestionsPageContainer.js +1 -90
  18. package/dist/components/exams/PartAudioUploader.js +1 -9
  19. package/dist/components/exams/TemplateSelector.js +1 -66
  20. package/dist/components/exams/api.js +1 -3
  21. package/dist/components/exams/create-exam.validation.js +1 -18
  22. package/dist/components/exams/exam-template.utils.js +1 -18
  23. package/dist/components/exams/index.js +1 -10
  24. package/dist/components/exams/take/ExamTakingPageContainer.js +1 -153
  25. package/dist/components/exams/take/GenericQuestionRenderer.js +1 -14
  26. package/dist/components/exams/take/exam-taking.utils.js +1 -88
  27. package/dist/components/exams/take/hooks/useSpeakingRecorder.js +1 -24
  28. package/dist/components/exams/take/index.js +1 -2
  29. package/dist/components/exams/take/types.js +1 -1
  30. package/dist/components/index.js +1 -42
  31. package/dist/components/questions/_shared/config/question-types.config.js +1 -333
  32. package/dist/components/questions/_shared/constants/color-palette.js +1 -21
  33. package/dist/components/questions/_shared/hooks/useAnswerGroupQuestionGroup.js +1 -105
  34. package/dist/components/questions/_shared/hooks/useBasicQuestionGroup.js +1 -222
  35. package/dist/components/questions/_shared/hooks/useCompareImagesGroup.js +1 -140
  36. package/dist/components/questions/_shared/hooks/useImageQuestionGroup.js +1 -123
  37. package/dist/components/questions/_shared/hooks/useInfoExchangeGroup.js +1 -50
  38. package/dist/components/questions/_shared/hooks/useQuestionFormState.js +1 -54
  39. package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +1 -123
  40. package/dist/components/questions/_shared/hooks/useQuestionListGroup.js +1 -121
  41. package/dist/components/questions/_shared/hooks/useQuestionOnChange.js +1 -70
  42. package/dist/components/questions/_shared/hooks/useSceneQuestionGroup.js +1 -194
  43. package/dist/components/questions/_shared/index.js +1 -7
  44. package/dist/components/questions/_shared/types/answer-the-question.type.js +1 -1
  45. package/dist/components/questions/_shared/types/arrange-letters-into-words.type.js +1 -1
  46. package/dist/components/questions/_shared/types/choose-correct-adjective.type.js +1 -3
  47. package/dist/components/questions/_shared/types/color-region.config.js +1 -1
  48. package/dist/components/questions/_shared/types/fill-in-blank.type.js +1 -1
  49. package/dist/components/questions/_shared/types/fill-missing-words-in-grid.type.js +1 -1
  50. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +1 -1
  51. package/dist/components/questions/_shared/types/index.js +1 -12
  52. package/dist/components/questions/_shared/types/label-the-picture.type.js +1 -1
  53. package/dist/components/questions/_shared/types/listen-and-choose-from-answer-group.type.js +1 -1
  54. package/dist/components/questions/_shared/types/listen-and-choose-objects-in-scene.type.js +1 -1
  55. package/dist/components/questions/_shared/types/listen-and-drag-objects-into-scene.type.js +1 -1
  56. package/dist/components/questions/_shared/types/listen-and-speak-answer.type.js +1 -1
  57. package/dist/components/questions/_shared/types/listen-and-speak-compare-images.type.js +1 -1
  58. package/dist/components/questions/_shared/types/listen-and-speak-image-group.type.js +1 -1
  59. package/dist/components/questions/_shared/types/listen-and-speak-info-exchange.type.js +1 -1
  60. package/dist/components/questions/_shared/types/listen-and-speak-odd-one-out.type.js +1 -3
  61. package/dist/components/questions/_shared/types/listen-and-speak-question-list.type.js +1 -1
  62. package/dist/components/questions/_shared/types/listen-and-speak-with-story-images.type.js +1 -3
  63. package/dist/components/questions/_shared/types/listen-and-tick-answer.type.js +1 -1
  64. package/dist/components/questions/_shared/types/listening-drawline.type.js +1 -1
  65. package/dist/components/questions/_shared/types/look-and-choose-answer.type.js +1 -1
  66. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +1 -1
  67. package/dist/components/questions/_shared/types/match-by-writing-answer.type.js +1 -1
  68. package/dist/components/questions/_shared/types/multiple-choice.type.js +1 -1
  69. package/dist/components/questions/_shared/types/question-group.type.js +1 -11
  70. package/dist/components/questions/_shared/types/read-and-color-objects.type.js +1 -1
  71. package/dist/components/questions/_shared/types/read-displayed-content.type.js +1 -1
  72. package/dist/components/questions/_shared/types/read-passage-and-answer-questions.type.js +1 -1
  73. package/dist/components/questions/_shared/types/speaking-describe-image.type.js +1 -1
  74. package/dist/components/questions/_shared/types/spontaneous-qa.type.js +1 -1
  75. package/dist/components/questions/_shared/types/word-fill-paragraph-with-options.type.js +1 -1
  76. package/dist/components/questions/_shared/types/word-fill-paragraph.type.js +1 -1
  77. package/dist/components/questions/_shared/types/word-fill-structured-form.type.js +1 -1
  78. package/dist/components/questions/_shared/types/word-ordering.type.js +1 -1
  79. package/dist/components/questions/_shared/types/write-a-short-letter.type.js +1 -1
  80. package/dist/components/questions/_shared/types/write-correct-verb-form.type.js +1 -3
  81. package/dist/components/questions/_shared/types/write-sentences.type.js +1 -1
  82. package/dist/components/questions/_shared/types/write-short-paragraph.type.js +1 -1
  83. package/dist/components/questions/_shared/utils/answer-builder.js +1 -79
  84. package/dist/components/questions/_shared/utils/createColorRegionRegistration.js +1 -39
  85. package/dist/components/questions/_shared/utils/id-generator.js +1 -3
  86. package/dist/components/questions/_shared/utils/question-validation.js +1 -21
  87. package/dist/components/questions/components/ColorNode.js +1 -85
  88. package/dist/components/questions/components/ColorRegionClient.js +1 -545
  89. package/dist/components/questions/components/ColorRegionCreator.js +1 -420
  90. package/dist/components/questions/components/ColorRegionNode.js +1 -59
  91. package/dist/components/questions/components/CreatorGuide.js +1 -103
  92. package/dist/components/questions/components/NameNode.js +1 -26
  93. package/dist/components/questions/components/QuestionBankOption.js +1 -46
  94. package/dist/components/questions/components/QuestionBasicInfoForm.js +1 -9
  95. package/dist/components/questions/components/QuestionCommonFields.js +1 -33
  96. package/dist/components/questions/components/QuestionSearchDropdown.js +1 -258
  97. package/dist/components/questions/components/QuestionTypeSelector.js +1 -32
  98. package/dist/components/questions/components/QuestionTypeSpecificForms.js +1 -6
  99. package/dist/components/questions/components/RegionNode.js +1 -94
  100. package/dist/components/questions/components/index.js +1 -14
  101. package/dist/components/questions/creator/QuestionCreator.js +1 -90
  102. package/dist/components/questions/creator/QuestionGroupCreator.js +1 -119
  103. package/dist/components/questions/creator/dedicated-component-router.js +1 -79
  104. package/dist/components/questions/creator/index.js +1 -3
  105. package/dist/components/questions/creator/question-type-registry.js +1 -80
  106. package/dist/components/questions/groups/ArticlesGroupCard.js +1 -121
  107. package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -50
  108. package/dist/components/questions/groups/DocumentGroupCard.js +1 -114
  109. package/dist/components/questions/groups/MatchAnswerGroupCard.js +1 -25
  110. package/dist/components/questions/index.js +1 -10
  111. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +1 -37
  112. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +1 -351
  113. package/dist/components/questions/types/answer-the-question/register.js +1 -67
  114. package/dist/components/questions/types/answer-the-question/transform.js +1 -36
  115. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +1 -141
  116. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +1 -118
  117. package/dist/components/questions/types/arrange-letters-into-words/index.js +1 -2
  118. package/dist/components/questions/types/arrange-letters-into-words/register.js +1 -4
  119. package/dist/components/questions/types/arrange-letters-into-words/transform.js +1 -24
  120. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -64
  121. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +1 -169
  122. package/dist/components/questions/types/choose-correct-adjective/index.js +1 -2
  123. package/dist/components/questions/types/choose-correct-adjective/register.js +1 -55
  124. package/dist/components/questions/types/choose-correct-adjective/transform.js +1 -16
  125. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +1 -131
  126. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +1 -581
  127. package/dist/components/questions/types/choose-the-correct-answer/index.js +1 -2
  128. package/dist/components/questions/types/choose-the-correct-answer/register.js +1 -101
  129. package/dist/components/questions/types/choose-the-correct-answer/transform.js +1 -43
  130. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +1 -275
  131. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +1 -448
  132. package/dist/components/questions/types/fill-in-blank/index.js +1 -2
  133. package/dist/components/questions/types/fill-in-blank/register.js +1 -138
  134. package/dist/components/questions/types/fill-in-blank/transform.js +1 -59
  135. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +1 -117
  136. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +1 -671
  137. package/dist/components/questions/types/fill-missing-words-in-grid/index.js +1 -2
  138. package/dist/components/questions/types/fill-missing-words-in-grid/register.js +1 -37
  139. package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +1 -15
  140. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +1 -262
  141. package/dist/components/questions/types/gn-speaking-interview/register.js +1 -121
  142. package/dist/components/questions/types/gn-speaking-interview/transform.js +1 -48
  143. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +1 -16
  144. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +1 -27
  145. package/dist/components/questions/types/image-object-matching/index.js +1 -2
  146. package/dist/components/questions/types/image-object-matching/register.js +1 -3
  147. package/dist/components/questions/types/image-object-matching/transform.js +1 -2
  148. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +1 -102
  149. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +1 -344
  150. package/dist/components/questions/types/label-the-picture/index.js +1 -2
  151. package/dist/components/questions/types/label-the-picture/register.js +1 -54
  152. package/dist/components/questions/types/label-the-picture/transform.js +1 -28
  153. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +1 -78
  154. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +1 -232
  155. package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +1 -2
  156. package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +1 -82
  157. package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +1 -27
  158. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +1 -70
  159. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +1 -386
  160. package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +1 -2
  161. package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +1 -100
  162. package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +1 -33
  163. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +1 -106
  164. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +1 -457
  165. package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +1 -2
  166. package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +1 -110
  167. package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +1 -35
  168. package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +1 -8
  169. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -22
  170. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +1 -291
  171. package/dist/components/questions/types/listen-and-speak-answer/index.js +1 -2
  172. package/dist/components/questions/types/listen-and-speak-answer/register.js +1 -84
  173. package/dist/components/questions/types/listen-and-speak-answer/transform.js +1 -27
  174. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -32
  175. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +1 -295
  176. package/dist/components/questions/types/listen-and-speak-compare-images/register.js +1 -79
  177. package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +1 -27
  178. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -34
  179. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +1 -285
  180. package/dist/components/questions/types/listen-and-speak-image-group/register.js +1 -81
  181. package/dist/components/questions/types/listen-and-speak-image-group/transform.js +1 -26
  182. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -38
  183. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +1 -385
  184. package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +1 -87
  185. package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +1 -32
  186. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -26
  187. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +1 -247
  188. package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +1 -59
  189. package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +1 -18
  190. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -26
  191. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +1 -256
  192. package/dist/components/questions/types/listen-and-speak-question-list/register.js +1 -81
  193. package/dist/components/questions/types/listen-and-speak-question-list/transform.js +1 -26
  194. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -26
  195. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +1 -230
  196. package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +1 -56
  197. package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +1 -16
  198. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +1 -72
  199. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +1 -230
  200. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
  201. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +1 -66
  202. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +1 -42
  203. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +1 -96
  204. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +1 -238
  205. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +1 -2
  206. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +1 -76
  207. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +1 -19
  208. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +1 -134
  209. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +1 -617
  210. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +1 -2
  211. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +1 -82
  212. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +1 -29
  213. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +1 -38
  214. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +1 -359
  215. package/dist/components/questions/types/match-by-writing-answer/index.js +1 -3
  216. package/dist/components/questions/types/match-by-writing-answer/register.js +1 -58
  217. package/dist/components/questions/types/match-by-writing-answer/transform.js +1 -61
  218. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +1 -16
  219. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +1 -23
  220. package/dist/components/questions/types/read-and-color-objects/index.js +1 -2
  221. package/dist/components/questions/types/read-and-color-objects/register.js +1 -3
  222. package/dist/components/questions/types/read-and-color-objects/transform.js +1 -36
  223. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +1 -125
  224. package/dist/components/questions/types/read-displayed-content/register.js +1 -64
  225. package/dist/components/questions/types/read-displayed-content/transform.js +1 -12
  226. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -64
  227. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +1 -511
  228. package/dist/components/questions/types/read-passage-and-answer-questions/index.js +1 -2
  229. package/dist/components/questions/types/read-passage-and-answer-questions/register.js +1 -58
  230. package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +1 -28
  231. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +1 -373
  232. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +1 -41
  233. package/dist/components/questions/types/speaking-conversation/register.js +1 -110
  234. package/dist/components/questions/types/speaking-conversation/transform.js +1 -34
  235. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +1 -74
  236. package/dist/components/questions/types/speaking-cue-card/register.js +1 -52
  237. package/dist/components/questions/types/speaking-cue-card/transform.js +1 -12
  238. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -10
  239. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +1 -161
  240. package/dist/components/questions/types/speaking-describe-image/index.js +1 -2
  241. package/dist/components/questions/types/speaking-describe-image/register.js +1 -69
  242. package/dist/components/questions/types/speaking-describe-image/transform.js +1 -16
  243. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +1 -234
  244. package/dist/components/questions/types/spontaneous-qa/register.js +1 -93
  245. package/dist/components/questions/types/spontaneous-qa/transform.js +1 -34
  246. package/dist/components/questions/types/true-false/TrueFalseClient.js +1 -75
  247. package/dist/components/questions/types/true-false/TrueFalseCreator.js +1 -244
  248. package/dist/components/questions/types/true-false/index.js +1 -2
  249. package/dist/components/questions/types/true-false/register.js +1 -77
  250. package/dist/components/questions/types/true-false/transform.js +1 -32
  251. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +1 -233
  252. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +1 -631
  253. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +1 -28
  254. package/dist/components/questions/types/word-fill-paragraph/index.js +1 -2
  255. package/dist/components/questions/types/word-fill-paragraph/register.js +1 -136
  256. package/dist/components/questions/types/word-fill-paragraph/transform.js +1 -56
  257. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -138
  258. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +1 -261
  259. package/dist/components/questions/types/word-fill-structured-form/index.js +1 -2
  260. package/dist/components/questions/types/word-fill-structured-form/register.js +1 -67
  261. package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -40
  262. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -84
  263. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +1 -192
  264. package/dist/components/questions/types/word-ordering/index.js +1 -2
  265. package/dist/components/questions/types/word-ordering/register.js +1 -46
  266. package/dist/components/questions/types/word-ordering/transform.js +1 -24
  267. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +1 -98
  268. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +1 -320
  269. package/dist/components/questions/types/write-a-short-letter/index.js +1 -2
  270. package/dist/components/questions/types/write-a-short-letter/register.js +1 -68
  271. package/dist/components/questions/types/write-a-short-letter/transform.js +1 -25
  272. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +1 -61
  273. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +1 -196
  274. package/dist/components/questions/types/write-correct-verb-form/index.js +1 -2
  275. package/dist/components/questions/types/write-correct-verb-form/register.js +1 -62
  276. package/dist/components/questions/types/write-correct-verb-form/transform.js +1 -17
  277. package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +1 -22
  278. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +1 -174
  279. package/dist/components/questions/types/write-sentences/index.js +1 -2
  280. package/dist/components/questions/types/write-sentences/register.js +1 -58
  281. package/dist/components/questions/types/write-sentences/transform.js +1 -28
  282. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -96
  283. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +1 -161
  284. package/dist/components/questions/types/write-short-paragraph/index.js +1 -2
  285. package/dist/components/questions/types/write-short-paragraph/register.js +1 -4
  286. package/dist/components/questions/types/write-short-paragraph/transform.js +1 -21
  287. package/dist/components/questions/viewer/QuestionGroupViewer.js +1 -36
  288. package/dist/components/questions/viewer/QuestionViewer.js +1 -446
  289. package/dist/components/questions/viewer/index.js +1 -2
  290. package/dist/components/results/ResultReviewPageContainer.js +1 -98
  291. package/dist/components/results/ReviewQuestionRenderer.js +1 -72
  292. package/dist/components/results/index.js +1 -2
  293. package/dist/components/results/result-review.utils.js +1 -6
  294. package/dist/components/results/review-data.js +1 -150
  295. package/dist/components/results/review-renderer.utils.js +1 -97
  296. package/dist/components/results/review-types.js +1 -1
  297. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +1 -138
  298. package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +1 -12
  299. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +1 -18
  300. package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +1 -11
  301. package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +1 -11
  302. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +1 -9
  303. package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +1 -13
  304. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +1 -8
  305. package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +1 -6
  306. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +1 -5
  307. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +1 -9
  308. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +1 -41
  309. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +1 -25
  310. package/dist/components/themes/cambridge-yle/index.js +1 -13
  311. package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +1 -24
  312. package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +1 -88
  313. package/dist/components/themes/english-certification/EcWordFillParagraph.js +1 -55
  314. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -156
  315. package/dist/components/themes/english-certification/EcWritingTask.js +1 -34
  316. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +1 -114
  317. package/dist/components/themes/english-certification/EnglishCertificationBrand.js +1 -11
  318. package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +1 -21
  319. package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +1 -15
  320. package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +1 -19
  321. package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +1 -148
  322. package/dist/components/themes/english-certification/EnglishCertificationHeader.js +1 -31
  323. package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +1 -71
  324. package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +1 -33
  325. package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +1 -16
  326. package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +1 -22
  327. package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +1 -37
  328. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +1 -72
  329. package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +1 -90
  330. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +1 -18
  331. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +1 -29
  332. package/dist/components/themes/english-certification/english-certification-theme.js +1 -58
  333. package/dist/components/themes/english-certification/grouped-question-utils.js +1 -218
  334. package/dist/components/themes/english-certification/index.js +1 -21
  335. package/dist/components/themes/index.js +1 -6
  336. package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +1 -170
  337. package/dist/components/themes/summer-sky/SummerSkyLayout.js +1 -221
  338. package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +1 -18
  339. package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +1 -194
  340. package/dist/components/themes/types.js +1 -1
  341. package/dist/components/ui/alert-dialog.js +1 -26
  342. package/dist/components/ui/alert.js +1 -22
  343. package/dist/components/ui/avatar.js +1 -12
  344. package/dist/components/ui/badge.js +1 -38
  345. package/dist/components/ui/button.js +1 -35
  346. package/dist/components/ui/calendar.js +1 -76
  347. package/dist/components/ui/card.js +1 -16
  348. package/dist/components/ui/carousel.js +1 -91
  349. package/dist/components/ui/checkbox.js +1 -9
  350. package/dist/components/ui/collapsible.js +1 -13
  351. package/dist/components/ui/command.js +1 -34
  352. package/dist/components/ui/confirm-dialog.js +1 -49
  353. package/dist/components/ui/dialog.js +1 -23
  354. package/dist/components/ui/drawer.js +1 -35
  355. package/dist/components/ui/dropdown-menu.js +1 -33
  356. package/dist/components/ui/file-upload.js +1 -155
  357. package/dist/components/ui/form.js +1 -62
  358. package/dist/components/ui/hover-card.js +1 -10
  359. package/dist/components/ui/image-preview.js +1 -29
  360. package/dist/components/ui/input.js +1 -8
  361. package/dist/components/ui/label.js +1 -9
  362. package/dist/components/ui/language-switcher.js +1 -15
  363. package/dist/components/ui/multi-select.js +1 -90
  364. package/dist/components/ui/points-input.js +1 -33
  365. package/dist/components/ui/popover.js +1 -26
  366. package/dist/components/ui/progress.js +1 -16
  367. package/dist/components/ui/radio-group.js +1 -12
  368. package/dist/components/ui/scroll-area.js +1 -11
  369. package/dist/components/ui/select.js +1 -38
  370. package/dist/components/ui/separator.js +1 -8
  371. package/dist/components/ui/sheet.js +1 -40
  372. package/dist/components/ui/single-select.js +1 -76
  373. package/dist/components/ui/skeleton.js +1 -6
  374. package/dist/components/ui/switch.js +1 -8
  375. package/dist/components/ui/table.js +1 -20
  376. package/dist/components/ui/tabs.js +1 -17
  377. package/dist/components/ui/textarea.js +1 -8
  378. package/dist/components/ui/tooltip.js +1 -11
  379. package/dist/index.js +1 -19
  380. package/dist/mcp/config.js +1 -32
  381. package/dist/mcp/http-client.js +1 -48
  382. package/dist/mcp/index.js +1 -29
  383. package/dist/mcp/tools/_helpers.js +1 -25
  384. package/dist/mcp/tools/exams.js +1 -439
  385. package/dist/mcp/tools/index.js +1 -6
  386. package/dist/mcp/tools/results.js +1 -19
  387. package/dist/shared/constants/ApiConstant.js +1 -276
  388. package/dist/shared/constants/QueryKeyConstant.js +1 -112
  389. package/dist/shared/constants/exam-level.enum.js +1 -41
  390. package/dist/shared/constants/landings/placement-test.constants.js +1 -431
  391. package/dist/shared/constants/question-skills.js +1 -267
  392. package/dist/shared/constants/routes.js +1 -81
  393. package/dist/shared/index.js +1 -7
  394. package/dist/shared/lib/hooks/index.js +1 -10
  395. package/dist/shared/lib/hooks/useAlertDialog.js +1 -57
  396. package/dist/shared/lib/hooks/useAudioPlayCounter.js +1 -30
  397. package/dist/shared/lib/hooks/useAudioPreview.js +1 -81
  398. package/dist/shared/lib/hooks/useAudioUpload.js +1 -24
  399. package/dist/shared/lib/hooks/useConfirmDialog.js +1 -89
  400. package/dist/shared/lib/hooks/useDebouncedCallback.js +1 -32
  401. package/dist/shared/lib/hooks/useDelayedAutoPlay.js +1 -12
  402. package/dist/shared/lib/hooks/useFileUpload.js +1 -24
  403. package/dist/shared/lib/hooks/useImageUrl.js +1 -5
  404. package/dist/shared/lib/hooks/usePresignedFileUrl.js +1 -10
  405. package/dist/shared/lib/hooks/useReactHookForm.js +1 -31
  406. package/dist/shared/lib/hooks/useToast.js +1 -62
  407. package/dist/shared/lib/i18n/index.js +1 -54
  408. package/dist/shared/lib/i18n/messages/en/admin.js +1 -2104
  409. package/dist/shared/lib/i18n/messages/en/auth.js +1 -86
  410. package/dist/shared/lib/i18n/messages/en/common.js +1 -140
  411. package/dist/shared/lib/i18n/messages/en/file-upload.js +1 -18
  412. package/dist/shared/lib/i18n/messages/en/student.js +1 -133
  413. package/dist/shared/lib/i18n/messages/en/terms.js +1 -37
  414. package/dist/shared/lib/i18n/messages/en.js +1 -15
  415. package/dist/shared/lib/i18n/messages/vi/admin.js +1 -2104
  416. package/dist/shared/lib/i18n/messages/vi/auth.js +1 -86
  417. package/dist/shared/lib/i18n/messages/vi/common.js +1 -140
  418. package/dist/shared/lib/i18n/messages/vi/file-upload.js +1 -18
  419. package/dist/shared/lib/i18n/messages/vi/student.js +1 -133
  420. package/dist/shared/lib/i18n/messages/vi/terms.js +1 -37
  421. package/dist/shared/lib/i18n/messages/vi.js +1 -15
  422. package/dist/shared/lib/i18n/types.js +1 -1
  423. package/dist/shared/lib/stores/examQuestionStore.js +1 -212
  424. package/dist/shared/lib/stores/localeStore.js +1 -10
  425. package/dist/shared/lib/utils/public-page.js +1 -44
  426. package/dist/shared/lib/utils/question-transform-types.js +1 -1
  427. package/dist/shared/lib/utils/question-transform.js +1 -174
  428. package/dist/shared/lib/utils.js +1 -168
  429. package/dist/shared/lib/validation/choose-correct-answer.validation.js +1 -111
  430. package/dist/shared/lib/validation/label-the-picture.validation.js +1 -19
  431. package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +1 -46
  432. package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +1 -21
  433. package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +1 -34
  434. package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +1 -40
  435. package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +1 -45
  436. package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +1 -19
  437. package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +1 -39
  438. package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +1 -32
  439. package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +1 -19
  440. package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +1 -28
  441. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +1 -12
  442. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +1 -47
  443. package/dist/shared/lib/validation/read-and-color-objects.validation.js +1 -29
  444. package/dist/shared/lib/validation/read-displayed-content.validation.js +1 -28
  445. package/dist/shared/lib/validation/speaking-conversation.validation.js +1 -75
  446. package/dist/shared/lib/validation/speaking-describe-image.validation.js +1 -31
  447. package/dist/shared/lib/validation/spontaneous-qa.validation.js +1 -48
  448. package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +1 -38
  449. package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +1 -39
  450. package/dist/shared/lib/validation/word-fill-paragraph.validation.js +1 -43
  451. package/dist/shared/lib/validation/word-ordering.validation.js +1 -33
  452. package/dist/shared/types/branch.types.js +1 -6
  453. package/dist/shared/types/common.types.js +1 -50
  454. package/dist/shared/types/entities/exam-schedule.types.js +1 -5
  455. package/dist/shared/types/entities/exam.types.js +1 -1
  456. package/dist/shared/types/entities/question.types.js +1 -4
  457. package/dist/shared/types/entities/result.types.js +1 -4
  458. package/dist/shared/types/entities/user.types.js +1 -4
  459. package/dist/shared/types/exam-taking.types.js +1 -2
  460. package/dist/shared/types/history.types.js +1 -34
  461. package/dist/shared/types/index.js +1 -1
  462. package/dist/shared/types/questions/choose-correct-adjective.js +1 -4
  463. package/dist/shared/types/questions/choose-the-correct-answer.js +1 -9
  464. package/dist/shared/types/questions/fill-missing-words-in-grid.js +1 -11
  465. package/dist/shared/types/questions/index.js +1 -40
  466. package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
  467. package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
  468. package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
  469. package/dist/shared/types/questions/listen-and-speak-info-exchange.js +1 -3
  470. package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +1 -3
  471. package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
  472. package/dist/shared/types/questions/listen-and-speak-with-story-images.js +1 -3
  473. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +1 -5
  474. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +1 -9
  475. package/dist/shared/types/questions/look-picture-fill-word-hint.js +1 -7
  476. package/dist/shared/types/questions/read-displayed-content.js +1 -1
  477. package/dist/shared/types/questions/speaking-conversation.js +1 -7
  478. package/dist/shared/types/questions/speaking-describe-image.js +1 -1
  479. package/dist/shared/types/questions/spontaneous-qa.js +1 -1
  480. package/dist/shared/types/questions/write-correct-verb-form.js +1 -12
  481. package/dist/shared/types/role.types.js +1 -1
  482. package/dist/shared/types/structure-management.js +1 -28
  483. package/dist/shared/types/student.types.js +1 -54
  484. package/dist/shared/types/teacher-dashboard-rooms.js +1 -2
  485. package/package.json +4 -2
@@ -1,2 +1 @@
1
- export * from './ChooseTheCorrectAnswerCreator';
2
- export * from './ChooseTheCorrectAnswerClient';
1
+ export*from"./ChooseTheCorrectAnswerCreator";export*from"./ChooseTheCorrectAnswerClient";
@@ -1,101 +1 @@
1
- import { ChooseTheCorrectAnswerCreator } from './ChooseTheCorrectAnswerCreator';
2
- export const chooseTheCorrectAnswerRegistration = {
3
- component: ChooseTheCorrectAnswerCreator,
4
- transformInitialData: (initialData) => {
5
- let creatorData = initialData?.answer;
6
- const content = initialData?.content;
7
- const answer = initialData?.answer;
8
- const points = initialData?.total_points
9
- ? parseFloat(initialData.total_points)
10
- : (initialData?.points || content?.points || answer?.points || 1);
11
- const explanation = initialData?.explanation || content?.explanation || answer?.explanation || '';
12
- // Extract group info from API format
13
- const questionGroup = initialData?.questionGroup || {};
14
- const groupPayload = questionGroup?.payload || {};
15
- if (content && typeof content === 'object' && (content.question !== undefined || content.options)) {
16
- const optionsStrings = content.options || [];
17
- const rawCorrectAnswer = answer?.answer;
18
- const normalizedCorrectAnswer = Array.isArray(rawCorrectAnswer)
19
- ? rawCorrectAnswer
20
- : typeof rawCorrectAnswer === 'number'
21
- ? rawCorrectAnswer
22
- : -1;
23
- const isMultipleAnswers = Boolean(content?.multipleAnswers
24
- ?? answer?.multipleAnswers
25
- ?? initialData?.multipleAnswers
26
- ?? groupPayload?.multipleAnswers
27
- ?? Array.isArray(normalizedCorrectAnswer));
28
- creatorData = {
29
- question: content.question || '',
30
- optionType: content.optionType || 'text',
31
- options: optionsStrings,
32
- correctAnswer: normalizedCorrectAnswer,
33
- multipleAnswers: isMultipleAnswers,
34
- imageUrl: content.imageUrl || '',
35
- askerName: content.askerName || '',
36
- answererName: content.answererName || '',
37
- isExample: initialData?.isExample || answer?.isExample || false,
38
- explanation,
39
- points,
40
- // Add group stuff
41
- groupTitle: groupPayload?.title || answer?.groupTitle || '',
42
- groupContent: groupPayload?.content || answer?.groupContent || '',
43
- groupImageUrl: groupPayload?.imageUrl || answer?.groupImageUrl || content?.groupImageUrl || '',
44
- groupNumber: questionGroup.groupNumber || answer?.groupNumber || 1,
45
- articles: groupPayload?.articles || answer?.articles || undefined,
46
- };
47
- }
48
- else if (answer && typeof answer === 'object' && (answer.question !== undefined || answer.options)) {
49
- creatorData = {
50
- ...answer,
51
- multipleAnswers: Boolean(answer?.multipleAnswers ?? initialData?.multipleAnswers ?? Array.isArray(answer?.correctAnswer)),
52
- optionType: answer.optionType || content?.optionType || 'text',
53
- imageUrl: answer.imageUrl || content?.imageUrl || '',
54
- isExample: initialData?.isExample || answer?.isExample || false,
55
- explanation,
56
- points,
57
- // Add group stuff
58
- groupTitle: groupPayload?.title || answer?.groupTitle || '',
59
- groupContent: groupPayload?.content || answer?.groupContent || '',
60
- groupImageUrl: groupPayload?.imageUrl || answer?.groupImageUrl || content?.groupImageUrl || '',
61
- groupNumber: questionGroup.groupNumber || answer?.groupNumber || 1,
62
- articles: groupPayload?.articles || answer?.articles || undefined,
63
- };
64
- }
65
- return creatorData;
66
- },
67
- getExtraProps: (ctx) => ({
68
- optionCount: ctx.optionCount || 4,
69
- optionMode: ctx.optionMode,
70
- defaultValue: ctx.defaultValue,
71
- defaultQuestion: ctx.defaultQuestion,
72
- viewMode: ctx.viewMode,
73
- onUnsavedChangesChange: ctx.onUnsavedChangesChange,
74
- validationRef: ctx.validationRef,
75
- groups: ctx.groups,
76
- groupType: ctx.groupType,
77
- articleCount: ctx.articleCount,
78
- questionIndexInPart: ctx.questionIndexInPart,
79
- partId: ctx.partId,
80
- questionConfig: ctx.questionConfig,
81
- multipleAnswers: ctx.multipleAnswers,
82
- }),
83
- wrapOnSave: (data, ctx) => ({
84
- type: ctx.questionType,
85
- content: ctx.state.content,
86
- points: data?.points ?? ctx.state.points ?? 1,
87
- level: ctx.state.level,
88
- difficulty: ctx.state.difficulty,
89
- skill: ctx.state.skill,
90
- answer: data,
91
- }),
92
- wrapOnChange: (data, ctx) => ({
93
- type: ctx.questionType,
94
- content: ctx.state.content,
95
- points: data?.points ?? ctx.state.points ?? 1,
96
- level: ctx.state.level,
97
- difficulty: ctx.state.difficulty,
98
- skill: ctx.state.skill,
99
- answer: data,
100
- }),
101
- };
1
+ import{ChooseTheCorrectAnswerCreator as e}from"./ChooseTheCorrectAnswerCreator";export const chooseTheCorrectAnswerRegistration={component:e,transformInitialData:e=>{let t=e?.answer;const o=e?.content,n=e?.answer,r=e?.total_points?parseFloat(e.total_points):e?.points||o?.points||n?.points||1,i=e?.explanation||o?.explanation||n?.explanation||"",s=e?.questionGroup||{},a=s?.payload||{};if(o&&"object"==typeof o&&(void 0!==o.question||o.options)){const p=o.options||[],l=n?.answer,u=Array.isArray(l)||"number"==typeof l?l:-1,g=Boolean(o?.multipleAnswers??n?.multipleAnswers??e?.multipleAnswers??a?.multipleAnswers??Array.isArray(u));t={question:o.question||"",optionType:o.optionType||"text",options:p,correctAnswer:u,multipleAnswers:g,imageUrl:o.imageUrl||"",askerName:o.askerName||"",answererName:o.answererName||"",isExample:e?.isExample||n?.isExample||!1,explanation:i,points:r,groupTitle:a?.title||n?.groupTitle||"",groupContent:a?.content||n?.groupContent||"",groupImageUrl:a?.imageUrl||n?.groupImageUrl||o?.groupImageUrl||"",groupNumber:s.groupNumber||n?.groupNumber||1,articles:a?.articles||n?.articles||void 0}}else n&&"object"==typeof n&&(void 0!==n.question||n.options)&&(t={...n,multipleAnswers:Boolean(n?.multipleAnswers??e?.multipleAnswers??Array.isArray(n?.correctAnswer)),optionType:n.optionType||o?.optionType||"text",imageUrl:n.imageUrl||o?.imageUrl||"",isExample:e?.isExample||n?.isExample||!1,explanation:i,points:r,groupTitle:a?.title||n?.groupTitle||"",groupContent:a?.content||n?.groupContent||"",groupImageUrl:a?.imageUrl||n?.groupImageUrl||o?.groupImageUrl||"",groupNumber:s.groupNumber||n?.groupNumber||1,articles:a?.articles||n?.articles||void 0});return t},getExtraProps:e=>({optionCount:e.optionCount||4,optionMode:e.optionMode,defaultValue:e.defaultValue,defaultQuestion:e.defaultQuestion,viewMode:e.viewMode,onUnsavedChangesChange:e.onUnsavedChangesChange,validationRef:e.validationRef,groups:e.groups,groupType:e.groupType,articleCount:e.articleCount,questionIndexInPart:e.questionIndexInPart,partId:e.partId,questionConfig:e.questionConfig,multipleAnswers:e.multipleAnswers}),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}),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})};
@@ -1,43 +1 @@
1
- export const transformChooseTheCorrectAnswer = (question) => {
2
- const answerData = question.answer;
3
- if (!answerData?.options || answerData.correctAnswer === undefined) {
4
- return { apiContent: {}, apiCorrectAnswer: {} };
5
- }
6
- const apiContent = {
7
- question: answerData.question || '',
8
- optionType: answerData.optionType || 'text',
9
- options: answerData.options,
10
- ...(answerData.multipleAnswers ? { multipleAnswers: true } : {}),
11
- };
12
- // Per-question image goes into content (not group card)
13
- if (answerData.imageUrl) {
14
- apiContent.imageUrl = answerData.imageUrl;
15
- }
16
- if (answerData.askerName) {
17
- apiContent.askerName = answerData.askerName;
18
- }
19
- if (answerData.answererName) {
20
- apiContent.answererName = answerData.answererName;
21
- }
22
- // Build basicGroupData when any group field is present
23
- const hasGroupData = !!(answerData.groupTitle || answerData.groupSubtitle || answerData.groupContent || answerData.groupImageUrl || (answerData.articles && answerData.articles.length > 0));
24
- const basicGroupData = hasGroupData
25
- ? {
26
- title: answerData.groupTitle || '',
27
- subtitle: answerData.groupSubtitle || '',
28
- content: answerData.groupContent || '',
29
- imageUrl: answerData.groupImageUrl || '',
30
- ...(answerData.articles ? { articles: answerData.articles } : {}),
31
- }
32
- : undefined;
33
- return {
34
- apiContent,
35
- apiCorrectAnswer: {
36
- answer: answerData.correctAnswer,
37
- ...(answerData.multipleAnswers ? { multipleAnswers: true } : {}),
38
- },
39
- isExample: answerData.isExample || false,
40
- basicGroupData,
41
- groupNumber: answerData.groupNumber || 1,
42
- };
43
- };
1
+ export const transformChooseTheCorrectAnswer=e=>{const r=e.answer;if(!r?.options||void 0===r.correctAnswer)return{apiContent:{},apiCorrectAnswer:{}};const t={question:r.question||"",optionType:r.optionType||"text",options:r.options,...r.multipleAnswers?{multipleAnswers:!0}:{}};r.imageUrl&&(t.imageUrl=r.imageUrl),r.askerName&&(t.askerName=r.askerName),r.answererName&&(t.answererName=r.answererName);const o=!!(r.groupTitle||r.groupSubtitle||r.groupContent||r.groupImageUrl||r.articles&&r.articles.length>0)?{title:r.groupTitle||"",subtitle:r.groupSubtitle||"",content:r.groupContent||"",imageUrl:r.groupImageUrl||"",...r.articles?{articles:r.articles}:{}}:void 0;return{apiContent:t,apiCorrectAnswer:{answer:r.correctAnswer,...r.multipleAnswers?{multipleAnswers:!0}:{}},isExample:r.isExample||!1,basicGroupData:o,groupNumber:r.groupNumber||1}};
@@ -1,275 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect, useMemo } from 'react';
4
- import { Input } from '../../../../components/ui/input';
5
- import { Check, X, PenLine, AlertTriangle, ClipboardList, Lightbulb, BookOpen, Type, Hash, } from 'lucide-react';
6
- import { cn } from '../../../../shared/lib/utils';
7
- import { usePresignedFileUrl } from '../../../../shared/lib/hooks';
8
- // Helper: Extract placeholder indices from question text
9
- function extractPlaceholderIndices(question) {
10
- const regex = /\{(\d+)\}/g;
11
- const indices = [];
12
- let match;
13
- while ((match = regex.exec(question)) !== null) {
14
- const index = parseInt(match[1], 10);
15
- if (!indices.includes(index)) {
16
- indices.push(index);
17
- }
18
- }
19
- return indices.sort((a, b) => a - b);
20
- }
21
- // Sub-component: Resolve presigned URL for group image
22
- function GroupImage({ src, alt, className }) {
23
- const { previewUrl, isLoading } = usePresignedFileUrl(src);
24
- if (isLoading) {
25
- return (_jsx("div", { className: "flex h-40 items-center justify-center", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-3 border-gray-200 border-t-indigo-500" }) }));
26
- }
27
- return (
28
- /* eslint-disable-next-line @next/next/no-img-element */
29
- _jsx("img", { src: previewUrl || src, alt: alt, className: cn('max-h-72 w-auto object-contain rounded-lg drop-shadow-sm', className), onError: (e) => {
30
- const target = e.target;
31
- target.onerror = null;
32
- target.src = '/images/placeholder-image.svg';
33
- } }));
34
- }
35
- export function FillInBlankClient({ questionData, onSubmit, isReviewMode = false, userAnswer = [], autoFillCorrectAnswers = false, explanation: explanationProp, }) {
36
- // Detect if this is new format (question + answers) or legacy format (blanks array)
37
- const isLegacyFormat = !questionData.question && questionData.blanks && questionData.blanks.length > 0;
38
- const explanation = explanationProp || questionData.explanation;
39
- // Group data - resolve from multiple possible field names
40
- const isGroup = questionData.isGroup;
41
- const groupTitle = questionData.groupTitle || questionData.title || '';
42
- const groupContent = questionData.groupContent || '';
43
- const groupImageUrl = questionData.groupImageUrl || '';
44
- const groupNumber = questionData.groupNumber;
45
- const hasGroupData = isGroup && (groupTitle || groupContent || groupImageUrl);
46
- // Custom hooks for presigned URL (question-level image, not group image)
47
- const { previewUrl: imagePreviewUrl, isLoading: isImageLoading } = usePresignedFileUrl(
48
- // Only use question-level imageUrl when NOT grouped (group image is handled separately)
49
- (!isGroup && questionData.imageUrl) ? questionData.imageUrl : '');
50
- // For new format: extract placeholders from question
51
- const placeholderIndices = useMemo(() => {
52
- if (isLegacyFormat)
53
- return [];
54
- return extractPlaceholderIndices(questionData.question || '');
55
- }, [questionData.question, isLegacyFormat]);
56
- // Initialize answers based on format
57
- const getInitialAnswers = () => {
58
- if (autoFillCorrectAnswers) {
59
- if (isLegacyFormat && questionData.blanks) {
60
- return questionData.blanks.map(b => b.correctAnswer);
61
- }
62
- return questionData.answers || [];
63
- }
64
- return userAnswer || [];
65
- };
66
- const [answers, setAnswers] = useState(getInitialAnswers());
67
- // Sync userAnswer when it changes
68
- useEffect(() => {
69
- if (autoFillCorrectAnswers) {
70
- if (isLegacyFormat && questionData.blanks) {
71
- setAnswers(questionData.blanks.map(b => b.correctAnswer));
72
- }
73
- else {
74
- setAnswers(questionData.answers || []);
75
- }
76
- }
77
- else if (userAnswer) {
78
- setAnswers(userAnswer);
79
- }
80
- }, [userAnswer, autoFillCorrectAnswers, questionData, isLegacyFormat]);
81
- // Handle answer change for specific placeholder index
82
- const handleAnswerChange = (index, value) => {
83
- if (isReviewMode)
84
- return;
85
- const newAnswers = [...answers];
86
- while (newAnswers.length <= index) {
87
- newAnswers.push('');
88
- }
89
- newAnswers[index] = value;
90
- setAnswers(newAnswers);
91
- onSubmit?.(newAnswers);
92
- };
93
- // Check if answer at index is correct
94
- const isAnswerCorrect = (index, userInput) => {
95
- let correctAnswer;
96
- if (isLegacyFormat && questionData.blanks?.[index]) {
97
- correctAnswer = questionData.blanks[index].correctAnswer;
98
- }
99
- else if (questionData.answers?.[index]) {
100
- correctAnswer = questionData.answers[index];
101
- }
102
- else {
103
- return false;
104
- }
105
- const answer = userInput.trim();
106
- const correct = correctAnswer.trim();
107
- if (questionData.caseSensitive) {
108
- return answer === correct;
109
- }
110
- else {
111
- return answer.toLowerCase() === correct.toLowerCase();
112
- }
113
- };
114
- // Calculate score
115
- const calculateScore = () => {
116
- let correct = 0;
117
- let total = 0;
118
- if (isLegacyFormat && questionData.blanks) {
119
- total = questionData.blanks.length;
120
- questionData.blanks.forEach((_, idx) => {
121
- if (isAnswerCorrect(idx, answers[idx] || '')) {
122
- correct++;
123
- }
124
- });
125
- }
126
- else {
127
- total = placeholderIndices.length;
128
- placeholderIndices.forEach((idx) => {
129
- if (isAnswerCorrect(idx, answers[idx] || '')) {
130
- correct++;
131
- }
132
- });
133
- }
134
- return { correct, total };
135
- };
136
- const score = isReviewMode ? calculateScore() : null;
137
- // =====================================================
138
- // SHARED SUB-RENDERS
139
- // =====================================================
140
- /** Group Block – displayed above the question when isGroup */
141
- const renderGroupBlock = () => {
142
- if (!hasGroupData)
143
- return null;
144
- return (_jsxs("div", { className: "relative overflow-hidden rounded-2xl border border-indigo-100 bg-white shadow-sm ring-1 ring-black/5 transition-all", children: [_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-indigo-50/80 via-white to-blue-50/30 opacity-70 pointer-events-none" }), _jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1.5 bg-gradient-to-b from-indigo-500 to-blue-600 rounded-l-2xl" }), _jsxs("div", { className: "relative p-6 sm:p-7", children: [_jsxs("div", { className: "flex items-start gap-4 mb-5 border-b border-indigo-50/60 pb-4", children: [_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-100 to-blue-100 shadow-inner ring-1 ring-indigo-200/50", children: _jsx(BookOpen, { className: "h-5 w-5 text-indigo-600" }) }), _jsxs("div", { className: "flex-1 pt-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [groupNumber && (_jsxs("span", { className: "inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-700 ring-1 ring-inset ring-indigo-700/10", children: ["Nh\u00F3m ", groupNumber] })), _jsx("span", { className: "inline-flex items-center rounded-md bg-orange-50 px-2 py-1 text-xs font-semibold text-orange-700 ring-1 ring-inset ring-orange-700/10", children: "\u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng" })] }), groupTitle && (_jsx("h4", { className: "text-xl font-bold text-slate-800 leading-tight tracking-tight", children: groupTitle }))] })] }), _jsxs("div", { className: "space-y-6 text-slate-700", children: [groupContent && (_jsx("div", { className: "prose prose-slate prose-p:leading-relaxed prose-p:mb-3 max-w-none text-[15px]", children: groupContent.split('\n').map((line, i) => (_jsx("p", { className: "last:mb-0", children: line }, i))) })), groupImageUrl && (_jsxs("div", { className: "mt-5 relative overflow-hidden rounded-xl border border-slate-200/60 bg-slate-50 shadow-sm transition-all hover:shadow-md", children: [_jsx("div", { className: "flex items-center justify-between border-b border-slate-200/60 bg-slate-100/50 px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("span", { className: "ml-2 text-[11px] font-semibold uppercase tracking-wider text-slate-500", children: "T\u00E0i li\u1EC7u \u0111\u00EDnh k\u00E8m" })] }) }), _jsx("div", { className: "flex items-center justify-center p-4 min-h-[160px]", children: _jsx(GroupImage, { src: groupImageUrl, alt: groupTitle || 'Hình ảnh nhóm' }) })] }))] })] })] }));
145
- };
146
- /** Render inline blanks within question text (new format) */
147
- const renderQuestionWithBlanks = () => {
148
- const question = questionData.question || '';
149
- const parts = question.split(/(\{\d+\})/g);
150
- return (_jsx("div", { className: "flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]", children: parts.map((part, partIndex) => {
151
- const match = part.match(/\{(\d+)\}/);
152
- if (match) {
153
- const placeholderIndex = parseInt(match[1], 10);
154
- const userInput = answers[placeholderIndex] || '';
155
- const isCorrect = isReviewMode && isAnswerCorrect(placeholderIndex, userInput);
156
- const isWrong = isReviewMode && userInput && !isCorrect;
157
- return (_jsxs("span", { className: "relative inline-flex items-center mx-0.5", children: [_jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-md bg-orange-100 text-[10px] font-bold text-orange-600 mr-1 ring-1 ring-orange-200/60", children: placeholderIndex + 1 }), _jsx(Input, { value: userInput, onChange: (e) => handleAnswerChange(placeholderIndex, e.target.value), disabled: isReviewMode, className: cn('h-9 w-28 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200', 'focus:ring-2 focus:ring-offset-1 focus:outline-none', isReviewMode
158
- ? isCorrect
159
- ? 'border-emerald-400 bg-emerald-50 text-emerald-700'
160
- : isWrong
161
- ? 'border-red-400 bg-red-50 text-red-700'
162
- : 'border-gray-200 bg-gray-50 text-gray-500'
163
- : 'border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50'), placeholder: "..." }), isReviewMode && (isCorrect || isWrong) && (_jsx("span", { className: cn('absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white', isCorrect ? 'bg-emerald-500' : 'bg-red-500'), children: isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5 text-white" })) : (_jsx(X, { className: "h-2.5 w-2.5 text-white" })) }))] }, partIndex));
164
- }
165
- else {
166
- return (_jsx("span", { className: "text-slate-800 font-medium", children: part }, partIndex));
167
- }
168
- }) }));
169
- };
170
- /** Legacy format: render blanks array */
171
- const renderLegacyBlank = (text, _blankId, blankIndex) => {
172
- const parts = text.split(/(\{0\})/g);
173
- return (_jsx("div", { className: "flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]", children: parts.map((part, partIdx) => {
174
- if (part === '{0}') {
175
- const userInput = answers[blankIndex] || '';
176
- const isCorrect = isReviewMode && isAnswerCorrect(blankIndex, userInput);
177
- const isWrong = isReviewMode && userInput && !isCorrect;
178
- return (_jsxs("span", { className: "relative inline-flex items-center mx-0.5", children: [_jsx(Input, { value: userInput, onChange: (e) => handleAnswerChange(blankIndex, e.target.value), disabled: isReviewMode, className: cn('h-9 w-32 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200', 'focus:ring-2 focus:ring-offset-1 focus:outline-none', isReviewMode
179
- ? isCorrect
180
- ? 'border-emerald-400 bg-emerald-50 text-emerald-700'
181
- : isWrong
182
- ? 'border-red-400 bg-red-50 text-red-700'
183
- : 'border-gray-200 bg-gray-50 text-gray-500'
184
- : 'border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50'), placeholder: "..." }), isReviewMode && (isCorrect || isWrong) && (_jsx("span", { className: cn('absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white', isCorrect ? 'bg-emerald-500' : 'bg-red-500'), children: isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5 text-white" })) : (_jsx(X, { className: "h-2.5 w-2.5 text-white" })) }))] }, partIdx));
185
- }
186
- else {
187
- return (_jsx("span", { className: "text-slate-800 font-medium", children: part }, partIdx));
188
- }
189
- }) }));
190
- };
191
- /** Hints pills block */
192
- const renderHints = () => {
193
- if (isReviewMode || !questionData.showHints || !questionData.hints || questionData.hints.length === 0) {
194
- return null;
195
- }
196
- return (_jsxs("div", { className: "rounded-xl border border-violet-200 bg-gradient-to-r from-violet-50/80 to-purple-50/50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-violet-100 ring-1 ring-violet-200/60", children: _jsx(Lightbulb, { className: "h-3.5 w-3.5 text-violet-600" }) }), _jsx("span", { className: "text-sm font-semibold text-violet-800", children: "G\u1EE3i \u00FD \u0111\u00E1p \u00E1n" })] }), _jsx("div", { className: "flex flex-wrap gap-2", children: questionData.hints.map((hint, index) => (_jsx("span", { className: "inline-flex items-center rounded-full border border-violet-200 bg-white px-3 py-1 text-sm font-medium text-violet-700 shadow-sm transition-all hover:border-violet-300 hover:bg-violet-50 hover:shadow", children: hint }, index))) })] }));
197
- };
198
- /** Case-sensitivity warning */
199
- const renderCaseSensitiveNote = () => {
200
- if (isReviewMode || !questionData.caseSensitive)
201
- return null;
202
- return (_jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50/50 px-4 py-3", children: [_jsx("div", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm", children: _jsx(Type, { className: "h-3.5 w-3.5" }) }), _jsxs("div", { children: [_jsx("span", { className: "text-sm font-semibold text-amber-800", children: "Ph\u00E2n bi\u1EC7t hoa/th\u01B0\u1EDDng" }), _jsx("span", { className: "text-sm text-amber-700 ml-1", children: "\u2013 Vui l\u00F2ng nh\u1EADp \u0111\u00FAng ch\u1EEF hoa/th\u01B0\u1EDDng" })] })] }));
203
- };
204
- /** Explanation card (review mode only) */
205
- const renderExplanation = () => {
206
- const explText = explanation || questionData.explanation;
207
- if (!isReviewMode || !explText)
208
- return null;
209
- return (_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.5 border-b border-blue-100 bg-white/60 px-5 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-slate-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("div", { className: "p-5", children: _jsx("p", { className: "text-sm text-slate-700 leading-relaxed", children: explText }) })] }));
210
- };
211
- /** Question-level image (non-group) */
212
- const renderQuestionImage = () => {
213
- if (isGroup)
214
- return null; // group image is rendered in group block
215
- if (!imagePreviewUrl && !questionData.imageUrl)
216
- return null;
217
- return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-gradient-to-br from-slate-50 to-gray-100 shadow-sm", children: [_jsx("div", { className: "border-b border-gray-100 px-3 py-1.5", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "h-2 w-2 rounded-full bg-red-400" }), _jsx("div", { className: "h-2 w-2 rounded-full bg-yellow-400" }), _jsx("div", { className: "h-2 w-2 rounded-full bg-green-400" }), _jsx("span", { className: "ml-2 text-xs font-medium text-gray-500", children: "H\u00ECnh \u1EA3nh" })] }) }), _jsx("div", { className: "flex items-center justify-center p-4", children: isImageLoading ? (_jsx("div", { className: "flex h-48 items-center justify-center", children: _jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-orange-500" }) })) : (
218
- /* eslint-disable-next-line @next/next/no-img-element */
219
- _jsx("img", { src: imagePreviewUrl || questionData.imageUrl, alt: "Question illustration", className: "max-h-56 w-auto object-contain rounded-md", onError: (e) => {
220
- const target = e.target;
221
- target.onerror = null;
222
- target.src = '/images/placeholder-image.svg';
223
- } })) })] }));
224
- };
225
- // =====================================================
226
- // NEW FORMAT RENDER
227
- // =====================================================
228
- if (!isLegacyFormat) {
229
- const hasAnyAnswer = placeholderIndices.some(idx => (answers[idx] || '').trim());
230
- return (_jsxs("div", { className: "space-y-4", children: [renderGroupBlock(), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm", children: _jsx(PenLine, { className: "h-4 w-4" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-semibold text-gray-700", children: "\u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng" }), _jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-700 ring-1 ring-inset ring-orange-200/60", children: [_jsx(Hash, { className: "h-3 w-3" }), placeholderIndices.length] })] })] }), isReviewMode && score && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold', score.correct === score.total
231
- ? 'bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60'
232
- : score.correct >= score.total / 2
233
- ? 'bg-yellow-100 text-yellow-700 ring-1 ring-yellow-200/60'
234
- : 'bg-red-100 text-red-700 ring-1 ring-red-200/60'), children: [score.correct === score.total && _jsx(Check, { className: "h-3 w-3" }), score.correct, "/", score.total, " \u0111\u00FAng"] }))] }), _jsxs("div", { className: "p-5 space-y-4", children: [_jsx("div", { className: "rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80", children: renderQuestionWithBlanks() }), renderQuestionImage(), renderHints(), isReviewMode && (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-white overflow-hidden shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-gray-100 bg-gradient-to-r from-slate-50 to-gray-50 px-4 py-2.5", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-slate-500 text-white", children: _jsx(ClipboardList, { className: "h-3 w-3" }) }), _jsx("h4", { className: "text-xs font-semibold text-gray-600 uppercase tracking-wider", children: "Chi ti\u1EBFt \u0111\u00E1p \u00E1n" })] }), _jsx("div", { className: "p-4 space-y-2.5", children: placeholderIndices.map((idx) => {
235
- const userInput = answers[idx] || '';
236
- const correctAnswer = questionData.answers?.[idx] || '';
237
- const isCorrect = isAnswerCorrect(idx, userInput);
238
- const hasInput = userInput.trim().length > 0;
239
- return (_jsxs("div", { className: cn('rounded-lg border p-3 transition-colors', isCorrect
240
- ? 'border-emerald-200 bg-emerald-50/50'
241
- : hasInput
242
- ? 'border-red-200 bg-red-50/50'
243
- : 'border-gray-100 bg-gray-50/50'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-orange-100 text-xs font-bold text-orange-600 ring-1 ring-orange-200/60", children: idx + 1 }), _jsxs("span", { className: "text-sm text-gray-500", children: ["Ch\u1ED7 tr\u1ED1ng ", idx + 1] })] }), _jsx("div", { className: cn('flex items-center gap-1 text-xs font-semibold', isCorrect ? 'text-emerald-600' : hasInput ? 'text-red-600' : 'text-gray-400'), children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-3.5 w-3.5" }), " \u0110\u00FAng"] })) : hasInput ? (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-3.5 w-3.5" }), " Sai"] })) : ('Bỏ trống') })] }), _jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2 text-sm", children: [_jsxs("div", { className: "flex items-center justify-between rounded-md bg-white px-3 py-2 border border-gray-100", children: [_jsx("span", { className: "text-gray-500 text-xs", children: "\u0110\u00E3 nh\u1EADp" }), _jsx("span", { className: cn('font-semibold', isCorrect ? 'text-emerald-600' : hasInput ? 'text-red-600' : 'text-gray-400 italic'), children: userInput || '—' })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md bg-emerald-50 px-3 py-2 border border-emerald-100", children: [_jsx("span", { className: "text-gray-500 text-xs", children: "\u0110\u00E1p \u00E1n" }), _jsx("span", { className: "font-semibold text-emerald-600", children: correctAnswer })] })] })] }, idx));
244
- }) })] })), !isReviewMode && !hasAnyAnswer && (_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.5", 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(AlertTriangle, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng \u0111i\u1EC1n c\u00E2u tr\u1EA3 l\u1EDDi v\u00E0o c\u00E1c ch\u1ED7 tr\u1ED1ng" })] }))] })] }), renderCaseSensitiveNote(), renderExplanation()] }));
245
- }
246
- // =====================================================
247
- // LEGACY FORMAT RENDER
248
- // =====================================================
249
- return (_jsxs("div", { className: "space-y-4", children: [renderGroupBlock(), questionData.blanks?.map((blank, index) => {
250
- const userInput = answers[index] || '';
251
- const isCorrect = isReviewMode && isAnswerCorrect(index, userInput);
252
- const hasAnswered = userInput.trim() !== '';
253
- return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm", children: _jsx(PenLine, { className: "h-4 w-4" }) }), _jsxs("span", { className: "text-sm font-semibold text-gray-700", children: ["C\u00E2u ", index + 1, ": \u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng"] })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold', isCorrect
254
- ? 'bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60'
255
- : 'bg-red-100 text-red-700 ring-1 ring-red-200/60'), 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-4", children: [_jsx("div", { className: "rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80", children: renderLegacyBlank(blank.text, blank.id, index) }), index === 0 && renderQuestionImage(), index === 0 && renderHints(), isReviewMode && (_jsx("div", { className: cn('rounded-xl border p-3 transition-colors', isCorrect
256
- ? 'border-emerald-200 bg-emerald-50/50'
257
- : hasAnswered
258
- ? 'border-red-200 bg-red-50/50'
259
- : 'border-gray-100 bg-gray-50/50'), children: _jsxs("div", { className: "space-y-2.5", children: [_jsxs("div", { className: "flex items-center justify-between rounded-md bg-white p-3 border border-gray-100", children: [_jsx("span", { className: "text-sm text-gray-500", children: "\u0110\u00E3 nh\u1EADp:" }), _jsx("span", { className: cn('text-sm font-semibold', isCorrect ? 'text-emerald-600' : hasAnswered ? 'text-red-600' : 'text-gray-400 italic'), children: userInput || '—' })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md bg-emerald-50 p-3 border border-emerald-100", children: [_jsx("span", { className: "text-sm text-gray-500", children: "\u0110\u00E1p \u00E1n \u0111\u00FAng:" }), _jsx("span", { className: "text-sm font-semibold text-emerald-600", children: blank.correctAnswer })] }), _jsxs("div", { className: cn('flex items-center justify-between rounded-md p-3 border', isCorrect
260
- ? 'bg-emerald-50 border-emerald-200'
261
- : 'bg-red-50 border-red-200'), children: [_jsx("span", { className: "text-sm text-gray-500", children: "K\u1EBFt qu\u1EA3:" }), _jsx("div", { className: cn('flex items-center gap-1.5 text-sm font-bold', isCorrect ? 'text-emerald-600' : 'text-red-600'), children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-4 w-4" }), " Ch\u00EDnh x\u00E1c"] })) : (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-4 w-4" }), " Sai"] })) })] })] }) })), !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.5", 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(AlertTriangle, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng \u0111i\u1EC1n c\u00E2u tr\u1EA3 l\u1EDDi" })] }))] })] }, blank.id));
262
- }), renderCaseSensitiveNote(), isReviewMode && score && (questionData.blanks?.length || 0) > 1 && (_jsx("div", { className: cn('overflow-hidden rounded-xl border shadow-sm', score.correct === score.total
263
- ? 'border-emerald-200 bg-gradient-to-r from-emerald-50 to-green-50'
264
- : score.correct >= score.total / 2
265
- ? 'border-yellow-200 bg-gradient-to-r from-yellow-50 to-amber-50'
266
- : 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50'), children: _jsxs("div", { className: "flex items-center justify-between px-5 py-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm', score.correct === score.total
267
- ? 'bg-gradient-to-br from-emerald-500 to-green-600'
268
- : score.correct >= score.total / 2
269
- ? 'bg-gradient-to-br from-yellow-500 to-amber-600'
270
- : 'bg-gradient-to-br from-red-500 to-rose-600'), children: score.correct === score.total ? (_jsx(Check, { className: "h-5 w-5" })) : (_jsx(ClipboardList, { className: "h-5 w-5" })) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-semibold text-gray-800", children: "T\u1ED5ng k\u1EBFt" }), _jsx("p", { className: "text-xs text-gray-500", children: "K\u1EBFt qu\u1EA3 b\u00E0i l\u00E0m c\u1EE7a b\u1EA1n" })] })] }), _jsxs("div", { className: "text-right", children: [_jsxs("div", { className: cn('text-2xl font-bold', score.correct === score.total
271
- ? 'text-emerald-600'
272
- : score.correct >= score.total / 2
273
- ? 'text-yellow-600'
274
- : 'text-red-600'), children: [score.correct, "/", score.total] }), _jsxs("div", { className: "text-xs text-gray-500", children: [Math.round((score.correct / score.total) * 100), "% ch\u00EDnh x\u00E1c"] })] })] }) })), renderExplanation()] }));
275
- }
1
+ "use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as a,useEffect as s,useMemo as l}from"react";import{Input as n}from"../../../../components/ui/input";import{Check as i,X as d,PenLine as o,AlertTriangle as c,ClipboardList as m,Lightbulb as g,BookOpen as h,Type as b,Hash as x}from"lucide-react";import{cn as f}from"../../../../shared/lib/utils";import{usePresignedFileUrl as u}from"../../../../shared/lib/hooks";function p({src:r,alt:t,className:a}){const{previewUrl:s,isLoading:l}=u(r);return l?e("div",{className:"flex h-40 items-center justify-center",children:e("div",{className:"h-6 w-6 animate-spin rounded-full border-3 border-gray-200 border-t-indigo-500"})}):e("img",{src:s||r,alt:t,className:f("max-h-72 w-auto object-contain rounded-lg drop-shadow-sm",a),onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})}export function FillInBlankClient({questionData:N,onSubmit:w,isReviewMode:v=!1,userAnswer:y=[],autoFillCorrectAnswers:j=!1,explanation:k}){const C=!N.question&&N.blanks&&N.blanks.length>0,q=k||N.explanation,U=N.isGroup,A=N.groupTitle||N.title||"",S=N.groupContent||"",E=N.groupImageUrl||"",I=N.groupNumber,L=U&&(A||S||E),{previewUrl:F,isLoading:G}=u(!U&&N.imageUrl?N.imageUrl:""),H=l(()=>C?[]:function(e){const r=/\{(\d+)\}/g,t=[];let a;for(;null!==(a=r.exec(e));){const e=parseInt(a[1],10);t.includes(e)||t.push(e)}return t.sort((e,r)=>e-r)}(N.question||""),[N.question,C]),[T,V]=a(j?C&&N.blanks?N.blanks.map(e=>e.correctAnswer):N.answers||[]:y||[]);s(()=>{j?C&&N.blanks?V(N.blanks.map(e=>e.correctAnswer)):V(N.answers||[]):y&&V(y)},[y,j,N,C]);const B=(e,r)=>{if(v)return;const t=[...T];for(;t.length<=e;)t.push("");t[e]=r,V(t),w?.(t)},K=(e,r)=>{let t;if(C&&N.blanks?.[e])t=N.blanks[e].correctAnswer;else{if(!N.answers?.[e])return!1;t=N.answers[e]}const a=r.trim(),s=t.trim();return N.caseSensitive?a===s:a.toLowerCase()===s.toLowerCase()},M=v?(()=>{let e=0,r=0;return C&&N.blanks?(r=N.blanks.length,N.blanks.forEach((r,t)=>{K(t,T[t]||"")&&e++})):(r=H.length,H.forEach(r=>{K(r,T[r]||"")&&e++})),{correct:e,total:r}})():null,D=()=>L?r("div",{className:"relative overflow-hidden rounded-2xl border border-indigo-100 bg-white shadow-sm ring-1 ring-black/5 transition-all",children:[e("div",{className:"absolute inset-0 bg-gradient-to-br from-indigo-50/80 via-white to-blue-50/30 opacity-70 pointer-events-none"}),e("div",{className:"absolute left-0 top-0 bottom-0 w-1.5 bg-gradient-to-b from-indigo-500 to-blue-600 rounded-l-2xl"}),r("div",{className:"relative p-6 sm:p-7",children:[r("div",{className:"flex items-start gap-4 mb-5 border-b border-indigo-50/60 pb-4",children:[e("div",{className:"flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-100 to-blue-100 shadow-inner ring-1 ring-indigo-200/50",children:e(h,{className:"h-5 w-5 text-indigo-600"})}),r("div",{className:"flex-1 pt-1",children:[r("div",{className:"flex items-center gap-2 mb-1",children:[I&&r("span",{className:"inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-700 ring-1 ring-inset ring-indigo-700/10",children:["Nhóm ",I]}),e("span",{className:"inline-flex items-center rounded-md bg-orange-50 px-2 py-1 text-xs font-semibold text-orange-700 ring-1 ring-inset ring-orange-700/10",children:"Điền vào chỗ trống"})]}),A&&e("h4",{className:"text-xl font-bold text-slate-800 leading-tight tracking-tight",children:A})]})]}),r("div",{className:"space-y-6 text-slate-700",children:[S&&e("div",{className:"prose prose-slate prose-p:leading-relaxed prose-p:mb-3 max-w-none text-[15px]",children:S.split("\n").map((r,t)=>e("p",{className:"last:mb-0",children:r},t))}),E&&r("div",{className:"mt-5 relative overflow-hidden rounded-xl border border-slate-200/60 bg-slate-50 shadow-sm transition-all hover:shadow-md",children:[e("div",{className:"flex items-center justify-between border-b border-slate-200/60 bg-slate-100/50 px-4 py-2",children:r("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("span",{className:"ml-2 text-[11px] font-semibold uppercase tracking-wider text-slate-500",children:"Tài liệu đính kèm"})]})}),e("div",{className:"flex items-center justify-center p-4 min-h-[160px]",children:e(p,{src:E,alt:A||"Hình ảnh nhóm"})})]})]})]})]}):null,P=()=>{const t=(N.question||"").split(/(\{\d+\})/g);return e("div",{className:"flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]",children:t.map((t,a)=>{const s=t.match(/\{(\d+)\}/);if(s){const t=parseInt(s[1],10),l=T[t]||"",o=v&&K(t,l),c=v&&l&&!o;return r("span",{className:"relative inline-flex items-center mx-0.5",children:[e("span",{className:"flex h-5 w-5 items-center justify-center rounded-md bg-orange-100 text-[10px] font-bold text-orange-600 mr-1 ring-1 ring-orange-200/60",children:t+1}),e(n,{value:l,onChange:e=>B(t,e.target.value),disabled:v,className:f("h-9 w-28 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200","focus:ring-2 focus:ring-offset-1 focus:outline-none",v?o?"border-emerald-400 bg-emerald-50 text-emerald-700":c?"border-red-400 bg-red-50 text-red-700":"border-gray-200 bg-gray-50 text-gray-500":"border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50"),placeholder:"..."}),v&&(o||c)&&e("span",{className:f("absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white",o?"bg-emerald-500":"bg-red-500"),children:e(o?i:d,{className:"h-2.5 w-2.5 text-white"})})]},a)}return e("span",{className:"text-slate-800 font-medium",children:t},a)})})},Q=(t,a,s)=>{const l=t.split(/(\{0\})/g);return e("div",{className:"flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]",children:l.map((t,a)=>{if("{0}"===t){const t=T[s]||"",l=v&&K(s,t),o=v&&t&&!l;return r("span",{className:"relative inline-flex items-center mx-0.5",children:[e(n,{value:t,onChange:e=>B(s,e.target.value),disabled:v,className:f("h-9 w-32 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200","focus:ring-2 focus:ring-offset-1 focus:outline-none",v?l?"border-emerald-400 bg-emerald-50 text-emerald-700":o?"border-red-400 bg-red-50 text-red-700":"border-gray-200 bg-gray-50 text-gray-500":"border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50"),placeholder:"..."}),v&&(l||o)&&e("span",{className:f("absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white",l?"bg-emerald-500":"bg-red-500"),children:e(l?i:d,{className:"h-2.5 w-2.5 text-white"})})]},a)}return e("span",{className:"text-slate-800 font-medium",children:t},a)})})},R=()=>!v&&N.showHints&&N.hints&&0!==N.hints.length?r("div",{className:"rounded-xl border border-violet-200 bg-gradient-to-r from-violet-50/80 to-purple-50/50 p-4",children:[r("div",{className:"flex items-center gap-2 mb-3",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-lg bg-violet-100 ring-1 ring-violet-200/60",children:e(g,{className:"h-3.5 w-3.5 text-violet-600"})}),e("span",{className:"text-sm font-semibold text-violet-800",children:"Gợi ý đáp án"})]}),e("div",{className:"flex flex-wrap gap-2",children:N.hints.map((r,t)=>e("span",{className:"inline-flex items-center rounded-full border border-violet-200 bg-white px-3 py-1 text-sm font-medium text-violet-700 shadow-sm transition-all hover:border-violet-300 hover:bg-violet-50 hover:shadow",children:r},t))})]}):null,z=()=>v||!N.caseSensitive?null:r("div",{className:"flex items-center gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50/50 px-4 py-3",children:[e("div",{className:"flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",children:e(b,{className:"h-3.5 w-3.5"})}),r("div",{children:[e("span",{className:"text-sm font-semibold text-amber-800",children:"Phân biệt hoa/thường"}),e("span",{className:"text-sm text-amber-700 ml-1",children:"– Vui lòng nhập đúng chữ hoa/thường"})]})]}),J=()=>{const t=q||N.explanation;return v&&t?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.5 border-b border-blue-100 bg-white/60 px-5 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-slate-800",children:"Giải thích"})]}),e("div",{className:"p-5",children:e("p",{className:"text-sm text-slate-700 leading-relaxed",children:t})})]}):null},O=()=>U?null:F||N.imageUrl?r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-gradient-to-br from-slate-50 to-gray-100 shadow-sm",children:[e("div",{className:"border-b border-gray-100 px-3 py-1.5",children:r("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"h-2 w-2 rounded-full bg-red-400"}),e("div",{className:"h-2 w-2 rounded-full bg-yellow-400"}),e("div",{className:"h-2 w-2 rounded-full bg-green-400"}),e("span",{className:"ml-2 text-xs font-medium text-gray-500",children:"Hình ảnh"})]})}),e("div",{className:"flex items-center justify-center p-4",children:G?e("div",{className:"flex h-48 items-center justify-center",children:e("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-orange-500"})}):e("img",{src:F||N.imageUrl,alt:"Question illustration",className:"max-h-56 w-auto object-contain rounded-md",onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})})]}):null;if(!C){const a=H.some(e=>(T[e]||"").trim());return r("div",{className:"space-y-4",children:[D(),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),r("div",{className:"flex items-center gap-2",children:[e("span",{className:"text-sm font-semibold text-gray-700",children:"Điền vào chỗ trống"}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-700 ring-1 ring-inset ring-orange-200/60",children:[e(x,{className:"h-3 w-3"}),H.length]})]})]}),v&&M&&r("div",{className:f("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold",M.correct===M.total?"bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60":M.correct>=M.total/2?"bg-yellow-100 text-yellow-700 ring-1 ring-yellow-200/60":"bg-red-100 text-red-700 ring-1 ring-red-200/60"),children:[M.correct===M.total&&e(i,{className:"h-3 w-3"}),M.correct,"/",M.total," đúng"]})]}),r("div",{className:"p-5 space-y-4",children:[e("div",{className:"rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80",children:P()}),O(),R(),v&&r("div",{className:"rounded-xl border border-gray-200 bg-white overflow-hidden shadow-sm",children:[r("div",{className:"flex items-center gap-2 border-b border-gray-100 bg-gradient-to-r from-slate-50 to-gray-50 px-4 py-2.5",children:[e("div",{className:"flex h-5 w-5 items-center justify-center rounded-full bg-slate-500 text-white",children:e(m,{className:"h-3 w-3"})}),e("h4",{className:"text-xs font-semibold text-gray-600 uppercase tracking-wider",children:"Chi tiết đáp án"})]}),e("div",{className:"p-4 space-y-2.5",children:H.map(a=>{const s=T[a]||"",l=N.answers?.[a]||"",n=K(a,s),o=s.trim().length>0;return r("div",{className:f("rounded-lg border p-3 transition-colors",n?"border-emerald-200 bg-emerald-50/50":o?"border-red-200 bg-red-50/50":"border-gray-100 bg-gray-50/50"),children:[r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded-md bg-orange-100 text-xs font-bold text-orange-600 ring-1 ring-orange-200/60",children:a+1}),r("span",{className:"text-sm text-gray-500",children:["Chỗ trống ",a+1]})]}),e("div",{className:f("flex items-center gap-1 text-xs font-semibold",n?"text-emerald-600":o?"text-red-600":"text-gray-400"),children:n?r(t,{children:[e(i,{className:"h-3.5 w-3.5"})," Đúng"]}):o?r(t,{children:[e(d,{className:"h-3.5 w-3.5"})," Sai"]}):"Bỏ trống"})]}),r("div",{className:"mt-2 grid grid-cols-2 gap-2 text-sm",children:[r("div",{className:"flex items-center justify-between rounded-md bg-white px-3 py-2 border border-gray-100",children:[e("span",{className:"text-gray-500 text-xs",children:"Đã nhập"}),e("span",{className:f("font-semibold",n?"text-emerald-600":o?"text-red-600":"text-gray-400 italic"),children:s||"—"})]}),r("div",{className:"flex items-center justify-between rounded-md bg-emerald-50 px-3 py-2 border border-emerald-100",children:[e("span",{className:"text-gray-500 text-xs",children:"Đáp án"}),e("span",{className:"font-semibold text-emerald-600",children:l})]})]})]},a)})})]}),!v&&!a&&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.5",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(c,{className:"h-3 w-3"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng điền câu trả lời vào các chỗ trống"})]})]})]}),z(),J()]})}return r("div",{className:"space-y-4",children:[D(),N.blanks?.map((a,s)=>{const l=T[s]||"",n=v&&K(s,l),m=""!==l.trim();return r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),r("span",{className:"text-sm font-semibold text-gray-700",children:["Câu ",s+1,": Điền vào chỗ trống"]})]}),v&&m&&r("div",{className:f("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold",n?"bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60":"bg-red-100 text-red-700 ring-1 ring-red-200/60"),children:[e(n?i:d,{className:"h-3.5 w-3.5"}),n?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-4",children:[e("div",{className:"rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80",children:Q(a.text,a.id,s)}),0===s&&O(),0===s&&R(),v&&e("div",{className:f("rounded-xl border p-3 transition-colors",n?"border-emerald-200 bg-emerald-50/50":m?"border-red-200 bg-red-50/50":"border-gray-100 bg-gray-50/50"),children:r("div",{className:"space-y-2.5",children:[r("div",{className:"flex items-center justify-between rounded-md bg-white p-3 border border-gray-100",children:[e("span",{className:"text-sm text-gray-500",children:"Đã nhập:"}),e("span",{className:f("text-sm font-semibold",n?"text-emerald-600":m?"text-red-600":"text-gray-400 italic"),children:l||"—"})]}),r("div",{className:"flex items-center justify-between rounded-md bg-emerald-50 p-3 border border-emerald-100",children:[e("span",{className:"text-sm text-gray-500",children:"Đáp án đúng:"}),e("span",{className:"text-sm font-semibold text-emerald-600",children:a.correctAnswer})]}),r("div",{className:f("flex items-center justify-between rounded-md p-3 border",n?"bg-emerald-50 border-emerald-200":"bg-red-50 border-red-200"),children:[e("span",{className:"text-sm text-gray-500",children:"Kết quả:"}),e("div",{className:f("flex items-center gap-1.5 text-sm font-bold",n?"text-emerald-600":"text-red-600"),children:r(t,n?{children:[e(i,{className:"h-4 w-4"})," Chính xác"]}:{children:[e(d,{className:"h-4 w-4"})," Sai"]})})]})]})}),!v&&!m&&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.5",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(c,{className:"h-3 w-3"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng điền câu trả lời"})]})]})]},a.id)}),z(),v&&M&&(N.blanks?.length||0)>1&&e("div",{className:f("overflow-hidden rounded-xl border shadow-sm",M.correct===M.total?"border-emerald-200 bg-gradient-to-r from-emerald-50 to-green-50":M.correct>=M.total/2?"border-yellow-200 bg-gradient-to-r from-yellow-50 to-amber-50":"border-red-200 bg-gradient-to-r from-red-50 to-rose-50"),children:r("div",{className:"flex items-center justify-between px-5 py-4",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:f("flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm",M.correct===M.total?"bg-gradient-to-br from-emerald-500 to-green-600":M.correct>=M.total/2?"bg-gradient-to-br from-yellow-500 to-amber-600":"bg-gradient-to-br from-red-500 to-rose-600"),children:M.correct===M.total?e(i,{className:"h-5 w-5"}):e(m,{className:"h-5 w-5"})}),r("div",{children:[e("h4",{className:"text-sm font-semibold text-gray-800",children:"Tổng kết"}),e("p",{className:"text-xs text-gray-500",children:"Kết quả bài làm của bạn"})]})]}),r("div",{className:"text-right",children:[r("div",{className:f("text-2xl font-bold",M.correct===M.total?"text-emerald-600":M.correct>=M.total/2?"text-yellow-600":"text-red-600"),children:[M.correct,"/",M.total]}),r("div",{className:"text-xs text-gray-500",children:[Math.round(M.correct/M.total*100),"% chính xác"]})]})]})}),J()]})}