@tinyweb_dev/oe-exam-sdk 1.0.5 → 1.0.7

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 (225) hide show
  1. package/dist/components/exams/ExamCreator.js +1 -16
  2. package/dist/components/exams/take/ExamTakingPageContainer.js +0 -12
  3. package/dist/components/exams/take/components/QuestionRenderer.js +2 -15
  4. package/dist/components/exams/take/components/question-renderers/index.d.ts +0 -3
  5. package/dist/components/exams/take/components/question-renderers/index.js +0 -3
  6. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.js +0 -4
  7. package/dist/components/exams/take/types/speaking.types.d.ts +0 -31
  8. package/dist/components/exams/take/types.d.ts +0 -65
  9. package/dist/components/exams/take/utils/answer-transformers.js +6 -60
  10. package/dist/components/exams/take/utils/question-transformers.d.ts +2 -15
  11. package/dist/components/exams/take/utils/question-transformers.js +0 -143
  12. package/dist/components/questions/_shared/components/compact/CompactCreatorHeader.d.ts +23 -0
  13. package/dist/components/questions/_shared/components/compact/CompactCreatorHeader.js +9 -0
  14. package/dist/components/questions/_shared/components/compact/CompactExampleToggle.d.ts +6 -0
  15. package/dist/components/questions/_shared/components/compact/CompactExampleToggle.js +8 -0
  16. package/dist/components/questions/_shared/components/compact/CompactExplanationToggle.d.ts +7 -0
  17. package/dist/components/questions/_shared/components/compact/CompactExplanationToggle.js +14 -0
  18. package/dist/components/questions/_shared/components/compact/CompactFieldCard.d.ts +9 -0
  19. package/dist/components/questions/_shared/components/compact/CompactFieldCard.js +7 -0
  20. package/dist/components/questions/_shared/components/compact/CompactPreviewBanner.d.ts +7 -0
  21. package/dist/components/questions/_shared/components/compact/CompactPreviewBanner.js +7 -0
  22. package/dist/components/questions/_shared/components/compact/CompactPreviewButton.d.ts +6 -0
  23. package/dist/components/questions/_shared/components/compact/CompactPreviewButton.js +7 -0
  24. package/dist/components/questions/_shared/components/compact/index.d.ts +6 -0
  25. package/dist/components/questions/_shared/components/compact/index.js +6 -0
  26. package/dist/components/questions/_shared/config/question-types.config.js +0 -24
  27. package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +0 -9
  28. package/dist/components/questions/_shared/types/index.d.ts +0 -1
  29. package/dist/components/questions/_shared/types/index.js +0 -1
  30. package/dist/components/questions/_shared/types/look-and-choose-answer.type.d.ts +0 -13
  31. package/dist/components/questions/_shared/utils/answer-builder.js +0 -11
  32. package/dist/components/questions/components/ColorRegionCreator.js +66 -63
  33. package/dist/components/questions/components/QuestionSearchDropdown.js +0 -8
  34. package/dist/components/questions/components/QuestionTypeSelector.js +0 -2
  35. package/dist/components/questions/components/index.d.ts +1 -0
  36. package/dist/components/questions/components/index.js +1 -0
  37. package/dist/components/questions/creator/question-type-registry.js +0 -8
  38. package/dist/components/questions/groups/ArticlesGroupCard.js +2 -2
  39. package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -1
  40. package/dist/components/questions/groups/DocumentGroupCard.js +1 -1
  41. package/dist/components/questions/groups/ImageLabelGroupCard.js +1 -1
  42. package/dist/components/questions/groups/MatchAnswerGroupCard.js +2 -2
  43. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -3
  44. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +1 -10
  45. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -2
  46. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -41
  47. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +2 -2
  48. package/dist/components/questions/question-bank/editor-adapters/index.js +2 -2
  49. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -1
  50. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -28
  51. package/dist/components/questions/question-bank/question-bank-picker.utils.js +0 -7
  52. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +16 -16
  53. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +36 -30
  54. package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.js +1 -1
  55. package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupCreator.js +7 -6
  56. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +2 -2
  57. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +11 -7
  58. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -1
  59. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +11 -5
  60. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +5 -5
  61. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +34 -28
  62. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseAnswerGroupImageUpload.js +2 -2
  63. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +1 -1
  64. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +44 -28
  65. package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupClient.js +7 -7
  66. package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupCreator.js +8 -5
  67. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +2 -2
  68. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +20 -16
  69. package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleClient.js +1 -1
  70. package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleCreator.js +66 -29
  71. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +5 -5
  72. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +45 -37
  73. package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.js +24 -20
  74. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +2 -2
  75. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +68 -65
  76. package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixClient.js +1 -1
  77. package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixCreator.js +45 -5
  78. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +2 -2
  79. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +18 -14
  80. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +2 -2
  81. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +30 -30
  82. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +2 -2
  83. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +24 -31
  84. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +2 -2
  85. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +29 -32
  86. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -1
  87. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +27 -29
  88. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -1
  89. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +11 -15
  90. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -1
  91. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +22 -24
  92. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -1
  93. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +17 -24
  94. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -1
  95. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +31 -31
  96. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -1
  97. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +11 -15
  98. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -1
  99. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +14 -15
  100. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +2 -2
  101. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +27 -25
  102. package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesClient.js +12 -12
  103. package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesCreator.js +8 -5
  104. package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureClient.js +8 -8
  105. package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureCreator.js +25 -20
  106. package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupClient.js +1 -1
  107. package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupCreator.js +13 -10
  108. package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupCreator.js +8 -5
  109. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +7 -11
  110. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -1
  111. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +15 -12
  112. package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesClient.js +1 -1
  113. package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesCreator.js +5 -5
  114. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +35 -39
  115. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +2 -2
  116. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardClient.js +1 -1
  117. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +7 -8
  118. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -1
  119. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +30 -23
  120. package/dist/components/questions/types/spontaneous-qa/SpontaneousQAClient.js +1 -1
  121. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +26 -19
  122. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +1 -1
  123. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +13 -11
  124. package/dist/components/questions/types/true-false/TrueFalseClient.js +2 -2
  125. package/dist/components/questions/types/true-false/TrueFalseCreator.js +35 -29
  126. package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupClient.js +1 -1
  127. package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupCreator.js +11 -7
  128. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -1
  129. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +11 -7
  130. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +2 -2
  131. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +21 -56
  132. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
  133. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +30 -24
  134. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +3 -3
  135. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +12 -14
  136. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -1
  137. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +27 -18
  138. package/dist/components/questions/types/word-ordering-group/WordOrderingGroupClient.js +7 -7
  139. package/dist/components/questions/types/word-ordering-group/WordOrderingGroupCreator.js +16 -13
  140. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +2 -2
  141. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +34 -28
  142. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +2 -2
  143. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +22 -22
  144. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +21 -18
  145. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -1
  146. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +7 -4
  147. package/dist/components/questions/viewer/QuestionViewer.js +0 -98
  148. package/dist/components/results/renderers/review-question-body-movers.js +2 -26
  149. package/dist/components/results/review-data.js +0 -4
  150. package/dist/components/ui/points-input.d.ts +1 -0
  151. package/dist/components/ui/points-input.js +12 -2
  152. package/dist/shared/constants/question-skills.js +0 -11
  153. package/dist/shared/lib/i18n/messages/en/admin.d.ts +0 -3
  154. package/dist/shared/lib/i18n/messages/en/admin.js +0 -3
  155. package/dist/shared/lib/i18n/messages/en.d.ts +0 -3
  156. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +0 -3
  157. package/dist/shared/lib/i18n/messages/vi/admin.js +0 -3
  158. package/dist/shared/lib/i18n/messages/vi.d.ts +0 -3
  159. package/dist/shared/lib/utils/question-reverse-transform.js +0 -19
  160. package/dist/shared/lib/utils/question-transform-types.d.ts +1 -23
  161. package/dist/shared/lib/utils/question-transform-validation.js +0 -40
  162. package/dist/shared/lib/utils/question-transform.js +0 -9
  163. package/dist/shared/types/common.types.d.ts +1 -1
  164. package/dist/shared/types/entities/question.types.d.ts +1 -11
  165. package/dist/shared/types/questions/index.d.ts +0 -3
  166. package/dist/shared/types/questions/index.js +0 -6
  167. package/package.json +1 -1
  168. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.d.ts +0 -2
  169. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +0 -131
  170. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.d.ts +0 -2
  171. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +0 -76
  172. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.d.ts +0 -2
  173. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +0 -68
  174. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.d.ts +0 -16
  175. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +0 -212
  176. package/dist/components/questions/_shared/types/gn-speaking-interview.type.d.ts +0 -32
  177. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +0 -1
  178. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.d.ts +0 -47
  179. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +0 -1
  180. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.d.ts +0 -2
  181. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +0 -262
  182. package/dist/components/questions/types/gn-speaking-interview/register.d.ts +0 -2
  183. package/dist/components/questions/types/gn-speaking-interview/register.js +0 -121
  184. package/dist/components/questions/types/gn-speaking-interview/transform.d.ts +0 -2
  185. package/dist/components/questions/types/gn-speaking-interview/transform.js +0 -48
  186. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.d.ts +0 -20
  187. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +0 -72
  188. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.d.ts +0 -15
  189. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +0 -230
  190. package/dist/components/questions/types/look-picture-choose-correct-answer/index.d.ts +0 -1
  191. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +0 -1
  192. package/dist/components/questions/types/look-picture-choose-correct-answer/register.d.ts +0 -2
  193. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +0 -66
  194. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.d.ts +0 -2
  195. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +0 -42
  196. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.d.ts +0 -6
  197. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +0 -96
  198. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.d.ts +0 -15
  199. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +0 -238
  200. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.d.ts +0 -2
  201. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +0 -2
  202. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.d.ts +0 -2
  203. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +0 -76
  204. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.d.ts +0 -2
  205. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +0 -19
  206. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.d.ts +0 -7
  207. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +0 -134
  208. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.d.ts +0 -3
  209. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +0 -617
  210. package/dist/components/questions/types/look-picture-fill-word-hint/index.d.ts +0 -2
  211. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +0 -2
  212. package/dist/components/questions/types/look-picture-fill-word-hint/register.d.ts +0 -2
  213. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +0 -82
  214. package/dist/components/questions/types/look-picture-fill-word-hint/transform.d.ts +0 -2
  215. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +0 -29
  216. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.d.ts +0 -9
  217. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +0 -12
  218. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.d.ts +0 -17
  219. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +0 -47
  220. package/dist/shared/types/questions/look-picture-choose-correct-answer.d.ts +0 -38
  221. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +0 -5
  222. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.d.ts +0 -63
  223. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +0 -9
  224. package/dist/shared/types/questions/look-picture-fill-word-hint.d.ts +0 -57
  225. package/dist/shared/types/questions/look-picture-fill-word-hint.js +0 -7
@@ -1,22 +1,19 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useRef, useState } from 'react';
4
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
5
4
  import { Label } from '../../../../components/ui/label';
6
5
  import { Button } from '../../../../components/ui/button';
7
6
  import { Input } from '../../../../components/ui/input';
8
- import { Textarea } from '../../../../components/ui/textarea';
9
7
  import { Form, FormControl, FormField, FormItem, FormMessage } from '../../../../components/ui/form';
10
8
  import { FileUpload } from '../../../../components/ui/file-upload';
11
- import { PointsInput } from '../../../../components/ui/points-input';
9
+ import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
12
10
  // Stores & hooks
13
11
  import { useCompareImagesGroup } from '../../_shared/hooks/useCompareImagesGroup';
14
12
  import { useReactHookForm } from '../../../../shared/lib/hooks/useReactHookForm';
15
13
  import { useDebouncedCallback, usePresignedFileUrl } from '../../../../shared/lib/hooks';
16
14
  import { listenAndSpeakCompareImagesSchema } from '../../../../shared/lib/validation/listen-and-speak-compare-images.validation';
17
15
  // Icons
18
- import { Plus, Trash2, Mic, Volume2, ImageIcon, MessageSquareText, ListChecks, BookOpen, Eye, Pencil, Info } from 'lucide-react';
19
- import { CreatorGuide } from '../../components/CreatorGuide';
16
+ import { Plus, Trash2, Mic, Volume2, ImageIcon, MessageSquareText, ListChecks, Info } from 'lucide-react';
20
17
  import { ListenAndSpeakCompareImagesClient } from './ListenAndSpeakCompareImagesClient';
21
18
  // ─── Sub-component: Image preview with presigned URL ─────────────────────────
22
19
  function ImagePreview({ imageUrl, label }) {
@@ -281,15 +278,14 @@ export function ListenAndSpeakCompareImagesCreator({ questionIndex, initialData,
281
278
  candidateImageUrl: candidateImageUrl || '',
282
279
  examinerImageUrl: examinerImageUrl || '',
283
280
  };
284
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Nghe v\u00E0 n\u00F3i \u2014 So s\u00E1nh h\u00ECnh \u1EA3nh (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Preview mode" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) }) }), _jsx(ListenAndSpeakCompareImagesClient, { questionData: questionData, isReviewMode: true })] }));
281
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(ListenAndSpeakCompareImagesClient, { questionData: questionData, isReviewMode: true })] }));
285
282
  }
