@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,141 +1 @@
1
- 'use client';
2
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect, useRef } from 'react';
4
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
5
- import { Check, X } from 'lucide-react';
6
- // Fisher-Yates shuffle algorithm
7
- function shuffleArray(array) {
8
- const shuffled = [...array];
9
- for (let i = shuffled.length - 1; i > 0; i--) {
10
- const j = Math.floor(Math.random() * (i + 1));
11
- [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
12
- }
13
- return shuffled;
14
- }
15
- export function ArrangeLettersIntoWordsClient({ questionData, onSubmit, isReviewMode = false, userAnswer, }) {
16
- // Initialize state for each subQuestion
17
- const [availableLetters, setAvailableLetters] = useState({});
18
- const [arrangedLetters, setArrangedLetters] = useState({});
19
- const [answers, setAnswers] = useState(userAnswer || {});
20
- // Store presigned URLs for images: { subQuestionId: presignedUrl }
21
- const [imagePreviewUrls, setImagePreviewUrls] = useState({});
22
- const fetchingRef = useRef(new Set());
23
- // Initialize shuffled letters for each subQuestion
24
- useEffect(() => {
25
- const initialAvailable = {};
26
- const initialArranged = {};
27
- questionData.subQuestions.forEach((sq) => {
28
- // Shuffle the correctWord into individual letters
29
- const letters = shuffleArray(sq.correctWord.split(''));
30
- initialAvailable[sq.id] = letters;
31
- initialArranged[sq.id] = [];
32
- });
33
- setAvailableLetters(initialAvailable);
34
- setArrangedLetters(initialArranged);
35
- }, [questionData.subQuestions]);
36
- // Sync userAnswer when it changes (e.g., when loading from server in review mode)
37
- useEffect(() => {
38
- if (userAnswer) {
39
- setAnswers(userAnswer);
40
- }
41
- }, [userAnswer]);
42
- // Fetch presigned URLs for images if needed
43
- useEffect(() => {
44
- questionData.subQuestions.forEach((sq) => {
45
- if (sq.imageUrl &&
46
- !sq.imageUrl.startsWith('http') &&
47
- !imagePreviewUrls[sq.id] &&
48
- !fetchingRef.current.has(sq.id)) {
49
- fetchingRef.current.add(sq.id);
50
- setImagePreviewUrls((prev) => ({
51
- ...prev,
52
- [sq.id]: sq.imageUrl,
53
- }));
54
- fetchingRef.current.delete(sq.id);
55
- }
56
- });
57
- }, [questionData.subQuestions, imagePreviewUrls]);
58
- // Get image preview URL for a subQuestion
59
- const getImagePreviewUrl = (subQuestion) => {
60
- if (!subQuestion.imageUrl)
61
- return '';
62
- // If it's already a full URL, use it directly
63
- if (subQuestion.imageUrl.startsWith('http')) {
64
- return subQuestion.imageUrl;
65
- }
66
- // Otherwise, use presigned URL if available
67
- return imagePreviewUrls[subQuestion.id] || subQuestion.imageUrl;
68
- };
69
- // Update answers when arrangedLetters change
70
- useEffect(() => {
71
- const newAnswers = {};
72
- Object.keys(arrangedLetters).forEach((subQuestionId) => {
73
- newAnswers[subQuestionId] = arrangedLetters[subQuestionId].join('');
74
- });
75
- setAnswers(newAnswers);
76
- onSubmit?.(newAnswers);
77
- }, [arrangedLetters, onSubmit]);
78
- // Handle click on available letter - move to arranged
79
- const handleLetterClick = (subQuestionId, letterIndex) => {
80
- if (isReviewMode)
81
- return;
82
- // Get the letter first before updating state
83
- const currentAvailable = availableLetters[subQuestionId] || [];
84
- const letter = currentAvailable[letterIndex];
85
- if (!letter)
86
- return;
87
- setAvailableLetters((prev) => {
88
- const letters = [...prev[subQuestionId]];
89
- letters.splice(letterIndex, 1);
90
- return { ...prev, [subQuestionId]: letters };
91
- });
92
- setArrangedLetters((prev) => {
93
- const arranged = [...(prev[subQuestionId] || [])];
94
- arranged.push(letter);
95
- return { ...prev, [subQuestionId]: arranged };
96
- });
97
- };
98
- // Handle click on arranged letter - move back to available
99
- const handleArrangedLetterClick = (subQuestionId, letterIndex) => {
100
- if (isReviewMode)
101
- return;
102
- // Get the letter first before updating state
103
- const currentArranged = arrangedLetters[subQuestionId] || [];
104
- const letter = currentArranged[letterIndex];
105
- if (!letter)
106
- return;
107
- setArrangedLetters((prev) => {
108
- const arranged = [...prev[subQuestionId]];
109
- arranged.splice(letterIndex, 1);
110
- return { ...prev, [subQuestionId]: arranged };
111
- });
112
- setAvailableLetters((prev) => {
113
- const letters = [...(prev[subQuestionId] || [])];
114
- letters.push(letter);
115
- return { ...prev, [subQuestionId]: letters };
116
- });
117
- };
118
- // Check if answer is correct (case insensitive)
119
- const isAnswerCorrect = (subQuestionId, userAnswerValue) => {
120
- const subQuestion = questionData.subQuestions.find((sq) => sq.id === subQuestionId);
121
- if (!subQuestion)
122
- return false;
123
- return userAnswerValue.trim().toLowerCase() === subQuestion.correctWord.trim().toLowerCase();
124
- };
125
- return (_jsx("div", { className: "space-y-6", children: questionData.subQuestions.map((subQuestion, sqIndex) => {
126
- const userAnswerValue = answers[subQuestion.id] || '';
127
- const isCorrect = isReviewMode && isAnswerCorrect(subQuestion.id, userAnswerValue);
128
- const available = availableLetters[subQuestion.id] || [];
129
- const arranged = arrangedLetters[subQuestion.id] || [];
130
- const imagePreviewUrl = getImagePreviewUrl(subQuestion);
131
- return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { className: "text-lg", children: ["C\u00E2u ", sqIndex + 1] }) }), _jsxs(CardContent, { className: "space-y-4", children: [imagePreviewUrl && (_jsx("div", { className: "flex justify-center", children: _jsx("div", { className: "relative h-48 w-full max-w-md overflow-hidden rounded-lg", children: _jsx("img", { src: imagePreviewUrl, alt: `Hint for question ${sqIndex + 1}`, className: "h-full w-full object-contain", onError: () => {
132
- console.error('Failed to load image:', subQuestion.imageUrl);
133
- } }) }) })), _jsxs("div", { children: [_jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "Ch\u1ECDn c\u00E1c ch\u1EEF c\u00E1i:" }), _jsx("div", { className: "flex flex-wrap gap-2", children: available.map((letter, index) => (_jsx("button", { onClick: () => handleLetterClick(subQuestion.id, index), disabled: isReviewMode, className: "flex h-12 w-12 items-center justify-center rounded-full border-2 border-blue-500 bg-white text-xl font-bold text-blue-600 transition-all hover:bg-blue-50 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50", children: letter }, `${letter}-${index}`))) })] }), _jsxs("div", { children: [_jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "S\u1EAFp x\u1EBFp th\u00E0nh t\u1EEB:" }), _jsx("div", { className: `min-h-[60px] rounded-lg border-2 p-4 ${isReviewMode
134
- ? isCorrect
135
- ? 'border-green-500 bg-green-50'
136
- : userAnswerValue.trim() !== ''
137
- ? 'border-red-500 bg-red-50'
138
- : 'border-gray-300 bg-gray-50'
139
- : 'border-gray-300 bg-gray-50'}`, children: _jsx("div", { className: "flex flex-wrap items-center gap-2", children: arranged.length === 0 ? (_jsx("span", { className: "text-gray-400", children: "G\u1EA1ch ngang \u0111\u1EC3 s\u1EAFp x\u1EBFp..." })) : (arranged.map((letter, index) => (_jsx("button", { onClick: () => handleArrangedLetterClick(subQuestion.id, index), disabled: isReviewMode, className: "flex h-12 w-12 items-center justify-center rounded-full border-2 border-gray-400 bg-white text-xl font-bold text-gray-700 transition-all hover:bg-gray-100 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50", children: letter }, `arranged-${letter}-${index}`)))) }) })] }), isReviewMode && (_jsx("div", { className: "flex items-center gap-2", children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-5 w-5 text-green-600" }), _jsx("span", { className: "text-sm text-green-600", children: "\u0110\u00FAng!" })] })) : userAnswerValue.trim() !== '' ? (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-5 w-5 text-red-600" }), _jsxs("span", { className: "text-sm text-red-600", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", _jsx("strong", { children: subQuestion.correctWord })] })] })) : null }))] })] }, subQuestion.id));
140
- }) }));
141
- }
1
+ "use client";import{jsxs as e,jsx as r,Fragment as t}from"react/jsx-runtime";import{useState as s,useEffect as n,useRef as i}from"react";import{Card as a,CardContent as l,CardHeader as d,CardTitle as o}from"../../../../components/ui/card";import{Check as c,X as m}from"lucide-react";export function ArrangeLettersIntoWordsClient({questionData:u,onSubmit:h,isReviewMode:g=!1,userAnswer:b}){const[p,f]=s({}),[x,w]=s({}),[N,y]=s(b||{}),[v,j]=s({}),U=i(new Set);n(()=>{const e={},r={};u.subQuestions.forEach(t=>{const s=function(e){const r=[...e];for(let e=r.length-1;e>0;e--){const t=Math.floor(Math.random()*(e+1));[r[e],r[t]]=[r[t],r[e]]}return r}(t.correctWord.split(""));e[t.id]=s,r[t.id]=[]}),f(e),w(r)},[u.subQuestions]),n(()=>{b&&y(b)},[b]),n(()=>{u.subQuestions.forEach(e=>{!e.imageUrl||e.imageUrl.startsWith("http")||v[e.id]||U.current.has(e.id)||(U.current.add(e.id),j(r=>({...r,[e.id]:e.imageUrl})),U.current.delete(e.id))})},[u.subQuestions,v]);n(()=>{const e={};Object.keys(x).forEach(r=>{e[r]=x[r].join("")}),y(e),h?.(e)},[x,h]);return r("div",{className:"space-y-6",children:u.subQuestions.map((s,n)=>{const i=N[s.id]||"",h=g&&((e,r)=>{const t=u.subQuestions.find(r=>r.id===e);return!!t&&r.trim().toLowerCase()===t.correctWord.trim().toLowerCase()})(s.id,i),b=p[s.id]||[],y=x[s.id]||[],j=(e=>e.imageUrl?e.imageUrl.startsWith("http")?e.imageUrl:v[e.id]||e.imageUrl:"")(s);return e(a,{children:[r(d,{children:e(o,{className:"text-lg",children:["Câu ",n+1]})}),e(l,{className:"space-y-4",children:[j&&r("div",{className:"flex justify-center",children:r("div",{className:"relative h-48 w-full max-w-md overflow-hidden rounded-lg",children:r("img",{src:j,alt:`Hint for question ${n+1}`,className:"h-full w-full object-contain",onError:()=>{console.error("Failed to load image:",s.imageUrl)}})})}),e("div",{children:[r("p",{className:"mb-2 text-sm font-medium text-gray-700",children:"Chọn các chữ cái:"}),r("div",{className:"flex flex-wrap gap-2",children:b.map((e,t)=>r("button",{onClick:()=>((e,r)=>{if(g)return;const t=(p[e]||[])[r];t&&(f(t=>{const s=[...t[e]];return s.splice(r,1),{...t,[e]:s}}),w(r=>{const s=[...r[e]||[]];return s.push(t),{...r,[e]:s}}))})(s.id,t),disabled:g,className:"flex h-12 w-12 items-center justify-center rounded-full border-2 border-blue-500 bg-white text-xl font-bold text-blue-600 transition-all hover:bg-blue-50 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50",children:e},`${e}-${t}`))})]}),e("div",{children:[r("p",{className:"mb-2 text-sm font-medium text-gray-700",children:"Sắp xếp thành từ:"}),r("div",{className:"min-h-[60px] rounded-lg border-2 p-4 "+(g?h?"border-green-500 bg-green-50":""!==i.trim()?"border-red-500 bg-red-50":"border-gray-300 bg-gray-50":"border-gray-300 bg-gray-50"),children:r("div",{className:"flex flex-wrap items-center gap-2",children:0===y.length?r("span",{className:"text-gray-400",children:"Gạch ngang để sắp xếp..."}):y.map((e,t)=>r("button",{onClick:()=>((e,r)=>{if(g)return;const t=(x[e]||[])[r];t&&(w(t=>{const s=[...t[e]];return s.splice(r,1),{...t,[e]:s}}),f(r=>{const s=[...r[e]||[]];return s.push(t),{...r,[e]:s}}))})(s.id,t),disabled:g,className:"flex h-12 w-12 items-center justify-center rounded-full border-2 border-gray-400 bg-white text-xl font-bold text-gray-700 transition-all hover:bg-gray-100 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50",children:e},`arranged-${e}-${t}`))})})]}),g&&r("div",{className:"flex items-center gap-2",children:h?e(t,{children:[r(c,{className:"h-5 w-5 text-green-600"}),r("span",{className:"text-sm text-green-600",children:"Đúng!"})]}):""!==i.trim()?e(t,{children:[r(m,{className:"h-5 w-5 text-red-600"}),e("span",{className:"text-sm text-red-600",children:["Đáp án đúng: ",r("strong",{children:s.correctWord})]})]}):null})]})]},s.id)})})}
@@ -1,118 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useRef, useEffect } from 'react';
4
- import { Button } from '../../../../components/ui/button';
5
- import { Label } from '../../../../components/ui/label';
6
- import { Input } from '../../../../components/ui/input';
7
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
8
- import { Pencil, Eye, Plus, Trash2 } from 'lucide-react';
9
- import { toast } from 'sonner';
10
- import { FileUpload } from '../../../../components/ui/file-upload';
11
- import { ArrangeLettersIntoWordsClient } from './ArrangeLettersIntoWordsClient';
12
- function ArrangeLettersIntoWordsCreatorContent({ initialData, onSave, // eslint-disable-line @typescript-eslint/no-unused-vars
13
- onCancel, // eslint-disable-line @typescript-eslint/no-unused-vars
14
- onChange, }) {
15
- // State
16
- const [subQuestions, setSubQuestions] = useState(initialData?.subQuestions || []);
17
- // Track previous initialData to detect changes
18
- const previousInitialDataRef = useRef(initialData);
19
- const isInitializingRef = useRef(false);
20
- // Use ref to store onChange to avoid dependency issues
21
- const onChangeRef = useRef(onChange);
22
- // Track previous payload to prevent unnecessary onChange calls
23
- const previousPayloadRef = useRef('');
24
- // Update onChange ref when it changes
25
- useEffect(() => {
26
- onChangeRef.current = onChange;
27
- }, [onChange]);
28
- // Sync state from initialData when it changes
29
- useEffect(() => {
30
- const initialDataChanged = JSON.stringify(previousInitialDataRef.current) !== JSON.stringify(initialData);
31
- if (initialDataChanged) {
32
- isInitializingRef.current = true;
33
- previousInitialDataRef.current = initialData;
34
- if (initialData) {
35
- if (initialData.subQuestions !== undefined)
36
- setSubQuestions(initialData.subQuestions);
37
- }
38
- else {
39
- setSubQuestions([]);
40
- }
41
- setTimeout(() => {
42
- isInitializingRef.current = false;
43
- }, 100);
44
- }
45
- }, [initialData]);
46
- useEffect(() => {
47
- // Skip onChange during initialization to prevent infinite loop
48
- if (isInitializingRef.current) {
49
- // Still update previous payload ref to track current state
50
- const currentPayload = JSON.stringify({ subQuestions });
51
- previousPayloadRef.current = currentPayload;
52
- return;
53
- }
54
- // Create payload
55
- const payload = { subQuestions };
56
- // Serialize payload for comparison
57
- const payloadString = JSON.stringify(payload);
58
- // Only call onChange if payload actually changed
59
- if (previousPayloadRef.current !== payloadString) {
60
- previousPayloadRef.current = payloadString;
61
- onChangeRef.current?.(payload);
62
- }
63
- }, [subQuestions]);
64
- // UI State
65
- const [isClientMode, setIsClientMode] = useState(false);
66
- // Store presigned URLs for images: { subQuestionId: presignedUrl }
67
- const [imagePreviewUrls, setImagePreviewUrls] = useState({});
68
- // Add new sub-question
69
- const addSubQuestion = () => {
70
- if (subQuestions.length >= 5) {
71
- toast.error('Tối đa 5 câu hỏi con!');
72
- return;
73
- }
74
- const newSubQuestion = {
75
- id: `subq-${Date.now()}`,
76
- correctWord: '',
77
- imageUrl: '',
78
- };
79
- setSubQuestions([...subQuestions, newSubQuestion]);
80
- };
81
- // Remove sub-question
82
- const removeSubQuestion = (id) => {
83
- if (subQuestions.length <= 1) {
84
- toast.error('Tối thiểu 1 câu hỏi con!');
85
- return;
86
- }
87
- setSubQuestions(subQuestions.filter((sq) => sq.id !== id));
88
- };
89
- // Update sub-question field
90
- const updateSubQuestion = (id, field, value) => {
91
- setSubQuestions(subQuestions.map((sq) => (sq.id === id ? { ...sq, [field]: value } : sq)));
92
- };
93
- // Update image preview URL
94
- const updateImagePreviewUrl = (subQuestionId, presignedUrl) => {
95
- setImagePreviewUrls((prev) => ({
96
- ...prev,
97
- [subQuestionId]: presignedUrl,
98
- }));
99
- };
100
- // If in client mode, render the Client component
101
- if (isClientMode) {
102
- const questionData = {
103
- subQuestions: subQuestions.map((sq) => ({
104
- ...sq,
105
- imageUrl: imagePreviewUrls[sq.id] || sq.imageUrl,
106
- })),
107
- };
108
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Arrange Letters Into Words (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Ch\u1EBF \u0111\u1ED9 xem tr\u01B0\u1EDBc" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) }) }), _jsx(ArrangeLettersIntoWordsClient, { questionData: questionData })] }));
109
- }
110
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Arrange Letters Into Words" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "T\u1EA1o c\u00E2u h\u1ECFi s\u1EAFp x\u1EBFp ch\u1EEF c\u00E1i th\u00E0nh t\u1EEB" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: subQuestions.length < 1, children: [_jsx(Eye, { className: "mr-2 h-4 w-4" }), "Client Mode"] })] }) }) }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(CardTitle, { children: ["C\u00E2u h\u1ECFi con (", subQuestions.length, "/5)"] }), _jsxs(Button, { onClick: addSubQuestion, disabled: subQuestions.length >= 5, variant: "outline", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Th\u00EAm c\u00E2u h\u1ECFi"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [subQuestions.map((subQuestion, sqIndex) => (_jsxs(Card, { className: "border-2", children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(CardTitle, { className: "text-lg", children: ["C\u00E2u ", sqIndex + 1] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => removeSubQuestion(subQuestion.id), disabled: subQuestions.length <= 1, children: _jsx(Trash2, { className: "h-4 w-4 text-red-500" }) })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: `correctWord-${subQuestion.id}`, children: "T\u1EEB \u0111\u00FAng *" }), _jsx(Input, { id: `correctWord-${subQuestion.id}`, value: subQuestion.correctWord, onChange: (e) => updateSubQuestion(subQuestion.id, 'correctWord', e.target.value.toUpperCase()), placeholder: "Nh\u1EADp t\u1EEB \u0111\u00FAng (vd: COMPUTER)", className: "mt-1", disabled: isClientMode }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "T\u1EEB n\u00E0y s\u1EBD \u0111\u01B0\u1EE3c x\u00E1o tr\u1ED9n th\u00E0nh c\u00E1c k\u00FD t\u1EF1 ng\u1EABu nhi\u00EAn khi hi\u1EC3n th\u1ECB" })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: `image-${subQuestion.id}`, children: "H\u00ECnh \u1EA3nh g\u1EE3i \u00FD *" }), _jsx(FileUpload, { id: `image-${subQuestion.id}`, label: "", accept: "image/*", value: subQuestion.imageUrl, onChange: (key) => updateSubQuestion(subQuestion.id, 'imageUrl', key), onPresignedUrlChange: (presignedUrl) => {
111
- updateImagePreviewUrl(subQuestion.id, presignedUrl);
112
- }, disabled: isClientMode, maxSize: 5, placeholder: "Upload \u1EA3nh", required: true, autoUpload: true, prefix: "questions" }), subQuestion.imageUrl && (_jsx("div", { className: "relative mt-2 h-32 w-full max-w-md overflow-hidden rounded border", children: _jsx("img", { src: imagePreviewUrls[subQuestion.id] || subQuestion.imageUrl, alt: `Preview for question ${sqIndex + 1}`, className: "h-full w-full object-contain", onError: () => {
113
- console.error('Failed to load image:', subQuestion.imageUrl);
114
- } }) }))] })] })] }, subQuestion.id))), subQuestions.length === 0 && (_jsx("div", { className: "py-8 text-center text-gray-500", children: _jsx("p", { children: "Ch\u01B0a c\u00F3 c\u00E2u h\u1ECFi con n\u00E0o. Nh\u1EA5n \"Th\u00EAm c\u00E2u h\u1ECFi\" \u0111\u1EC3 b\u1EAFt \u0111\u1EA7u." }) }))] })] })] }));
115
- }
116
- export function ArrangeLettersIntoWordsCreator(props) {
117
- return _jsx(ArrangeLettersIntoWordsCreatorContent, { ...props });
118
- }
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as i,useRef as t,useEffect as n}from"react";import{Button as c}from"../../../../components/ui/button";import{Label as s}from"../../../../components/ui/label";import{Input as l}from"../../../../components/ui/input";import{Card as a,CardContent as o,CardHeader as d,CardTitle as m}from"../../../../components/ui/card";import{Pencil as h,Eye as u,Plus as g,Trash2 as p}from"lucide-react";import{toast as f}from"sonner";import{FileUpload as v}from"../../../../components/ui/file-upload";import{ArrangeLettersIntoWordsClient as N}from"./ArrangeLettersIntoWordsClient";function x({initialData:x,onSave:b,onCancel:y,onChange:C}){const[w,U]=i(x?.subQuestions||[]),T=t(x),W=t(!1),j=t(C),Q=t("");n(()=>{j.current=C},[C]),n(()=>{JSON.stringify(T.current)!==JSON.stringify(x)&&(W.current=!0,T.current=x,x?void 0!==x.subQuestions&&U(x.subQuestions):U([]),setTimeout(()=>{W.current=!1},100))},[x]),n(()=>{if(W.current){const e=JSON.stringify({subQuestions:w});return void(Q.current=e)}const e={subQuestions:w},r=JSON.stringify(e);Q.current!==r&&(Q.current=r,j.current?.(e))},[w]);const[k,S]=i(!1),[$,q]=i({}),O=(e,r,i)=>{U(w.map(t=>t.id===e?{...t,[r]:i}:t))};if(k){const i={subQuestions:w.map(e=>({...e,imageUrl:$[e.id]||e.imageUrl}))};return r("div",{className:"space-y-6",children:[e(a,{children:e(d,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(m,{children:"Arrange Letters Into Words (Preview)"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Chế độ xem trước"})]}),r(c,{variant:"outline",size:"sm",onClick:()=>S(!1),children:[e(h,{className:"mr-2 h-4 w-4"}),"Quay lại Edit Mode"]})]})})}),e(N,{questionData:i})]})}return r("div",{className:"space-y-6",children:[e(a,{children:e(d,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(m,{children:"Arrange Letters Into Words"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Tạo câu hỏi sắp xếp chữ cái thành từ"})]}),r(c,{variant:"outline",size:"sm",onClick:()=>S(!0),disabled:w.length<1,children:[e(u,{className:"mr-2 h-4 w-4"}),"Client Mode"]})]})})}),r(a,{children:[e(d,{children:r("div",{className:"flex items-center justify-between",children:[r(m,{children:["Câu hỏi con (",w.length,"/5)"]}),r(c,{onClick:()=>{if(w.length>=5)return void f.error("Tối đa 5 câu hỏi con!");const e={id:`subq-${Date.now()}`,correctWord:"",imageUrl:""};U([...w,e])},disabled:w.length>=5,variant:"outline",children:[e(g,{className:"mr-2 h-4 w-4"}),"Thêm câu hỏi"]})]})}),r(o,{className:"space-y-4",children:[w.map((i,t)=>r(a,{className:"border-2",children:[e(d,{children:r("div",{className:"flex items-center justify-between",children:[r(m,{className:"text-lg",children:["Câu ",t+1]}),e(c,{variant:"ghost",size:"sm",onClick:()=>{return e=i.id,void(w.length<=1?f.error("Tối thiểu 1 câu hỏi con!"):U(w.filter(r=>r.id!==e)));var e},disabled:w.length<=1,children:e(p,{className:"h-4 w-4 text-red-500"})})]})}),r(o,{className:"space-y-4",children:[r("div",{children:[e(s,{htmlFor:`correctWord-${i.id}`,children:"Từ đúng *"}),e(l,{id:`correctWord-${i.id}`,value:i.correctWord,onChange:e=>O(i.id,"correctWord",e.target.value.toUpperCase()),placeholder:"Nhập từ đúng (vd: COMPUTER)",className:"mt-1",disabled:k}),e("p",{className:"mt-1 text-xs text-gray-500",children:"Từ này sẽ được xáo trộn thành các ký tự ngẫu nhiên khi hiển thị"})]}),r("div",{children:[e(s,{htmlFor:`image-${i.id}`,children:"Hình ảnh gợi ý *"}),e(v,{id:`image-${i.id}`,label:"",accept:"image/*",value:i.imageUrl,onChange:e=>O(i.id,"imageUrl",e),onPresignedUrlChange:e=>{((e,r)=>{q(i=>({...i,[e]:r}))})(i.id,e)},disabled:k,maxSize:5,placeholder:"Upload ảnh",required:!0,autoUpload:!0,prefix:"questions"}),i.imageUrl&&e("div",{className:"relative mt-2 h-32 w-full max-w-md overflow-hidden rounded border",children:e("img",{src:$[i.id]||i.imageUrl,alt:`Preview for question ${t+1}`,className:"h-full w-full object-contain",onError:()=>{console.error("Failed to load image:",i.imageUrl)}})})]})]})]},i.id)),0===w.length&&e("div",{className:"py-8 text-center text-gray-500",children:e("p",{children:'Chưa có câu hỏi con nào. Nhấn "Thêm câu hỏi" để bắt đầu.'})})]})]})]})}export function ArrangeLettersIntoWordsCreator(r){return e(x,{...r})}
@@ -1,2 +1 @@
1
- export * from './ArrangeLettersIntoWordsCreator';
2
- export * from './ArrangeLettersIntoWordsClient';
1
+ export*from"./ArrangeLettersIntoWordsCreator";export*from"./ArrangeLettersIntoWordsClient";
@@ -1,4 +1 @@
1
- import { ArrangeLettersIntoWordsCreator } from './ArrangeLettersIntoWordsCreator';
2
- export const arrangeLettersIntoWordsRegistration = {
3
- component: ArrangeLettersIntoWordsCreator,
4
- };
1
+ import{ArrangeLettersIntoWordsCreator as r}from"./ArrangeLettersIntoWordsCreator";export const arrangeLettersIntoWordsRegistration={component:r};
@@ -1,24 +1 @@
1
- export const transformArrangeLettersIntoWords = (question) => {
2
- const answerData = question.answer;
3
- if (!answerData?.subQuestions) {
4
- return { apiContent: {}, apiCorrectAnswer: {} };
5
- }
6
- const subQuestions = (answerData.subQuestions || []).map((sq) => ({
7
- id: sq.id,
8
- imageUrl: sq.imageUrl || '',
9
- }));
10
- const answers = (answerData.subQuestions || []).reduce((acc, sq) => {
11
- if (sq.id && sq.correctWord) {
12
- acc[sq.id] = sq.correctWord;
13
- }
14
- return acc;
15
- }, {});
16
- return {
17
- apiContent: {
18
- subQuestions,
19
- },
20
- apiCorrectAnswer: {
21
- answers,
22
- },
23
- };
24
- };
1
+ export const transformArrangeLettersIntoWords=r=>{const e=r.answer;if(!e?.subQuestions)return{apiContent:{},apiCorrectAnswer:{}};return{apiContent:{subQuestions:(e.subQuestions||[]).map(r=>({id:r.id,imageUrl:r.imageUrl||""}))},apiCorrectAnswer:{answers:(e.subQuestions||[]).reduce((r,e)=>(e.id&&e.correctWord&&(r[e.id]=e.correctWord),r),{})}}};
@@ -1,64 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState } from 'react';
4
- import { cn } from '../../../../shared/lib/utils';
5
- import { Check, X, ListChecks, Lightbulb } from 'lucide-react';
6
- export function ChooseCorrectAdjectiveClient({ questionData, onSubmit, isReviewMode = false, userAnswer, }) {
7
- const [selectedAnswer, setSelectedAnswer] = useState(userAnswer);
8
- const handleAnswerChange = (index) => {
9
- if (isReviewMode)
10
- return;
11
- setSelectedAnswer(index);
12
- onSubmit?.(index);
13
- };
14
- const isCorrect = (index) => {
15
- return index === questionData.correctAnswer;
16
- };
17
- const isSelected = (index) => {
18
- return selectedAnswer === index;
19
- };
20
- const userAnswerCorrect = selectedAnswer !== undefined && isCorrect(selectedAnswer);
21
- const hasAnswered = selectedAnswer !== undefined;
22
- // Get the correct answer text
23
- const correctAnswerText = questionData.options[questionData.correctAnswer];
24
- return (_jsx("div", { className: "space-y-5", children: _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: cn('flex items-center justify-between border-b px-5 py-3', isReviewMode && userAnswerCorrect && 'border-green-200 bg-gradient-to-r from-green-50 to-emerald-50', isReviewMode && hasAnswered && !userAnswerCorrect && 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50', (!isReviewMode || !hasAnswered) && 'border-gray-100 bg-gradient-to-r from-gray-50 to-white'), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-8 w-8 items-center justify-center rounded-lg text-white shadow-sm', isReviewMode && userAnswerCorrect && 'bg-gradient-to-br from-green-500 to-emerald-600', isReviewMode && hasAnswered && !userAnswerCorrect && 'bg-gradient-to-br from-red-500 to-rose-600', (!isReviewMode || !hasAnswered) && 'bg-gradient-to-br from-teal-500 to-cyan-600'), children: _jsx(ListChecks, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Ch\u1ECDn t\u00EDnh t\u1EEB \u0111\u00FAng" })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold', userAnswerCorrect ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'), children: [userAnswerCorrect ? _jsx(Check, { className: "h-3.5 w-3.5" }) : _jsx(X, { className: "h-3.5 w-3.5" }), userAnswerCorrect ? 'Đúng' : 'Sai'] }))] }), _jsxs("div", { className: "p-5 space-y-5", children: [_jsxs("div", { className: "rounded-xl bg-gradient-to-br from-slate-50 to-gray-50 border border-gray-100 p-5", children: [_jsx("div", { className: "text-lg leading-relaxed flex flex-wrap items-center gap-1", children: questionData.sentence.split('{0}').map((part, index, arr) => (_jsxs("span", { children: [_jsx("span", { className: "text-gray-800", children: part }), index < arr.length - 1 && (_jsx("span", { className: "inline-flex items-center mx-1", children: _jsx("span", { className: cn('inline-block min-w-[100px] px-3 py-1 text-center font-bold rounded-lg border-2 border-dashed', hasAnswered
25
- ? isReviewMode
26
- ? userAnswerCorrect
27
- ? 'border-green-400 bg-green-100 text-green-800'
28
- : 'border-red-400 bg-red-100 text-red-800'
29
- : 'border-indigo-400 bg-indigo-100 text-indigo-800'
30
- : 'border-gray-300 bg-gray-100 text-gray-400'), children: hasAnswered ? questionData.options[selectedAnswer] : '_______' }) }))] }, index))) }), _jsxs("div", { className: "mt-3 flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-gray-500", children: "L\u1EF1a ch\u1ECDn:" }), _jsxs("span", { className: "text-sm font-medium text-gray-600", children: ["(", questionData.options.join(' / '), ")"] })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium text-gray-600 mb-3", children: "Ch\u1ECDn \u0111\u00E1p \u00E1n:" }), _jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: questionData.options.map((option, index) => {
31
- const selected = isSelected(index);
32
- const correct = isCorrect(index);
33
- const letter = String.fromCharCode(65 + index);
34
- return (_jsxs("button", { type: "button", onClick: () => handleAnswerChange(index), disabled: isReviewMode, className: cn('group flex items-center gap-2 rounded-xl border-2 p-3 text-left transition-all', isReviewMode
35
- ? correct
36
- ? 'border-green-400 bg-green-50'
37
- : selected
38
- ? 'border-red-400 bg-red-50'
39
- : 'border-gray-200 bg-gray-50'
40
- : selected
41
- ? 'border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100'
42
- : 'border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm'), children: [_jsx("div", { className: cn('flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all', isReviewMode
43
- ? correct
44
- ? 'bg-green-500 text-white'
45
- : selected
46
- ? 'bg-red-500 text-white'
47
- : 'bg-gray-200 text-gray-600'
48
- : selected
49
- ? 'bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm'
50
- : 'bg-gray-100 text-gray-600 group-hover:bg-gray-200'), children: letter }), _jsx("span", { className: cn('flex-1 text-sm font-semibold', isReviewMode && correct
51
- ? 'text-green-800'
52
- : isReviewMode && selected && !correct
53
- ? 'text-red-800'
54
- : 'text-gray-700'), children: option }), isReviewMode && (correct || selected) && (_jsx("div", { className: cn('flex h-5 w-5 items-center justify-center rounded-full', correct ? 'bg-green-500' : 'bg-red-500'), children: correct
55
- ? _jsx(Check, { className: "h-3 w-3 text-white" })
56
- : _jsx(X, { className: "h-3 w-3 text-white" }) }))] }, index));
57
- }) })] }), isReviewMode && (_jsxs("div", { className: "space-y-4 pt-2", children: [_jsxs("div", { className: "rounded-xl border border-green-200 bg-gradient-to-r from-green-50 to-emerald-50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-green-200", children: _jsx(Check, { className: "h-3.5 w-3.5 text-green-700" }) }), _jsx("span", { className: "text-sm font-medium text-green-800", children: "C\u00E2u ho\u00E0n ch\u1EC9nh:" })] }), _jsx("p", { className: "text-base font-medium text-green-900 pl-8", children: questionData.sentence.replace('{0}', correctAnswerText) })] }), _jsx("div", { className: cn('rounded-xl p-4', userAnswerCorrect
58
- ? 'bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200'
59
- : 'bg-gradient-to-r from-red-50 to-rose-50 border border-red-200'), 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', userAnswerCorrect
60
- ? 'bg-gradient-to-br from-green-500 to-emerald-600'
61
- : 'bg-gradient-to-br from-red-500 to-rose-600'), children: userAnswerCorrect ? _jsx(Check, { className: "h-5 w-5" }) : _jsx(X, { className: "h-5 w-5" }) }), _jsxs("div", { children: [_jsx("p", { className: cn('text-sm font-semibold', userAnswerCorrect ? 'text-green-800' : 'text-red-800'), children: userAnswerCorrect ? 'Chính xác!' : 'Chưa đúng' }), _jsx("p", { className: cn('text-xs', userAnswerCorrect ? 'text-green-600' : 'text-red-600'), children: userAnswerCorrect
62
- ? 'Bạn đã chọn đúng tính từ.'
63
- : `Đáp án đúng là "${correctAnswerText}".` })] })] }) }), questionData.explanation && (_jsx("div", { className: "rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm", children: _jsx(Lightbulb, { className: "h-4 w-4" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-semibold text-blue-800", children: "Gi\u1EA3i th\u00EDch:" }), _jsx("p", { className: "text-sm text-blue-700 mt-1", children: questionData.explanation })] })] }) }))] })), !isReviewMode && !hasAnswered && (_jsx("div", { className: "rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 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("span", { className: "text-sm font-bold", children: "!" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-amber-800", children: "Ch\u1ECDn t\u00EDnh t\u1EEB ph\u00F9 h\u1EE3p" }), _jsx("p", { className: "text-xs text-amber-600", children: "Nh\u1EA5n v\u00E0o m\u1ED9t trong c\u00E1c l\u1EF1a ch\u1ECDn b\u00EAn tr\u00EAn." })] })] }) }))] })] }) }));
64
- }
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t}from"react";import{cn as n}from"../../../../shared/lib/utils";import{Check as d,X as a,ListChecks as s,Lightbulb as i}from"lucide-react";export function ChooseCorrectAdjectiveClient({questionData:o,onSubmit:l,isReviewMode:c=!1,userAnswer:m}){const[g,h]=t(m),b=e=>e===o.correctAnswer,x=void 0!==g&&b(g),p=void 0!==g,f=o.options[o.correctAnswer];return e("div",{className:"space-y-5",children:r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:n("flex items-center justify-between border-b px-5 py-3",c&&x&&"border-green-200 bg-gradient-to-r from-green-50 to-emerald-50",c&&p&&!x&&"border-red-200 bg-gradient-to-r from-red-50 to-rose-50",(!c||!p)&&"border-gray-100 bg-gradient-to-r from-gray-50 to-white"),children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-8 w-8 items-center justify-center rounded-lg text-white shadow-sm",c&&x&&"bg-gradient-to-br from-green-500 to-emerald-600",c&&p&&!x&&"bg-gradient-to-br from-red-500 to-rose-600",(!c||!p)&&"bg-gradient-to-br from-teal-500 to-cyan-600"),children:e(s,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Chọn tính từ đúng"})]}),c&&p&&r("div",{className:n("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",x?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(x?d:a,{className:"h-3.5 w-3.5"}),x?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-5",children:[r("div",{className:"rounded-xl bg-gradient-to-br from-slate-50 to-gray-50 border border-gray-100 p-5",children:[e("div",{className:"text-lg leading-relaxed flex flex-wrap items-center gap-1",children:o.sentence.split("{0}").map((t,d,a)=>r("span",{children:[e("span",{className:"text-gray-800",children:t}),d<a.length-1&&e("span",{className:"inline-flex items-center mx-1",children:e("span",{className:n("inline-block min-w-[100px] px-3 py-1 text-center font-bold rounded-lg border-2 border-dashed",p?c?x?"border-green-400 bg-green-100 text-green-800":"border-red-400 bg-red-100 text-red-800":"border-indigo-400 bg-indigo-100 text-indigo-800":"border-gray-300 bg-gray-100 text-gray-400"),children:p?o.options[g]:"_______"})})]},d))}),r("div",{className:"mt-3 flex items-center gap-2",children:[e("span",{className:"text-sm text-gray-500",children:"Lựa chọn:"}),r("span",{className:"text-sm font-medium text-gray-600",children:["(",o.options.join(" / "),")"]})]})]}),r("div",{className:"space-y-2",children:[e("p",{className:"text-sm font-medium text-gray-600 mb-3",children:"Chọn đáp án:"}),e("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:o.options.map((t,s)=>{const i=(e=>g===e)(s),o=b(s),m=String.fromCharCode(65+s);return r("button",{type:"button",onClick:()=>(e=>{c||(h(e),l?.(e))})(s),disabled:c,className:n("group flex items-center gap-2 rounded-xl border-2 p-3 text-left transition-all",c?o?"border-green-400 bg-green-50":i?"border-red-400 bg-red-50":"border-gray-200 bg-gray-50":i?"border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100":"border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm"),children:[e("div",{className:n("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all",c?o?"bg-green-500 text-white":i?"bg-red-500 text-white":"bg-gray-200 text-gray-600":i?"bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm":"bg-gray-100 text-gray-600 group-hover:bg-gray-200"),children:m}),e("span",{className:n("flex-1 text-sm font-semibold",c&&o?"text-green-800":c&&i&&!o?"text-red-800":"text-gray-700"),children:t}),c&&(o||i)&&e("div",{className:n("flex h-5 w-5 items-center justify-center rounded-full",o?"bg-green-500":"bg-red-500"),children:e(o?d:a,{className:"h-3 w-3 text-white"})})]},s)})})]}),c&&r("div",{className:"space-y-4 pt-2",children:[r("div",{className:"rounded-xl border border-green-200 bg-gradient-to-r from-green-50 to-emerald-50 p-4",children:[r("div",{className:"flex items-center gap-2 mb-2",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-lg bg-green-200",children:e(d,{className:"h-3.5 w-3.5 text-green-700"})}),e("span",{className:"text-sm font-medium text-green-800",children:"Câu hoàn chỉnh:"})]}),e("p",{className:"text-base font-medium text-green-900 pl-8",children:o.sentence.replace("{0}",f)})]}),e("div",{className:n("rounded-xl p-4",x?"bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200":"bg-gradient-to-r from-red-50 to-rose-50 border border-red-200"),children:r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm",x?"bg-gradient-to-br from-green-500 to-emerald-600":"bg-gradient-to-br from-red-500 to-rose-600"),children:e(x?d:a,{className:"h-5 w-5"})}),r("div",{children:[e("p",{className:n("text-sm font-semibold",x?"text-green-800":"text-red-800"),children:x?"Chính xác!":"Chưa đúng"}),e("p",{className:n("text-xs",x?"text-green-600":"text-red-600"),children:x?"Bạn đã chọn đúng tính từ.":`Đáp án đúng là "${f}".`})]})]})}),o.explanation&&e("div",{className:"rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-4",children:r("div",{className:"flex items-start gap-3",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm",children:e(i,{className:"h-4 w-4"})}),r("div",{children:[e("p",{className:"text-sm font-semibold text-blue-800",children:"Giải thích:"}),e("p",{className:"text-sm text-blue-700 mt-1",children:o.explanation})]})]})})]}),!c&&!p&&e("div",{className:"rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4",children:r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 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("span",{className:"text-sm font-bold",children:"!"})}),r("div",{children:[e("p",{className:"text-sm font-medium text-amber-800",children:"Chọn tính từ phù hợp"}),e("p",{className:"text-xs text-amber-600",children:"Nhấn vào một trong các lựa chọn bên trên."})]})]})})]})]})})}