@tinyweb_dev/oe-exam-sdk 1.0.6 → 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,14 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef, useEffect } from 'react';
4
- import { Button } from '../../../../components/ui/button';
5
4
  import { Label } from '../../../../components/ui/label';
6
5
  import { Input } from '../../../../components/ui/input';
7
- import { Textarea } from '../../../../components/ui/textarea';
8
- import { PointsInput } from '../../../../components/ui/points-input';
9
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
10
6
  import { Switch } from '../../../../components/ui/switch';
11
- import { Pencil, Eye, Lightbulb, PenTool, MessageSquare, ToggleLeft, CheckCircle2, BookOpen } from 'lucide-react';
7
+ import { Eye, PenTool, MessageSquare, ToggleLeft, CheckCircle2 } from 'lucide-react';
8
+ import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
12
9
  import { WriteCorrectVerbFormClient } from './WriteCorrectVerbFormClient';
13
10
  import { useDebouncedCallback } from '../../../../shared/lib/hooks';
14
11
  function WriteCorrectVerbFormCreatorContent({ initialData, onSave, onCancel, onChange, externalErrors, onUnsavedChangesChange, validationRef, }) {
@@ -171,25 +168,28 @@ function WriteCorrectVerbFormCreatorContent({ initialData, onSave, onCancel, onC
171
168
  caseSensitive,
172
169
  instruction,
173
170
  };
174
- 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, { children: "Write the Correct Form of the Verb (Preview)" }), _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(WriteCorrectVerbFormClient, { questionData: { ...questionData, explanation }, isReviewMode: true, userAnswer: correctAnswer })] }));
171
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(WriteCorrectVerbFormClient, { questionData: { ...questionData, explanation }, isReviewMode: true, userAnswer: correctAnswer })] }));
175
172
  }
176
173
  // ============ CREATOR UI ============