286
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(CreatorGuide, { colorScheme: "blue", steps: [
287
- { text: 'Upload 2 hình ảnh so sánh: Hình thí sinh (Candidate) và Hình giám khảo (Examiner) — dùng chung cho nhóm' },
288
- { text: 'Câu hỏi đầu tiên trong nhóm sẽ quản lý hình ảnh chung, các câu sau tham chiếu' },
289
- { text: 'Upload audio câu hỏi cho từng câu — giám khảo hỏi về sự khác biệt giữa 2 hình' },
290
- { text: 'Nhập các đáp án mong muốn mô tả sự khác biệt', highlight: true },
291
- { text: 'Thêm giải thích cho từng điểm khác biệt' },
292
- ], tips: ['Chọn hình có sự khác biệt rõ ràng nhưng không quá dễ phát hiện'] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-blue-100/50", children: [_jsx("div", { className: "h-1.5 bg-gradient-to-r from-blue-500 via-indigo-500 to-purple-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-blue-500 to-indigo-600 shadow-md", children: _jsx(ListChecks, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold text-gray-900", children: "Nh\u00F3m \u0111\u00E1p \u00E1n" }), _jsxs("div", { className: "mt-1.5 inline-flex items-center gap-1.5 rounded-full bg-blue-100 px-3 py-1 text-sm font-medium text-blue-700", children: [_jsx("span", { children: "\uD83D\uDDBC\uFE0F" }), _jsxs("span", { children: ["Nh\u00F3m ", displayGroupNumber] }), _jsx("span", { className: "text-xs font-normal opacity-75 ml-1", children: "(D\u00F9ng chung)" })] })] })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: !watchedAudioUrl || watchedExpectedAnswers.filter((a) => a.trim()).length === 0, className: "gap-2 border-blue-200 text-blue-600 hover:bg-blue-50 hover:text-blue-700", children: [_jsx(Eye, { className: "h-4 w-4" }), "Preview"] })] }) })] }), isFirstInGroup ? (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-amber-400 to-orange-400" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-100", children: _jsx(ImageIcon, { className: "h-3.5 w-3.5 text-amber-600" }) }), _jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "H\u00ECnh \u1EA3nh so s\u00E1nh" })] }) }), _jsx(CardContent, { className: "space-y-4", children: _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: ["\uD83D\uDCF7 Candidate's Copy Image ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FileUpload, { id: `candidate-img-group-${displayGroupNumber}`, label: "", accept: "image/*", value: candidateImageUrl || '', onChange: (url) => updateCandidateImage(url), maxSize: 5, placeholder: "Upload Candidate's Copy", autoUpload: true, prefix: "questions/compare-images" }), candidateImageUrl && (_jsx(ImagePreview, { imageUrl: candidateImageUrl, label: "Candidate's Copy" })), !candidateImageUrl && (_jsxs("div", { className: `flex flex-col items-center justify-center rounded-xl border-2 border-dashed ${groupImageErrors.candidate ? 'border-red-300 bg-red-50/50' : 'border-amber-200 bg-amber-50/50'} py-6 px-4 text-center`, children: [_jsx(ImageIcon, { className: `h-8 w-8 ${groupImageErrors.candidate ? 'text-red-400' : 'text-amber-400'} mb-2` }), _jsx("p", { className: "text-xs text-gray-500", children: "H\u00ECnh \u1EA3nh d\u00E0nh cho th\u00ED sinh" })] })), groupImageErrors.candidate && (_jsx("p", { className: "text-sm font-medium text-destructive", children: groupImageErrors.candidate }))] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: ["\uD83D\uDCF7 Examiner's Copy Image ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FileUpload, { id: `examiner-img-group-${displayGroupNumber}`, label: "", accept: "image/*", value: examinerImageUrl || '', onChange: (url) => updateExaminerImage(url), maxSize: 5, placeholder: "Upload Examiner's Copy", autoUpload: true, prefix: "questions/compare-images" }), examinerImageUrl && (_jsx(ImagePreview, { imageUrl: examinerImageUrl, label: "Examiner's Copy" })), !examinerImageUrl && (_jsxs("div", { className: `flex flex-col items-center justify-center rounded-xl border-2 border-dashed ${groupImageErrors.examiner ? 'border-red-300 bg-red-50/50' : 'border-orange-200 bg-orange-50/50'} py-6 px-4 text-center`, children: [_jsx(ImageIcon, { className: `h-8 w-8 ${groupImageErrors.examiner ? 'text-red-400' : 'text-orange-400'} mb-2` }), _jsx("p", { className: "text-xs text-gray-500", children: "H\u00ECnh \u1EA3nh d\u00E0nh cho gi\u00E1m kh\u1EA3o" })] })), groupImageErrors.examiner && (_jsx("p", { className: "text-sm font-medium text-destructive", children: groupImageErrors.examiner }))] })] }) })] })) : (
293
- /* Read-only view of shared images for non-first questions in group */
294
- _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow shadow-amber-100/30", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-amber-400 to-orange-400" }), _jsx(CardHeader, { className: "pb-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-100", children: _jsx(ImageIcon, { className: "h-3.5 w-3.5 text-amber-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "H\u00ECnh \u1EA3nh so s\u00E1nh" }), _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500", children: ["Nh\u00F3m ", displayGroupNumber, " \u2014 Ch\u1EC9 \u0111\u1ECDc"] })] }), _jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: "\u0110\u01B0\u1EE3c qu\u1EA3n l\u00FD b\u1EDFi c\u00E2u h\u1ECFi \u0111\u1EA7u ti\u00EAn trong nh\u00F3m" })] })] }) }), _jsx(CardContent, { className: "pt-0", children: candidateImageUrl || examinerImageUrl ? (_jsxs("div", { className: "space-y-4", children: [candidateImageUrl && (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "inline-block rounded-lg border-2 border-amber-400 bg-gradient-to-r from-gray-600 to-gray-700 px-8 py-2 text-sm font-bold uppercase tracking-widest text-white shadow-lg ring-1 ring-amber-300/50", children: "Candidate's Copy" }) }), _jsx(ImagePreview, { imageUrl: candidateImageUrl, label: "Candidate's Copy" })] })), examinerImageUrl && (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "inline-block rounded-lg border-2 border-orange-400 bg-gradient-to-r from-gray-600 to-gray-700 px-8 py-2 text-sm font-bold uppercase tracking-widest text-white shadow-lg ring-1 ring-orange-300/50", children: "Examiner's Copy" }) }), _jsx(ImagePreview, { imageUrl: examinerImageUrl, label: "Examiner's Copy" })] }))] })) : (_jsx("div", { className: "text-center py-4 text-sm text-gray-400 italic", children: "Ch\u01B0a c\u00F3 h\u00ECnh \u1EA3nh n\u00E0o trong nh\u00F3m" })) })] })), _jsxs(Form, { ...form, children: [_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-indigo-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-indigo-400 to-purple-400" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 shadow-sm", children: _jsx(Mic, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "C\u00E2u h\u1ECFi Nghe & So s\u00E1nh" }), _jsx("p", { className: "text-sm text-gray-500", children: "H\u1ECDc sinh nghe \u00E2m thanh v\u00E0 n\u00F3i \u0111i\u1EC3m kh\u00E1c bi\u1EC7t gi\u1EEFa hai h\u00ECnh \u1EA3nh" })] })] }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsx("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4", children: _jsxs("div", { className: "flex flex-col md:flex-row gap-6", children: [_jsx("div", { className: "flex-1", children: _jsx(PointsInput, { ...form.register('points', { valueAsNumber: true }), error: form.formState.errors?.points?.message }) }), _jsx("div", { className: "flex-1 flex flex-col justify-center pt-2" })] }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), "\u00C2m thanh c\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FormField, { control: control, name: "audioUrl", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormControl, { children: _jsx(FileUpload, { id: `audio-compare-${displayQuestionNumber}`, label: "", accept: "audio/*", value: field.value, onChange: (url) => { field.onChange(url); clearErrors('audioUrl'); }, maxSize: 10, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "listen-and-speak" }) }), _jsx(FormMessage, {})] })) })] })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-green-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-green-400 to-emerald-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", 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-green-500 to-emerald-600 shadow-sm", children: _jsx(MessageSquareText, { className: "h-4 w-4 text-white" }) }), _jsx("div", { children: _jsxs(CardTitle, { className: "text-lg font-semibold text-gray-800", children: ["\u0110\u00E1p \u00E1n mong mu\u1ED1n (", watchedExpectedAnswers.filter((a) => a.trim()).length, ")"] }) })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2.5", children: [_jsx(Info, { className: "h-4 w-4 text-blue-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "text-xs text-blue-700 space-y-1", children: [_jsx("p", { children: "Nh\u1EADp c\u00E1c c\u00E2u tr\u1EA3 l\u1EDDi mong mu\u1ED1n. C\u00F3 th\u1EC3 th\u00EAm nhi\u1EC1u \u0111\u00E1p \u00E1n n\u1EBFu c\u00F3 nhi\u1EC1u c\u00E1ch tr\u1EA3 l\u1EDDi \u0111\u00FAng." }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m th\u1EE7 c\u00F4ng:" }), " Gi\u00E1o vi\u00EAn d\u00F9ng c\u00E1c \u0111\u00E1p \u00E1n n\u00E0y l\u00E0m tham kh\u1EA3o \u0111\u1EC3 ch\u1EA5m \u0111i\u1EC3m."] }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng (AI):" }), " H\u1EC7 th\u1ED1ng d\u00F9ng AI so s\u00E1nh gi\u1ECDng n\u00F3i c\u1EE7a h\u1ECDc sinh v\u1EDBi c\u00E1c \u0111\u00E1p \u00E1n \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng ch\u1EA5m \u0111i\u1EC3m."] })] })] }), _jsxs("div", { className: "space-y-3", children: [watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 font-semibold shadow-sm text-sm", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { placeholder: `VD: ${index === 0 ? 'The tree is bigger in picture A' : 'The dog is brown in picture B'}`, value: answer || '', onChange: (e) => handleExpectedAnswerChange(index, e.target.value), className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "text-red-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))), form.formState.errors?.expectedAnswers && !Array.isArray(form.formState.errors.expectedAnswers) && (_jsx("p", { className: "text-sm text-red-500", children: form.formState.errors.expectedAnswers.message }))] })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-amber-400 to-orange-400" }), _jsx(CardHeader, { className: "pb-4", 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-amber-500 to-orange-500 shadow-sm", children: _jsx(BookOpen, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx("span", { className: "inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2.5 py-0.5 text-xs font-medium text-amber-600", children: "Kh\u00F4ng b\u1EAFt bu\u1ED9c" })] }), _jsx("p", { className: "text-sm text-gray-500 mt-0.5", children: "Gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng \u2014 hi\u1EC3n th\u1ECB sau khi h\u1ECDc sinh ho\u00E0n th\u00E0nh c\u00E2u h\u1ECFi" })] })] }) }), _jsx(CardContent, { children: _jsx(Textarea, { ...form.register('explanation'), placeholder: "VD: C\u00E2u tr\u1EA3 l\u1EDDi \u0111\u00FAng l\u00E0... v\u00EC...", className: "min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none", rows: 3 }) })] })] })] }));
283
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(ListChecks, { className: "h-3.5 w-3.5" }), title: "Nh\u00F3m \u0111\u00E1p \u00E1n", extraActions: _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600", children: ["Nh\u00F3m ", displayGroupNumber] }), points: {
284
+ value: watchedPoints,
285
+ onValueChange: (value) => form.setValue('points', value, { shouldValidate: true }),
286
+ error: form.formState.errors?.points?.message,
287
+ }, preview: {
288
+ onClick: () => setIsClientMode(true),
289
+ disabled: !watchedAudioUrl || watchedExpectedAnswers.filter((a) => a.trim()).length === 0,
290
+ } }), contentClassName: "hidden", children: null }), isFirstInGroup ? (_jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(ImageIcon, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("p", { className: "text-sm font-semibold text-gray-800", children: "H\u00ECnh \u1EA3nh so s\u00E1nh" })] }), children: _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: ["\uD83D\uDCF7 Candidate's Copy Image ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FileUpload, { id: `candidate-img-group-${displayGroupNumber}`, label: "", accept: "image/*", value: candidateImageUrl || '', onChange: (url) => updateCandidateImage(url), maxSize: 5, placeholder: "Upload Candidate's Copy", autoUpload: true, prefix: "questions/compare-images" }), candidateImageUrl && (_jsx(ImagePreview, { imageUrl: candidateImageUrl, label: "Candidate's Copy" })), !candidateImageUrl && (_jsxs("div", { className: `flex flex-col items-center justify-center rounded-xl border-2 border-dashed ${groupImageErrors.candidate ? 'border-red-300 bg-red-50/50' : 'border-amber-200 bg-amber-50/50'} py-6 px-4 text-center`, children: [_jsx(ImageIcon, { className: `h-8 w-8 ${groupImageErrors.candidate ? 'text-red-400' : 'text-amber-400'} mb-2` }), _jsx("p", { className: "text-xs text-gray-500", children: "H\u00ECnh \u1EA3nh d\u00E0nh cho th\u00ED sinh" })] })), groupImageErrors.candidate && (_jsx("p", { className: "text-sm font-medium text-destructive", children: groupImageErrors.candidate }))] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: ["\uD83D\uDCF7 Examiner's Copy Image ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FileUpload, { id: `examiner-img-group-${displayGroupNumber}`, label: "", accept: "image/*", value: examinerImageUrl || '', onChange: (url) => updateExaminerImage(url), maxSize: 5, placeholder: "Upload Examiner's Copy", autoUpload: true, prefix: "questions/compare-images" }), examinerImageUrl && (_jsx(ImagePreview, { imageUrl: examinerImageUrl, label: "Examiner's Copy" })), !examinerImageUrl && (_jsxs("div", { className: `flex flex-col items-center justify-center rounded-xl border-2 border-dashed ${groupImageErrors.examiner ? 'border-red-300 bg-red-50/50' : 'border-orange-200 bg-orange-50/50'} py-6 px-4 text-center`, children: [_jsx(ImageIcon, { className: `h-8 w-8 ${groupImageErrors.examiner ? 'text-red-400' : 'text-orange-400'} mb-2` }), _jsx("p", { className: "text-xs text-gray-500", children: "H\u00ECnh \u1EA3nh d\u00E0nh cho gi\u00E1m kh\u1EA3o" })] })), groupImageErrors.examiner && (_jsx("p", { className: "text-sm font-medium text-destructive", children: groupImageErrors.examiner }))] })] }) })) : (_jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(ImageIcon, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: "text-sm font-semibold text-gray-800", children: "H\u00ECnh \u1EA3nh so s\u00E1nh" }), _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500", children: ["Nh\u00F3m ", displayGroupNumber, " \u2014 Ch\u1EC9 \u0111\u1ECDc"] })] }), _jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: "\u0110\u01B0\u1EE3c qu\u1EA3n l\u00FD b\u1EDFi c\u00E2u h\u1ECFi \u0111\u1EA7u ti\u00EAn trong nh\u00F3m" })] })] }), children: candidateImageUrl || examinerImageUrl ? (_jsxs("div", { className: "space-y-4", children: [candidateImageUrl && (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "inline-block rounded-lg border-2 border-amber-400 bg-gradient-to-r from-gray-600 to-gray-700 px-8 py-2 text-sm font-bold uppercase tracking-widest text-white shadow-lg ring-1 ring-amber-300/50", children: "Candidate's Copy" }) }), _jsx(ImagePreview, { imageUrl: candidateImageUrl, label: "Candidate's Copy" })] })), examinerImageUrl && (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "inline-block rounded-lg border-2 border-orange-400 bg-gradient-to-r from-gray-600 to-gray-700 px-8 py-2 text-sm font-bold uppercase tracking-widest text-white shadow-lg ring-1 ring-orange-300/50", children: "Examiner's Copy" }) }), _jsx(ImagePreview, { imageUrl: examinerImageUrl, label: "Examiner's Copy" })] }))] })) : (_jsx("div", { className: "text-center py-4 text-sm text-gray-400 italic", children: "Ch\u01B0a c\u00F3 h\u00ECnh \u1EA3nh n\u00E0o trong nh\u00F3m" })) })), _jsxs(Form, { ...form, children: [_jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Mic, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("p", { className: "text-sm font-semibold text-gray-800", children: "C\u00E2u h\u1ECFi Nghe & So s\u00E1nh" })] }), children: _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), "\u00C2m thanh c\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FormField, { control: control, name: "audioUrl", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormControl, { children: _jsx(FileUpload, { id: `audio-compare-${displayQuestionNumber}`, label: "", accept: "audio/*", value: field.value, onChange: (url) => { field.onChange(url); clearErrors('audioUrl'); }, maxSize: 10, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "listen-and-speak" }) }), _jsx(FormMessage, {})] })) })] }) }), _jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(MessageSquareText, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("p", { className: "text-sm font-semibold text-gray-800", children: ["\u0110\u00E1p \u00E1n mong mu\u1ED1n (", watchedExpectedAnswers.filter((a) => a.trim()).length, ")"] })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }), children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2.5", children: [_jsx(Info, { className: "h-4 w-4 text-blue-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "text-xs text-blue-700 space-y-1", children: [_jsx("p", { children: "Nh\u1EADp c\u00E1c c\u00E2u tr\u1EA3 l\u1EDDi mong mu\u1ED1n. C\u00F3 th\u1EC3 th\u00EAm nhi\u1EC1u \u0111\u00E1p \u00E1n n\u1EBFu c\u00F3 nhi\u1EC1u c\u00E1ch tr\u1EA3 l\u1EDDi \u0111\u00FAng." }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m th\u1EE7 c\u00F4ng:" }), " Gi\u00E1o vi\u00EAn d\u00F9ng c\u00E1c \u0111\u00E1p \u00E1n n\u00E0y l\u00E0m tham kh\u1EA3o \u0111\u1EC3 ch\u1EA5m \u0111i\u1EC3m."] }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng (AI):" }), " H\u1EC7 th\u1ED1ng d\u00F9ng AI so s\u00E1nh gi\u1ECDng n\u00F3i c\u1EE7a h\u1ECDc sinh v\u1EDBi c\u00E1c \u0111\u00E1p \u00E1n \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng ch\u1EA5m \u0111i\u1EC3m."] })] })] }), _jsxs("div", { className: "space-y-3", children: [watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 font-semibold shadow-sm text-sm", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { placeholder: `VD: ${index === 0 ? 'The tree is bigger in picture A' : 'The dog is brown in picture B'}`, value: answer || '', onChange: (e) => handleExpectedAnswerChange(index, e.target.value), className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "text-red-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))), form.formState.errors?.expectedAnswers && !Array.isArray(form.formState.errors.expectedAnswers) && (_jsx("p", { className: "text-sm text-red-500", children: form.formState.errors.expectedAnswers.message }))] })] }), _jsx(CompactExplanationToggle, { value: watchedExplanation || '', onValueChange: (value) => form.setValue('explanation', value, { shouldValidate: true }), defaultVisible: Boolean(watchedExplanation) })] })] }));
295
291
  }
@@ -18,7 +18,7 @@ function ImageWithPresigned({ url, alt }) {
18
18
  // ─── Main Client Component ───────────────────────────────────────────────────
19
19
  export function ListenAndSpeakImageGroupClient({ questionData, isReviewMode = false, }) {
20
20
  const { audioUrl, activeImageId, groupImages = [], expectedAnswers = [], explanation } = questionData;
21
- return (_jsxs("div", { className: "space-y-4", children: [questionData.isBackup && (_jsxs("div", { className: "inline-flex self-center items-center gap-1.5 px-3 py-1.5 rounded-md bg-amber-50 text-amber-700 border border-amber-200 text-xs font-bold shadow-sm", children: [_jsx("span", { children: "\uD83D\uDD04" }), " C\u00E2u h\u1ECFi d\u1EF1 ph\u00F2ng"] })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-indigo-50 to-blue-50 px-5 py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-blue-600 text-white shadow-sm", children: _jsx(Images, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Nghe v\u00E0 n\u00F3i (Nh\u00F3m h\u00ECnh \u1EA3nh)" })] }) }), _jsxs("div", { className: "p-5 space-y-5", children: [audioUrl ? (_jsx(QuestionAudioPlayer, { audioUrl: audioUrl })) : (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3", children: [_jsx(Volume2, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-xs text-gray-400", children: "Ch\u01B0a c\u00F3 audio c\u00E2u h\u1ECFi" })] })), groupImages.length > 0 ? (_jsx("div", { className: "rounded-xl border border-gray-100 bg-gradient-to-b from-gray-50/80 to-white p-5", children: _jsx("div", { className: "flex flex-row justify-center gap-4 sm:gap-5 flex-wrap", children: groupImages.map((img, index) => {
21
+ return (_jsxs("div", { className: "space-y-4", children: [questionData.isBackup && (_jsxs("div", { className: "inline-flex self-center items-center gap-1.5 px-3 py-1.5 rounded-md bg-amber-50 text-amber-700 border border-amber-200 text-xs font-bold shadow-sm", children: [_jsx("span", { children: "\uD83D\uDD04" }), " C\u00E2u h\u1ECFi d\u1EF1 ph\u00F2ng"] })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gray-50 px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100 text-gray-600", children: _jsx(Images, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Nghe v\u00E0 n\u00F3i (Nh\u00F3m h\u00ECnh \u1EA3nh)" })] }) }), _jsxs("div", { className: "p-3 space-y-3", children: [audioUrl ? (_jsx(QuestionAudioPlayer, { audioUrl: audioUrl })) : (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3", children: [_jsx(Volume2, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-xs text-gray-400", children: "Ch\u01B0a c\u00F3 audio c\u00E2u h\u1ECFi" })] })), groupImages.length > 0 ? (_jsx("div", { className: "rounded-xl border border-gray-100 bg-gradient-to-b from-gray-50/80 to-white p-5", children: _jsx("div", { className: "flex flex-row justify-center gap-4 sm:gap-5 flex-wrap", children: groupImages.map((img, index) => {
22
22
  const isActive = img.id === activeImageId;
23
23
  const letter = String.fromCharCode(65 + index);
24
24
  return (_jsxs("div", { className: cn('flex flex-col items-center gap-2 transition-transform duration-300', isActive && 'scale-[1.03]'), children: [_jsxs("div", { className: cn('relative w-28 h-28 sm:w-36 sm:h-36 rounded-xl overflow-hidden flex items-center justify-center bg-white transition-all duration-300', isActive
@@ -1,16 +1,14 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useRef, useState } from 'react';
4
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
5
4
  import { Label } from '../../../../components/ui/label';
6
5
  import { Button } from '../../../../components/ui/button';
7
6
  import { Input } from '../../../../components/ui/input';
8
- import { Textarea } from '../../../../components/ui/textarea';
9
- import { Plus, Trash2, Pencil, Eye, Mic, Volume2, ImageIcon, Image as ImageIcon2, CheckCircle2, MessageSquareText, Info, ListChecks, BookOpen } from 'lucide-react';
7
+ import { Plus, Trash2, Mic, Volume2, ImageIcon, Image as ImageIcon2, CheckCircle2, MessageSquareText, Info, ListChecks } from 'lucide-react';
10
8
  import { useReactHookForm } from '../../../../shared/lib/hooks/useReactHookForm';
11
9
  import { useDebouncedCallback, usePresignedFileUrl } from '../../../../shared/lib/hooks';
12
10
  import { FileUpload } from '../../../../components/ui/file-upload';
13
- import { PointsInput } from '../../../../components/ui/points-input';
11
+ import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
14
12
  // Stores & hooks
15
13
  import { useImageQuestionGroup } from '../../_shared/hooks/useImageQuestionGroup';
16
14
  import { generateObjectId } from '../../_shared/utils/id-generator';
@@ -18,7 +16,6 @@ import { generateObjectId } from '../../_shared/utils/id-generator';
18
16
  import { ListenAndSpeakImageGroupClient } from './ListenAndSpeakImageGroupClient';
19
17
  // Validation & Types
20
18
  import { listenAndSpeakImageGroupFormSchema } from '../../../../shared/lib/validation/listen-and-speak-image-group.validation';
21
- import { CreatorGuide } from '../../components/CreatorGuide';
22
19
  // ─── Sub-component: Image preview with presigned URL ─────────────────────────
23
20
  function ImagePreview({ imageUrl }) {
24
21
  const { previewUrl } = usePresignedFileUrl(imageUrl);
@@ -261,25 +258,26 @@ export function ListenAndSpeakImageGroupCreator({ initialData, onSave, onCancel,
261
258
  groupImages: images,
262
259
  groupNumber: isGrouped ? currentGroupNumber : undefined,
263
260
  };
264
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Nghe v\u00E0 tr\u1EA3 l\u1EDDi theo nh\u00F3m \u1EA3nh (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Preview mode" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) }) }), _jsx(ListenAndSpeakImageGroupClient, { questionData: questionData, isReviewMode: true })] }));
261
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(ListenAndSpeakImageGroupClient, { questionData: questionData, isReviewMode: true })] }));
265
262
  }
266
263
  // ─── Creator UI ────────────────────────────────────────────────────────────
267
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(CreatorGuide, { colorScheme: "emerald", steps: [
268
- { text: 'Thêm hình ảnh vào nhóm — mỗi hình cần có URL và nhãn mô tả' },
269
- { text: 'Hình ảnh dùng chung cho tất cả câu hỏi trong nhóm (câu hỏi đầu tiên sẽ quản lý)' },
270
- { text: 'Upload audio câu hỏi cho từng câu — giám khảo sẽ hỏi về từng hình' },
271
- { text: 'Chọn hình ảnh đang được hỏi (active image) cho mỗi câu', highlight: true },
272
- { text: 'Nhập các đáp án mong muốn và giải thích' },
273
- ], tips: ['Sắp xếp hình ảnh theo thứ tự logic, gắn nhãn rõ ràng'] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-emerald-100/50", children: [_jsx("div", { className: "h-1.5 bg-gradient-to-r from-emerald-500 via-teal-500 to-cyan-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-emerald-500 to-teal-600 shadow-md", children: _jsx(ListChecks, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold text-gray-900", children: "Nh\u00F3m \u0111\u00E1p \u00E1n" }), _jsxs("div", { className: "mt-1.5 inline-flex items-center gap-1.5 rounded-full bg-emerald-100 px-3 py-1 text-sm font-medium text-emerald-700", children: [_jsx("span", { children: "\uD83D\uDDBC\uFE0F" }), _jsxs("span", { children: ["Nh\u00F3m ", currentGroupNumber] }), _jsx("span", { className: "text-xs font-normal opacity-75 ml-1", children: "(D\u00F9ng chung)" })] })] })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: !watchedAudioUrl || watchedExpectedAnswers.filter((a) => a.trim()).length === 0, className: "gap-2 border-emerald-200 text-emerald-600 hover:bg-emerald-50 hover:text-emerald-700", children: [_jsx(Eye, { className: "h-4 w-4" }), "Preview"] })] }) })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-emerald-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-emerald-400 to-teal-400" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-emerald-100", children: _jsx(ImageIcon2, { className: "h-3.5 w-3.5 text-emerald-600" }) }), _jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "Nh\u00F3m H\u00ECnh \u1EA2nh" })] }), images.length < 4 && (_jsxs(Button, { variant: "outline", size: "sm", onClick: handleAddImage, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50 hover:text-green-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm h\u00ECnh \u1EA3nh"] }))] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: images.map((img, index) => (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white text-sm font-bold shadow-sm", children: String.fromCharCode(65 + index) }), _jsxs("span", { className: "text-sm font-semibold text-gray-700", children: ["H\u00ECnh \u1EA3nh ", String.fromCharCode(65 + index)] })] }), images.length > 1 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => handleRemoveImage(index), className: "h-7 w-7 p-0 text-red-500 hover:text-red-700 hover:bg-red-50", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }), _jsx(FileUpload, { id: `group-img-${img.id}`, label: "", accept: "image/*", value: img.url, onChange: (url) => handleUpdateImage(index, 'url', url), maxSize: 5, placeholder: "Upload h\u00ECnh \u1EA3nh", autoUpload: true, prefix: "questions/images" }), img.url && _jsx(ImagePreview, { imageUrl: img.url }), _jsxs("div", { className: "mt-3", children: [_jsx(Label, { className: "text-xs font-medium text-gray-600", children: "Nh\u00E3n" }), _jsx(Input, { value: img.label, onChange: (e) => handleUpdateImage(index, 'label', e.target.value), placeholder: "Nh\u1EADp nh\u00E3n / m\u00F4 t\u1EA3 ng\u1EAFn", className: "mt-1 border-gray-200" })] })] }, img.id))) }), images.length === 0 && (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-indigo-300 p-8 bg-indigo-50/50", children: [_jsx(ImageIcon2, { className: "h-10 w-10 text-indigo-400 mb-2" }), _jsx("p", { className: "text-sm text-gray-500 mb-3", children: "Ch\u01B0a c\u00F3 h\u00ECnh \u1EA3nh n\u00E0o" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: handleAddImage, className: "gap-2", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm h\u00ECnh \u1EA3nh \u0111\u1EA7u ti\u00EAn"] })] }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-indigo-100/50", children: [_jsx("div", { className: "h-1.5 bg-gradient-to-r from-indigo-500 to-blue-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-500 to-blue-600 shadow-md", children: _jsx(Mic, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold text-gray-900", children: "Nghe v\u00E0 tr\u1EA3 l\u1EDDi" }), _jsx("p", { className: "text-sm text-gray-500", children: "H\u1ECDc sinh nghe \u00E2m thanh v\u00E0 thu \u00E2m c\u00E2u tr\u1EA3 l\u1EDDi cho b\u1EE9c \u1EA3nh \u0111\u01B0\u1EE3c ch\u1ECDn" })] })] }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsx("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4", children: _jsx("div", { className: "w-full md:w-1/2", children: _jsx(PointsInput, { ...form.register('points', { valueAsNumber: true }), error: form.hasError('points') ? form.getFieldError('points') : undefined }) }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-indigo-500" }), "Ch\u1ECDn h\u00ECnh \u1EA3nh \u0111ang \u0111\u01B0\u1EE3c h\u1ECFi"] }), images.filter((o) => o.url).length > 0 ? (_jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: images.map((img, index) => {
274
- if (!img.url)
275
- return null;
276
- const isSelected = watchedActiveImageId === img.id;
277
- return (_jsxs("button", { type: "button", onClick: () => {
278
- form.setValue('activeImageId', img.id, { shouldValidate: true, shouldDirty: true });
279
- }, className: `relative text-left rounded-xl border-2 p-2 transition-all ${isSelected
280
- ? 'border-indigo-500 bg-indigo-50 ring-2 ring-indigo-200 shadow-md'
281
- : 'border-gray-200 hover:border-gray-400 hover:shadow-sm'}`, children: [_jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx("div", { className: `flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold shadow-sm ${isSelected
282
- ? 'bg-indigo-500 text-white'
283
- : 'bg-gray-100 text-gray-600'}`, children: String.fromCharCode(65 + index) }), _jsx(ImagePreviewInline, { imageUrl: img.url }), img.label && (_jsx("p", { className: `text-xs text-center ${isSelected ? 'text-indigo-700 font-medium' : 'text-gray-600'}`, children: img.label }))] }), isSelected && (_jsx("div", { className: "absolute top-1 right-1", children: _jsx(CheckCircle2, { className: "h-5 w-5 text-indigo-500" }) }))] }, img.id));
284
- }) })) : (_jsx("p", { className: "text-sm text-amber-600 italic", children: "Vui l\u00F2ng upload \u1EA3nh cho h\u00ECnh \u1EA3nh \u1EDF ph\u1EA7n tr\u00EAn tr\u01B0\u1EDBc" })), form.hasError('activeImageId') && (_jsx("div", { className: "mt-2 rounded-lg border border-red-200 bg-red-50 p-3", children: _jsxs("p", { className: "text-sm text-red-700", children: ["\u26A0\uFE0F ", form.getFieldError('activeImageId')] }) })), !form.hasError('activeImageId') && !watchedActiveImageId && images.filter((o) => o.url).length > 0 && (_jsx("p", { className: "mt-1 text-xs text-amber-600", children: "Ch\u01B0a ch\u1ECDn h\u00ECnh \u1EA3nh \u0111ang \u0111\u01B0\u1EE3c h\u1ECFi" }))] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), "Audio c\u00E2u h\u1ECFi"] }), _jsx(FileUpload, { id: "question-audio", label: "", accept: "audio/*", value: watchedAudioUrl, onChange: (url) => form.setValue('audioUrl', url, { shouldValidate: true, shouldDirty: true }), maxSize: 20, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "questions/audio" }), form.hasError('audioUrl') && (_jsx("p", { className: "text-sm text-red-600", children: form.getFieldError('audioUrl') })), audioPreviewUrl && (_jsx("audio", { controls: true, className: "mt-2 w-full", src: audioPreviewUrl, children: "Tr\u00ECnh duy\u1EC7t kh\u00F4ng h\u1ED7 tr\u1EE3 audio." }))] }), externalErrors && externalErrors.length > 0 && (_jsx("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 p-4", children: _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "C\u1EA7n ph\u1EA3i s\u1EEDa c\u00E1c l\u1ED7i sau:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] }) }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-green-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-green-400 to-emerald-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", 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-green-500 to-emerald-600 shadow-sm", children: _jsx(MessageSquareText, { className: "h-4 w-4 text-white" }) }), _jsx("div", { children: _jsxs(CardTitle, { className: "text-lg font-semibold text-gray-800", children: ["\u0110\u00E1p \u00E1n mong mu\u1ED1n (", watchedExpectedAnswers.filter((a) => a.trim()).length, ")"] }) })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2.5", children: [_jsx(Info, { className: "h-4 w-4 text-blue-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "text-xs text-blue-700 space-y-1", children: [_jsx("p", { children: "Nh\u1EADp c\u00E1c c\u00E2u tr\u1EA3 l\u1EDDi mong mu\u1ED1n. C\u00F3 th\u1EC3 th\u00EAm nhi\u1EC1u \u0111\u00E1p \u00E1n n\u1EBFu c\u00F3 nhi\u1EC1u c\u00E1ch tr\u1EA3 l\u1EDDi \u0111\u00FAng." }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m th\u1EE7 c\u00F4ng:" }), " Gi\u00E1o vi\u00EAn d\u00F9ng c\u00E1c \u0111\u00E1p \u00E1n n\u00E0y l\u00E0m tham kh\u1EA3o \u0111\u1EC3 ch\u1EA5m \u0111i\u1EC3m."] }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng (AI):" }), " H\u1EC7 th\u1ED1ng d\u00F9ng AI so s\u00E1nh gi\u1ECDng n\u00F3i c\u1EE7a h\u1ECDc sinh v\u1EDBi c\u00E1c \u0111\u00E1p \u00E1n \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng ch\u1EA5m \u0111i\u1EC3m."] })] })] }), _jsxs("div", { className: "space-y-3", children: [watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 font-semibold shadow-sm text-sm", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { value: answer || '', onChange: (e) => updateExpectedAnswer(index, e.target.value), placeholder: `Ví dụ: ${index === 0 ? 'A kite' : 'It is a kite'}`, className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "text-red-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))), form.formState.errors?.expectedAnswers && !Array.isArray(form.formState.errors.expectedAnswers) && (_jsx("p", { className: "text-sm text-red-500", children: form.formState.errors.expectedAnswers.message }))] })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-amber-400 to-orange-400" }), _jsx(CardHeader, { className: "pb-4", 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-amber-500 to-orange-500 shadow-sm", children: _jsx(BookOpen, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx("span", { className: "inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2.5 py-0.5 text-xs font-medium text-amber-600", children: "Kh\u00F4ng b\u1EAFt bu\u1ED9c" })] }), _jsx("p", { className: "text-sm text-gray-500 mt-0.5", children: "Gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng \u2014 hi\u1EC3n th\u1ECB sau khi h\u1ECDc sinh ho\u00E0n th\u00E0nh c\u00E2u h\u1ECFi" })] })] }) }), _jsx(CardContent, { children: _jsx(Textarea, { value: watchedExplanation, onChange: (e) => form.setValue('explanation', e.target.value, { shouldValidate: true }), placeholder: "VD: C\u00E2u tr\u1EA3 l\u1EDDi \u0111\u00FAng l\u00E0... v\u00EC...", rows: 3, className: "min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none" }) })] })] }));
264
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(ListChecks, { className: "h-3.5 w-3.5" }), title: "Nh\u00F3m \u0111\u00E1p \u00E1n", extraActions: _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600", children: ["Nh\u00F3m ", currentGroupNumber] }), points: {
265
+ value: watchedPoints,
266
+ onValueChange: (value) => form.setValue('points', value, { shouldValidate: true }),
267
+ error: form.hasError('points') ? form.getFieldError('points') : undefined,
268
+ }, preview: {
269
+ onClick: () => setIsClientMode(true),
270
+ disabled: !watchedAudioUrl || watchedExpectedAnswers.filter((a) => a.trim()).length === 0,
271
+ } }), contentClassName: "hidden", children: null }), _jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(ImageIcon2, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("p", { className: "text-sm font-semibold text-gray-800", children: "Nh\u00F3m H\u00ECnh \u1EA2nh" })] }), images.length < 4 && (_jsxs(Button, { variant: "outline", size: "sm", onClick: handleAddImage, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50 hover:text-green-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm h\u00ECnh \u1EA3nh"] }))] }), children: [_jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: images.map((img, index) => (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white text-sm font-bold shadow-sm", children: String.fromCharCode(65 + index) }), _jsxs("span", { className: "text-sm font-semibold text-gray-700", children: ["H\u00ECnh \u1EA3nh ", String.fromCharCode(65 + index)] })] }), images.length > 1 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => handleRemoveImage(index), className: "h-7 w-7 p-0 text-red-500 hover:text-red-700 hover:bg-red-50", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }), _jsx(FileUpload, { id: `group-img-${img.id}`, label: "", accept: "image/*", value: img.url, onChange: (url) => handleUpdateImage(index, 'url', url), maxSize: 5, placeholder: "Upload h\u00ECnh \u1EA3nh", autoUpload: true, prefix: "questions/images" }), img.url && _jsx(ImagePreview, { imageUrl: img.url }), _jsxs("div", { className: "mt-3", children: [_jsx(Label, { className: "text-xs font-medium text-gray-600", children: "Nh\u00E3n" }), _jsx(Input, { value: img.label, onChange: (e) => handleUpdateImage(index, 'label', e.target.value), placeholder: "Nh\u1EADp nh\u00E3n / m\u00F4 t\u1EA3 ng\u1EAFn", className: "mt-1 border-gray-200" })] })] }, img.id))) }), images.length === 0 && (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-indigo-300 p-8 bg-indigo-50/50", children: [_jsx(ImageIcon2, { className: "h-10 w-10 text-indigo-400 mb-2" }), _jsx("p", { className: "text-sm text-gray-500 mb-3", children: "Ch\u01B0a c\u00F3 h\u00ECnh \u1EA3nh n\u00E0o" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: handleAddImage, className: "gap-2", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm h\u00ECnh \u1EA3nh \u0111\u1EA7u ti\u00EAn"] })] }))] }), _jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(Mic, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("p", { className: "text-sm font-semibold text-gray-800", children: "Nghe v\u00E0 tr\u1EA3 l\u1EDDi" })] }), children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-indigo-500" }), "Ch\u1ECDn h\u00ECnh \u1EA3nh \u0111ang \u0111\u01B0\u1EE3c h\u1ECFi"] }), images.filter((o) => o.url).length > 0 ? (_jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: images.map((img, index) => {
272
+ if (!img.url)
273
+ return null;
274
+ const isSelected = watchedActiveImageId === img.id;
275
+ return (_jsxs("button", { type: "button", onClick: () => {
276
+ form.setValue('activeImageId', img.id, { shouldValidate: true, shouldDirty: true });
277
+ }, className: `relative text-left rounded-xl border-2 p-2 transition-all ${isSelected
278
+ ? 'border-indigo-500 bg-indigo-50 ring-2 ring-indigo-200 shadow-md'
279
+ : 'border-gray-200 hover:border-gray-400 hover:shadow-sm'}`, children: [_jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx("div", { className: `flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold shadow-sm ${isSelected
280
+ ? 'bg-indigo-500 text-white'
281
+ : 'bg-gray-100 text-gray-600'}`, children: String.fromCharCode(65 + index) }), _jsx(ImagePreviewInline, { imageUrl: img.url }), img.label && (_jsx("p", { className: `text-xs text-center ${isSelected ? 'text-indigo-700 font-medium' : 'text-gray-600'}`, children: img.label }))] }), isSelected && (_jsx("div", { className: "absolute top-1 right-1", children: _jsx(CheckCircle2, { className: "h-5 w-5 text-indigo-500" }) }))] }, img.id));
282
+ }) })) : (_jsx("p", { className: "text-sm text-amber-600 italic", children: "Vui l\u00F2ng upload \u1EA3nh cho h\u00ECnh \u1EA3nh \u1EDF ph\u1EA7n tr\u00EAn tr\u01B0\u1EDBc" })), form.hasError('activeImageId') && (_jsx("div", { className: "mt-2 rounded-lg border border-red-200 bg-red-50 p-3", children: _jsxs("p", { className: "text-sm text-red-700", children: ["\u26A0\uFE0F ", form.getFieldError('activeImageId')] }) })), !form.hasError('activeImageId') && !watchedActiveImageId && images.filter((o) => o.url).length > 0 && (_jsx("p", { className: "mt-1 text-xs text-amber-600", children: "Ch\u01B0a ch\u1ECDn h\u00ECnh \u1EA3nh \u0111ang \u0111\u01B0\u1EE3c h\u1ECFi" }))] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), "Audio c\u00E2u h\u1ECFi"] }), _jsx(FileUpload, { id: "question-audio", label: "", accept: "audio/*", value: watchedAudioUrl, onChange: (url) => form.setValue('audioUrl', url, { shouldValidate: true, shouldDirty: true }), maxSize: 20, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "questions/audio" }), form.hasError('audioUrl') && (_jsx("p", { className: "text-sm text-red-600", children: form.getFieldError('audioUrl') })), audioPreviewUrl && (_jsx("audio", { controls: true, className: "mt-2 w-full", src: audioPreviewUrl, children: "Tr\u00ECnh duy\u1EC7t kh\u00F4ng h\u1ED7 tr\u1EE3 audio." }))] }), externalErrors && externalErrors.length > 0 && (_jsx("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 p-4", children: _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "C\u1EA7n ph\u1EA3i s\u1EEDa c\u00E1c l\u1ED7i sau:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] }) }))] }), _jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(MessageSquareText, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("p", { className: "text-sm font-semibold text-gray-800", children: ["\u0110\u00E1p \u00E1n mong mu\u1ED1n (", watchedExpectedAnswers.filter((a) => a.trim()).length, ")"] })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }), children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2.5", children: [_jsx(Info, { className: "h-4 w-4 text-blue-500 mt-0.5 flex-shrink-0" }), _jsxs("div", { className: "text-xs text-blue-700 space-y-1", children: [_jsx("p", { children: "Nh\u1EADp c\u00E1c c\u00E2u tr\u1EA3 l\u1EDDi mong mu\u1ED1n. C\u00F3 th\u1EC3 th\u00EAm nhi\u1EC1u \u0111\u00E1p \u00E1n n\u1EBFu c\u00F3 nhi\u1EC1u c\u00E1ch tr\u1EA3 l\u1EDDi \u0111\u00FAng." }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m th\u1EE7 c\u00F4ng:" }), " Gi\u00E1o vi\u00EAn d\u00F9ng c\u00E1c \u0111\u00E1p \u00E1n n\u00E0y l\u00E0m tham kh\u1EA3o \u0111\u1EC3 ch\u1EA5m \u0111i\u1EC3m."] }), _jsxs("p", { children: [_jsx("span", { className: "font-semibold", children: "\u2022 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng (AI):" }), " H\u1EC7 th\u1ED1ng d\u00F9ng AI so s\u00E1nh gi\u1ECDng n\u00F3i c\u1EE7a h\u1ECDc sinh v\u1EDBi c\u00E1c \u0111\u00E1p \u00E1n \u0111\u1EC3 t\u1EF1 \u0111\u1ED9ng ch\u1EA5m \u0111i\u1EC3m."] })] })] }), _jsxs("div", { className: "space-y-3", children: [watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 font-semibold shadow-sm text-sm", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { value: answer || '', onChange: (e) => updateExpectedAnswer(index, e.target.value), placeholder: `Ví dụ: ${index === 0 ? 'A kite' : 'It is a kite'}`, className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "text-red-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))), form.formState.errors?.expectedAnswers && !Array.isArray(form.formState.errors.expectedAnswers) && (_jsx("p", { className: "text-sm text-red-500", children: form.formState.errors.expectedAnswers.message }))] })] }), _jsx(CompactExplanationToggle, { value: watchedExplanation || '', onValueChange: (value) => form.setValue('explanation', value, { shouldValidate: true }), defaultVisible: Boolean(watchedExplanation) })] }));
285
283
  }
@@ -32,7 +32,7 @@ export function ListenAndSpeakInfoExchangeClient({ questionData, isReviewMode =
32
32
  .map((f) => ({ key: f.key, value: f.answer }));
33
33
  const examinerRows = (qData.examinerFields || [])
34
34
  .map((f) => ({ key: f.key, value: f.answer }));
35
- return (_jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-indigo-50 to-blue-50 px-5 py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-blue-600 text-white shadow-sm", children: _jsx(ArrowLeftRight, { className: "h-4 w-4" }) }), _jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["Nghe v\u00E0 n\u00F3i (Trao \u0111\u1ED5i th\u00F4ng tin \u2014 ", viewMode === 'ANSWER' ? 'Trả lời' : 'Đặt câu hỏi', ")"] })] }) }), _jsxs("div", { className: "p-5 space-y-5", children: [audioUrl ? (_jsx(QuestionAudioPlayer, { audioUrl: audioUrl })) : (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3", children: [_jsx(Volume2, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-xs text-gray-400", children: "Ch\u01B0a c\u00F3 audio c\u00E2u h\u1ECFi" })] })), _jsxs("div", { className: "flex flex-col lg:flex-row gap-4", children: [imageUrl && (_jsx("div", { className: "lg:w-1/2", children: _jsx(ImagePreview, { imageUrl: imageUrl, title: title }) })), _jsxs("div", { className: "flex-1 space-y-4", children: [_jsx(InfoTable, { label: "CANDIDATE'S COPY", title: title, rows: candidateRows, headerColor: "bg-teal-600" }), _jsx(InfoTable, { label: "EXAMINER'S COPY", title: title, rows: examinerRows, headerColor: "bg-amber-600" })] })] }), _jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-dashed border-gray-300 bg-gray-50/80 px-4 py-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-indigo-50 ring-2 ring-indigo-100/50", children: _jsx(Mic, { className: "w-4 h-4 text-indigo-400" }) }), _jsx("p", { className: "text-xs text-gray-400", children: viewMode === 'ANSWER'
35
+ return (_jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gray-50 px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100 text-gray-600", children: _jsx(ArrowLeftRight, { className: "h-4 w-4" }) }), _jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["Nghe v\u00E0 n\u00F3i (Trao \u0111\u1ED5i th\u00F4ng tin \u2014 ", viewMode === 'ANSWER' ? 'Trả lời' : 'Đặt câu hỏi', ")"] })] }) }), _jsxs("div", { className: "p-3 space-y-3", children: [audioUrl ? (_jsx(QuestionAudioPlayer, { audioUrl: audioUrl })) : (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3", children: [_jsx(Volume2, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-xs text-gray-400", children: "Ch\u01B0a c\u00F3 audio c\u00E2u h\u1ECFi" })] })), _jsxs("div", { className: "flex flex-col lg:flex-row gap-4", children: [imageUrl && (_jsx("div", { className: "lg:w-1/2", children: _jsx(ImagePreview, { imageUrl: imageUrl, title: title }) })), _jsxs("div", { className: "flex-1 space-y-4", children: [_jsx(InfoTable, { label: "CANDIDATE'S COPY", title: title, rows: candidateRows, headerColor: "bg-teal-600" }), _jsx(InfoTable, { label: "EXAMINER'S COPY", title: title, rows: examinerRows, headerColor: "bg-amber-600" })] })] }), _jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-dashed border-gray-300 bg-gray-50/80 px-4 py-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-indigo-50 ring-2 ring-indigo-100/50", children: _jsx(Mic, { className: "w-4 h-4 text-indigo-400" }) }), _jsx("p", { className: "text-xs text-gray-400", children: viewMode === 'ANSWER'
36
36
  ? 'Học sinh sẽ nhấn nút ghi âm và nói câu trả lời tại đây'
37
37
  : 'Học sinh sẽ nhấn nút ghi âm và đặt câu hỏi tại đây' })] }), isReviewMode && expectedAnswers.length > 0 && (_jsxs("div", { className: "rounded-xl border border-green-200 bg-green-50/80 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsx("h4", { className: "text-sm font-semibold text-green-800", children: viewMode === 'ANSWER' ? 'Các đáp án mong muốn' : 'Các câu hỏi mong muốn' })] }), _jsx("div", { className: "space-y-2", children: expectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-center gap-2.5 rounded-lg bg-white/70 border border-green-100 px-3 py-2", children: [_jsx("span", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-green-100 text-green-700 text-xs font-bold", children: index + 1 }), _jsx("span", { className: "text-sm text-green-800", children: answer })] }, index))) })] })), isReviewMode && explanation && (_jsxs("div", { className: "rounded-xl border border-indigo-200 bg-indigo-50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Info, { className: "h-4 w-4 text-indigo-600" }), _jsx("p", { className: "text-sm font-semibold text-indigo-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("p", { className: "text-sm text-indigo-700 leading-relaxed", children: explanation })] }))] })] }) }));
38
38
  }
@@ -1,23 +1,20 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useRef, useState } from 'react';
4
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
5
4
  import { Label } from '../../../../components/ui/label';
6
5
  import { Button } from '../../../../components/ui/button';
7
6
  import { Input } from '../../../../components/ui/input';
8
- import { Textarea } from '../../../../components/ui/textarea';
9
7
  import { Form, FormControl, FormField, FormItem, FormMessage } from '../../../../components/ui/form';
10
8
  import { FileUpload } from '../../../../components/ui/file-upload';
11
- import { PointsInput } from '../../../../components/ui/points-input';
9
+ import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
12
10
  // Stores & hooks
13
11
  import { useInfoExchangeGroup } from '../../_shared/hooks/useInfoExchangeGroup';
14
12
  import { usePresignedFileUrl } from '../../../../shared/lib/hooks';
15
13
  import { listenAndSpeakInfoExchangeSchema, } from '../../../../shared/lib/validation/listen-and-speak-info-exchange.validation';
16
14
  // Utilities & Icons
17
- import { Plus, Trash2, Mic, Volume2, Table2, MessageSquareText, ImageIcon, BookOpen, Eye, Pencil, Info, ListChecks } from 'lucide-react';
15
+ import { Plus, Trash2, Mic, Volume2, Table2, MessageSquareText, ImageIcon, Info, ListChecks } from 'lucide-react';
18
16
  import { useReactHookForm } from '../../../../shared/lib/hooks/useReactHookForm';
19
17
  import { useDebouncedCallback } from '../../../../shared/lib/hooks/useDebouncedCallback';
20
- import { CreatorGuide } from '../../components/CreatorGuide';
21
18
  import { ListenAndSpeakInfoExchangeClient } from './ListenAndSpeakInfoExchangeClient';
22
19
  // ─── Sub-component: Image preview with presigned URL ─────────────────────────
23
20
  function ImagePreview({ imageUrl, label }) {
@@ -352,7 +349,7 @@ export function ListenAndSpeakInfoExchangeCreator({ questionIndex, initialData,
352
349
  const [isClientMode, setIsClientMode] = useState(false);
353
350
  // ─── Preview Mode ────────────────────────────────────────────────
354
351
  if (isClientMode) {
355
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(CardTitle, { className: "text-lg font-bold", children: "\uD83D\uDC41\uFE0F Ch\u1EBF \u0111\u1ED9 xem tr\u01B0\u1EDBc (Preview)" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i ch\u1EC9nh s\u1EEDa"] })] }) }) }), _jsx(ListenAndSpeakInfoExchangeClient, { questionData: {
352
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(ListenAndSpeakInfoExchangeClient, { questionData: {
356
353
  audioUrl: watchedAudioUrl,
357
354
  title: groupTitle,
358
355
  imageUrl: groupImageUrl,
@@ -364,22 +361,18 @@ export function ListenAndSpeakInfoExchangeCreator({ questionIndex, initialData,
364
361
  explanation: watchedExplanation,
365
362
  }, viewMode: viewMode })] }));
366
363
  }
367
- return (_jsxs("div", { className: "space-y-6", children: [_jsx(CreatorGuide, { colorScheme: "blue", steps: [
368
- { text: 'Nhập tiêu đề chung cho bảng thông tin (ví dụ: Shopping List, Holiday Plans)' },
369
- { text: 'Upload hình ảnh minh họa nếu có' },
370
- { text: 'Thiết lập bảng thông tin Candidate và Examiner — mỗi bảng có các cặp key/value' },
371
- { text: 'Upload audio câu hỏi cho từng câu' },
372
- { text: 'Chọn chế độ: ANSWER (trả lời) hoặc ASK (đặt câu hỏi)' },
373
- { text: 'Nhập đáp án/câu hỏi mong muốn và giải thích' },
374
- ], tips: ['Trường có giá trị "?" là trường học sinh cần tìm câu trả lời'] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-blue-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-blue-500 via-indigo-500 to-purple-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 shadow-sm", children: _jsx(ListChecks, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsxs(CardTitle, { className: "text-lg font-bold text-gray-900", children: ["Trao \u0111\u1ED5i th\u00F4ng tin \u2014 C\u00E2u #", displayQuestionNumber] }), _jsx("p", { className: "text-sm text-gray-500", children: modeLabel })] })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: !watchedAudioUrl, className: "gap-2 border-blue-200 text-blue-600 hover:bg-blue-50 disabled:opacity-50", children: [_jsx(Eye, { className: "h-4 w-4" }), "Preview"] })] }) })] }), _jsxs("div", { className: `inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-semibold border ${modeColors.badge}`, children: [modeColors.icon, " ", viewMode === 'ANSWER' ? 'Examiner → Candidate' : 'Candidate → Examiner', _jsx("span", { className: "text-gray-400", children: "|" }), " ", modeLabel] }), isFirstInGroup ? (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-teal-100/50", children: [_jsx("div", { className: "h-1.5 bg-gradient-to-r from-teal-500 via-emerald-500 to-cyan-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-teal-500 to-emerald-600 shadow-md", children: _jsx(Table2, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-lg font-bold text-gray-900", children: "Th\u00F4ng tin chung" }), isGrouped && (_jsxs("span", { className: "inline-flex items-center rounded-full border border-teal-300 bg-teal-100 px-2.5 py-0.5 text-xs font-semibold text-teal-700", children: ["Nh\u00F3m ", currentGroupNumber] }))] }), _jsx("p", { className: "text-sm text-gray-500", children: "D\u00F9ng chung cho t\u1EA5t c\u1EA3 c\u00E2u h\u1ECFi trong nh\u00F3m \u2014 Ti\u00EAu \u0111\u1EC1, h\u00ECnh \u1EA3nh, v\u00E0 2 b\u1EA3ng th\u00F4ng tin" })] })] }) }), _jsxs(CardContent, { className: "space-y-5", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(MessageSquareText, { className: "h-4 w-4 text-teal-500" }), "Ti\u00EAu \u0111\u1EC1 ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: groupTitle, onChange: (e) => {
375
- updateGroupData({ title: e.target.value });
376
- setValue('title', e.target.value, { shouldDirty: true });
377
- }, placeholder: "VD: Katy's house", className: "border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200" })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-teal-500" }), "H\u00ECnh \u1EA3nh minh ho\u1EA1"] }), _jsx(FileUpload, { accept: "image/*", value: groupImageUrl, onChange: (url) => {
378
- updateGroupData({ imageUrl: url });
379
- setValue('imageUrl', url, { shouldDirty: true });
380
- }, placeholder: "Upload h\u00ECnh \u1EA3nh", label: "", autoUpload: true, prefix: "info-exchange" }), groupImageUrl && (_jsx(ImagePreview, { imageUrl: groupImageUrl, label: "H\u00ECnh \u1EA3nh minh ho\u1EA1" }))] }), _jsxs("div", { className: "space-y-5", children: [_jsx("div", { className: "space-y-3", children: _jsxs("div", { className: "rounded-xl border border-teal-200 overflow-hidden shadow-sm bg-white", children: [_jsx("div", { className: "bg-gradient-to-r from-teal-600 to-emerald-600 px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-white/20 backdrop-blur-sm", children: _jsx(Table2, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: "Candidate's Copy" }), _jsx("p", { className: "text-[10px] text-teal-100 font-medium", children: "B\u1EA3ng th\u00F4ng tin h\u1ECDc sinh nh\u00ECn th\u1EA5y" })] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "inline-flex items-center rounded-full bg-white/20 backdrop-blur-sm px-2 py-0.5 text-[10px] font-bold text-white", children: [groupCandidateFields.length, " d\u00F2ng"] }) })] }) }), _jsx("div", { className: "bg-teal-50/60 border-b border-teal-100 px-4 py-2", children: _jsx("p", { className: "text-xs font-semibold text-teal-800 text-center", children: groupTitle || '(Chưa nhập tiêu đề)' }) }), _jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] bg-gradient-to-r from-teal-50/80 to-emerald-50/80 border-b border-teal-100", children: [_jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider text-center", children: "#" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Value" }), _jsx("div", {})] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupCandidateFields.map((field, index) => (_jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] items-center bg-white hover:bg-teal-50/30 transition-colors group/row", children: [_jsx("div", { className: "px-2 py-2 flex justify-center", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-teal-100 text-teal-700 font-bold text-[11px]", children: index + 1 }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.key, onChange: (e) => handleUpdateCandidateField(index, 'key', e.target.value), placeholder: "VD: Where", className: "h-8 text-sm border-gray-200 bg-white focus:border-teal-400 focus:ring-teal-200 transition-all" }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.answer, onChange: (e) => handleUpdateCandidateField(index, 'answer', e.target.value), placeholder: "VD: King Road", className: "h-8 text-sm border-gray-200 bg-white focus:border-teal-400 focus:ring-teal-200 transition-all" }) }), _jsx("div", { className: "px-1 py-1.5 flex justify-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => handleRemoveCandidateField(index), disabled: groupCandidateFields.length <= 1, className: "h-7 w-7 text-gray-300 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/row:opacity-100 transition-all disabled:opacity-0 disabled:group-hover/row:opacity-30", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) })] }, index))) }), _jsx("div", { className: "border-t border-dashed border-teal-200 bg-teal-50/30", children: _jsxs("button", { type: "button", onClick: handleAddCandidateField, className: "w-full flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold text-teal-600 hover:text-teal-700 hover:bg-teal-50 transition-colors cursor-pointer", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm d\u00F2ng"] }) })] }) }), _jsx("div", { className: "space-y-3", children: _jsxs("div", { className: "rounded-xl border border-amber-200 overflow-hidden shadow-sm bg-white", children: [_jsx("div", { className: "bg-gradient-to-r from-amber-600 to-orange-600 px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-white/20 backdrop-blur-sm", children: _jsx(Table2, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: "Examiner's Copy" }), _jsx("p", { className: "text-[10px] text-amber-100 font-medium", children: "B\u1EA3ng th\u00F4ng tin gi\u00E1m kh\u1EA3o nh\u00ECn th\u1EA5y" })] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "inline-flex items-center rounded-full bg-white/20 backdrop-blur-sm px-2 py-0.5 text-[10px] font-bold text-white", children: [groupExaminerFields.length, " d\u00F2ng"] }) })] }) }), _jsx("div", { className: "bg-amber-50/60 border-b border-amber-100 px-4 py-2", children: _jsx("p", { className: "text-xs font-semibold text-amber-800 text-center", children: groupTitle || '(Chưa nhập tiêu đề)' }) }), _jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] bg-gradient-to-r from-amber-50/80 to-orange-50/80 border-b border-amber-100", children: [_jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider text-center", children: "#" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Value" }), _jsx("div", {})] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupExaminerFields.map((field, index) => (_jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] items-center bg-white hover:bg-amber-50/30 transition-colors group/row", children: [_jsx("div", { className: "px-2 py-2 flex justify-center", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-amber-100 text-amber-700 font-bold text-[11px]", children: index + 1 }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.key, onChange: (e) => handleUpdateExaminerField(index, 'key', e.target.value), placeholder: "VD: Where", className: "h-8 text-sm border-gray-200 bg-white focus:border-amber-400 focus:ring-amber-200 transition-all" }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.answer, onChange: (e) => handleUpdateExaminerField(index, 'answer', e.target.value), placeholder: "VD: King Road", className: "h-8 text-sm border-gray-200 bg-white focus:border-amber-400 focus:ring-amber-200 transition-all" }) }), _jsx("div", { className: "px-1 py-1.5 flex justify-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => handleRemoveExaminerField(index), disabled: groupExaminerFields.length <= 1, className: "h-7 w-7 text-gray-300 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/row:opacity-100 transition-all disabled:opacity-0 disabled:group-hover/row:opacity-30", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) })] }, index))) }), _jsx("div", { className: "border-t border-dashed border-amber-200 bg-amber-50/30", children: _jsxs("button", { type: "button", onClick: handleAddExaminerField, className: "w-full flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold text-amber-600 hover:text-amber-700 hover:bg-amber-50 transition-colors cursor-pointer", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm d\u00F2ng"] }) })] }) })] })] })] })) : (
381
- /* Read-only view of the shared group data for non-first questions */
382
- _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow shadow-teal-100/30", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-teal-400 via-emerald-400 to-cyan-400" }), _jsx(CardHeader, { className: "pb-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-teal-100 shadow-sm", children: _jsx(Table2, { className: "h-4 w-4 text-teal-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-base font-semibold text-gray-800", children: "Th\u00F4ng tin chung" }), _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500", children: ["Nh\u00F3m ", currentGroupNumber, " \u2014 Ch\u1EC9 \u0111\u1ECDc"] })] }), _jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: "\u0110\u01B0\u1EE3c qu\u1EA3n l\u00FD b\u1EDFi c\u00E2u h\u1ECFi \u0111\u1EA7u ti\u00EAn trong nh\u00F3m" })] })] }) }), _jsx(CardContent, { className: "pt-0", children: _jsxs("div", { className: "space-y-3", children: [groupTitle && (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-lg bg-teal-50/50 border border-teal-100", children: [_jsx(MessageSquareText, { className: "h-4 w-4 text-teal-500 shrink-0" }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: groupTitle })] })), groupImageUrl && (_jsx(ImagePreview, { imageUrl: groupImageUrl, label: groupTitle || 'Hình ảnh minh hoạ' })), _jsxs("div", { className: "space-y-4", children: [groupCandidateFields.length > 0 && (_jsxs("div", { className: "rounded-xl overflow-hidden border border-teal-200 shadow-sm", children: [_jsx("div", { className: "bg-gradient-to-r from-teal-600 to-emerald-600 px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded bg-white/20", children: _jsx(Table2, { className: "h-3 w-3 text-white" }) }), _jsx("span", { className: "text-xs font-bold text-white tracking-wide", children: "Candidate's Copy" })] }), _jsxs("span", { className: "text-[10px] font-semibold text-teal-100 bg-white/15 rounded-full px-1.5 py-0.5", children: [groupCandidateFields.length, " d\u00F2ng"] })] }) }), _jsx("div", { className: "bg-teal-50/60 text-center font-semibold text-xs py-2 border-b border-teal-100 text-teal-800", children: groupTitle || '(Chưa nhập tiêu đề)' }), _jsxs("div", { className: "grid grid-cols-2 bg-teal-50/40 border-b border-teal-100", children: [_jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Value" })] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupCandidateFields.map((row, index) => (_jsxs("div", { className: "grid grid-cols-2 bg-white hover:bg-teal-50/20 transition-colors", children: [_jsx("div", { className: "px-3 py-2 text-sm font-medium text-gray-700", children: row.key || _jsx("span", { className: "text-gray-300 italic", children: '(Chưa nhập)' }) }), _jsx("div", { className: "px-3 py-2 text-sm text-gray-800", children: row.answer || _jsx("span", { className: "text-gray-300", children: '—' }) })] }, index))) })] })), groupExaminerFields.length > 0 && (_jsxs("div", { className: "rounded-xl overflow-hidden border border-amber-200 shadow-sm", children: [_jsx("div", { className: "bg-gradient-to-r from-amber-600 to-orange-600 px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded bg-white/20", children: _jsx(Table2, { className: "h-3 w-3 text-white" }) }), _jsx("span", { className: "text-xs font-bold text-white tracking-wide", children: "Examiner's Copy" })] }), _jsxs("span", { className: "text-[10px] font-semibold text-amber-100 bg-white/15 rounded-full px-1.5 py-0.5", children: [groupExaminerFields.length, " d\u00F2ng"] })] }) }), _jsx("div", { className: "bg-amber-50/60 text-center font-semibold text-xs py-2 border-b border-amber-100 text-amber-800", children: groupTitle || '(Chưa nhập tiêu đề)' }), _jsxs("div", { className: "grid grid-cols-2 bg-amber-50/40 border-b border-amber-100", children: [_jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Value" })] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupExaminerFields.map((row, index) => (_jsxs("div", { className: "grid grid-cols-2 bg-white hover:bg-amber-50/20 transition-colors", children: [_jsx("div", { className: "px-3 py-2 text-sm font-medium text-gray-700", children: row.key || _jsx("span", { className: "text-gray-300 italic", children: '(Chưa nhập)' }) }), _jsx("div", { className: "px-3 py-2 text-sm text-gray-800", children: row.answer || _jsx("span", { className: "text-gray-300", children: '—' }) })] }, index))) })] }))] }), groupCandidateFields.length === 0 && groupExaminerFields.length === 0 && (_jsx("div", { className: "text-center py-4 text-sm text-gray-400 italic", children: "Ch\u01B0a c\u00F3 d\u1EEF li\u1EC7u b\u1EA3ng th\u00F4ng tin" }))] }) })] })), _jsxs(Form, { ...form, children: [_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-indigo-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 shadow-sm", children: _jsx(Mic, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsxs(CardTitle, { className: "text-lg font-bold text-gray-900", children: ["C\u00E2u h\u1ECFi #", displayQuestionNumber] }), _jsx("p", { className: "text-sm text-gray-500", children: viewMode === 'ANSWER'
383
- ? 'Học sinh nghe câu hỏi của Examiner và trả lời'
384
- : 'Học sinh đặt câu hỏi cho Examiner' })] })] }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsx("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4", children: _jsx("div", { className: "flex flex-col md:flex-row gap-6", children: _jsx("div", { className: "flex-1", children: _jsx(PointsInput, { ...form.register('points', { valueAsNumber: true }), error: form.formState.errors?.points?.message }) }) }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), audioLabel, " ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FormField, { control: control, name: "audioUrl", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormControl, { children: _jsx(FileUpload, { id: `audio-info-exchange-${displayQuestionNumber}`, label: "", accept: "audio/*", value: field.value, onChange: (url) => { field.onChange(url); clearErrors('audioUrl'); }, maxSize: 10, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "info-exchange" }) }), _jsx(FormMessage, {})] })) })] })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-green-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-green-400 to-emerald-500" }), _jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-green-500 to-emerald-600 shadow-sm", children: _jsx(MessageSquareText, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-lg font-bold text-gray-900", children: "\u0110\u00E1p \u00E1n mong mu\u1ED1n" }), _jsxs("p", { className: "text-sm text-gray-500", children: [watchedExpectedAnswers.filter(a => a.trim()).length, " \u0111\u00E1p \u00E1n \u0111\u00E3 nh\u1EADp"] })] })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2 text-xs text-blue-700", children: [_jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: "Ch\u1EA5m th\u1EE7 c\u00F4ng: gi\u00E1o vi\u00EAn tham kh\u1EA3o \u0111\u00E1p \u00E1n \u0111\u1EC3 ch\u1EA5m \u00B7 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng: AI so s\u00E1nh gi\u1ECDng n\u00F3i h\u1ECDc sinh v\u1EDBi \u0111\u00E1p \u00E1n." })] }), _jsx(FormField, { control: control, name: "expectedAnswers", render: () => (_jsxs(FormItem, { children: [_jsx("div", { className: "space-y-3", children: watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 text-sm font-bold mt-1", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { placeholder: answerPlaceholder, value: answer || '', onChange: (e) => handleExpectedAnswerChange(index, e.target.value), className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "mt-0.5 h-8 w-8 rounded-full text-gray-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", "aria-label": `Xóa đáp án ${index + 1}`, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))) }), form.formState.errors?.expectedAnswers?.message && (_jsx(FormMessage, {}))] })) })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50", children: [_jsx("div", { className: "h-1 bg-gradient-to-r from-amber-400 to-orange-400" }), _jsx(CardHeader, { className: "pb-4", 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-amber-500 to-orange-500 shadow-sm", children: _jsx(BookOpen, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-lg font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx("span", { className: "inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2.5 py-0.5 text-xs font-medium text-amber-600", children: "Kh\u00F4ng b\u1EAFt bu\u1ED9c" })] }), _jsx("p", { className: "text-sm text-gray-500 mt-0.5", children: "Gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng \u2014 hi\u1EC3n th\u1ECB sau khi h\u1ECDc sinh ho\u00E0n th\u00E0nh c\u00E2u h\u1ECFi" })] })] }) }), _jsx(CardContent, { children: _jsx(Textarea, { ...form.register('explanation'), placeholder: "VD: C\u00E2u tr\u1EA3 l\u1EDDi \u0111\u00FAng l\u00E0... v\u00EC...", className: "min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none", rows: 3 }) })] })] })] }));
364
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(ListChecks, { className: "h-3.5 w-3.5" }), title: `Trao đổi thông tin — Câu #${displayQuestionNumber}`, extraActions: _jsx("span", { className: `inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${modeColors.badge}`, children: modeLabel }), points: {
365
+ value: watchedPoints,
366
+ onValueChange: (value) => form.setValue('points', value, { shouldValidate: true }),
367
+ error: form.formState.errors?.points?.message,
368
+ }, preview: {
369
+ onClick: () => setIsClientMode(true),
370
+ disabled: !watchedAudioUrl,
371
+ } }), contentClassName: "hidden", children: null }), _jsxs("div", { className: `inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-semibold border ${modeColors.badge}`, children: [modeColors.icon, " ", viewMode === 'ANSWER' ? 'Examiner → Candidate' : 'Candidate → Examiner', _jsx("span", { className: "text-gray-400", children: "|" }), " ", modeLabel] }), isFirstInGroup ? (_jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Table2, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: "text-sm font-semibold text-gray-800", children: "Th\u00F4ng tin chung" }), isGrouped && (_jsxs("span", { className: "inline-flex items-center rounded-full border border-teal-300 bg-teal-100 px-2.5 py-0.5 text-xs font-semibold text-teal-700", children: ["Nh\u00F3m ", currentGroupNumber] }))] }), _jsx("p", { className: "text-sm text-gray-500", children: "D\u00F9ng chung cho t\u1EA5t c\u1EA3 c\u00E2u h\u1ECFi trong nh\u00F3m \u2014 Ti\u00EAu \u0111\u1EC1, h\u00ECnh \u1EA3nh, v\u00E0 2 b\u1EA3ng th\u00F4ng tin" })] })] }), children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(MessageSquareText, { className: "h-4 w-4 text-teal-500" }), "Ti\u00EAu \u0111\u1EC1 ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: groupTitle, onChange: (e) => {
372
+ updateGroupData({ title: e.target.value });
373
+ setValue('title', e.target.value, { shouldDirty: true });
374
+ }, placeholder: "VD: Katy's house", className: "border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200" })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-teal-500" }), "H\u00ECnh \u1EA3nh minh ho\u1EA1"] }), _jsx(FileUpload, { accept: "image/*", value: groupImageUrl, onChange: (url) => {
375
+ updateGroupData({ imageUrl: url });
376
+ setValue('imageUrl', url, { shouldDirty: true });
377
+ }, placeholder: "Upload h\u00ECnh \u1EA3nh", label: "", autoUpload: true, prefix: "info-exchange" }), groupImageUrl && (_jsx(ImagePreview, { imageUrl: groupImageUrl, label: "H\u00ECnh \u1EA3nh minh ho\u1EA1" }))] }), _jsxs("div", { className: "space-y-5", children: [_jsx("div", { className: "space-y-3", children: _jsxs("div", { className: "rounded-xl border border-teal-200 overflow-hidden shadow-sm bg-white", children: [_jsx("div", { className: "bg-gradient-to-r from-teal-600 to-emerald-600 px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-white/20 backdrop-blur-sm", children: _jsx(Table2, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: "Candidate's Copy" }), _jsx("p", { className: "text-[10px] text-teal-100 font-medium", children: "B\u1EA3ng th\u00F4ng tin h\u1ECDc sinh nh\u00ECn th\u1EA5y" })] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "inline-flex items-center rounded-full bg-white/20 backdrop-blur-sm px-2 py-0.5 text-[10px] font-bold text-white", children: [groupCandidateFields.length, " d\u00F2ng"] }) })] }) }), _jsx("div", { className: "bg-teal-50/60 border-b border-teal-100 px-4 py-2", children: _jsx("p", { className: "text-xs font-semibold text-teal-800 text-center", children: groupTitle || '(Chưa nhập tiêu đề)' }) }), _jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] bg-gradient-to-r from-teal-50/80 to-emerald-50/80 border-b border-teal-100", children: [_jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider text-center", children: "#" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Value" }), _jsx("div", {})] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupCandidateFields.map((field, index) => (_jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] items-center bg-white hover:bg-teal-50/30 transition-colors group/row", children: [_jsx("div", { className: "px-2 py-2 flex justify-center", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-teal-100 text-teal-700 font-bold text-[11px]", children: index + 1 }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.key, onChange: (e) => handleUpdateCandidateField(index, 'key', e.target.value), placeholder: "VD: Where", className: "h-8 text-sm border-gray-200 bg-white focus:border-teal-400 focus:ring-teal-200 transition-all" }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.answer, onChange: (e) => handleUpdateCandidateField(index, 'answer', e.target.value), placeholder: "VD: King Road", className: "h-8 text-sm border-gray-200 bg-white focus:border-teal-400 focus:ring-teal-200 transition-all" }) }), _jsx("div", { className: "px-1 py-1.5 flex justify-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => handleRemoveCandidateField(index), disabled: groupCandidateFields.length <= 1, className: "h-7 w-7 text-gray-300 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/row:opacity-100 transition-all disabled:opacity-0 disabled:group-hover/row:opacity-30", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) })] }, index))) }), _jsx("div", { className: "border-t border-dashed border-teal-200 bg-teal-50/30", children: _jsxs("button", { type: "button", onClick: handleAddCandidateField, className: "w-full flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold text-teal-600 hover:text-teal-700 hover:bg-teal-50 transition-colors cursor-pointer", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm d\u00F2ng"] }) })] }) }), _jsx("div", { className: "space-y-3", children: _jsxs("div", { className: "rounded-xl border border-amber-200 overflow-hidden shadow-sm bg-white", children: [_jsx("div", { className: "bg-gradient-to-r from-amber-600 to-orange-600 px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-white/20 backdrop-blur-sm", children: _jsx(Table2, { className: "h-4 w-4 text-white" }) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: "Examiner's Copy" }), _jsx("p", { className: "text-[10px] text-amber-100 font-medium", children: "B\u1EA3ng th\u00F4ng tin gi\u00E1m kh\u1EA3o nh\u00ECn th\u1EA5y" })] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: "inline-flex items-center rounded-full bg-white/20 backdrop-blur-sm px-2 py-0.5 text-[10px] font-bold text-white", children: [groupExaminerFields.length, " d\u00F2ng"] }) })] }) }), _jsx("div", { className: "bg-amber-50/60 border-b border-amber-100 px-4 py-2", children: _jsx("p", { className: "text-xs font-semibold text-amber-800 text-center", children: groupTitle || '(Chưa nhập tiêu đề)' }) }), _jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] bg-gradient-to-r from-amber-50/80 to-orange-50/80 border-b border-amber-100", children: [_jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider text-center", children: "#" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-2 py-2 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Value" }), _jsx("div", {})] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupExaminerFields.map((field, index) => (_jsxs("div", { className: "grid grid-cols-[40px_1fr_1fr_36px] items-center bg-white hover:bg-amber-50/30 transition-colors group/row", children: [_jsx("div", { className: "px-2 py-2 flex justify-center", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-amber-100 text-amber-700 font-bold text-[11px]", children: index + 1 }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.key, onChange: (e) => handleUpdateExaminerField(index, 'key', e.target.value), placeholder: "VD: Where", className: "h-8 text-sm border-gray-200 bg-white focus:border-amber-400 focus:ring-amber-200 transition-all" }) }), _jsx("div", { className: "px-1.5 py-1.5", children: _jsx(Input, { value: field.answer, onChange: (e) => handleUpdateExaminerField(index, 'answer', e.target.value), placeholder: "VD: King Road", className: "h-8 text-sm border-gray-200 bg-white focus:border-amber-400 focus:ring-amber-200 transition-all" }) }), _jsx("div", { className: "px-1 py-1.5 flex justify-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => handleRemoveExaminerField(index), disabled: groupExaminerFields.length <= 1, className: "h-7 w-7 text-gray-300 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/row:opacity-100 transition-all disabled:opacity-0 disabled:group-hover/row:opacity-30", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) })] }, index))) }), _jsx("div", { className: "border-t border-dashed border-amber-200 bg-amber-50/30", children: _jsxs("button", { type: "button", onClick: handleAddExaminerField, className: "w-full flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold text-amber-600 hover:text-amber-700 hover:bg-amber-50 transition-colors cursor-pointer", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm d\u00F2ng"] }) })] }) })] })] })) : (_jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Table2, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: "text-sm font-semibold text-gray-800", children: "Th\u00F4ng tin chung" }), _jsxs("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500", children: ["Nh\u00F3m ", currentGroupNumber, " \u2014 Ch\u1EC9 \u0111\u1ECDc"] })] }), _jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: "\u0110\u01B0\u1EE3c qu\u1EA3n l\u00FD b\u1EDFi c\u00E2u h\u1ECFi \u0111\u1EA7u ti\u00EAn trong nh\u00F3m" })] })] }), children: _jsxs("div", { className: "space-y-3", children: [groupTitle && (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-lg bg-teal-50/50 border border-teal-100", children: [_jsx(MessageSquareText, { className: "h-4 w-4 text-teal-500 shrink-0" }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: groupTitle })] })), groupImageUrl && (_jsx(ImagePreview, { imageUrl: groupImageUrl, label: groupTitle || 'Hình ảnh minh hoạ' })), _jsxs("div", { className: "space-y-4", children: [groupCandidateFields.length > 0 && (_jsxs("div", { className: "rounded-xl overflow-hidden border border-teal-200 shadow-sm", children: [_jsx("div", { className: "bg-gradient-to-r from-teal-600 to-emerald-600 px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded bg-white/20", children: _jsx(Table2, { className: "h-3 w-3 text-white" }) }), _jsx("span", { className: "text-xs font-bold text-white tracking-wide", children: "Candidate's Copy" })] }), _jsxs("span", { className: "text-[10px] font-semibold text-teal-100 bg-white/15 rounded-full px-1.5 py-0.5", children: [groupCandidateFields.length, " d\u00F2ng"] })] }) }), _jsx("div", { className: "bg-teal-50/60 text-center font-semibold text-xs py-2 border-b border-teal-100 text-teal-800", children: groupTitle || '(Chưa nhập tiêu đề)' }), _jsxs("div", { className: "grid grid-cols-2 bg-teal-50/40 border-b border-teal-100", children: [_jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-teal-600 uppercase tracking-wider", children: "Value" })] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupCandidateFields.map((row, index) => (_jsxs("div", { className: "grid grid-cols-2 bg-white hover:bg-teal-50/20 transition-colors", children: [_jsx("div", { className: "px-3 py-2 text-sm font-medium text-gray-700", children: row.key || _jsx("span", { className: "text-gray-300 italic", children: '(Chưa nhập)' }) }), _jsx("div", { className: "px-3 py-2 text-sm text-gray-800", children: row.answer || _jsx("span", { className: "text-gray-300", children: '—' }) })] }, index))) })] })), groupExaminerFields.length > 0 && (_jsxs("div", { className: "rounded-xl overflow-hidden border border-amber-200 shadow-sm", children: [_jsx("div", { className: "bg-gradient-to-r from-amber-600 to-orange-600 px-3 py-2.5", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded bg-white/20", children: _jsx(Table2, { className: "h-3 w-3 text-white" }) }), _jsx("span", { className: "text-xs font-bold text-white tracking-wide", children: "Examiner's Copy" })] }), _jsxs("span", { className: "text-[10px] font-semibold text-amber-100 bg-white/15 rounded-full px-1.5 py-0.5", children: [groupExaminerFields.length, " d\u00F2ng"] })] }) }), _jsx("div", { className: "bg-amber-50/60 text-center font-semibold text-xs py-2 border-b border-amber-100 text-amber-800", children: groupTitle || '(Chưa nhập tiêu đề)' }), _jsxs("div", { className: "grid grid-cols-2 bg-amber-50/40 border-b border-amber-100", children: [_jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Key" }), _jsx("div", { className: "px-3 py-1.5 text-[10px] font-bold text-amber-600 uppercase tracking-wider", children: "Value" })] }), _jsx("div", { className: "divide-y divide-gray-100", children: groupExaminerFields.map((row, index) => (_jsxs("div", { className: "grid grid-cols-2 bg-white hover:bg-amber-50/20 transition-colors", children: [_jsx("div", { className: "px-3 py-2 text-sm font-medium text-gray-700", children: row.key || _jsx("span", { className: "text-gray-300 italic", children: '(Chưa nhập)' }) }), _jsx("div", { className: "px-3 py-2 text-sm text-gray-800", children: row.answer || _jsx("span", { className: "text-gray-300", children: '—' }) })] }, index))) })] }))] }), groupCandidateFields.length === 0 && groupExaminerFields.length === 0 && (_jsx("div", { className: "text-center py-4 text-sm text-gray-400 italic", children: "Ch\u01B0a c\u00F3 d\u1EEF li\u1EC7u b\u1EA3ng th\u00F4ng tin" }))] }) })), _jsxs(Form, { ...form, children: [_jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Mic, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("p", { className: "text-sm font-semibold text-gray-800", children: ["C\u00E2u h\u1ECFi #", displayQuestionNumber] })] }), children: _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Volume2, { className: "h-4 w-4 text-indigo-500" }), audioLabel, " ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(FormField, { control: control, name: "audioUrl", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormControl, { children: _jsx(FileUpload, { id: `audio-info-exchange-${displayQuestionNumber}`, label: "", accept: "audio/*", value: field.value, onChange: (url) => { field.onChange(url); clearErrors('audioUrl'); }, maxSize: 10, placeholder: "T\u1EA3i l\u00EAn file \u00E2m thanh (mp3, wav...)", autoUpload: true, prefix: "info-exchange" }) }), _jsx(FormMessage, {})] })) })] }) }), _jsxs(CompactFieldCard, { header: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(MessageSquareText, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("p", { className: "text-sm font-semibold text-gray-800", children: "\u0110\u00E1p \u00E1n mong mu\u1ED1n" })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addExpectedAnswer, className: "gap-2 border-green-200 text-green-600 hover:bg-green-50", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n"] })] }), children: [_jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50/60 px-3 py-2 text-xs text-blue-700", children: [_jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: "Ch\u1EA5m th\u1EE7 c\u00F4ng: gi\u00E1o vi\u00EAn tham kh\u1EA3o \u0111\u00E1p \u00E1n \u0111\u1EC3 ch\u1EA5m \u00B7 Ch\u1EA5m t\u1EF1 \u0111\u1ED9ng: AI so s\u00E1nh gi\u1ECDng n\u00F3i h\u1ECDc sinh v\u1EDBi \u0111\u00E1p \u00E1n." })] }), _jsx(FormField, { control: control, name: "expectedAnswers", render: () => (_jsxs(FormItem, { children: [_jsx("div", { className: "space-y-3", children: watchedExpectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-start gap-3 group/answer", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-700 text-sm font-bold mt-1", children: index + 1 }), _jsxs("div", { className: "flex-1", children: [_jsx(Input, { placeholder: answerPlaceholder, value: answer || '', onChange: (e) => handleExpectedAnswerChange(index, e.target.value), className: "border-gray-200 focus:border-green-300 focus:ring-green-200" }), form.formState.errors?.expectedAnswers?.[index]?.message && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: form.formState.errors.expectedAnswers[index]?.message }))] }), watchedExpectedAnswers.length > 1 && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeExpectedAnswer(index), className: "mt-0.5 h-8 w-8 rounded-full text-gray-400 hover:text-red-600 hover:bg-red-50 opacity-0 group-hover/answer:opacity-100 transition-opacity", "aria-label": `Xóa đáp án ${index + 1}`, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }, index))) }), form.formState.errors?.expectedAnswers?.message && (_jsx(FormMessage, {}))] })) })] }), _jsx(CompactExplanationToggle, { value: watchedExplanation || '', onValueChange: (value) => form.setValue('explanation', value, { shouldValidate: true }), defaultVisible: Boolean(watchedExplanation) })] })] }));
385
378
  }
@@ -20,7 +20,7 @@ function OddOneOutImage({ imageUrl, index }) {
20
20
  // ─── Main Client Component ───────────────────────────────────────────────────
21
21
  export function ListenAndSpeakOddOneOutClient({ questionData, isReviewMode = false, }) {
22
22
  const { audioUrl, images, oddOneOutIndex, expectedAnswers = [], explanation } = questionData;
23
- return (_jsxs("div", { className: "space-y-4", children: [questionData.isBackup && (_jsxs("div", { className: "inline-flex self-center items-center gap-1.5 px-3 py-1.5 rounded-md bg-amber-50 text-amber-700 border border-amber-200 text-xs font-bold shadow-sm", children: [_jsx("span", { children: "\uD83D\uDD04" }), " C\u00E2u h\u1ECFi d\u1EF1 ph\u00F2ng"] })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-indigo-50 to-blue-50 px-5 py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-indigo-500 to-blue-600 text-white shadow-sm", children: _jsx(CircleOff, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Nghe v\u00E0 n\u00F3i (T\u00ECm h\u00ECnh kh\u00E1c lo\u1EA1i)" })] }) }), _jsxs("div", { className: "p-5 space-y-5", children: [images && images.length > 0 && (_jsx("div", { className: "bg-gradient-to-br from-amber-50/80 to-orange-50/60 rounded-2xl p-6 border border-amber-100/80 shadow-sm space-y-4", children: images.length === 4 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "grid grid-cols-3 gap-4", children: images.slice(0, 3).map((imgUrl, index) => (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx("span", { className: `flex h-6 w-6 items-center justify-center rounded-md text-xs font-bold ${isReviewMode && oddOneOutIndex === index ? 'bg-red-200 text-red-800' : 'bg-amber-200 text-amber-800'}`, children: index + 1 }), isReviewMode && oddOneOutIndex === index && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-[10px] font-bold text-red-700", children: [_jsx(CircleOff, { className: "h-2.5 w-2.5" }), "Kh\u00E1c lo\u1EA1i"] }))] }), _jsx("div", { className: `relative aspect-square rounded-xl overflow-hidden border-2 bg-white shadow-sm ${isReviewMode && oddOneOutIndex === index ? 'border-red-400 ring-2 ring-red-200' : 'border-gray-200'}`, children: imgUrl ? (_jsx(OddOneOutImage, { imageUrl: imgUrl, index: index })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-gray-400 text-sm", children: _jsx(ImageIcon, { className: "h-6 w-6" }) })) })] }, index))) }), _jsx("div", { className: "flex justify-center", children: _jsx("div", { className: "w-1/3", children: _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx("span", { className: `flex h-6 w-6 items-center justify-center rounded-md text-xs font-bold ${isReviewMode && oddOneOutIndex === 3 ? 'bg-red-200 text-red-800' : 'bg-amber-200 text-amber-800'}`, children: "4" }), isReviewMode && oddOneOutIndex === 3 && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-[10px] font-bold text-red-700", children: [_jsx(CircleOff, { className: "h-2.5 w-2.5" }), "Kh\u00E1c lo\u1EA1i"] }))] }), _jsx("div", { className: `relative aspect-square rounded-xl overflow-hidden border-2 bg-white shadow-sm ${isReviewMode && oddOneOutIndex === 3 ? 'border-red-400 ring-2 ring-red-200' : 'border-gray-200'}`, children: images[3] ? (_jsx(OddOneOutImage, { imageUrl: images[3], index: 3 })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-gray-400 text-sm", children: _jsx(ImageIcon, { className: "h-6 w-6" }) })) })] }) }) })] })) : (
23
+ return (_jsxs("div", { className: "space-y-4", children: [questionData.isBackup && (_jsxs("div", { className: "inline-flex self-center items-center gap-1.5 px-3 py-1.5 rounded-md bg-amber-50 text-amber-700 border border-amber-200 text-xs font-bold shadow-sm", children: [_jsx("span", { children: "\uD83D\uDD04" }), " C\u00E2u h\u1ECFi d\u1EF1 ph\u00F2ng"] })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsx("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gray-50 px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100 text-gray-600", children: _jsx(CircleOff, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Nghe v\u00E0 n\u00F3i (T\u00ECm h\u00ECnh kh\u00E1c lo\u1EA1i)" })] }) }), _jsxs("div", { className: "p-3 space-y-3", children: [images && images.length > 0 && (_jsx("div", { className: "bg-gradient-to-br from-amber-50/80 to-orange-50/60 rounded-2xl p-6 border border-amber-100/80 shadow-sm space-y-4", children: images.length === 4 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "grid grid-cols-3 gap-4", children: images.slice(0, 3).map((imgUrl, index) => (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx("span", { className: `flex h-6 w-6 items-center justify-center rounded-md text-xs font-bold ${isReviewMode && oddOneOutIndex === index ? 'bg-red-200 text-red-800' : 'bg-amber-200 text-amber-800'}`, children: index + 1 }), isReviewMode && oddOneOutIndex === index && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-[10px] font-bold text-red-700", children: [_jsx(CircleOff, { className: "h-2.5 w-2.5" }), "Kh\u00E1c lo\u1EA1i"] }))] }), _jsx("div", { className: `relative aspect-square rounded-xl overflow-hidden border-2 bg-white shadow-sm ${isReviewMode && oddOneOutIndex === index ? 'border-red-400 ring-2 ring-red-200' : 'border-gray-200'}`, children: imgUrl ? (_jsx(OddOneOutImage, { imageUrl: imgUrl, index: index })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-gray-400 text-sm", children: _jsx(ImageIcon, { className: "h-6 w-6" }) })) })] }, index))) }), _jsx("div", { className: "flex justify-center", children: _jsx("div", { className: "w-1/3", children: _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx("span", { className: `flex h-6 w-6 items-center justify-center rounded-md text-xs font-bold ${isReviewMode && oddOneOutIndex === 3 ? 'bg-red-200 text-red-800' : 'bg-amber-200 text-amber-800'}`, children: "4" }), isReviewMode && oddOneOutIndex === 3 && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-[10px] font-bold text-red-700", children: [_jsx(CircleOff, { className: "h-2.5 w-2.5" }), "Kh\u00E1c lo\u1EA1i"] }))] }), _jsx("div", { className: `relative aspect-square rounded-xl overflow-hidden border-2 bg-white shadow-sm ${isReviewMode && oddOneOutIndex === 3 ? 'border-red-400 ring-2 ring-red-200' : 'border-gray-200'}`, children: images[3] ? (_jsx(OddOneOutImage, { imageUrl: images[3], index: 3 })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-gray-400 text-sm", children: _jsx(ImageIcon, { className: "h-6 w-6" }) })) })] }) }) })] })) : (
24
24
  /* Fallback: equal grid for other counts */
25
25
  _jsx("div", { className: "grid grid-cols-2 gap-4", children: images.map((imgUrl, index) => (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx("span", { className: `flex h-6 w-6 items-center justify-center rounded-md text-xs font-bold ${isReviewMode && oddOneOutIndex === index ? 'bg-red-200 text-red-800' : 'bg-amber-200 text-amber-800'}`, children: index + 1 }), isReviewMode && oddOneOutIndex === index && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-[10px] font-bold text-red-700", children: [_jsx(CircleOff, { className: "h-2.5 w-2.5" }), "Kh\u00E1c lo\u1EA1i"] }))] }), _jsx("div", { className: `relative aspect-square rounded-xl overflow-hidden border-2 bg-white shadow-sm ${isReviewMode && oddOneOutIndex === index ? 'border-red-400 ring-2 ring-red-200' : 'border-gray-200'}`, children: imgUrl ? (_jsx(OddOneOutImage, { imageUrl: imgUrl, index: index })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-gray-400 text-sm", children: _jsx(ImageIcon, { className: "h-6 w-6" }) })) })] }, index))) })) })), audioUrl ? (_jsx(QuestionAudioPlayer, { audioUrl: audioUrl })) : (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3", children: [_jsx(Volume2, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-xs text-gray-400", children: "Ch\u01B0a c\u00F3 audio c\u00E2u h\u1ECFi" })] })), _jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-dashed border-gray-300 bg-gray-50/80 px-4 py-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-indigo-50 ring-2 ring-indigo-100/50", children: _jsx(Mic, { className: "w-4 h-4 text-indigo-400" }) }), _jsx("p", { className: "text-xs text-gray-400", children: "H\u1ECDc sinh s\u1EBD nh\u1EA5n n\u00FAt ghi \u00E2m v\u00E0 n\u00F3i c\u00E2u tr\u1EA3 l\u1EDDi t\u1EA1i \u0111\u00E2y" })] }), isReviewMode && expectedAnswers.length > 0 && (_jsxs("div", { className: "rounded-xl border border-green-200 bg-green-50/80 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsx("h4", { className: "text-sm font-semibold text-green-800", children: "C\u00E1c \u0111\u00E1p \u00E1n mong mu\u1ED1n" })] }), _jsx("div", { className: "space-y-2", children: expectedAnswers.map((answer, index) => (_jsxs("div", { className: "flex items-center gap-2.5 rounded-lg bg-white/70 border border-green-100 px-3 py-2", children: [_jsx("span", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-green-100 text-green-700 text-xs font-bold", children: index + 1 }), _jsx("span", { className: "text-sm text-green-800", children: answer })] }, index))) })] })), isReviewMode && explanation && (_jsxs("div", { className: "rounded-xl border border-indigo-200 bg-indigo-50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Info, { className: "h-4 w-4 text-indigo-600" }), _jsx("p", { className: "text-sm font-semibold text-indigo-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("p", { className: "text-sm text-indigo-700 leading-relaxed", children: explanation })] }))] })] })] }));
26
26
  }