@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,103 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState } from 'react';
4
- import { Lightbulb, ChevronDown } from 'lucide-react';
5
- import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '../../../components/ui/collapsible';
6
- import { cn } from '../../../shared/lib/utils';
7
- // ─── Color Scheme Map ─────────────────────────────────────────────────────────
8
- const colorSchemes = {
9
- blue: {
10
- border: 'border-blue-200',
11
- bg: 'bg-gradient-to-r from-blue-50 to-indigo-50',
12
- icon: 'bg-blue-100 text-blue-600',
13
- title: 'text-blue-800',
14
- dot: 'bg-blue-400',
15
- text: 'text-blue-700',
16
- tipBg: 'bg-blue-100/60',
17
- tipText: 'text-blue-700',
18
- hoverBg: 'hover:from-blue-100/80 hover:to-indigo-100/60',
19
- },
20
- purple: {
21
- border: 'border-purple-200',
22
- bg: 'bg-gradient-to-r from-purple-50 to-violet-50',
23
- icon: 'bg-purple-100 text-purple-600',
24
- title: 'text-purple-800',
25
- dot: 'bg-purple-400',
26
- text: 'text-purple-700',
27
- tipBg: 'bg-purple-100/60',
28
- tipText: 'text-purple-700',
29
- hoverBg: 'hover:from-purple-100/80 hover:to-violet-100/60',
30
- },
31
- emerald: {
32
- border: 'border-emerald-200',
33
- bg: 'bg-gradient-to-r from-emerald-50 to-teal-50',
34
- icon: 'bg-emerald-100 text-emerald-600',
35
- title: 'text-emerald-800',
36
- dot: 'bg-emerald-400',
37
- text: 'text-emerald-700',
38
- tipBg: 'bg-emerald-100/60',
39
- tipText: 'text-emerald-700',
40
- hoverBg: 'hover:from-emerald-100/80 hover:to-teal-100/60',
41
- },
42
- amber: {
43
- border: 'border-amber-200',
44
- bg: 'bg-gradient-to-r from-amber-50 to-orange-50',
45
- icon: 'bg-amber-100 text-amber-600',
46
- title: 'text-amber-800',
47
- dot: 'bg-amber-400',
48
- text: 'text-amber-700',
49
- tipBg: 'bg-amber-100/60',
50
- tipText: 'text-amber-700',
51
- hoverBg: 'hover:from-amber-100/80 hover:to-orange-100/60',
52
- },
53
- cyan: {
54
- border: 'border-cyan-200',
55
- bg: 'bg-gradient-to-r from-cyan-50 to-sky-50',
56
- icon: 'bg-cyan-100 text-cyan-600',
57
- title: 'text-cyan-800',
58
- dot: 'bg-cyan-400',
59
- text: 'text-cyan-700',
60
- tipBg: 'bg-cyan-100/60',
61
- tipText: 'text-cyan-700',
62
- hoverBg: 'hover:from-cyan-100/80 hover:to-sky-100/60',
63
- },
64
- rose: {
65
- border: 'border-rose-200',
66
- bg: 'bg-gradient-to-r from-rose-50 to-pink-50',
67
- icon: 'bg-rose-100 text-rose-600',
68
- title: 'text-rose-800',
69
- dot: 'bg-rose-400',
70
- text: 'text-rose-700',
71
- tipBg: 'bg-rose-100/60',
72
- tipText: 'text-rose-700',
73
- hoverBg: 'hover:from-rose-100/80 hover:to-pink-100/60',
74
- },
75
- teal: {
76
- border: 'border-teal-200',
77
- bg: 'bg-gradient-to-r from-teal-50 to-emerald-50',
78
- icon: 'bg-teal-100 text-teal-600',
79
- title: 'text-teal-800',
80
- dot: 'bg-teal-400',
81
- text: 'text-teal-700',
82
- tipBg: 'bg-teal-100/60',
83
- tipText: 'text-teal-700',
84
- hoverBg: 'hover:from-teal-100/80 hover:to-emerald-100/60',
85
- },
86
- orange: {
87
- border: 'border-orange-200',
88
- bg: 'bg-gradient-to-r from-orange-50 to-amber-50',
89
- icon: 'bg-orange-100 text-orange-600',
90
- title: 'text-orange-800',
91
- dot: 'bg-orange-400',
92
- text: 'text-orange-700',
93
- tipBg: 'bg-orange-100/60',
94
- tipText: 'text-orange-700',
95
- hoverBg: 'hover:from-orange-100/80 hover:to-amber-100/60',
96
- },
97
- };
98
- // ─── Component ────────────────────────────────────────────────────────────────
99
- export function CreatorGuide({ steps, tips = [], colorScheme = 'blue' }) {
100
- const [isOpen, setIsOpen] = useState(false);
101
- const colors = colorSchemes[colorScheme];
102
- return (_jsx(Collapsible, { open: isOpen, onOpenChange: setIsOpen, children: _jsxs("div", { className: cn('rounded-xl border shadow-sm overflow-hidden', colors.border, colors.bg), children: [_jsx(CollapsibleTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: cn('flex w-full items-center gap-3 px-5 py-3.5 transition-colors cursor-pointer', colors.bg, colors.hoverBg), children: [_jsx("div", { className: cn('flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg', colors.icon), children: _jsx(Lightbulb, { className: "h-4 w-4" }) }), _jsx("span", { className: cn('text-sm font-semibold flex-1 text-left', colors.title), children: "H\u01B0\u1EDBng d\u1EABn t\u1EA1o c\u00E2u h\u1ECFi" }), _jsx(ChevronDown, { className: cn('h-4 w-4 transition-transform duration-200', colors.text, isOpen && 'rotate-180') })] }) }), _jsx(CollapsibleContent, { children: _jsx("div", { className: "px-5 pb-4 pt-0", children: _jsxs("div", { className: "ml-11 space-y-1.5", children: [steps.map((step, index) => (_jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("span", { className: cn('mt-1.5 h-1.5 w-1.5 flex-shrink-0 rounded-full', colors.dot) }), _jsx("span", { className: cn('text-sm leading-relaxed', colors.text, step.highlight && 'font-semibold'), children: step.text })] }, index))), tips.length > 0 && (_jsx("div", { className: cn('mt-3 rounded-lg px-3 py-2', colors.tipBg), children: tips.map((tip, index) => (_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-sm", children: "\uD83D\uDCA1" }), _jsxs("span", { className: cn('text-sm font-medium', colors.tipText), children: [_jsx("strong", { children: "M\u1EB9o:" }), " ", tip] })] }, index))) }))] }) }) })] }) }));
103
- }
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as r}from"react";import{Lightbulb as o,ChevronDown as a}from"lucide-react";import{Collapsible as l,CollapsibleTrigger as i,CollapsibleContent as n}from"../../../components/ui/collapsible";import{cn as d}from"../../../shared/lib/utils";const g={blue:{border:"border-blue-200",bg:"bg-gradient-to-r from-blue-50 to-indigo-50",icon:"bg-blue-100 text-blue-600",title:"text-blue-800",dot:"bg-blue-400",text:"text-blue-700",tipBg:"bg-blue-100/60",tipText:"text-blue-700",hoverBg:"hover:from-blue-100/80 hover:to-indigo-100/60"},purple:{border:"border-purple-200",bg:"bg-gradient-to-r from-purple-50 to-violet-50",icon:"bg-purple-100 text-purple-600",title:"text-purple-800",dot:"bg-purple-400",text:"text-purple-700",tipBg:"bg-purple-100/60",tipText:"text-purple-700",hoverBg:"hover:from-purple-100/80 hover:to-violet-100/60"},emerald:{border:"border-emerald-200",bg:"bg-gradient-to-r from-emerald-50 to-teal-50",icon:"bg-emerald-100 text-emerald-600",title:"text-emerald-800",dot:"bg-emerald-400",text:"text-emerald-700",tipBg:"bg-emerald-100/60",tipText:"text-emerald-700",hoverBg:"hover:from-emerald-100/80 hover:to-teal-100/60"},amber:{border:"border-amber-200",bg:"bg-gradient-to-r from-amber-50 to-orange-50",icon:"bg-amber-100 text-amber-600",title:"text-amber-800",dot:"bg-amber-400",text:"text-amber-700",tipBg:"bg-amber-100/60",tipText:"text-amber-700",hoverBg:"hover:from-amber-100/80 hover:to-orange-100/60"},cyan:{border:"border-cyan-200",bg:"bg-gradient-to-r from-cyan-50 to-sky-50",icon:"bg-cyan-100 text-cyan-600",title:"text-cyan-800",dot:"bg-cyan-400",text:"text-cyan-700",tipBg:"bg-cyan-100/60",tipText:"text-cyan-700",hoverBg:"hover:from-cyan-100/80 hover:to-sky-100/60"},rose:{border:"border-rose-200",bg:"bg-gradient-to-r from-rose-50 to-pink-50",icon:"bg-rose-100 text-rose-600",title:"text-rose-800",dot:"bg-rose-400",text:"text-rose-700",tipBg:"bg-rose-100/60",tipText:"text-rose-700",hoverBg:"hover:from-rose-100/80 hover:to-pink-100/60"},teal:{border:"border-teal-200",bg:"bg-gradient-to-r from-teal-50 to-emerald-50",icon:"bg-teal-100 text-teal-600",title:"text-teal-800",dot:"bg-teal-400",text:"text-teal-700",tipBg:"bg-teal-100/60",tipText:"text-teal-700",hoverBg:"hover:from-teal-100/80 hover:to-emerald-100/60"},orange:{border:"border-orange-200",bg:"bg-gradient-to-r from-orange-50 to-amber-50",icon:"bg-orange-100 text-orange-600",title:"text-orange-800",dot:"bg-orange-400",text:"text-orange-700",tipBg:"bg-orange-100/60",tipText:"text-orange-700",hoverBg:"hover:from-orange-100/80 hover:to-amber-100/60"}};export function CreatorGuide({steps:b,tips:m=[],colorScheme:s="blue"}){const[p,x]=r(!1),c=g[s];return e(l,{open:p,onOpenChange:x,children:t("div",{className:d("rounded-xl border shadow-sm overflow-hidden",c.border,c.bg),children:[e(i,{asChild:!0,children:t("button",{type:"button",className:d("flex w-full items-center gap-3 px-5 py-3.5 transition-colors cursor-pointer",c.bg,c.hoverBg),children:[e("div",{className:d("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg",c.icon),children:e(o,{className:"h-4 w-4"})}),e("span",{className:d("text-sm font-semibold flex-1 text-left",c.title),children:"Hướng dẫn tạo câu hỏi"}),e(a,{className:d("h-4 w-4 transition-transform duration-200",c.text,p&&"rotate-180")})]})}),e(n,{children:e("div",{className:"px-5 pb-4 pt-0",children:t("div",{className:"ml-11 space-y-1.5",children:[b.map((r,o)=>t("div",{className:"flex items-start gap-2.5",children:[e("span",{className:d("mt-1.5 h-1.5 w-1.5 flex-shrink-0 rounded-full",c.dot)}),e("span",{className:d("text-sm leading-relaxed",c.text,r.highlight&&"font-semibold"),children:r.text})]},o)),m.length>0&&e("div",{className:d("mt-3 rounded-lg px-3 py-2",c.tipBg),children:m.map((r,o)=>t("div",{className:"flex items-start gap-2",children:[e("span",{className:"text-sm",children:"💡"}),t("span",{className:d("text-sm font-medium",c.tipText),children:[e("strong",{children:"Mẹo:"})," ",r]})]},o))})]})})})]})})}
@@ -1,26 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button } from '../../../components/ui/button';
3
- import { Badge } from '../../../components/ui/badge';
4
- import { X } from 'lucide-react';
5
- export function NameNode({ data, variant = 'creator' }) {
6
- const isClientMode = variant === 'client';
7
- const isCompact = data.displayMode === 'compact';
8
- const textClass = isCompact ? 'text-[11px]' : 'text-[13px]';
9
- if (isClientMode) {
10
- const baseClass = data.isConnected
11
- ? 'relative flex h-full w-full items-center justify-center overflow-hidden rounded-2xl bg-white transition-all duration-200 ease-out'
12
- : 'relative inline-flex min-w-[110px] items-center justify-center overflow-hidden rounded-2xl border border-gray-300 bg-white px-3 py-2 transition-all duration-200 ease-out hover:border-blue-400 cursor-move';
13
- return (_jsxs("div", { className: `${baseClass} ${data.highlightClass ?? ''}`, style: data.highlightStyle, children: [data.isHighlighted && (_jsx("div", { className: "pointer-events-none absolute inset-0 z-[1] rounded-2xl bg-black/40" })), _jsx("span", { className: `relative ${data.isHighlighted ? 'z-[2]' : 'z-[1]'} font-medium text-black ${textClass}`, children: data.name })] }));
14
- }
15
- const isConnectedCreator = data.isConnected;
16
- const baseClassesCreator = isCompact
17
- ? 'relative inline-flex min-w-[110px] items-center justify-between rounded-2xl border px-3 py-2 text-xs transition-all'
18
- : 'relative flex min-w-[180px] items-center justify-between rounded-2xl border-2 px-3 py-2 text-sm transition-all';
19
- const creatorClass = isConnectedCreator
20
- ? `${baseClassesCreator} border-green-500 bg-green-50 ring-2 ring-green-200`
21
- : `${baseClassesCreator} border-gray-200 bg-white hover:border-blue-300`;
22
- return (_jsxs("div", { className: creatorClass, children: [_jsx("span", { className: `font-medium text-gray-900 ${textClass}`, children: data.name }), _jsxs("div", { className: "flex items-center gap-2", children: [data.isConnected && (_jsx(Badge, { variant: "outline", className: "bg-green-50 text-xs text-green-700", children: "\u2713" })), data.isEditMode && (_jsx(Button, { size: "icon", variant: "ghost", className: "h-6 w-6", onClick: (e) => {
23
- e.stopPropagation();
24
- data.onRemove();
25
- }, children: _jsx(X, { className: "h-3 w-3" }) }))] })] }));
26
- }
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Button as i}from"../../../components/ui/button";import{Badge as n}from"../../../components/ui/badge";import{X as r}from"lucide-react";export function NameNode({data:o,variant:a="creator"}){const s="client"===a,l="compact"===o.displayMode,d=l?"text-[11px]":"text-[13px]";if(s){const i=o.isConnected?"relative flex h-full w-full items-center justify-center overflow-hidden rounded-2xl bg-white transition-all duration-200 ease-out":"relative inline-flex min-w-[110px] items-center justify-center overflow-hidden rounded-2xl border border-gray-300 bg-white px-3 py-2 transition-all duration-200 ease-out hover:border-blue-400 cursor-move";return t("div",{className:`${i} ${o.highlightClass??""}`,style:o.highlightStyle,children:[o.isHighlighted&&e("div",{className:"pointer-events-none absolute inset-0 z-[1] rounded-2xl bg-black/40"}),e("span",{className:`relative ${o.isHighlighted?"z-[2]":"z-[1]"} font-medium text-black ${d}`,children:o.name})]})}const c=o.isConnected,m=l?"relative inline-flex min-w-[110px] items-center justify-between rounded-2xl border px-3 py-2 text-xs transition-all":"relative flex min-w-[180px] items-center justify-between rounded-2xl border-2 px-3 py-2 text-sm transition-all";return t("div",{className:c?`${m} border-green-500 bg-green-50 ring-2 ring-green-200`:`${m} border-gray-200 bg-white hover:border-blue-300`,children:[e("span",{className:`font-medium text-gray-900 ${d}`,children:o.name}),t("div",{className:"flex items-center gap-2",children:[o.isConnected&&e(n,{variant:"outline",className:"bg-green-50 text-xs text-green-700",children:"✓"}),o.isEditMode&&e(i,{size:"icon",variant:"ghost",className:"h-6 w-6",onClick:e=>{e.stopPropagation(),o.onRemove()},children:e(r,{className:"h-3 w-3"})})]})]})}
@@ -1,46 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Label } from '../../../components/ui/label';
4
- import { Input } from '../../../components/ui/input';
5
- import { Card, CardContent } from '../../../components/ui/card';
6
- import { Alert, AlertDescription } from '../../../components/ui/alert';
7
- import { Database, CheckCircle2, ExternalLink } from 'lucide-react';
8
- import Link from 'next/link';
9
- // Validation constants
10
- const CODE_MAX_LENGTH = 100;
11
- const TITLE_MAX_LENGTH = 255;
12
- // Pattern: only alphanumeric characters, underscore, and hyphen
13
- const CODE_PATTERN = /^[a-zA-Z0-9_-]*$/;
14
- /**
15
- * Shared component for "Add to Question Bank" option.
16
- *
17
- * Has two modes:
18
- * 1. NEW: When existingBank is null - shows editable code/title inputs
19
- * 2. EXISTING: When existingBank has data - shows read-only info with link to edit
20
- *
21
- * Validation rules:
22
- * - Code: Required, max 100 chars, only letters, numbers, underscore (_), hyphen (-)
23
- * - Title: Required, max 255 chars
24
- *
25
- * Used by all question type creators to allow adding questions to the question bank.
26
- */
27
- export function QuestionBankOption({ checked, onCheckedChange, code, onCodeChange, title, onTitleChange, error, codeError, existingBank, disabled = false, }) {
28
- // Handle code change with pattern validation
29
- const handleCodeChange = (value) => {
30
- // Only allow valid characters (alphanumeric, underscore, hyphen)
31
- if (CODE_PATTERN.test(value)) {
32
- onCodeChange(value.slice(0, CODE_MAX_LENGTH));
33
- }
34
- };
35
- // Handle title change with max length
36
- const handleTitleChange = (value) => {
37
- onTitleChange(value.slice(0, TITLE_MAX_LENGTH));
38
- };
39
- // If existing bank data exists, show read-only mode
40
- const isExistingBank = existingBank && existingBank.id;
41
- return (_jsx(Card, { className: `border-dashed ${isExistingBank ? 'border-green-300 bg-green-50/50' : checked ? 'border-blue-300 bg-blue-50/50' : 'border-gray-300 bg-gray-50/50'}`, children: _jsx(CardContent, { className: "pt-4", children: isExistingBank ? (
42
- // EXISTING BANK MODE - Read-only display with edit link
43
- _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-green-100", children: _jsx(CheckCircle2, { className: "h-5 w-5 text-green-600" }) }), _jsx("div", { children: _jsx("span", { className: "text-sm font-medium text-green-700", children: "\u0110\u00E3 th\u00EAm v\u00E0o ng\u00E2n h\u00E0ng c\u00E2u h\u1ECFi" }) })] }), _jsxs("div", { className: "mt-4 pl-11 space-y-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "questionCode", className: "text-sm font-medium text-gray-600", children: "M\u00E3 c\u00E2u h\u1ECFi" }), _jsx(Input, { id: "questionCode", value: existingBank.code, readOnly: true, disabled: true, className: "mt-1.5 bg-gray-100 text-gray-900 cursor-not-allowed" })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "questionTitle", className: "text-sm font-medium text-gray-600", children: "Ti\u00EAu \u0111\u1EC1 c\u00E2u h\u1ECFi" }), _jsx(Input, { id: "questionTitle", value: existingBank.title, readOnly: true, disabled: true, className: "mt-1.5 bg-gray-100 text-gray-900 cursor-not-allowed" })] }), _jsxs(Alert, { className: "border-blue-200 bg-blue-50", children: [_jsx(Database, { className: "h-4 w-4 text-blue-600" }), _jsx(AlertDescription, { className: "text-sm text-blue-800", children: _jsxs(Link, { href: `/manage/question-banks?code=${encodeURIComponent(existingBank.code)}`, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1.5 text-blue-600 hover:text-blue-800 font-medium hover:underline", children: ["Ng\u00E2n h\u00E0ng c\u00E2u h\u1ECFi", _jsx(ExternalLink, { className: "h-3.5 w-3.5" })] }) })] })] })] })) : (
44
- // NEW BANK MODE - Editable inputs
45
- _jsxs(_Fragment, { children: [_jsxs("label", { className: `flex items-center gap-3 ${disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`, children: [_jsx("input", { type: "checkbox", checked: checked, onChange: (e) => !disabled && onCheckedChange(e.target.checked), disabled: disabled, className: "h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Database, { className: `h-4 w-4 ${checked ? 'text-blue-600' : 'text-gray-500'}` }), _jsx("span", { className: `text-sm font-medium ${checked ? 'text-blue-700' : 'text-gray-700'}`, children: "Th\u00EAm v\u00E0o ng\u00E2n h\u00E0ng c\u00E2u h\u1ECFi" })] })] }), checked && (_jsxs("div", { className: "mt-4 pl-7 space-y-4", children: [_jsxs("div", { children: [_jsxs(Label, { htmlFor: "questionCode", className: "text-sm font-medium", children: ["M\u00E3 c\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "questionCode", value: code, onChange: (e) => handleCodeChange(e.target.value), placeholder: 'VD: "Q001", "GRID_001", "MC-PAST-01"...', className: `mt-1.5 ${codeError ? 'border-red-500 focus:ring-red-500' : ''}`, disabled: disabled, maxLength: CODE_MAX_LENGTH }), _jsxs("div", { className: "mt-1 flex justify-between", children: [codeError ? (_jsx("p", { className: "text-sm text-red-500", children: codeError })) : (_jsx("p", { className: "text-xs text-gray-500", children: "Ch\u1EC9 ch\u1EEF c\u00E1i, s\u1ED1, d\u1EA5u g\u1EA1ch d\u01B0\u1EDBi (_) v\u00E0 g\u1EA1ch ngang (-)" })), _jsxs("span", { className: "text-xs text-gray-400", children: [code.length, "/", CODE_MAX_LENGTH] })] })] }), _jsxs("div", { children: [_jsxs(Label, { htmlFor: "questionTitle", className: "text-sm font-medium", children: ["Ti\u00EAu \u0111\u1EC1 c\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "questionTitle", value: title, onChange: (e) => handleTitleChange(e.target.value), placeholder: 'VD: "Grid \u0111i\u1EC1n t\u1EEB v\u1EC1 \u0111\u1ED9ng v\u1EADt", "Tr\u1EAFc nghi\u1EC7m th\u00EC qu\u00E1 kh\u1EE9"...', className: `mt-1.5 ${error ? 'border-red-500 focus:ring-red-500' : ''}`, disabled: disabled, maxLength: TITLE_MAX_LENGTH }), _jsxs("div", { className: "mt-1 flex justify-between", children: [error ? (_jsx("p", { className: "text-sm text-red-500", children: error })) : (_jsx("p", { className: "text-xs text-gray-500", children: "M\u00E3 v\u00E0 ti\u00EAu \u0111\u1EC1 gi\u00FAp t\u00ECm ki\u1EBFm c\u00E2u h\u1ECFi trong \u0111\u1EC1 thi kh\u00E1c" })), _jsxs("span", { className: "text-xs text-gray-400", children: [title.length, "/", TITLE_MAX_LENGTH] })] })] })] }))] })) }) }));
46
- }
1
+ "use client";import{jsx as e,jsxs as t,Fragment as r}from"react/jsx-runtime";import{Label as a}from"../../../components/ui/label";import{Input as n}from"../../../components/ui/input";import{Card as l,CardContent as s}from"../../../components/ui/card";import{Alert as i,AlertDescription as c}from"../../../components/ui/alert";import{Database as d,CheckCircle2 as o,ExternalLink as m}from"lucide-react";import h from"next/link";const u=/^[a-zA-Z0-9_-]*$/;export function QuestionBankOption({checked:g,onCheckedChange:x,code:b,onCodeChange:p,title:N,onTitleChange:f,error:v,codeError:y,existingBank:C,disabled:k=!1}){const w=C&&C.id;return e(l,{className:"border-dashed "+(w?"border-green-300 bg-green-50/50":g?"border-blue-300 bg-blue-50/50":"border-gray-300 bg-gray-50/50"),children:e(s,{className:"pt-4",children:t(r,w?{children:[t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-full bg-green-100",children:e(o,{className:"h-5 w-5 text-green-600"})}),e("div",{children:e("span",{className:"text-sm font-medium text-green-700",children:"Đã thêm vào ngân hàng câu hỏi"})})]}),t("div",{className:"mt-4 pl-11 space-y-4",children:[t("div",{children:[e(a,{htmlFor:"questionCode",className:"text-sm font-medium text-gray-600",children:"Mã câu hỏi"}),e(n,{id:"questionCode",value:C.code,readOnly:!0,disabled:!0,className:"mt-1.5 bg-gray-100 text-gray-900 cursor-not-allowed"})]}),t("div",{children:[e(a,{htmlFor:"questionTitle",className:"text-sm font-medium text-gray-600",children:"Tiêu đề câu hỏi"}),e(n,{id:"questionTitle",value:C.title,readOnly:!0,disabled:!0,className:"mt-1.5 bg-gray-100 text-gray-900 cursor-not-allowed"})]}),t(i,{className:"border-blue-200 bg-blue-50",children:[e(d,{className:"h-4 w-4 text-blue-600"}),e(c,{className:"text-sm text-blue-800",children:t(h,{href:`/manage/question-banks?code=${encodeURIComponent(C.code)}`,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1.5 text-blue-600 hover:text-blue-800 font-medium hover:underline",children:["Ngân hàng câu hỏi",e(m,{className:"h-3.5 w-3.5"})]})})]})]})]}:{children:[t("label",{className:"flex items-center gap-3 "+(k?"cursor-not-allowed opacity-50":"cursor-pointer"),children:[e("input",{type:"checkbox",checked:g,onChange:e=>!k&&x(e.target.checked),disabled:k,className:"h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed"}),t("div",{className:"flex items-center gap-2",children:[e(d,{className:"h-4 w-4 "+(g?"text-blue-600":"text-gray-500")}),e("span",{className:"text-sm font-medium "+(g?"text-blue-700":"text-gray-700"),children:"Thêm vào ngân hàng câu hỏi"})]})]}),g&&t("div",{className:"mt-4 pl-7 space-y-4",children:[t("div",{children:[t(a,{htmlFor:"questionCode",className:"text-sm font-medium",children:["Mã câu hỏi ",e("span",{className:"text-red-500",children:"*"})]}),e(n,{id:"questionCode",value:b,onChange:e=>{return t=e.target.value,void(u.test(t)&&p(t.slice(0,100)));var t},placeholder:'VD: "Q001", "GRID_001", "MC-PAST-01"...',className:"mt-1.5 "+(y?"border-red-500 focus:ring-red-500":""),disabled:k,maxLength:100}),t("div",{className:"mt-1 flex justify-between",children:[e("p",y?{className:"text-sm text-red-500",children:y}:{className:"text-xs text-gray-500",children:"Chỉ chữ cái, số, dấu gạch dưới (_) và gạch ngang (-)"}),t("span",{className:"text-xs text-gray-400",children:[b.length,"/",100]})]})]}),t("div",{children:[t(a,{htmlFor:"questionTitle",className:"text-sm font-medium",children:["Tiêu đề câu hỏi ",e("span",{className:"text-red-500",children:"*"})]}),e(n,{id:"questionTitle",value:N,onChange:e=>{return t=e.target.value,void f(t.slice(0,255));var t},placeholder:'VD: "Grid điền từ về động vật", "Trắc nghiệm thì quá khứ"...',className:"mt-1.5 "+(v?"border-red-500 focus:ring-red-500":""),disabled:k,maxLength:255}),t("div",{className:"mt-1 flex justify-between",children:[e("p",v?{className:"text-sm text-red-500",children:v}:{className:"text-xs text-gray-500",children:"Mã và tiêu đề giúp tìm kiếm câu hỏi trong đề thi khác"}),t("span",{className:"text-xs text-gray-400",children:[N.length,"/",255]})]})]})]})]})})})}
@@ -1,9 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Label } from '../../../components/ui/label';
3
- import { Input } from '../../../components/ui/input';
4
- import { Textarea } from '../../../components/ui/textarea';
5
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../../components/ui/select';
6
- import { QuestionTypeSelector } from './QuestionTypeSelector';
7
- export function QuestionBasicInfoForm({ questionType, content, level, difficulty, skill, points, isEmbedded, prefilledType, onQuestionTypeChange, onContentChange, onLevelChange, onDifficultyChange, onSkillChange, onPointsChange, }) {
8
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "questionType", children: "Lo\u1EA1i c\u00E2u h\u1ECFi *" }), _jsx(QuestionTypeSelector, { value: questionType, onValueChange: onQuestionTypeChange, disabled: isEmbedded && !!prefilledType })] }), questionType !== 'CHOOSE_THE_CORRECT_ANSWER' && (_jsxs("div", { children: [_jsx(Label, { htmlFor: "content", children: "N\u1ED9i dung c\u00E2u h\u1ECFi *" }), _jsx(Textarea, { id: "content", value: content, onChange: (e) => onContentChange(e.target.value), placeholder: "Nh\u1EADp n\u1ED9i dung c\u00E2u h\u1ECFi...", className: "mt-1", rows: 3 })] })), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "level", children: "C\u1EA5p \u0111\u1ED9 *" }), _jsxs(Select, { value: level, onValueChange: (value) => onLevelChange(value), children: [_jsx(SelectTrigger, { id: "level", className: "mt-1", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "A1", children: "A1" }), _jsx(SelectItem, { value: "A2", children: "A2" }), _jsx(SelectItem, { value: "B1", children: "B1" }), _jsx(SelectItem, { value: "B2", children: "B2" }), _jsx(SelectItem, { value: "C1", children: "C1" }), _jsx(SelectItem, { value: "C2", children: "C2" })] })] })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "difficulty", children: "\u0110\u1ED9 kh\u00F3 *" }), _jsxs(Select, { value: difficulty, onValueChange: (value) => onDifficultyChange(value), children: [_jsx(SelectTrigger, { id: "difficulty", className: "mt-1", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "EASY", children: "D\u1EC5" }), _jsx(SelectItem, { value: "MEDIUM", children: "Trung b\u00ECnh" }), _jsx(SelectItem, { value: "HARD", children: "Kh\u00F3" })] })] })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "skill", children: "K\u1EF9 n\u0103ng *" }), _jsxs(Select, { value: skill, onValueChange: (value) => onSkillChange(value), children: [_jsx(SelectTrigger, { id: "skill", className: "mt-1", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "LISTENING", children: "Listening" }), _jsx(SelectItem, { value: "READING", children: "Reading" }), _jsx(SelectItem, { value: "WRITING", children: "Writing" }), _jsx(SelectItem, { value: "SPEAKING", children: "Speaking" })] })] })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "points", children: "\u0110i\u1EC3m *" }), _jsx(Input, { id: "points", type: "number", value: points, onChange: (e) => onPointsChange(Number(e.target.value)), className: "mt-1", min: 1 })] })] })] }));
9
- }
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import{Label as i}from"../../../components/ui/label";import{Input as l}from"../../../components/ui/input";import{Textarea as r}from"../../../components/ui/textarea";import{Select as a,SelectContent as c,SelectItem as d,SelectTrigger as h,SelectValue as o}from"../../../components/ui/select";import{QuestionTypeSelector as t}from"./QuestionTypeSelector";export function QuestionBasicInfoForm({questionType:u,content:s,level:m,difficulty:v,skill:p,points:g,isEmbedded:C,prefilledType:f,onQuestionTypeChange:N,onContentChange:y,onLevelChange:E,onDifficultyChange:T,onSkillChange:A,onPointsChange:I}){return n("div",{className:"space-y-4",children:[n("div",{children:[e(i,{htmlFor:"questionType",children:"Loại câu hỏi *"}),e(t,{value:u,onValueChange:N,disabled:C&&!!f})]}),"CHOOSE_THE_CORRECT_ANSWER"!==u&&n("div",{children:[e(i,{htmlFor:"content",children:"Nội dung câu hỏi *"}),e(r,{id:"content",value:s,onChange:e=>y(e.target.value),placeholder:"Nhập nội dung câu hỏi...",className:"mt-1",rows:3})]}),n("div",{className:"grid grid-cols-2 gap-4",children:[n("div",{children:[e(i,{htmlFor:"level",children:"Cấp độ *"}),n(a,{value:m,onValueChange:e=>E(e),children:[e(h,{id:"level",className:"mt-1",children:e(o,{})}),n(c,{children:[e(d,{value:"A1",children:"A1"}),e(d,{value:"A2",children:"A2"}),e(d,{value:"B1",children:"B1"}),e(d,{value:"B2",children:"B2"}),e(d,{value:"C1",children:"C1"}),e(d,{value:"C2",children:"C2"})]})]})]}),n("div",{children:[e(i,{htmlFor:"difficulty",children:"Độ khó *"}),n(a,{value:v,onValueChange:e=>T(e),children:[e(h,{id:"difficulty",className:"mt-1",children:e(o,{})}),n(c,{children:[e(d,{value:"EASY",children:"Dễ"}),e(d,{value:"MEDIUM",children:"Trung bình"}),e(d,{value:"HARD",children:"Khó"})]})]})]}),n("div",{children:[e(i,{htmlFor:"skill",children:"Kỹ năng *"}),n(a,{value:p,onValueChange:e=>A(e),children:[e(h,{id:"skill",className:"mt-1",children:e(o,{})}),n(c,{children:[e(d,{value:"LISTENING",children:"Listening"}),e(d,{value:"READING",children:"Reading"}),e(d,{value:"WRITING",children:"Writing"}),e(d,{value:"SPEAKING",children:"Speaking"})]})]})]}),n("div",{children:[e(i,{htmlFor:"points",children:"Điểm *"}),e(l,{id:"points",type:"number",value:g,onChange:e=>I(Number(e.target.value)),className:"mt-1",min:1})]})]})]})}
@@ -1,33 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Label } from '../../../components/ui/label';
4
- import { Textarea } from '../../../components/ui/textarea';
5
- import { Card, CardContent, CardHeader, CardTitle } from '../../../components/ui/card';
6
- import { PointsInput } from '../../../components/ui/points-input';
7
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../../components/ui/select';
8
- /**
9
- * Shared component for common question fields:
10
- * - Points (điểm số)
11
- * - Difficulty (độ khó)
12
- * - Explanation (giải thích)
13
- *
14
- * Used by all question type creators to ensure consistency.
15
- */
16
- export function QuestionCommonFields({ points, onPointsChange, difficulty = 'MEDIUM', onDifficultyChange, showDifficulty = true, explanation = '', onExplanationChange, showExplanation = true, layout = 'horizontal', }) {
17
- const getDifficultyLabel = (diff) => {
18
- switch (diff) {
19
- case 'EASY':
20
- return 'Dễ';
21
- case 'MEDIUM':
22
- return 'Trung bình';
23
- case 'HARD':
24
- return 'Khó';
25
- default:
26
- return diff;
27
- }
28
- };
29
- return (_jsxs(Card, { children: [_jsx(CardHeader, { className: "pb-3", children: _jsx(CardTitle, { className: "text-base", children: "Th\u00F4ng tin c\u01A1 b\u1EA3n" }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: layout === 'horizontal' ? 'grid grid-cols-2 gap-4' : 'space-y-4', children: [_jsx("div", { children: _jsx(PointsInput, { defaultValue: points, onChange: (e) => {
30
- const value = Number(e.target.value);
31
- onPointsChange(value || 1);
32
- } }) }), showDifficulty && onDifficultyChange && (_jsxs("div", { children: [_jsx(Label, { htmlFor: "difficulty", className: "text-sm font-medium", children: "\u0110\u1ED9 kh\u00F3" }), _jsxs(Select, { value: difficulty, onValueChange: (value) => onDifficultyChange(value), children: [_jsx(SelectTrigger, { id: "difficulty", className: "mt-1.5", children: _jsx(SelectValue, { placeholder: "Ch\u1ECDn \u0111\u1ED9 kh\u00F3", children: getDifficultyLabel(difficulty) }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "EASY", children: "D\u1EC5" }), _jsx(SelectItem, { value: "MEDIUM", children: "Trung b\u00ECnh" }), _jsx(SelectItem, { value: "HARD", children: "Kh\u00F3" })] })] })] }))] }), showExplanation && onExplanationChange && (_jsxs("div", { children: [_jsx(Label, { htmlFor: "explanation", className: "text-sm font-medium", children: "Gi\u1EA3i th\u00EDch" }), _jsx(Textarea, { id: "explanation", value: explanation, onChange: (e) => onExplanationChange(e.target.value), placeholder: "Nh\u1EADp gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng...", className: "mt-1.5", rows: 3 }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "Gi\u1EA3i th\u00EDch s\u1EBD \u0111\u01B0\u1EE3c hi\u1EC3n th\u1ECB cho h\u1ECDc sinh sau khi n\u1ED9p b\u00E0i" })] }))] })] }));
33
- }
1
+ "use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{Label as i}from"../../../components/ui/label";import{Textarea as t}from"../../../components/ui/textarea";import{Card as a,CardContent as l,CardHeader as c,CardTitle as r}from"../../../components/ui/card";import{PointsInput as o}from"../../../components/ui/points-input";import{Select as h,SelectContent as s,SelectItem as m,SelectTrigger as u,SelectValue as d}from"../../../components/ui/select";export function QuestionCommonFields({points:p,onPointsChange:f,difficulty:g="MEDIUM",onDifficultyChange:x,showDifficulty:v=!0,explanation:N="",onExplanationChange:y,showExplanation:D=!0,layout:b="horizontal"}){return n(a,{children:[e(c,{className:"pb-3",children:e(r,{className:"text-base",children:"Thông tin cơ bản"})}),n(l,{className:"space-y-4",children:[n("div",{className:"horizontal"===b?"grid grid-cols-2 gap-4":"space-y-4",children:[e("div",{children:e(o,{defaultValue:p,onChange:e=>{const n=Number(e.target.value);f(n||1)}})}),v&&x&&n("div",{children:[e(i,{htmlFor:"difficulty",className:"text-sm font-medium",children:"Độ khó"}),n(h,{value:g,onValueChange:e=>x(e),children:[e(u,{id:"difficulty",className:"mt-1.5",children:e(d,{placeholder:"Chọn độ khó",children:(e=>{switch(e){case"EASY":return"Dễ";case"MEDIUM":return"Trung bình";case"HARD":return"Khó";default:return e}})(g)})}),n(s,{children:[e(m,{value:"EASY",children:"Dễ"}),e(m,{value:"MEDIUM",children:"Trung bình"}),e(m,{value:"HARD",children:"Khó"})]})]})]})]}),D&&y&&n("div",{children:[e(i,{htmlFor:"explanation",className:"text-sm font-medium",children:"Giải thích"}),e(t,{id:"explanation",value:N,onChange:e=>y(e.target.value),placeholder:"Nhập giải thích cho đáp án đúng...",className:"mt-1.5",rows:3}),e("p",{className:"mt-1 text-xs text-gray-500",children:"Giải thích sẽ được hiển thị cho học sinh sau khi nộp bài"})]})]})]})}
@@ -1,258 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useMemo, useState } from 'react';
4
- import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../../components/ui/dropdown-menu';
5
- import { Input } from '../../../components/ui/input';
6
- import { Badge } from '../../../components/ui/badge';
7
- import { Loader2, Search, Image as ImageIcon, FileText, Grid3X3, BookOpen, Library, Sparkles, Hash, BarChart3, Lightbulb, CheckCircle2, } from 'lucide-react';
8
- import { useQuery } from '@tanstack/react-query';
9
- import { ScrollArea } from '../../../components/ui/scroll-area';
10
- import { cn } from '../../../shared/lib/utils';
11
- const truncate = (text, maxLength) => {
12
- if (!text)
13
- return '';
14
- // Convert to string if it's not already
15
- const textStr = typeof text === 'string' ? text : String(text);
16
- if (textStr.length <= maxLength)
17
- return textStr;
18
- return `${textStr.substring(0, maxLength)}...`;
19
- };
20
- // Image-based question types
21
- const IMAGE_BASED_TYPES = [
22
- 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER',
23
- 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER',
24
- 'LOOK_PICTURE_FILL_WORD_HINT',
25
- 'FILL_IN_BLANK',
26
- 'LABEL_THE_PICTURE',
27
- 'READ_AND_COLOR_OBJECTS',
28
- 'IMAGE_OBJECT_MATCHING',
29
- 'FILL_IN_BLANK',
30
- ];
31
- // Passage-based question types
32
- const PASSAGE_BASED_TYPES = [
33
- 'READ_PASSAGE_AND_ANSWER_QUESTIONS',
34
- 'READ_PASSAGE_AND_COMPLETE_STORY',
35
- ];
36
- // Grid-based question types
37
- const GRID_BASED_TYPES = ['FILL_MISSING_WORDS_IN_GRID'];
38
- // Get display icon for question type
39
- const getQuestionTypeIcon = (type) => {
40
- if (IMAGE_BASED_TYPES.includes(type)) {
41
- return _jsx(ImageIcon, { className: "h-4 w-4 text-blue-500" });
42
- }
43
- if (PASSAGE_BASED_TYPES.includes(type)) {
44
- return _jsx(BookOpen, { className: "h-4 w-4 text-green-500" });
45
- }
46
- if (GRID_BASED_TYPES.includes(type)) {
47
- return _jsx(Grid3X3, { className: "h-4 w-4 text-purple-500" });
48
- }
49
- return _jsx(FileText, { className: "h-4 w-4 text-gray-500" });
50
- };
51
- // Get question type display name in Vietnamese
52
- const getQuestionTypeName = (type) => {
53
- const typeMap = {
54
- 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER': 'Nhìn tranh điền chỗ trống',
55
- 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': 'Nhìn tranh chọn đáp án',
56
- 'LOOK_PICTURE_FILL_WORD_HINT': 'Nhìn tranh điền từ gợi ý',
57
- 'FILL_MISSING_WORDS_IN_GRID': 'Điền chữ trong bảng',
58
- 'CHOOSE_THE_CORRECT_ANSWER': 'Chọn đáp án đúng',
59
- 'LABEL_THE_PICTURE': 'Gắn nhãn hình ảnh',
60
- 'READ_AND_COLOR_OBJECTS': 'Đọc và tô màu',
61
- 'IMAGE_OBJECT_MATCHING': 'Ghép hình ảnh - Đối tượng',
62
- 'WRITE_CORRECT_VERB_FORM': 'Viết dạng động từ',
63
- 'FILL_IN_BLANK': 'Điền vào chỗ trống',
64
- 'READ_PASSAGE_AND_ANSWER_QUESTIONS': 'Đọc hiểu',
65
- };
66
- return type ? typeMap[type] || type.replace(/_/g, ' ').toLowerCase() : 'Chưa xác định';
67
- };
68
- // Enhanced function to extract display text from different question content structures
69
- export const getQuestionDisplayText = (question) => {
70
- return getContentDisplayText(question.content, question.type);
71
- };
72
- // Extract display text from content object (for cases where we have content but not full Question)
73
- export const getContentDisplayText = (content, type) => {
74
- if (!content)
75
- return type || 'Câu hỏi';
76
- // Handle string content directly
77
- if (typeof content === 'string') {
78
- return content;
79
- }
80
- // Handle object content based on question type
81
- if (typeof content === 'object') {
82
- // LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER, LOOK_PICTURE_CHOOSE_CORRECT_ANSWER
83
- if (content.subQuestions && Array.isArray(content.subQuestions)) {
84
- const firstSubQ = content.subQuestions[0];
85
- if (firstSubQ?.question) {
86
- return firstSubQ.question;
87
- }
88
- }
89
- // For content with direct question field (single question format)
90
- if (content.question) {
91
- return content.question;
92
- }
93
- // LOOK_PICTURE_FILL_WORD_HINT - show word pattern
94
- if (content.word) {
95
- return `Điền chữ: ${content.word}`;
96
- }
97
- // READ_PASSAGE_AND_ANSWER_QUESTIONS
98
- if (content.passage) {
99
- return content.passageTitle || truncate(content.passage, 60);
100
- }
101
- // FILL_MISSING_WORDS_IN_GRID
102
- if (content.grid && content.rows && content.columns) {
103
- return `Lưới ${content.rows}x${content.columns}`;
104
- }
105
- // LABEL_THE_PICTURE
106
- if (content.wordBank) {
107
- const words = content.wordBank.map((w) => w.text || w).slice(0, 3).join(', ');
108
- return `Từ vựng: ${words}${content.wordBank.length > 3 ? '...' : ''}`;
109
- }
110
- // READ_AND_COLOR_OBJECTS / IMAGE_OBJECT_MATCHING
111
- if (content.colorNodes || content.regionNodes) {
112
- const regionCount = content.regionNodes?.length || 0;
113
- return `${regionCount} vùng tô màu`;
114
- }
115
- // WRITE_A_SHORT_LETTER
116
- if (content.contexts) {
117
- const firstContext = content.contexts[0];
118
- return firstContext?.text ? truncate(firstContext.text, 50) : 'Viết thư ngắn';
119
- }
120
- // CHOOSE_THE_CORRECT_ANSWER
121
- if (content.options && Array.isArray(content.options)) {
122
- return content.questionText || content.question || 'Câu hỏi trắc nghiệm';
123
- }
124
- // FILL_IN_BLANK
125
- if (content.blanks) {
126
- const firstBlank = content.blanks[0];
127
- return firstBlank?.text || content.sentence || 'Điền vào chỗ trống';
128
- }
129
- // Fallback: try common field names
130
- if (content.instruction)
131
- return content.instruction;
132
- if (content.mainTitle)
133
- return content.mainTitle;
134
- if (content.title)
135
- return content.title;
136
- if (content.text)
137
- return content.text;
138
- }
139
- return type || 'Câu hỏi';
140
- };
141
- // Get difficulty badge color
142
- const getDifficultyBadgeClass = (difficulty) => {
143
- switch (difficulty?.toUpperCase()) {
144
- case 'EASY':
145
- return 'bg-green-100 text-green-700 border-green-200';
146
- case 'HARD':
147
- return 'bg-red-100 text-red-700 border-red-200';
148
- default:
149
- return 'bg-yellow-100 text-yellow-700 border-yellow-200';
150
- }
151
- };
152
- // Get difficulty display name
153
- const getDifficultyName = (difficulty) => {
154
- switch (difficulty?.toUpperCase()) {
155
- case 'EASY':
156
- return 'Dễ';
157
- case 'HARD':
158
- return 'Khó';
159
- case 'MEDIUM':
160
- return 'TB';
161
- default:
162
- return 'TB';
163
- }
164
- };
165
- // Get subquestion count if applicable
166
- const getSubQuestionCount = (question) => {
167
- const content = question.content;
168
- if (!content)
169
- return null;
170
- if (content.subQuestions && Array.isArray(content.subQuestions)) {
171
- return content.subQuestions.length;
172
- }
173
- return null;
174
- };
175
- export function QuestionSearchDropdown({ questionType, onSelect, selectedQuestionLabel, placeholder = 'Tìm câu hỏi từ ngân hàng', disabled = false, buttonClassName, compact = false, searchQuestions, }) {
176
- const [open, setOpen] = useState(false);
177
- const [searchTerm, setSearchTerm] = useState('');
178
- const [debouncedTerm, setDebouncedTerm] = useState('');
179
- useEffect(() => {
180
- const handler = setTimeout(() => {
181
- setDebouncedTerm(searchTerm.trim());
182
- }, 300);
183
- return () => clearTimeout(handler);
184
- }, [searchTerm]);
185
- // Transform QuestionBankItem to Question format with extended info
186
- const transformToQuestion = (item) => ({
187
- id: item.id,
188
- type: item.questionType,
189
- content: item.content,
190
- answer: item.correctAnswer,
191
- points: parseFloat(String(item.points ?? 1)) || 1,
192
- difficulty: item.difficulty?.toUpperCase(),
193
- skill: (item.skill || undefined),
194
- explanation: item.explanation || undefined,
195
- level: 'A1', // Default value
196
- createdAt: item.createdAt,
197
- updatedAt: item.updatedAt,
198
- // Extended info from question bank
199
- code: item.code,
200
- title: item.title || undefined,
201
- usageCount: item.usageCount,
202
- });
203
- // Host app may provide dynamic search directly via component props.
204
- const { data: questionBankData, isFetching } = useQuery({
205
- queryKey: ['questionBanks', 'search', questionType, debouncedTerm],
206
- queryFn: async () => {
207
- if (!searchQuestions)
208
- return { data: [], meta: { totalItems: 0 } };
209
- return searchQuestions({
210
- questionType,
211
- keyword: debouncedTerm || undefined,
212
- page: 1,
213
- size: 10,
214
- });
215
- },
216
- enabled: open && Boolean(questionType) && Boolean(searchQuestions) && (debouncedTerm.length > 0 || !!questionType),
217
- staleTime: 60 * 1000,
218
- refetchOnWindowFocus: false,
219
- });
220
- // Transform API response to Question array
221
- const questions = useMemo(() => {
222
- if (!questionBankData?.data)
223
- return [];
224
- return questionBankData.data.map(transformToQuestion);
225
- }, [questionBankData]);
226
- const totalItems = questionBankData?.meta?.totalItems || 0;
227
- const hasNoResults = !isFetching && questions.length === 0 && debouncedTerm.length > 0;
228
- // Show empty bank message when: API returned (questionBankData exists), no questions, and no search term
229
- const hasEmptyBank = !isFetching && questionBankData && questions.length === 0 && debouncedTerm.length === 0;
230
- // Only show initial tips when: not fetching, no API response yet (first open before any query)
231
- const showInitialMessage = !isFetching && !questionBankData && questions.length === 0 && debouncedTerm.length === 0;
232
- const buttonLabel = useMemo(() => {
233
- if (selectedQuestionLabel) {
234
- return truncate(selectedQuestionLabel, 40);
235
- }
236
- return placeholder;
237
- }, [placeholder, selectedQuestionLabel]);
238
- const handleSelect = (question) => {
239
- onSelect(question);
240
- setOpen(false);
241
- setSearchTerm('');
242
- setDebouncedTerm('');
243
- };
244
- return (_jsxs(DropdownMenu, { open: open, onOpenChange: (value) => setOpen(!disabled && value), children: [_jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: compact ? (_jsxs("button", { type: "button", className: cn('group inline-flex h-8 items-center gap-1.5 rounded-md border px-3 text-sm font-medium transition-all', selectedQuestionLabel
245
- ? 'border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100'
246
- : 'border-indigo-200 text-indigo-600 hover:bg-indigo-50 hover:text-indigo-700', 'focus:outline-none focus:ring-2 focus:ring-indigo-200 focus:ring-offset-1', disabled && 'cursor-not-allowed opacity-50', buttonClassName), children: [selectedQuestionLabel ? (_jsx(CheckCircle2, { className: "h-4 w-4" })) : (_jsx(Library, { className: "h-4 w-4" })), selectedQuestionLabel ? 'Đã chọn' : 'Ngân hàng'] })) : (_jsxs("button", { type: "button", className: cn('group relative flex w-full items-center gap-3 rounded-xl border bg-white p-3 text-left shadow-sm transition-all', selectedQuestionLabel
247
- ? 'border-emerald-200 bg-gradient-to-r from-emerald-50/50 to-teal-50/50'
248
- : 'border-gray-200 hover:border-indigo-200 hover:bg-gradient-to-r hover:from-indigo-50/30 hover:to-purple-50/30', 'focus:outline-none focus:ring-2 focus:ring-indigo-200 focus:ring-offset-1', disabled && 'cursor-not-allowed opacity-50', buttonClassName), children: [_jsx("div", { className: cn('flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg transition-all', selectedQuestionLabel
249
- ? 'bg-gradient-to-br from-emerald-500 to-teal-600 shadow-sm'
250
- : 'bg-gradient-to-br from-indigo-100 to-purple-100 group-hover:from-indigo-500 group-hover:to-purple-600 group-hover:shadow-sm'), children: selectedQuestionLabel ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-white" })) : (_jsx(Library, { className: cn('h-5 w-5 transition-colors', 'text-indigo-500 group-hover:text-white') })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: cn('text-xs font-medium uppercase tracking-wide', selectedQuestionLabel ? 'text-emerald-600' : 'text-indigo-500'), children: selectedQuestionLabel ? '✓ Đã chọn từ ngân hàng' : 'Ngân hàng câu hỏi' }) }), _jsx("p", { className: cn('mt-0.5 truncate text-sm', selectedQuestionLabel ? 'font-medium text-gray-800' : 'text-gray-500'), children: selectedQuestionLabel
251
- ? truncate(selectedQuestionLabel, 55)
252
- : 'Nhấn để tìm và sử dụng câu hỏi có sẵn' })] }), _jsx("div", { className: cn('flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-all', selectedQuestionLabel
253
- ? 'bg-emerald-100 text-emerald-600'
254
- : 'bg-gray-100 text-gray-400 group-hover:bg-indigo-100 group-hover:text-indigo-600'), children: _jsx(Search, { className: "h-4 w-4" }) })] })) }), _jsxs(DropdownMenuContent, { className: "w-[520px] p-0", align: compact ? "end" : "start", children: [_jsx("div", { className: "border-b border-gray-100 bg-gradient-to-r from-indigo-50 to-purple-50 px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 shadow-sm", children: _jsx(Library, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-800", children: "Ng\u00E2n h\u00E0ng c\u00E2u h\u1ECFi" }), _jsx("p", { className: "text-xs text-gray-500", children: "Ch\u1ECDn c\u00E2u h\u1ECFi c\u00F3 s\u1EB5n \u0111\u1EC3 \u0111i\u1EC1n nhanh v\u00E0o form" })] })] }) }), _jsxs("div", { className: "border-b border-gray-100 bg-gray-50/50 p-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx(Input, { placeholder: "T\u00ECm theo m\u00E3, ti\u00EAu \u0111\u1EC1 ho\u1EB7c n\u1ED9i dung...", value: searchTerm, onChange: (event) => setSearchTerm(event.target.value), autoFocus: true, className: "border-gray-200 bg-white pl-10 pr-10 transition-all focus:border-indigo-300 focus:ring-indigo-200" }), isFetching && (_jsx(Loader2, { className: "absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin text-indigo-500" }))] }), _jsxs("div", { className: "mt-2 flex items-center justify-between", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx(Badge, { variant: "outline", className: "border-indigo-200 bg-indigo-50 text-indigo-700", children: getQuestionTypeName(questionType) }) }), totalItems > 0 && (_jsxs("span", { className: "text-xs text-gray-500", children: ["Hi\u1EC3n th\u1ECB ", questions.length, "/", totalItems, " k\u1EBFt qu\u1EA3"] }))] })] }), _jsx(ScrollArea, { className: "h-80", children: showInitialMessage ? (_jsxs("div", { className: "flex flex-col items-center justify-center p-8 text-center", children: [_jsx("div", { className: "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-purple-100", children: _jsx(Sparkles, { className: "h-8 w-8 text-indigo-500" }) }), _jsx("p", { className: "text-sm font-medium text-gray-700", children: "T\u00ECm c\u00E2u h\u1ECFi t\u1EEB ng\u00E2n h\u00E0ng" }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "Nh\u1EADp m\u00E3 c\u00E2u h\u1ECFi, ti\u00EAu \u0111\u1EC1 ho\u1EB7c t\u1EEB kh\u00F3a \u0111\u1EC3 t\u00ECm ki\u1EBFm" }), _jsx("div", { className: "mt-4 rounded-lg border border-blue-200 bg-blue-50 p-3", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Lightbulb, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-blue-500" }), _jsxs("div", { className: "text-left text-xs text-blue-700", children: [_jsx("p", { className: "font-medium", children: "M\u1EB9o t\u00ECm ki\u1EBFm nhanh:" }), _jsxs("ul", { className: "mt-1 list-inside list-disc space-y-0.5 text-blue-600", children: [_jsx("li", { children: "Nh\u1EADp m\u00E3 c\u00E2u h\u1ECFi (VD: M001)" }), _jsx("li", { children: "Nh\u1EADp ti\u00EAu \u0111\u1EC1 ho\u1EB7c m\u1ED9t ph\u1EA7n n\u1ED9i dung" }), _jsx("li", { children: "K\u1EBFt qu\u1EA3 s\u1EBD t\u1EF1 \u0111\u1ED9ng c\u1EADp nh\u1EADt" })] })] })] }) })] })) : hasEmptyBank ? (_jsxs("div", { className: "flex flex-col items-center justify-center p-8 text-center", children: [_jsx("div", { className: "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-amber-100", children: _jsx(Library, { className: "h-8 w-8 text-amber-500" }) }), _jsx("p", { className: "text-sm font-medium text-gray-700", children: "Ch\u01B0a c\u00F3 c\u00E2u h\u1ECFi trong ng\u00E2n h\u00E0ng" }), _jsxs("p", { className: "mt-1 text-xs text-gray-500", children: ["Ng\u00E2n h\u00E0ng c\u00E2u h\u1ECFi ch\u01B0a c\u00F3 d\u1EEF li\u1EC7u cho lo\u1EA1i: ", _jsx("strong", { children: getQuestionTypeName(questionType) })] }), _jsx("p", { className: "mt-2 text-xs text-gray-400", children: "H\u00E3y th\u00EAm c\u00E2u h\u1ECFi v\u00E0o ng\u00E2n h\u00E0ng ho\u1EB7c t\u1EA1o c\u00E2u h\u1ECFi m\u1EDBi" })] })) : hasNoResults ? (_jsxs("div", { className: "flex flex-col items-center justify-center p-8 text-center", children: [_jsx("div", { className: "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100", children: _jsx(Search, { className: "h-8 w-8 text-gray-400" }) }), _jsx("p", { className: "text-sm font-medium text-gray-700", children: "Kh\u00F4ng t\u00ECm th\u1EA5y k\u1EBFt qu\u1EA3" }), _jsxs("p", { className: "mt-1 text-xs text-gray-500", children: ["Th\u1EED t\u00ECm v\u1EDBi t\u1EEB kh\u00F3a kh\u00E1c: \"", debouncedTerm, "\""] })] })) : (_jsx("div", { className: "divide-y divide-gray-100 p-2", children: questions.map((question) => {
255
- const subQuestionCount = getSubQuestionCount(question);
256
- return (_jsxs(DropdownMenuItem, { className: "flex cursor-pointer flex-col items-start gap-2 rounded-xl p-3 transition-all hover:bg-gradient-to-r hover:from-indigo-50 hover:to-purple-50 focus:bg-gradient-to-r focus:from-indigo-50 focus:to-purple-50", onSelect: () => handleSelect(question), children: [_jsxs("div", { className: "flex w-full items-start justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [question.code && (_jsxs("div", { className: "flex items-center gap-1 rounded-md bg-gradient-to-r from-indigo-500 to-purple-500 px-2 py-0.5 text-xs font-bold text-white shadow-sm", children: [_jsx(Hash, { className: "h-3 w-3" }), question.code] })), _jsx("div", { className: "flex-shrink-0", children: getQuestionTypeIcon(question.type) })] }), question.usageCount !== undefined && question.usageCount > 0 && (_jsxs("div", { className: "flex items-center gap-1 text-xs text-gray-500", title: "S\u1ED1 l\u1EA7n s\u1EED d\u1EE5ng", children: [_jsx(BarChart3, { className: "h-3 w-3" }), question.usageCount] }))] }), question.title && (_jsx("p", { className: "text-sm font-semibold text-gray-800", children: truncate(question.title, 60) })), _jsx("p", { className: "text-xs text-gray-600", children: truncate(getQuestionDisplayText(question), 80) }), _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx(Badge, { variant: "outline", className: cn('px-2 py-0.5 text-[10px] font-semibold', getDifficultyBadgeClass(question.difficulty)), children: getDifficultyName(question.difficulty) }), _jsxs(Badge, { variant: "outline", className: "border-blue-200 bg-blue-50 px-2 py-0.5 text-[10px] font-semibold text-blue-700", children: [question.points || 1, " \u0111i\u1EC3m"] }), question.skill && (_jsx(Badge, { variant: "outline", className: "border-gray-200 bg-gray-50 px-2 py-0.5 text-[10px] font-semibold text-gray-600", children: question.skill.toLowerCase() })), subQuestionCount && subQuestionCount > 1 && (_jsxs(Badge, { variant: "outline", className: "border-purple-200 bg-purple-50 px-2 py-0.5 text-[10px] font-semibold text-purple-700", children: [subQuestionCount, " c\u00E2u con"] }))] })] }, question.id));
257
- }) })) }), _jsx("div", { className: "border-t border-gray-100 bg-gray-50/50 px-4 py-2", children: _jsx("p", { className: "text-center text-xs text-gray-500", children: "Click \u0111\u1EC3 ch\u1ECDn c\u00E2u h\u1ECFi v\u00E0 t\u1EF1 \u0111\u1ED9ng \u0111i\u1EC1n v\u00E0o form" }) })] })] }));
258
- }
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useEffect as n,useMemo as r,useState as i}from"react";import{DropdownMenu as s,DropdownMenuContent as a,DropdownMenuItem as o,DropdownMenuTrigger as l}from"../../../components/ui/dropdown-menu";import{Input as c}from"../../../components/ui/input";import{Badge as d}from"../../../components/ui/badge";import{Loader2 as m,Search as u,Image as h,FileText as g,Grid3X3 as p,BookOpen as x,Library as f,Sparkles as N,Hash as b,BarChart3 as y,Lightbulb as v,CheckCircle2 as _}from"lucide-react";import{useQuery as w}from"@tanstack/react-query";import{ScrollArea as C}from"../../../components/ui/scroll-area";import{cn as E}from"../../../shared/lib/utils";const A=(e,t)=>{if(!e)return"";const n="string"==typeof e?e:String(e);return n.length<=t?n:`${n.substring(0,t)}...`},T=["LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER","LOOK_PICTURE_CHOOSE_CORRECT_ANSWER","LOOK_PICTURE_FILL_WORD_HINT","FILL_IN_BLANK","LABEL_THE_PICTURE","READ_AND_COLOR_OBJECTS","IMAGE_OBJECT_MATCHING","FILL_IN_BLANK"],O=["READ_PASSAGE_AND_ANSWER_QUESTIONS","READ_PASSAGE_AND_COMPLETE_STORY"],R=["FILL_MISSING_WORDS_IN_GRID"],I=e=>e?{LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:"Nhìn tranh điền chỗ trống",LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:"Nhìn tranh chọn đáp án",LOOK_PICTURE_FILL_WORD_HINT:"Nhìn tranh điền từ gợi ý",FILL_MISSING_WORDS_IN_GRID:"Điền chữ trong bảng",CHOOSE_THE_CORRECT_ANSWER:"Chọn đáp án đúng",LABEL_THE_PICTURE:"Gắn nhãn hình ảnh",READ_AND_COLOR_OBJECTS:"Đọc và tô màu",IMAGE_OBJECT_MATCHING:"Ghép hình ảnh - Đối tượng",WRITE_CORRECT_VERB_FORM:"Viết dạng động từ",FILL_IN_BLANK:"Điền vào chỗ trống",READ_PASSAGE_AND_ANSWER_QUESTIONS:"Đọc hiểu"}[e]||e.replace(/_/g," ").toLowerCase():"Chưa xác định";export const getQuestionDisplayText=e=>getContentDisplayText(e.content,e.type);export const getContentDisplayText=(e,t)=>{if(!e)return t||"Câu hỏi";if("string"==typeof e)return e;if("object"==typeof e){if(e.subQuestions&&Array.isArray(e.subQuestions)){const t=e.subQuestions[0];if(t?.question)return t.question}if(e.question)return e.question;if(e.word)return`Điền chữ: ${e.word}`;if(e.passage)return e.passageTitle||A(e.passage,60);if(e.grid&&e.rows&&e.columns)return`Lưới ${e.rows}x${e.columns}`;if(e.wordBank){return`Từ vựng: ${e.wordBank.map(e=>e.text||e).slice(0,3).join(", ")}${e.wordBank.length>3?"...":""}`}if(e.colorNodes||e.regionNodes){return`${e.regionNodes?.length||0} vùng tô màu`}if(e.contexts){const t=e.contexts[0];return t?.text?A(t.text,50):"Viết thư ngắn"}if(e.options&&Array.isArray(e.options))return e.questionText||e.question||"Câu hỏi trắc nghiệm";if(e.blanks){const t=e.blanks[0];return t?.text||e.sentence||"Điền vào chỗ trống"}if(e.instruction)return e.instruction;if(e.mainTitle)return e.mainTitle;if(e.title)return e.title;if(e.text)return e.text}return t||"Câu hỏi"};const L=e=>{switch(e?.toUpperCase()){case"EASY":return"bg-green-100 text-green-700 border-green-200";case"HARD":return"bg-red-100 text-red-700 border-red-200";default:return"bg-yellow-100 text-yellow-700 border-yellow-200"}},S=e=>{switch(e?.toUpperCase()){case"EASY":return"Dễ";case"HARD":return"Khó";default:return"TB"}};export function QuestionSearchDropdown({questionType:k,onSelect:D,selectedQuestionLabel:B,placeholder:j="Tìm câu hỏi từ ngân hàng",disabled:q=!1,buttonClassName:H,compact:F=!1,searchQuestions:K}){const[G,Q]=i(!1),[U,W]=i(""),[P,M]=i("");n(()=>{const e=setTimeout(()=>{M(U.trim())},300);return()=>clearTimeout(e)},[U]);const $=e=>({id:e.id,type:e.questionType,content:e.content,answer:e.correctAnswer,points:parseFloat(String(e.points??1))||1,difficulty:e.difficulty?.toUpperCase(),skill:e.skill||void 0,explanation:e.explanation||void 0,level:"A1",createdAt:e.createdAt,updatedAt:e.updatedAt,code:e.code,title:e.title||void 0,usageCount:e.usageCount}),{data:J,isFetching:V}=w({queryKey:["questionBanks","search",k,P],queryFn:async()=>K?K({questionType:k,keyword:P||void 0,page:1,size:10}):{data:[],meta:{totalItems:0}},enabled:G&&Boolean(k)&&Boolean(K)&&(P.length>0||!!k),staleTime:6e4,refetchOnWindowFocus:!1}),Y=r(()=>J?.data?J.data.map($):[],[J]),z=J?.meta?.totalItems||0,X=!V&&0===Y.length&&P.length>0,Z=!V&&J&&0===Y.length&&0===P.length,ee=!V&&!J&&0===Y.length&&0===P.length;r(()=>B?A(B,40):j,[j,B]);return t(s,{open:G,onOpenChange:e=>Q(!q&&e),children:[e(l,{asChild:!0,disabled:q,children:t("button",F?{type:"button",className:E("group inline-flex h-8 items-center gap-1.5 rounded-md border px-3 text-sm font-medium transition-all",B?"border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100":"border-indigo-200 text-indigo-600 hover:bg-indigo-50 hover:text-indigo-700","focus:outline-none focus:ring-2 focus:ring-indigo-200 focus:ring-offset-1",q&&"cursor-not-allowed opacity-50",H),children:[e(B?_:f,{className:"h-4 w-4"}),B?"Đã chọn":"Ngân hàng"]}:{type:"button",className:E("group relative flex w-full items-center gap-3 rounded-xl border bg-white p-3 text-left shadow-sm transition-all",B?"border-emerald-200 bg-gradient-to-r from-emerald-50/50 to-teal-50/50":"border-gray-200 hover:border-indigo-200 hover:bg-gradient-to-r hover:from-indigo-50/30 hover:to-purple-50/30","focus:outline-none focus:ring-2 focus:ring-indigo-200 focus:ring-offset-1",q&&"cursor-not-allowed opacity-50",H),children:[e("div",{className:E("flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg transition-all",B?"bg-gradient-to-br from-emerald-500 to-teal-600 shadow-sm":"bg-gradient-to-br from-indigo-100 to-purple-100 group-hover:from-indigo-500 group-hover:to-purple-600 group-hover:shadow-sm"),children:B?e(_,{className:"h-5 w-5 text-white"}):e(f,{className:E("h-5 w-5 transition-colors","text-indigo-500 group-hover:text-white")})}),t("div",{className:"min-w-0 flex-1",children:[e("div",{className:"flex items-center gap-2",children:e("span",{className:E("text-xs font-medium uppercase tracking-wide",B?"text-emerald-600":"text-indigo-500"),children:B?"✓ Đã chọn từ ngân hàng":"Ngân hàng câu hỏi"})}),e("p",{className:E("mt-0.5 truncate text-sm",B?"font-medium text-gray-800":"text-gray-500"),children:B?A(B,55):"Nhấn để tìm và sử dụng câu hỏi có sẵn"})]}),e("div",{className:E("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-all",B?"bg-emerald-100 text-emerald-600":"bg-gray-100 text-gray-400 group-hover:bg-indigo-100 group-hover:text-indigo-600"),children:e(u,{className:"h-4 w-4"})})]})}),t(a,{className:"w-[520px] p-0",align:F?"end":"start",children:[e("div",{className:"border-b border-gray-100 bg-gradient-to-r from-indigo-50 to-purple-50 px-4 py-3",children:t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 shadow-sm",children:e(f,{className:"h-4 w-4 text-white"})}),t("div",{className:"flex-1",children:[e("h3",{className:"text-sm font-semibold text-gray-800",children:"Ngân hàng câu hỏi"}),e("p",{className:"text-xs text-gray-500",children:"Chọn câu hỏi có sẵn để điền nhanh vào form"})]})]})}),t("div",{className:"border-b border-gray-100 bg-gray-50/50 p-3",children:[t("div",{className:"relative",children:[e(u,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),e(c,{placeholder:"Tìm theo mã, tiêu đề hoặc nội dung...",value:U,onChange:e=>W(e.target.value),autoFocus:!0,className:"border-gray-200 bg-white pl-10 pr-10 transition-all focus:border-indigo-300 focus:ring-indigo-200"}),V&&e(m,{className:"absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin text-indigo-500"})]}),t("div",{className:"mt-2 flex items-center justify-between",children:[e("div",{className:"flex items-center gap-2",children:e(d,{variant:"outline",className:"border-indigo-200 bg-indigo-50 text-indigo-700",children:I(k)})}),z>0&&t("span",{className:"text-xs text-gray-500",children:["Hiển thị ",Y.length,"/",z," kết quả"]})]})]}),e(C,{className:"h-80",children:ee?t("div",{className:"flex flex-col items-center justify-center p-8 text-center",children:[e("div",{className:"mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-purple-100",children:e(N,{className:"h-8 w-8 text-indigo-500"})}),e("p",{className:"text-sm font-medium text-gray-700",children:"Tìm câu hỏi từ ngân hàng"}),e("p",{className:"mt-1 text-xs text-gray-500",children:"Nhập mã câu hỏi, tiêu đề hoặc từ khóa để tìm kiếm"}),e("div",{className:"mt-4 rounded-lg border border-blue-200 bg-blue-50 p-3",children:t("div",{className:"flex items-start gap-2",children:[e(v,{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-blue-500"}),t("div",{className:"text-left text-xs text-blue-700",children:[e("p",{className:"font-medium",children:"Mẹo tìm kiếm nhanh:"}),t("ul",{className:"mt-1 list-inside list-disc space-y-0.5 text-blue-600",children:[e("li",{children:"Nhập mã câu hỏi (VD: M001)"}),e("li",{children:"Nhập tiêu đề hoặc một phần nội dung"}),e("li",{children:"Kết quả sẽ tự động cập nhật"})]})]})]})})]}):Z?t("div",{className:"flex flex-col items-center justify-center p-8 text-center",children:[e("div",{className:"mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-amber-100",children:e(f,{className:"h-8 w-8 text-amber-500"})}),e("p",{className:"text-sm font-medium text-gray-700",children:"Chưa có câu hỏi trong ngân hàng"}),t("p",{className:"mt-1 text-xs text-gray-500",children:["Ngân hàng câu hỏi chưa có dữ liệu cho loại: ",e("strong",{children:I(k)})]}),e("p",{className:"mt-2 text-xs text-gray-400",children:"Hãy thêm câu hỏi vào ngân hàng hoặc tạo câu hỏi mới"})]}):X?t("div",{className:"flex flex-col items-center justify-center p-8 text-center",children:[e("div",{className:"mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100",children:e(u,{className:"h-8 w-8 text-gray-400"})}),e("p",{className:"text-sm font-medium text-gray-700",children:"Không tìm thấy kết quả"}),t("p",{className:"mt-1 text-xs text-gray-500",children:['Thử tìm với từ khóa khác: "',P,'"']})]}):e("div",{className:"divide-y divide-gray-100 p-2",children:Y.map(n=>{const r=(e=>{const t=e.content;return t&&t.subQuestions&&Array.isArray(t.subQuestions)?t.subQuestions.length:null})(n);return t(o,{className:"flex cursor-pointer flex-col items-start gap-2 rounded-xl p-3 transition-all hover:bg-gradient-to-r hover:from-indigo-50 hover:to-purple-50 focus:bg-gradient-to-r focus:from-indigo-50 focus:to-purple-50",onSelect:()=>(e=>{D(e),Q(!1),W(""),M("")})(n),children:[t("div",{className:"flex w-full items-start justify-between gap-2",children:[t("div",{className:"flex items-center gap-2",children:[n.code&&t("div",{className:"flex items-center gap-1 rounded-md bg-gradient-to-r from-indigo-500 to-purple-500 px-2 py-0.5 text-xs font-bold text-white shadow-sm",children:[e(b,{className:"h-3 w-3"}),n.code]}),e("div",{className:"flex-shrink-0",children:(i=n.type,T.includes(i)?e(h,{className:"h-4 w-4 text-blue-500"}):O.includes(i)?e(x,{className:"h-4 w-4 text-green-500"}):R.includes(i)?e(p,{className:"h-4 w-4 text-purple-500"}):e(g,{className:"h-4 w-4 text-gray-500"}))})]}),void 0!==n.usageCount&&n.usageCount>0&&t("div",{className:"flex items-center gap-1 text-xs text-gray-500",title:"Số lần sử dụng",children:[e(y,{className:"h-3 w-3"}),n.usageCount]})]}),n.title&&e("p",{className:"text-sm font-semibold text-gray-800",children:A(n.title,60)}),e("p",{className:"text-xs text-gray-600",children:A(getQuestionDisplayText(n),80)}),t("div",{className:"flex flex-wrap items-center gap-1.5",children:[e(d,{variant:"outline",className:E("px-2 py-0.5 text-[10px] font-semibold",L(n.difficulty)),children:S(n.difficulty)}),t(d,{variant:"outline",className:"border-blue-200 bg-blue-50 px-2 py-0.5 text-[10px] font-semibold text-blue-700",children:[n.points||1," điểm"]}),n.skill&&e(d,{variant:"outline",className:"border-gray-200 bg-gray-50 px-2 py-0.5 text-[10px] font-semibold text-gray-600",children:n.skill.toLowerCase()}),r&&r>1&&t(d,{variant:"outline",className:"border-purple-200 bg-purple-50 px-2 py-0.5 text-[10px] font-semibold text-purple-700",children:[r," câu con"]})]})]},n.id);var i})})}),e("div",{className:"border-t border-gray-100 bg-gray-50/50 px-4 py-2",children:e("p",{className:"text-center text-xs text-gray-500",children:"Click để chọn câu hỏi và tự động điền vào form"})})]})]})}