177
- return (_jsxs("div", { className: "space-y-6", children: [_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-orange-500 via-amber-500 to-yellow-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-orange-500 to-amber-600 shadow-md", children: _jsx(PenTool, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold text-gray-900", children: "Vi\u1EBFt d\u1EA1ng \u0111\u00FAng c\u1EE7a \u0111\u1ED9ng t\u1EEB" }), _jsx("p", { className: "text-sm text-gray-500", children: "Chia \u0111\u1ED9ng t\u1EEB trong ngo\u1EB7c \u0111\u00FAng th\u00EC" })] })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: !isValid(), className: "gap-2 border-amber-200 text-amber-600 hover:bg-amber-50 hover:text-amber-700", children: [_jsx(Eye, { className: "h-4 w-4" }), "Xem tr\u01B0\u1EDBc"] })] }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsx("div", { className: "rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4", children: _jsx(PointsInput, { defaultValue: points, onChange: (e) => setPoints(Number(e.target.value) || 1) }) }), _jsx("div", { className: "rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-5 shadow-sm", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-amber-100", children: _jsx(Lightbulb, { className: "h-4 w-4 text-amber-600" }) }), _jsxs("div", { className: "text-sm text-amber-900", children: [_jsx("p", { className: "font-semibold text-amber-800", children: "H\u01B0\u1EDBng d\u1EABn t\u1EA1o c\u00E2u h\u1ECFi" }), _jsxs("ul", { className: "mt-2 space-y-1.5 text-amber-700", children: [_jsxs("li", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-400" }), "S\u1EED d\u1EE5ng ", _jsx("code", { className: "mx-1 rounded bg-amber-100 px-1.5 py-0.5 font-mono text-amber-800", children: '{0}' }), " \u0111\u1EC3 \u0111\u00E1nh d\u1EA5u ch\u1ED7 tr\u1ED1ng trong c\u00E2u"] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-400" }), "Nh\u1EADp \u0111\u1ED9ng t\u1EEB g\u1EE3i \u00FD (d\u1EA1ng nguy\u00EAn m\u1EABu) v\u00E0o \u00F4 \"G\u1EE3i \u00FD \u0111\u1ED9ng t\u1EEB\""] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-400" }), "H\u1ECDc sinh s\u1EBD vi\u1EBFt d\u1EA1ng \u0111\u00FAng c\u1EE7a \u0111\u1ED9ng t\u1EEB \u0111\u1EC3 ho\u00E0n th\u00E0nh c\u00E2u"] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-400" }), "V\u00ED d\u1EE5: ", _jsxs("code", { className: "ml-1 rounded bg-amber-100 px-1.5 py-0.5 font-mono text-amber-800 select-all cursor-pointer", title: "Click \u0111\u1EC3 copy", children: ["John ", '{0}', " his homework at night."] })] })] })] })] }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-amber-500" }), "C\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: sentence, onChange: (e) => {
178
- setSentence(e.target.value);
179
- if (validationErrors.sentence) {
180
- setValidationErrors(prev => ({ ...prev, sentence: undefined }));
181
- }
182
- }, placeholder: "V\u00ED d\u1EE5: John {0} his homework at night.", className: `border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 ${validationErrors.sentence ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.sentence && (_jsx("p", { className: "text-sm text-red-600", children: validationErrors.sentence }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: `rounded-xl border-2 p-4 transition-all ${verbHint ? 'border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50' : 'border-gray-200 bg-white'}`, children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-700", children: [_jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-amber-100 text-xs font-bold text-amber-600", children: "V" }), "G\u1EE3i \u00FD \u0111\u1ED9ng t\u1EEB ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: verbHint, onChange: (e) => {
183
- setVerbHint(e.target.value);
184
- if (validationErrors.verbHint) {
185
- setValidationErrors(prev => ({ ...prev, verbHint: undefined }));
186
- }
187
- }, placeholder: "V\u00ED d\u1EE5: do", className: `mt-2 border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 ${validationErrors.verbHint ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.verbHint && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.verbHint }))] }), _jsxs("div", { className: `rounded-xl border-2 p-4 transition-all ${correctAnswer ? 'border-green-200 bg-gradient-to-r from-green-50 to-emerald-50' : 'border-gray-200 bg-white'}`, children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-700", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), "\u0110\u00E1p \u00E1n \u0111\u00FAng ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: correctAnswer, onChange: (e) => {
188
- setCorrectAnswer(e.target.value);
189
- if (validationErrors.correctAnswer) {
190
- setValidationErrors(prev => ({ ...prev, correctAnswer: undefined }));
191
- }
192
- }, placeholder: "V\u00ED d\u1EE5: does", className: `mt-2 border-gray-200 bg-white transition-all focus:border-green-300 focus:ring-green-200 ${validationErrors.correctAnswer ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.correctAnswer && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.correctAnswer }))] })] }), _jsxs("div", { className: "flex items-center justify-between rounded-xl border-2 border-gray-200 bg-white p-4 transition-all hover:border-gray-300", 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-gray-100", children: _jsx(ToggleLeft, { className: "h-4 w-4 text-gray-600" }) }), _jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "caseSensitive", className: "font-semibold text-gray-800", children: "Ph\u00E2n bi\u1EC7t ch\u1EEF hoa/th\u01B0\u1EDDng" }), _jsx("p", { className: "text-sm text-gray-500", children: "B\u1EADt n\u1EBFu \u0111\u00E1p \u00E1n c\u1EA7n kh\u1EDBp ch\u00EDnh x\u00E1c (v\u00ED d\u1EE5: \"Does\" \u2260 \"does\")" })] })] }), _jsx(Switch, { id: "caseSensitive", checked: caseSensitive, onCheckedChange: setCaseSensitive })] }), sentence && verbHint && (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2 text-xs font-semibold text-gray-600", children: [_jsx(Eye, { className: "h-3.5 w-3.5" }), "Xem tr\u01B0\u1EDBc c\u00E2u h\u1ECFi"] }), _jsxs("p", { className: "text-sm text-gray-700", children: [sentence.replace('{0}', '_______'), " ", _jsxs("span", { className: "font-semibold text-amber-600", children: ["(", verbHint, ")"] })] }), correctAnswer && (_jsxs("div", { className: "mt-2 flex items-center gap-2 rounded-lg bg-green-50 px-3 py-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-500" }), _jsxs("span", { className: "text-sm text-green-700", children: ["\u0110\u00E1p \u00E1n: ", _jsx("strong", { children: sentence.replace('{0}', correctAnswer) })] })] }))] })), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100", children: _jsx("span", { className: "text-lg", children: "\u274C" }) }), _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] })] }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white 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, { id: "explanation", value: explanation, onChange: (e) => setExplanation(e.target.value), 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" }) })] })] }));
174
+ return (_jsx("div", { className: "space-y-3", children: _jsxs(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(PenTool, { className: "h-3.5 w-3.5" }), title: "Vi\u1EBFt d\u1EA1ng \u0111\u00FAng c\u1EE7a \u0111\u1ED9ng t\u1EEB", points: { value: points, onValueChange: setPoints }, preview: {
175
+ onClick: () => setIsClientMode(true),
176
+ disabled: !isValid(),
177
+ } }), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsxs(Label, { className: "flex items-center gap-1.5 text-sm font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-3.5 w-3.5 text-amber-500" }), "C\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: sentence, onChange: (e) => {
178
+ setSentence(e.target.value);
179
+ if (validationErrors.sentence) {
180
+ setValidationErrors(prev => ({ ...prev, sentence: undefined }));
181
+ }
182
+ }, placeholder: "V\u00ED d\u1EE5: John {0} his homework at night.", className: `h-8 border-gray-200 bg-white ${validationErrors.sentence ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.sentence && (_jsx("p", { className: "text-sm text-red-600", children: validationErrors.sentence }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-2.5", children: [_jsxs("div", { className: `rounded-md border p-2.5 ${verbHint ? 'border-amber-200 bg-amber-50/70' : 'border-gray-200 bg-white'}`, children: [_jsxs(Label, { className: "flex items-center gap-1.5 text-xs font-semibold text-gray-700", children: [_jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-md bg-amber-100 text-[10px] font-bold text-amber-600", children: "V" }), "G\u1EE3i \u00FD \u0111\u1ED9ng t\u1EEB ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: verbHint, onChange: (e) => {
183
+ setVerbHint(e.target.value);
184
+ if (validationErrors.verbHint) {
185
+ setValidationErrors(prev => ({ ...prev, verbHint: undefined }));
186
+ }
187
+ }, placeholder: "V\u00ED d\u1EE5: do", className: `mt-1.5 h-8 border-gray-200 bg-white ${validationErrors.verbHint ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.verbHint && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.verbHint }))] }), _jsxs("div", { className: `rounded-md border p-2.5 ${correctAnswer ? 'border-green-200 bg-green-50/70' : 'border-gray-200 bg-white'}`, children: [_jsxs(Label, { className: "flex items-center gap-1.5 text-xs font-semibold text-gray-700", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5 text-green-600" }), "\u0110\u00E1p \u00E1n \u0111\u00FAng ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { value: correctAnswer, onChange: (e) => {
188
+ setCorrectAnswer(e.target.value);
189
+ if (validationErrors.correctAnswer) {
190
+ setValidationErrors(prev => ({ ...prev, correctAnswer: undefined }));
191
+ }
192
+ }, placeholder: "V\u00ED d\u1EE5: does", className: `mt-1.5 h-8 border-gray-200 bg-white ${validationErrors.correctAnswer ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.correctAnswer && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.correctAnswer }))] })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md border border-gray-200 bg-white px-2.5 py-2", 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(ToggleLeft, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "caseSensitive", className: "text-sm font-semibold text-gray-800", children: "Ph\u00E2n bi\u1EC7t ch\u1EEF hoa/th\u01B0\u1EDDng" }), _jsx("p", { className: "text-xs text-gray-500", children: "B\u1EADt n\u1EBFu \u0111\u00E1p \u00E1n c\u1EA7n kh\u1EDBp ch\u00EDnh x\u00E1c (v\u00ED d\u1EE5: \"Does\" \u2260 \"does\")" })] })] }), _jsx(Switch, { id: "caseSensitive", checked: caseSensitive, onCheckedChange: setCaseSensitive })] }), sentence && verbHint && (_jsxs("div", { className: "rounded-md border border-gray-200 bg-gray-50 p-2.5", children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 text-xs font-semibold text-gray-600", children: [_jsx(Eye, { className: "h-3.5 w-3.5" }), "Xem tr\u01B0\u1EDBc c\u00E2u h\u1ECFi"] }), _jsxs("p", { className: "text-sm text-gray-700", children: [sentence.replace('{0}', '_______'), " ", _jsxs("span", { className: "font-semibold text-amber-600", children: ["(", verbHint, ")"] })] }), correctAnswer && (_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 rounded-md bg-green-50 px-2.5 py-1.5", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5 text-green-500" }), _jsxs("span", { className: "text-xs text-green-700", children: ["\u0110\u00E1p \u00E1n: ", _jsx("strong", { children: sentence.replace('{0}', correctAnswer) })] })] }))] })), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 rounded-md border border-red-200 bg-red-50 p-2 text-xs text-red-700", children: [_jsx("span", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("span", { children: externalErrors.join(' · ') })] })), _jsx(CompactExplanationToggle, { value: explanation, onValueChange: setExplanation, defaultVisible: Boolean(initialData?.explanation) })] }) }));
193
193
  }
194
194
  export function WriteCorrectVerbFormCreator(props) {
195
195
  return _jsx(WriteCorrectVerbFormCreatorContent, { ...props });
@@ -1,13 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef, useEffect } from 'react';
4
- import { Button } from '../../../../components/ui/button';
5
4
  import { Input } from '../../../../components/ui/input';
6
5
  import { Label } from '../../../../components/ui/label';
7
6
  import { Textarea } from '../../../../components/ui/textarea';
8
- import { PointsInput } from '../../../../components/ui/points-input';
9
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
10
- import { Pencil, Eye, PenLine, BookOpen, Hash } from 'lucide-react';
7
+ import { PenLine, BookOpen, Hash } from 'lucide-react';
8
+ import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
11
9
  import { WriteSentencesClient } from './WriteSentencesClient';
12
10
  import { useDebouncedCallback } from '../../../../shared/lib/hooks';
13
11
  import { BasicQuestionGroupCard } from '../../groups/BasicQuestionGroupCard';
@@ -152,22 +150,27 @@ function WriteSentencesCreatorContent({ initialData, onChange, externalErrors, v
152
150
  instruction,
153
151
  sentenceCount,
154
152
  };
155
- 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: "Write Sentences (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Ch\u1EBF \u0111\u1ED9 xem tr\u01B0\u1EDBc" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) }) }), _jsx(WriteSentencesClient, { questionData: questionData, onSubmit: () => { }, isReviewMode: true, explanation: explanation })] }));
153
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(WriteSentencesClient, { questionData: questionData, onSubmit: () => { }, isReviewMode: true, explanation: explanation })] }));
156
154
  }
157
155
  // Creator UI
158
- return (_jsxs("div", { className: "space-y-6", children: [isGrouped && (_jsx(BasicQuestionGroupCard, { groupNumber: currentGroupNumber, title: groupTitle, subtitle: groupSubtitle, content: groupContent, imageUrl: imageUrl, onTitleChange: setGroupTitle, onSubtitleChange: setGroupSubtitle, onContentChange: setGroupContent, onImageChange: setImageUrl, uploadIdPrefix: `write-sentences-${partId ?? 'group'}` })), _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-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-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-teal-500 to-emerald-600 shadow-md", children: _jsx(PenLine, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold text-gray-900", children: "Vi\u1EBFt c\u00E2u" }), _jsx("p", { className: "text-sm text-gray-500", children: "H\u1ECDc sinh t\u1EF1 vi\u1EBFt m\u1ED9t c\u00E2u ho\u00E0n ch\u1EC9nh" })] })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), 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" }), "Xem tr\u01B0\u1EDBc"] })] }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx("div", { className: "rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4", children: _jsx(PointsInput, { defaultValue: points, onChange: (e) => setPoints(Number(e.target.value) || 1) }) }), _jsxs("div", { className: "rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4", children: [_jsxs(Label, { htmlFor: "sentenceCount", className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Hash, { className: "h-4 w-4 text-teal-500" }), "S\u1ED1 c\u00E2u c\u1EA7n vi\u1EBFt ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "sentenceCount", type: "number", min: 1, max: 10, value: sentenceCount ?? '', onChange: (e) => {
159
- const raw = e.target.value;
160
- if (raw === '') {
161
- setSentenceCount(undefined);
162
- }
163
- else {
164
- const val = parseInt(raw, 10);
165
- setSentenceCount(isNaN(val) ? undefined : Math.max(1, val));
166
- }
167
- if (validationErrors.sentenceCount) {
168
- setValidationErrors((prev) => ({ ...prev, sentenceCount: undefined }));
169
- }
170
- }, placeholder: "Nh\u1EADp s\u1ED1 c\u00E2u...", className: `mt-1.5 border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200 ${validationErrors.sentenceCount ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.sentenceCount && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.sentenceCount }))] })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "instruction", className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(BookOpen, { className: "h-4 w-4 text-teal-500" }), "H\u01B0\u1EDBng d\u1EABn ", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(Textarea, { id: "instruction", value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "V\u00ED d\u1EE5: Now write two sentences about the picture.", rows: 2, className: "border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200" })] }), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100", children: _jsx("span", { className: "text-lg", children: "\u274C" }) }), _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] })] }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white 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, { id: "explanation", value: explanation, onChange: (e) => setExplanation(e.target.value), 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" }) })] })] }));
156
+ return (_jsxs("div", { className: "space-y-3", children: [isGrouped && (_jsx(BasicQuestionGroupCard, { groupNumber: currentGroupNumber, title: groupTitle, subtitle: groupSubtitle, content: groupContent, imageUrl: imageUrl, onTitleChange: setGroupTitle, onSubtitleChange: setGroupSubtitle, onContentChange: setGroupContent, onImageChange: setImageUrl, uploadIdPrefix: `write-sentences-${partId ?? 'group'}` })), _jsxs(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(PenLine, { className: "h-3.5 w-3.5" }), title: "Vi\u1EBFt c\u00E2u", points: {
157
+ value: points,
158
+ onValueChange: setPoints,
159
+ }, preview: {
160
+ onClick: () => setIsClientMode(true),
161
+ } }), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsxs(Label, { htmlFor: "sentenceCount", className: "flex items-center gap-1.5 text-sm font-semibold text-gray-800", children: [_jsx(Hash, { className: "h-3.5 w-3.5 text-teal-500" }), "S\u1ED1 c\u00E2u c\u1EA7n vi\u1EBFt ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "sentenceCount", type: "number", min: 1, max: 10, value: sentenceCount ?? '', onChange: (e) => {
162
+ const raw = e.target.value;
163
+ if (raw === '') {
164
+ setSentenceCount(undefined);
165
+ }
166
+ else {
167
+ const val = parseInt(raw, 10);
168
+ setSentenceCount(isNaN(val) ? undefined : Math.max(1, val));
169
+ }
170
+ if (validationErrors.sentenceCount) {
171
+ setValidationErrors((prev) => ({ ...prev, sentenceCount: undefined }));
172
+ }
173
+ }, placeholder: "Nh\u1EADp s\u1ED1 c\u00E2u...", className: `mt-1.5 border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200 ${validationErrors.sentenceCount ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.sentenceCount && (_jsx("p", { className: "mt-1 text-sm text-red-600", children: validationErrors.sentenceCount }))] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs(Label, { htmlFor: "instruction", className: "flex items-center gap-1.5 text-sm font-semibold text-gray-800", children: [_jsx(BookOpen, { className: "h-3.5 w-3.5 text-teal-500" }), "H\u01B0\u1EDBng d\u1EABn ", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(Textarea, { id: "instruction", value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "V\u00ED d\u1EE5: Now write two sentences about the picture.", rows: 2, className: "border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200" })] }), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 rounded-md border border-red-200 bg-red-50 p-2 text-xs text-red-700", children: [_jsx("span", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("span", { children: externalErrors.join(' · ') })] }))] }), _jsx(CompactExplanationToggle, { value: explanation, onValueChange: setExplanation })] }));
171
174
  }
172
175
  export function WriteSentencesCreator(props) {
173
176
  return _jsx(WriteSentencesCreatorContent, { ...props });
@@ -62,7 +62,7 @@ export function WriteShortParagraphClient({ questionData, onSubmit, isReviewMode
62
62
  return 'Text';
63
63
  }
64
64
  };
65
- return (_jsxs("div", { className: "space-y-6", children: [instruction && (_jsx(Card, { children: _jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-lg", children: instruction }) }) })), contexts.length > 0 && (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Contexts" }) }), _jsx(CardContent, { children: _jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3", children: contexts.map((ctx, index) => (_jsx(ContextDisplay, { context: ctx, index: index }, ctx.id))) }) })] })), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(CardTitle, { children: "Vi\u1EBFt b\u00E0i" }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: `text-sm font-semibold ${isValidWordCount ? 'text-green-600' : 'text-red-600'}`, children: [wordCount, " / ", minWords, maxWords ? ` - ${maxWords}` : '+', " t\u1EEB"] }) })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "writing-answer", children: "N\u1ED9i dung b\u00E0i vi\u1EBFt" }), _jsx(Textarea, { id: "writing-answer", value: answer, onChange: (e) => handleAnswerChange(e.target.value), placeholder: "Nh\u1EADp n\u1ED9i dung b\u00E0i vi\u1EBFt c\u1EE7a b\u1EA1n...", className: "mt-2 min-h-[200px]", rows: 10, disabled: isReviewMode })] }), !isReviewMode && (_jsx("div", { className: "flex items-start gap-2 rounded-lg border p-3", children: isValidWordCount ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-0.5 h-5 w-5 rounded-full bg-green-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium text-green-700", children: "\u0110\u00E3 \u0111\u1EE7 s\u1ED1 t\u1EEB y\u00EAu c\u1EA7u" }), _jsxs("p", { className: "text-xs text-green-600", children: ["B\u1EA1n \u0111\u00E3 vi\u1EBFt ", wordCount, " t\u1EEB. Y\u00EAu c\u1EA7u: ", minWords, maxWords ? ` - ${maxWords}` : '+', " t\u1EEB."] })] })] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircle, { className: "h-5 w-5 text-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium text-amber-700", children: "Ch\u01B0a \u0111\u1EE7 s\u1ED1 t\u1EEB y\u00EAu c\u1EA7u" }), _jsxs("p", { className: "text-xs text-amber-600", children: ["B\u1EA1n \u0111\u00E3 vi\u1EBFt ", wordCount, " t\u1EEB. C\u1EA7n \u00EDt nh\u1EA5t ", minWords, " t\u1EEB.", maxWords && wordCount > maxWords && _jsxs("span", { children: [" T\u1ED1i \u0111a ", maxWords, " t\u1EEB."] })] })] })] })) }))] })] })] }));
65
+ return (_jsxs("div", { className: "space-y-3", children: [instruction && (_jsx(Card, { className: "border-0 shadow-sm", children: _jsx(CardHeader, { className: "px-3 py-2", children: _jsx(CardTitle, { className: "text-sm", children: instruction }) }) })), contexts.length > 0 && (_jsxs(Card, { className: "border-0 shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsx(CardTitle, { className: "text-sm", children: "Contexts" }) }), _jsx(CardContent, { className: "p-3 space-y-3", children: _jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3", children: contexts.map((ctx, index) => (_jsx(ContextDisplay, { context: ctx, index: index }, ctx.id))) }) })] })), _jsxs(Card, { className: "border-0 shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(CardTitle, { className: "text-sm", children: "Vi\u1EBFt b\u00E0i" }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("span", { className: `text-sm font-semibold ${isValidWordCount ? 'text-green-600' : 'text-red-600'}`, children: [wordCount, " / ", minWords, maxWords ? ` - ${maxWords}` : '+', " t\u1EEB"] }) })] }) }), _jsxs(CardContent, { className: "space-y-3 p-3", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "writing-answer", children: "N\u1ED9i dung b\u00E0i vi\u1EBFt" }), _jsx(Textarea, { id: "writing-answer", value: answer, onChange: (e) => handleAnswerChange(e.target.value), placeholder: "Nh\u1EADp n\u1ED9i dung b\u00E0i vi\u1EBFt c\u1EE7a b\u1EA1n...", className: "mt-2 min-h-[200px]", rows: 10, disabled: isReviewMode })] }), !isReviewMode && (_jsx("div", { className: "flex items-start gap-2 rounded-lg border p-3", children: isValidWordCount ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-0.5 h-5 w-5 rounded-full bg-green-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium text-green-700", children: "\u0110\u00E3 \u0111\u1EE7 s\u1ED1 t\u1EEB y\u00EAu c\u1EA7u" }), _jsxs("p", { className: "text-xs text-green-600", children: ["B\u1EA1n \u0111\u00E3 vi\u1EBFt ", wordCount, " t\u1EEB. Y\u00EAu c\u1EA7u: ", minWords, maxWords ? ` - ${maxWords}` : '+', " t\u1EEB."] })] })] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircle, { className: "h-5 w-5 text-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium text-amber-700", children: "Ch\u01B0a \u0111\u1EE7 s\u1ED1 t\u1EEB y\u00EAu c\u1EA7u" }), _jsxs("p", { className: "text-xs text-amber-600", children: ["B\u1EA1n \u0111\u00E3 vi\u1EBFt ", wordCount, " t\u1EEB. C\u1EA7n \u00EDt nh\u1EA5t ", minWords, " t\u1EEB.", maxWords && wordCount > maxWords && _jsxs("span", { children: [" T\u1ED1i \u0111a ", maxWords, " t\u1EEB."] })] })] })] })) }))] })] })] }));
66
66
  }
67
67
  function ContextDisplay({ context, index }) {
68
68
  const { previewUrl } = usePresignedFileUrl(context.type !== 'text' ? context.url || '' : '');
@@ -5,8 +5,8 @@ import { Button } from '../../../../components/ui/button';
5
5
  import { Label } from '../../../../components/ui/label';
6
6
  import { Input } from '../../../../components/ui/input';
7
7
  import { Textarea } from '../../../../components/ui/textarea';
8
- import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
9
- import { Pencil, Eye, X, Image, Music, FileText } from 'lucide-react';
8
+ import { X, Image, Music, FileText } from 'lucide-react';
9
+ import { CompactCreatorHeader, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
10
10
  import { FileUpload } from '../../../../components/ui/file-upload';
11
11
  import { WriteShortParagraphClient } from './WriteShortParagraphClient';
12
12
  import { usePresignedFileUrl } from '../../../../shared/lib/hooks';
@@ -113,9 +113,12 @@ onChange, }) {
113
113
  maxWords,
114
114
  instruction,
115
115
  };
116
- return (_jsxs("div", { className: "space-y-6", children: [_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, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold tracking-tight text-gray-900", children: "Write Short Paragraph (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Ch\u1EBF \u0111\u1ED9 xem tr\u01B0\u1EDBc" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) })] }), _jsx(WriteShortParagraphClient, { questionData: questionData, onSubmit: () => { } })] }));
116
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(WriteShortParagraphClient, { questionData: questionData, onSubmit: () => { } })] }));
117
117
  }
118
- return (_jsxs("div", { className: "space-y-6", children: [_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, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { className: "text-xl font-bold tracking-tight text-gray-900", children: "Write Short Paragraph" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "T\u1EA1o b\u00E0i t\u1EADp vi\u1EBFt \u0111o\u1EA1n v\u0103n v\u1EDBi nhi\u1EC1u content (\u1EA3nh, audio, text)" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: contexts.length === 0 || minWords < 1, children: [_jsx(Eye, { className: "mr-2 h-4 w-4" }), "Client Mode"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "instruction", className: "text-sm font-semibold text-gray-700", children: "H\u01B0\u1EDBng d\u1EABn" }), _jsx(Textarea, { id: "instruction", value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "V\u00ED d\u1EE5: Look at the three pictures. Write about this story.", className: "mt-1", rows: 2 })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "minWords", className: "text-sm font-semibold text-gray-700", children: "S\u1ED1 t\u1EEB t\u1ED1i thi\u1EC3u *" }), _jsx(Input, { id: "minWords", type: "number", min: "1", value: minWords, onChange: (e) => setMinWords(parseInt(e.target.value) || 1), placeholder: "20", className: "mt-1" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "maxWords", className: "text-sm font-semibold text-gray-700", children: "S\u1ED1 t\u1EEB t\u1ED1i \u0111a (t\u00F9y ch\u1ECDn)" }), _jsx(Input, { id: "maxWords", type: "number", min: minWords, value: maxWords || '', onChange: (e) => setMaxWords(e.target.value ? parseInt(e.target.value) : undefined), placeholder: "Kh\u00F4ng gi\u1EDBi h\u1EA1n", className: "mt-1" })] })] })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-xl shadow-blue-100/40 ring-1 ring-gray-100", children: [_jsx(CardHeader, { className: "bg-gradient-to-br from-indigo-50/50 via-white to-blue-50/30 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(FileText, { className: "h-5 w-5 text-white" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-lg font-bold text-gray-900", children: "Contexts" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Th\u00EAm c\u00E1c context (\u1EA3nh, audio, ho\u1EB7c text) \u0111\u1EC3 h\u1ECDc sinh xem khi vi\u1EBFt" })] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('image'), className: "flex items-center gap-2 border-indigo-200 bg-indigo-50 text-indigo-700 hover:bg-indigo-100 hover:text-indigo-800", children: [_jsx(Image, { className: "h-4 w-4" }), "Th\u00EAm \u1EA3nh"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('audio'), className: "flex items-center gap-2 border-purple-200 bg-purple-50 text-purple-700 hover:bg-purple-100 hover:text-purple-800", children: [_jsx(Music, { className: "h-4 w-4" }), "Th\u00EAm audio"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('text'), className: "flex items-center gap-2 border-blue-200 bg-blue-50 text-blue-700 hover:bg-blue-100 hover:text-blue-800", children: [_jsx(FileText, { className: "h-4 w-4" }), "Th\u00EAm text"] })] })] }) }), _jsx(CardContent, { className: "space-y-4 pt-6", children: contexts.length > 0 ? (contexts.map((ctx, index) => (_jsx(ContextItem, { context: ctx, index: index, onUpdate: updateContext, onRemove: removeContext }, ctx.id)))) : (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-12", children: [_jsx("div", { className: "mb-4 rounded-full bg-gray-200 p-4", children: _jsx(Image, { className: "h-8 w-8 text-gray-400" }) }), _jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "Ch\u01B0a c\u00F3 context n\u00E0o" }), _jsx("p", { className: "mb-4 text-xs text-gray-500", children: "Nh\u1EA5n c\u00E1c n\u00FAt b\u00EAn tr\u00EAn \u0111\u1EC3 th\u00EAm context" })] })) })] })] }));
118
+ return (_jsxs("div", { className: "space-y-3", children: [_jsxs(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(FileText, { className: "h-3.5 w-3.5" }), title: "Write Short Paragraph", preview: {
119
+ onClick: () => setIsClientMode(true),
120
+ disabled: contexts.length === 0 || minWords < 1,
121
+ } }), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "instruction", className: "text-sm font-semibold text-gray-700", children: "H\u01B0\u1EDBng d\u1EABn" }), _jsx(Textarea, { id: "instruction", value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "V\u00ED d\u1EE5: Look at the three pictures. Write about this story.", className: "mt-1", rows: 2 })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "minWords", className: "text-sm font-semibold text-gray-700", children: "S\u1ED1 t\u1EEB t\u1ED1i thi\u1EC3u *" }), _jsx(Input, { id: "minWords", type: "number", min: "1", value: minWords, onChange: (e) => setMinWords(parseInt(e.target.value) || 1), placeholder: "20", className: "mt-1" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "maxWords", className: "text-sm font-semibold text-gray-700", children: "S\u1ED1 t\u1EEB t\u1ED1i \u0111a (t\u00F9y ch\u1ECDn)" }), _jsx(Input, { id: "maxWords", type: "number", min: minWords, value: maxWords || '', onChange: (e) => setMaxWords(e.target.value ? parseInt(e.target.value) : undefined), placeholder: "Kh\u00F4ng gi\u1EDBi h\u1EA1n", className: "mt-1" })] })] })] }), _jsx(CompactFieldCard, { header: _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", 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(FileText, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsx("span", { className: "text-sm font-bold text-gray-900", children: "Contexts" })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('image'), className: "flex items-center gap-2 border-indigo-200 bg-indigo-50 text-indigo-700 hover:bg-indigo-100 hover:text-indigo-800", children: [_jsx(Image, { className: "h-4 w-4" }), "Th\u00EAm \u1EA3nh"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('audio'), className: "flex items-center gap-2 border-purple-200 bg-purple-50 text-purple-700 hover:bg-purple-100 hover:text-purple-800", children: [_jsx(Music, { className: "h-4 w-4" }), "Th\u00EAm audio"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => addContext('text'), className: "flex items-center gap-2 border-blue-200 bg-blue-50 text-blue-700 hover:bg-blue-100 hover:text-blue-800", children: [_jsx(FileText, { className: "h-4 w-4" }), "Th\u00EAm text"] })] })] }), children: contexts.length > 0 ? (contexts.map((ctx, index) => (_jsx(ContextItem, { context: ctx, index: index, onUpdate: updateContext, onRemove: removeContext }, ctx.id)))) : (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-12", children: [_jsx("div", { className: "mb-4 rounded-full bg-gray-200 p-4", children: _jsx(Image, { className: "h-8 w-8 text-gray-400" }) }), _jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "Ch\u01B0a c\u00F3 context n\u00E0o" }), _jsx("p", { className: "mb-4 text-xs text-gray-500", children: "Nh\u1EA5n c\u00E1c n\u00FAt b\u00EAn tr\u00EAn \u0111\u1EC3 th\u00EAm context" })] })) })] }));
119
122
  }
120
123
  function ContextItem({ context, index, onUpdate, onRemove }) {
121
124
  const { previewUrl } = usePresignedFileUrl(context.type !== 'text' ? context.url || '' : '');
@@ -11,12 +11,9 @@ import { ReadAndColorObjectsClient } from '../types/read-and-color-objects/ReadA
11
11
  import { ArrangeLettersIntoWordsClient } from '../types/arrange-letters-into-words/ArrangeLettersIntoWordsClient';
12
12
  import { WriteShortParagraphClient } from '../types/write-short-paragraph/WriteShortParagraphClient';
13
13
  import { LabelThePictureClient } from '../types/label-the-picture/LabelThePictureClient';
14
- import { LookPictureFillWordHintClient } from '../types/look-picture-fill-word-hint/LookPictureFillWordHintClient';
15
14
  import { ReadPassageAndAnswerQuestionsClient } from '../types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient';
16
15
  import { ChooseTheCorrectAnswerClient } from '../types/choose-the-correct-answer/ChooseTheCorrectAnswerClient';
17
16
  import { WriteAShortLetterClient } from '../types/write-a-short-letter/WriteAShortLetterClient';
18
- import { LookPictureChooseCorrectAnswerClient } from '../types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient';
19
- import { LookPictureFillBlankChooseAnswerClient } from '../types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient';
20
17
  import { FillMissingWordsInGridClient } from '../types/fill-missing-words-in-grid/FillMissingWordsInGridClient';
21
18
  import { CrosswordPuzzleClient } from '../types/crossword-puzzle/CrosswordPuzzleClient';
22
19
  import { FindWordsInMatrixClient } from '../types/find-words-in-matrix/FindWordsInMatrixClient';
@@ -393,50 +390,6 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
393
390
  onSubmitAnswer?.(userConnections);
394
391
  } }));
395
392
  };
396
- const renderLookPictureFillWordHint = () => {
397
- const answer = question.answer;
398
- const content = question.content;
399
- // Check if question has group info (from API)
400
- const questionGroup = question.questionGroup;
401
- let subQuestions = [];
402
- if (answer?.subQuestions && answer.subQuestions.length > 0) {
403
- subQuestions = answer.subQuestions;
404
- }
405
- else if (content?.imageUrl && content?.word) {
406
- // Single question format - transform to subQuestions
407
- subQuestions = [{
408
- id: question.id,
409
- imageUrl: content.imageUrl,
410
- word: content.word,
411
- correctAnswer: answer?.correctAnswer || '',
412
- groupNumber: questionGroup?.groupNumber || 1,
413
- }];
414
- }
415
- // Get hintLetters from multiple sources (priority order):
416
- // 1. questionGroup.payload.hintLetters (from API group payload)
417
- // 2. answer.hintLetters
418
- // 3. content.hintLetters
419
- const hintLetters = questionGroup?.payload?.hintLetters ||
420
- answer?.hintLetters ||
421
- content?.hintLetters ||
422
- [];
423
- // Build hintLettersByGroup if we have a groupNumber
424
- const groupNumber = questionGroup?.groupNumber || 1;
425
- const hintLettersByGroup = {};
426
- if (hintLetters.length > 0) {
427
- hintLettersByGroup[groupNumber] = hintLetters;
428
- }
429
- const questionData = {
430
- subQuestions,
431
- hintLetters,
432
- hintLettersByGroup,
433
- groups: [{ number: groupNumber, questionCount: subQuestions.length }],
434
- };
435
- return (_jsx(LookPictureFillWordHintClient, { questionData: questionData, userAnswer: userAnswer, isReviewMode: isReviewMode, explanation: question.explanation, onSubmit: (answers) => {
436
- setSelectedAnswer(answers);
437
- onSubmitAnswer?.(answers);
438
- } }));
439
- };
440
393
  const renderReadPassageAndAnswerQuestions = () => {
441
394
  const answer = question.answer;
442
395
  const questionData = {
@@ -450,50 +403,6 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
450
403
  onSubmitAnswer?.(answers);
451
404
  } }));
452
405
  };
453
- const renderLookPictureChooseCorrectAnswer = () => {
454
- const content = question.content;
455
- const answer = question.answer;
456
- // Merge correct answers into subQuestions
457
- const subQuestions = (content?.subQuestions || answer?.subQuestions || []).map((sq) => {
458
- const correctAnswerId = answer?.answers?.[sq.id] || sq.correctAnswer;
459
- return {
460
- ...sq,
461
- options: (sq.options || []).map((opt) => ({
462
- ...opt,
463
- isCorrect: opt.id === correctAnswerId,
464
- })),
465
- };
466
- });
467
- const questionData = {
468
- subQuestions,
469
- };
470
- return (_jsx(LookPictureChooseCorrectAnswerClient, { questionData: questionData, userAnswer: userAnswer, isReviewMode: isReviewMode, onSubmit: (answers) => {
471
- setSelectedAnswer(answers);
472
- onSubmitAnswer?.(answers);
473
- } }));
474
- };
475
- const renderLookPictureFillBlankChooseAnswer = () => {
476
- const content = question.content;
477
- const answer = question.answer;
478
- // Merge correct answers into subQuestions
479
- const subQuestions = (content?.subQuestions || answer?.subQuestions || []).map((sq) => {
480
- const correctAnswerId = answer?.answers?.[sq.id] || sq.correctAnswer;
481
- return {
482
- ...sq,
483
- options: (sq.options || []).map((opt) => ({
484
- ...opt,
485
- isCorrect: opt.id === correctAnswerId,
486
- })),
487
- };
488
- });
489
- const questionData = {
490
- subQuestions,
491
- };
492
- return (_jsx(LookPictureFillBlankChooseAnswerClient, { questionData: questionData, userAnswer: userAnswer, isReviewMode: isReviewMode, onSubmit: (answers) => {
493
- setSelectedAnswer(answers);
494
- onSubmitAnswer?.(answers);
495
- } }));
496
- };
497
406
  const renderFillMissingWordsInGrid = () => {
498
407
  const content = question.content;
499
408
  const answer = question.answer;
@@ -629,19 +538,12 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
629
538
  case 'WRITE_A_SHORT_LETTER':
630
539
  return renderWriteAShortLetter();
631
540
  // Marketing exam questions grade 1-2
632
- case 'LOOK_PICTURE_FILL_WORD_HINT':
633
- return renderLookPictureFillWordHint();
634
541
  case 'LABEL_THE_PICTURE':
635
542
  return renderLabelThePicture();
636
543
  case 'READ_AND_COLOR_OBJECTS':
637
544
  return renderReadAndColorObjects();
638
545
  case 'READ_PASSAGE_AND_ANSWER_QUESTIONS':
639
546
  return renderReadPassageAndAnswerQuestions();
640
- // Additional marketing exam questions
641
- case 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER':
642
- return renderLookPictureChooseCorrectAnswer();
643
- case 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER':
644
- return renderLookPictureFillBlankChooseAnswer();
645
547
  case 'FILL_MISSING_WORDS_IN_GRID':
646
548
  return renderFillMissingWordsInGrid();
647
549
  case 'WORD_FILL_PARAGRAPH':
@@ -4,8 +4,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
4
4
  * Movers fallback review cases (isReviewMode=true).
5
5
  * Source: oe-exam-fe ReviewQuestionRenderer.tsx
6
6
  */
7
- import { MoversAnswerTheQuestionRenderer, MoversFillWordHintRenderer, MoversGridFillRenderer, MoversLabelThePictureRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversPictureChooseRenderer, MoversPictureFillBlankChooseRenderer, MoversReadingPassageRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversFillInBlankGroupRenderer, MoversMatchingWithLinesGroupRenderer, MoversCrossOutWordGroupRenderer, MoversWordFillParagraphRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderingRenderer, MoversWordOrderingGroupRenderer, MoversWriteSentencesRenderer, MoversWritingRenderer, MoversCrosswordPuzzleRenderer, ChooseThenAnswerGroupRenderer, SortWordsIntoCategoriesRenderer, } from '../../../components/exams/take/components/question-renderers';
8
- import { transformAnswerTheQuestion, transformFillWordHint, transformGridFill, transformLabelPicture, transformMatchByWritingAnswer, transformMatchWordToPicture, transformPictureChoose, transformPictureFillBlankChoose, transformReadingPassage, transformTrueFalse, transformTrueFalseCorrectGroup, transformFillInBlankGroup, transformMatchingWithLinesGroup, transformWordFillParagraph, transformWordFillStructuredForm, transformWordOrdering, transformWordOrderingGroupTake, transformWriteSentences, transformWriteShortLetter, transformCrosswordPuzzle, transformChooseThenAnswerGroup, transformSortWordsIntoCategories, } from '../../../components/exams/take/utils/question-transformers';
7
+ import { MoversAnswerTheQuestionRenderer, MoversGridFillRenderer, MoversLabelThePictureRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversReadingPassageRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversFillInBlankGroupRenderer, MoversMatchingWithLinesGroupRenderer, MoversCrossOutWordGroupRenderer, MoversWordFillParagraphRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderingRenderer, MoversWordOrderingGroupRenderer, MoversWriteSentencesRenderer, MoversWritingRenderer, MoversCrosswordPuzzleRenderer, ChooseThenAnswerGroupRenderer, SortWordsIntoCategoriesRenderer, } from '../../../components/exams/take/components/question-renderers';
8
+ import { transformAnswerTheQuestion, transformGridFill, transformLabelPicture, transformMatchByWritingAnswer, transformMatchWordToPicture, transformReadingPassage, transformTrueFalse, transformTrueFalseCorrectGroup, transformFillInBlankGroup, transformMatchingWithLinesGroup, transformWordFillParagraph, transformWordFillStructuredForm, transformWordOrdering, transformWordOrderingGroupTake, transformWriteSentences, transformWriteShortLetter, transformCrosswordPuzzle, transformChooseThenAnswerGroup, transformSortWordsIntoCategories, } from '../../../components/exams/take/utils/question-transformers';
9
9
  import { normalizeCrossOutWordGroupAnswer, transformCrossOutWordGroup, } from '../../../components/exams/take/utils/cross-out-word-group.transformer';
10
10
  function asApiQuestions(questions) {
11
11
  return questions;
@@ -28,22 +28,6 @@ export function renderMoversReviewBody(ctx) {
28
28
  const gradingInfo = essayGradingMap[firstQuestion.id];
29
29
  return (_jsx(MoversWritingRenderer, { partNumber: partNo, partName: part.name, prompt: data.prompt, requirements: data.requirements, minWords: data.minWords, maxWords: data.maxWords, answer: writingAnswer, onAnswerChange: handleAnswerChange, isReviewMode: true, guideImages: data.guideImages, passage: data.passage, teacherScore: gradingInfo?.score, maxScore: gradingInfo?.maxScore, teacherFeedback: gradingInfo?.teacherFeedback, writingAssessment: gradingInfo?.writingAssessment }));
30
30
  }
31
- case 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': {
32
- const data = transformPictureChoose(apiQuestions);
33
- const subQuestionsWithCorrect = data.subQuestions.map((sq) => ({
34
- ...sq,
35
- correctOptionId: correctOptionIdMap[sq.id],
36
- }));
37
- return (_jsx(MoversPictureChooseRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, subQuestions: subQuestionsWithCorrect, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true }));
38
- }
39
- case 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER': {
40
- const data = transformPictureFillBlankChoose(apiQuestions);
41
- const subQuestionsWithCorrect = data.subQuestions.map((sq) => ({
42
- ...sq,
43
- correctOptionId: correctOptionIdMap[sq.id],
44
- }));
45
- return (_jsx(MoversPictureFillBlankChooseRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, subQuestions: subQuestionsWithCorrect, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true }));
46
- }
47
31
  case 'READ_PASSAGE_AND_ANSWER_QUESTIONS': {
48
32
  const data = transformReadingPassage(apiQuestions);
49
33
  return (_jsx(MoversReadingPassageRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: data.questions.length, passageTitle: data.passageTitle, passage: data.passage, passageImageUrl: data.passageImageUrl, questions: data.questions, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true, correctOptionIdMap: correctOptionIdMap }));
@@ -58,14 +42,6 @@ export function renderMoversReviewBody(ctx) {
58
42
  }));
59
43
  return (_jsx(MoversLabelThePictureRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: data.labels.length, imageUrl: data.imageUrl, wordBank: data.wordBank, labels: labelsWithCorrect, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true }));
60
44
  }
61
- case 'LOOK_PICTURE_FILL_WORD_HINT': {
62
- const data = transformFillWordHint(apiQuestions);
63
- const subQuestionsWithCorrect = data.subQuestions.map((sq) => ({
64
- ...sq,
65
- correctAnswer: correctAnswerTextMap[sq.id],
66
- }));
67
- return (_jsx(MoversFillWordHintRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, hintLetters: data.hintLetters, subQuestions: subQuestionsWithCorrect, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true }));
68
- }
69
45
  case 'FILL_MISSING_WORDS_IN_GRID': {
70
46
  const data = transformGridFill(apiQuestions);
71
47
  const questionId = questions[0]?.id;
@@ -1,7 +1,6 @@
1
1
  import { normalizeCrossOutWordGroupAnswer } from '../../components/exams/take/utils/cross-out-word-group.transformer';
2
2
  const FLATTENED_ANSWER_TYPES = new Set([
3
3
  'READ_PASSAGE_AND_ANSWER_QUESTIONS',
4
- 'LOOK_PICTURE_FILL_WORD_HINT',
5
4
  'LABEL_THE_PICTURE',
6
5
  'READ_AND_COLOR_OBJECTS',
7
6
  'IMAGE_OBJECT_MATCHING',
@@ -286,9 +285,6 @@ function transformStudentAnswer(questionId, questionType, value) {
286
285
  }
287
286
  if (questionType === 'LABEL_THE_PICTURE')
288
287
  return record.answers ?? value;
289
- if (questionType === 'LOOK_PICTURE_FILL_WORD_HINT' && typeof record.answer === 'string' && record.answer.includes(',')) {
290
- return Object.fromEntries(record.answer.split(',').map((item, index) => [`${questionId}-blank-${index}`, item.trim()]));
291
- }
292
288
  if (questionType === 'WORD_FILL_PARAGRAPH') {
293
289
  if (Array.isArray(record.answers))
294
290
  return record.answers;
@@ -4,6 +4,7 @@ interface PointsInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, '
4
4
  error?: string;
5
5
  required?: boolean;
6
6
  allowZero?: boolean;
7
+ onValueChange?: (value: number) => void;
7
8
  }
8
9
  /**
9
10
  * A specialized input component for "Điểm số" (points/score) fields.
@@ -10,7 +10,7 @@ import { cn } from '../../shared/lib/utils';
10
10
  * - Allows clearing the input to enter new values
11
11
  * - Strips non-digit characters automatically
12
12
  */
13
- export const PointsInput = forwardRef(({ label = 'Điểm số', error, required = true, allowZero = false, className, id, ...props }, ref) => {
13
+ export const PointsInput = forwardRef(({ label = 'Điểm số', error, required = true, allowZero = false, className, id, onValueChange, onChange, ...props }, ref) => {
14
14
  const inputId = id || 'points';
15
15
  const handleInput = (e) => {
16
16
  const input = e.target;
@@ -28,6 +28,16 @@ export const PointsInput = forwardRef(({ label = 'Điểm số', error, required
28
28
  input.value = intValue < minVal ? minVal.toString() : intValue.toString();
29
29
  }
30
30
  };
31
- return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Label, { htmlFor: inputId, className: "whitespace-nowrap text-sm font-medium", children: [label, " ", required && _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { ref: ref, id: inputId, type: "number", step: "1", min: allowZero ? "0" : "1", onInput: handleInput, className: cn('w-20', error && 'border-red-500 focus:ring-red-500', className), ...props }), error && _jsx("p", { className: "text-sm text-red-600", children: error })] }));
31
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Label, { htmlFor: inputId, className: "whitespace-nowrap text-sm font-medium", children: [label, " ", required && _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { ref: ref, id: inputId, type: "number", step: "1", min: allowZero ? "0" : "1", onInput: handleInput, onChange: (e) => {
32
+ onChange?.(e);
33
+ if (onValueChange) {
34
+ const raw = e.target.value;
35
+ if (raw === '')
36
+ return;
37
+ const parsed = parseInt(raw, 10);
38
+ if (!Number.isNaN(parsed))
39
+ onValueChange(parsed);
40
+ }
41
+ }, className: cn('w-20', error && 'border-red-500 focus:ring-red-500', className), ...props }), error && _jsx("p", { className: "text-sm text-red-600", children: error })] }));
32
42
  });
33
43
  PointsInput.displayName = 'PointsInput';
@@ -36,7 +36,6 @@ export const QUESTION_TYPE_SKILLS = {
36
36
  'SPONTANEOUS_QA': SkillEnum.SPEAKING,
37
37
  'SPEAKING_CONVERSATION': SkillEnum.SPEAKING,
38
38
  'SPEAKING_CUE_CARD': SkillEnum.SPEAKING,
39
- 'GN_SPEAKING_INTERVIEW': SkillEnum.SPEAKING,
40
39
  // ========================================
41
40
  // READING SKILLS (Đọc) - Marketing Exam Types
42
41
  // ========================================
@@ -57,9 +56,6 @@ export const QUESTION_TYPE_SKILLS = {
57
56
  'MATCHING_WITH_LINES_GROUP': SkillEnum.READING,
58
57
  // Visual-based reading questions
59
58
  'LABEL_THE_PICTURE': SkillEnum.READING,
60
- 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': SkillEnum.READING,
61
- 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER': SkillEnum.READING,
62
- 'LOOK_PICTURE_FILL_WORD_HINT': SkillEnum.READING,
63
59
  'READ_AND_COLOR_OBJECTS': SkillEnum.READING,
64
60
  'IMAGE_OBJECT_MATCHING': SkillEnum.READING,
65
61
  // Other reading types
@@ -140,9 +136,6 @@ export const MARKETING_QUESTION_TYPES_BY_SKILL = {
140
136
  'FILL_IN_BLANK',
141
137
  'FILL_MISSING_WORDS_IN_GRID',
142
138
  'LABEL_THE_PICTURE',
143
- 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER',
144
- 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER',
145
- 'LOOK_PICTURE_FILL_WORD_HINT',
146
139
  'READ_AND_COLOR_OBJECTS',
147
140
  'IMAGE_OBJECT_MATCHING',
148
141
  'READ_PASSAGE_AND_ANSWER_QUESTIONS',
@@ -188,9 +181,6 @@ export const QUESTION_TYPE_LABELS = {
188
181
  'FILL_MISSING_WORDS_IN_GRID': 'Điền từ vào lưới',
189
182
  'READ_PASSAGE_AND_ANSWER_QUESTIONS': 'Đọc hiểu - Trả lời',
190
183
  'LABEL_THE_PICTURE': 'Gắn nhãn hình ảnh',
191
- 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': 'Nhìn ảnh - Chọn đáp án',
192
- 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER': 'Nhìn ảnh - Điền và chọn',
193
- 'LOOK_PICTURE_FILL_WORD_HINT': 'Nhìn ảnh - Điền từ gợi ý',
194
184
  'READ_AND_COLOR_OBJECTS': 'Đọc - Tô màu',
195
185
  'IMAGE_OBJECT_MATCHING': 'Ghép hình ảnh - Đối tượng',
196
186
  'TRUE_FALSE': 'Đúng/Sai',
@@ -252,7 +242,6 @@ export const QUESTION_TYPE_LABELS = {
252
242
  'SPEAKING_DESCRIBE_IMAGE': 'Nhìn tranh và mô tả (Speaking Part 2)',
253
243
  'SPONTANEOUS_QA': 'Hỏi đáp tự phát (Speaking Part 3)',
254
244
  'SPEAKING_CONVERSATION': 'Hội thoại Speaking (KFS Speaking)',
255
- 'GN_SPEAKING_INTERVIEW': 'GN Speaking - Hỏi đáp (Virtual + Real)',
256
245
  };
257
246
  /**
258
247
  * Get the label for a question type
@@ -1561,9 +1561,6 @@ declare const admin: {
1561
1561
  readonly 'admin.exams.partEditor.skillReading': "Reading";
1562
1562
  readonly 'admin.exams.partEditor.skillWriting': "Writing";
1563
1563
  readonly 'admin.exams.partEditor.qtFillMissingWordsInGrid': "Fill in missing letters";
1564
- readonly 'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': "Look at picture, fill in the blank";
1565
- readonly 'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': "Look at picture, choose correct answer";
1566
- readonly 'admin.exams.partEditor.qtLookPictureFillWordHint': "Look at picture, fill word (with hint)";
1567
1564
  readonly 'admin.exams.partEditor.qtLabelThePicture': "Label the picture";
1568
1565
  readonly 'admin.exams.partEditor.qtReadAndColorObjects': "Read and color";
1569
1566
  readonly 'admin.exams.partEditor.qtMultipleChoice': "Multiple choice";
@@ -1711,9 +1711,6 @@ const admin = {
1711
1711
  'admin.exams.partEditor.skillReading': 'Reading',
1712
1712
  'admin.exams.partEditor.skillWriting': 'Writing',
1713
1713
  'admin.exams.partEditor.qtFillMissingWordsInGrid': 'Fill in missing letters',
1714
- 'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': 'Look at picture, fill in the blank',
1715
- 'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': 'Look at picture, choose correct answer',
1716
- 'admin.exams.partEditor.qtLookPictureFillWordHint': 'Look at picture, fill word (with hint)',
1717
1714
  'admin.exams.partEditor.qtLabelThePicture': 'Label the picture',
1718
1715
  'admin.exams.partEditor.qtReadAndColorObjects': 'Read and color',
1719
1716
  'admin.exams.partEditor.qtMultipleChoice': 'Multiple choice',
@@ -1718,9 +1718,6 @@ declare const en: {
1718
1718
  readonly 'admin.exams.partEditor.skillReading': "Reading";
1719
1719
  readonly 'admin.exams.partEditor.skillWriting': "Writing";
1720
1720
  readonly 'admin.exams.partEditor.qtFillMissingWordsInGrid': "Fill in missing letters";
1721
- readonly 'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': "Look at picture, fill in the blank";
1722
- readonly 'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': "Look at picture, choose correct answer";
1723
- readonly 'admin.exams.partEditor.qtLookPictureFillWordHint': "Look at picture, fill word (with hint)";
1724
1721
  readonly 'admin.exams.partEditor.qtLabelThePicture': "Label the picture";
1725
1722
  readonly 'admin.exams.partEditor.qtReadAndColorObjects': "Read and color";
1726
1723
  readonly 'admin.exams.partEditor.qtMultipleChoice': "Multiple choice";
@@ -1561,9 +1561,6 @@ declare const admin: {
1561
1561
  readonly 'admin.exams.partEditor.skillReading': "Đọc";
1562
1562
  readonly 'admin.exams.partEditor.skillWriting': "Viết";
1563
1563
  readonly 'admin.exams.partEditor.qtFillMissingWordsInGrid': "Điền chữ cái còn thiếu";
1564
- readonly 'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': "Nhìn tranh, điền vào chỗ trống";
1565
- readonly 'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': "Nhìn tranh, chọn đáp án đúng";
1566
- readonly 'admin.exams.partEditor.qtLookPictureFillWordHint': "Nhìn tranh, điền từ (có gợi ý)";
1567
1564
  readonly 'admin.exams.partEditor.qtLabelThePicture': "Gắn nhãn cho tranh";
1568
1565
  readonly 'admin.exams.partEditor.qtReadAndColorObjects': "Đọc và tô màu";
1569
1566
  readonly 'admin.exams.partEditor.qtMultipleChoice': "Trắc nghiệm";