@tinyweb_dev/oe-exam-sdk 1.0.6 → 1.0.8

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 (239) 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/choose-the-correct-answer-group.type.d.ts +2 -2
  29. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.js +5 -1
  30. package/dist/components/questions/_shared/types/index.d.ts +0 -1
  31. package/dist/components/questions/_shared/types/index.js +0 -1
  32. package/dist/components/questions/_shared/types/look-and-choose-answer.type.d.ts +0 -13
  33. package/dist/components/questions/_shared/utils/answer-builder.js +0 -11
  34. package/dist/components/questions/components/ColorRegionCreator.js +66 -63
  35. package/dist/components/questions/components/QuestionSearchDropdown.js +0 -8
  36. package/dist/components/questions/components/QuestionTypeSelector.js +0 -2
  37. package/dist/components/questions/components/index.d.ts +1 -0
  38. package/dist/components/questions/components/index.js +1 -0
  39. package/dist/components/questions/creator/question-type-registry.js +0 -8
  40. package/dist/components/questions/groups/ArticlesGroupCard.js +2 -2
  41. package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -1
  42. package/dist/components/questions/groups/DocumentGroupCard.js +1 -1
  43. package/dist/components/questions/groups/ImageLabelGroupCard.js +1 -1
  44. package/dist/components/questions/groups/MatchAnswerGroupCard.js +2 -2
  45. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -3
  46. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +1 -10
  47. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -2
  48. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -41
  49. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +2 -2
  50. package/dist/components/questions/question-bank/editor-adapters/index.js +2 -2
  51. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -1
  52. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -28
  53. package/dist/components/questions/question-bank/question-bank-picker.utils.js +0 -7
  54. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +16 -16
  55. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +36 -30
  56. package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.js +1 -1
  57. package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupCreator.js +7 -6
  58. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +2 -2
  59. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +11 -7
  60. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -1
  61. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +11 -5
  62. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +5 -5
  63. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +34 -28
  64. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseAnswerGroupImageUpload.d.ts +7 -0
  65. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseAnswerGroupImageUpload.js +5 -2
  66. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +9 -5
  67. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +65 -62
  68. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupItemEditor.d.ts +6 -0
  69. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupItemEditor.js +145 -0
  70. package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +6 -15
  71. package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +5 -4
  72. package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupClient.js +7 -7
  73. package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupCreator.js +8 -5
  74. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +2 -2
  75. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +20 -16
  76. package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleClient.js +1 -1
  77. package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleCreator.js +66 -29
  78. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +5 -5
  79. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +45 -37
  80. package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.js +24 -20
  81. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +2 -2
  82. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +68 -65
  83. package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixClient.js +1 -1
  84. package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixCreator.js +45 -5
  85. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +2 -2
  86. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +18 -14
  87. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +2 -2
  88. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +30 -30
  89. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +2 -2
  90. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +24 -31
  91. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +2 -2
  92. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +29 -32
  93. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -1
  94. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +27 -29
  95. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -1
  96. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +11 -15
  97. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -1
  98. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +22 -24
  99. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -1
  100. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +17 -24
  101. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -1
  102. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +31 -31
  103. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -1
  104. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +11 -15
  105. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -1
  106. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +14 -15
  107. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +2 -2
  108. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +27 -25
  109. package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesClient.js +12 -12
  110. package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesCreator.js +8 -5
  111. package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureClient.js +8 -8
  112. package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureCreator.js +25 -20
  113. package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupClient.js +1 -1
  114. package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupCreator.js +13 -10
  115. package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupCreator.js +8 -5
  116. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +7 -11
  117. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -1
  118. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +15 -12
  119. package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesClient.js +1 -1
  120. package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesCreator.js +5 -5
  121. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +35 -39
  122. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +2 -2
  123. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardClient.js +1 -1
  124. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +7 -8
  125. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -1
  126. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +30 -23
  127. package/dist/components/questions/types/spontaneous-qa/SpontaneousQAClient.js +1 -1
  128. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +26 -19
  129. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.d.ts +1 -1
  130. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +79 -3
  131. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +13 -11
  132. package/dist/components/questions/types/spontaneous-qa-group/index.d.ts +1 -0
  133. package/dist/components/questions/types/spontaneous-qa-group/index.js +1 -0
  134. package/dist/components/questions/types/spontaneous-qa-group/map-spontaneous-qa-group-data.d.ts +2 -0
  135. package/dist/components/questions/types/spontaneous-qa-group/map-spontaneous-qa-group-data.js +74 -0
  136. package/dist/components/questions/types/true-false/TrueFalseClient.js +2 -2
  137. package/dist/components/questions/types/true-false/TrueFalseCreator.js +35 -29
  138. package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupClient.js +1 -1
  139. package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupCreator.js +11 -7
  140. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -1
  141. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +11 -7
  142. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +2 -2
  143. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +21 -56
  144. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
  145. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +30 -24
  146. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +3 -3
  147. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +12 -14
  148. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -1
  149. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +27 -18
  150. package/dist/components/questions/types/word-ordering-group/WordOrderingGroupClient.js +7 -7
  151. package/dist/components/questions/types/word-ordering-group/WordOrderingGroupCreator.js +16 -13
  152. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +2 -2
  153. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +34 -28
  154. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +2 -2
  155. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +22 -22
  156. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +21 -18
  157. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -1
  158. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +7 -4
  159. package/dist/components/questions/viewer/QuestionViewer.js +0 -98
  160. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +4 -79
  161. package/dist/components/results/renderers/review-question-body-movers.js +2 -26
  162. package/dist/components/results/review-data.js +0 -4
  163. package/dist/components/ui/points-input.d.ts +1 -0
  164. package/dist/components/ui/points-input.js +12 -2
  165. package/dist/shared/constants/question-skills.js +0 -11
  166. package/dist/shared/lib/i18n/messages/en/admin.d.ts +0 -3
  167. package/dist/shared/lib/i18n/messages/en/admin.js +0 -3
  168. package/dist/shared/lib/i18n/messages/en.d.ts +0 -3
  169. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +0 -3
  170. package/dist/shared/lib/i18n/messages/vi/admin.js +0 -3
  171. package/dist/shared/lib/i18n/messages/vi.d.ts +0 -3
  172. package/dist/shared/lib/utils/question-reverse-transform.js +4 -23
  173. package/dist/shared/lib/utils/question-transform-types.d.ts +1 -23
  174. package/dist/shared/lib/utils/question-transform-validation.js +0 -40
  175. package/dist/shared/lib/utils/question-transform.js +0 -9
  176. package/dist/shared/types/common.types.d.ts +1 -1
  177. package/dist/shared/types/entities/question.types.d.ts +1 -11
  178. package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +1 -1
  179. package/dist/shared/types/questions/index.d.ts +0 -3
  180. package/dist/shared/types/questions/index.js +0 -6
  181. package/package.json +1 -1
  182. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.d.ts +0 -2
  183. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +0 -131
  184. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.d.ts +0 -2
  185. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +0 -76
  186. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.d.ts +0 -2
  187. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +0 -68
  188. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.d.ts +0 -16
  189. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +0 -212
  190. package/dist/components/questions/_shared/types/gn-speaking-interview.type.d.ts +0 -32
  191. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +0 -1
  192. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.d.ts +0 -47
  193. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +0 -1
  194. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.d.ts +0 -2
  195. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +0 -262
  196. package/dist/components/questions/types/gn-speaking-interview/register.d.ts +0 -2
  197. package/dist/components/questions/types/gn-speaking-interview/register.js +0 -121
  198. package/dist/components/questions/types/gn-speaking-interview/transform.d.ts +0 -2
  199. package/dist/components/questions/types/gn-speaking-interview/transform.js +0 -48
  200. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.d.ts +0 -20
  201. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +0 -72
  202. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.d.ts +0 -15
  203. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +0 -230
  204. package/dist/components/questions/types/look-picture-choose-correct-answer/index.d.ts +0 -1
  205. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +0 -1
  206. package/dist/components/questions/types/look-picture-choose-correct-answer/register.d.ts +0 -2
  207. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +0 -66
  208. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.d.ts +0 -2
  209. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +0 -42
  210. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.d.ts +0 -6
  211. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +0 -96
  212. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.d.ts +0 -15
  213. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +0 -238
  214. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.d.ts +0 -2
  215. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +0 -2
  216. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.d.ts +0 -2
  217. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +0 -76
  218. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.d.ts +0 -2
  219. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +0 -19
  220. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.d.ts +0 -7
  221. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +0 -134
  222. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.d.ts +0 -3
  223. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +0 -617
  224. package/dist/components/questions/types/look-picture-fill-word-hint/index.d.ts +0 -2
  225. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +0 -2
  226. package/dist/components/questions/types/look-picture-fill-word-hint/register.d.ts +0 -2
  227. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +0 -82
  228. package/dist/components/questions/types/look-picture-fill-word-hint/transform.d.ts +0 -2
  229. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +0 -29
  230. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.d.ts +0 -9
  231. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +0 -12
  232. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.d.ts +0 -17
  233. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +0 -47
  234. package/dist/shared/types/questions/look-picture-choose-correct-answer.d.ts +0 -38
  235. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +0 -5
  236. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.d.ts +0 -63
  237. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +0 -9
  238. package/dist/shared/types/questions/look-picture-fill-word-hint.d.ts +0 -57
  239. package/dist/shared/types/questions/look-picture-fill-word-hint.js +0 -7
@@ -1,76 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState } from 'react';
4
- import { ZoomIn, Check, X } from 'lucide-react';
5
- import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
6
- import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
7
- import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
8
- // Image with zoom functionality
9
- function QuestionImage({ imageUrl, alt }) {
10
- const [isZoomed, setIsZoomed] = useState(false);
11
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative flex items-center justify-center", children: [_jsx(ResolvedImage, { src: imageUrl, alt: alt, className: "max-h-[180px] cursor-pointer rounded-lg object-contain shadow-md", onClick: () => setIsZoomed(true) }), _jsx("button", { type: "button", onClick: () => setIsZoomed(true), className: "absolute right-2 top-2 rounded-full bg-white/80 p-1.5 shadow-md hover:bg-white", "aria-label": "Zoom image", children: _jsx(ZoomIn, { className: "h-4 w-4 text-gray-600" }) })] }), isZoomed && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70", onClick: () => setIsZoomed(false), children: _jsx(ResolvedImage, { src: imageUrl, alt: `${alt} (zoomed)`, className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
12
- }
13
- // Single Sub-Question Component
14
- function SubQuestionItem({ subQuestion, selectedOptionId, onSelect, isReviewMode, id, }) {
15
- // Review mode states
16
- const isUserCorrect = isReviewMode && selectedOptionId === subQuestion.correctOptionId;
17
- const getOptionStyle = (optionId) => {
18
- if (!isReviewMode) {
19
- return selectedOptionId === optionId
20
- ? 'border-blue-500 bg-[#f4f9ff]'
21
- : 'border-blue-200 bg-white hover:border-blue-300 hover:bg-blue-50/30';
22
- }
23
- // Review mode
24
- const isSelected = selectedOptionId === optionId;
25
- const isCorrect = subQuestion.correctOptionId === optionId;
26
- if (isCorrect) {
27
- // ✅ Green if user answered correctly
28
- // ⚪ Blue if user didn't answer or was wrong (show correct answer)
29
- return isUserCorrect
30
- ? 'border-green-500 bg-green-50'
31
- : 'border-blue-500 bg-blue-50';
32
- }
33
- if (isSelected && !isCorrect) {
34
- // ❌ Red for wrong answer
35
- return 'border-red-500 bg-red-50';
36
- }
37
- return 'border-blue-200 bg-white';
38
- };
39
- const getRadioStyle = (optionId) => {
40
- if (!isReviewMode) {
41
- return selectedOptionId === optionId
42
- ? 'border-blue-500 bg-blue-500'
43
- : 'border-gray-300 bg-white';
44
- }
45
- // Review mode
46
- const isSelected = selectedOptionId === optionId;
47
- const isCorrect = subQuestion.correctOptionId === optionId;
48
- if (isCorrect) {
49
- return isUserCorrect
50
- ? 'border-green-500 bg-green-500'
51
- : 'border-blue-500 bg-blue-500';
52
- }
53
- if (isSelected && !isCorrect) {
54
- return 'border-red-500 bg-red-500';
55
- }
56
- return 'border-gray-300 bg-white';
57
- };
58
- // Get icon for review mode
59
- const getReviewIcon = (optionId) => {
60
- if (!isReviewMode)
61
- return null;
62
- const isSelected = selectedOptionId === optionId;
63
- const isCorrect = subQuestion.correctOptionId === optionId;
64
- if (isCorrect) {
65
- return _jsx(Check, { className: "h-4 w-4 text-white" });
66
- }
67
- if (isSelected && !isCorrect) {
68
- return _jsx(X, { className: "h-4 w-4 text-white" });
69
- }
70
- return null;
71
- };
72
- return (_jsxs("div", { id: id, className: "rounded-lg border border-gray-200 bg-white p-4 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white", children: subQuestion.questionNumber }), _jsx(QuestionImage, { imageUrl: subQuestion.imageUrl, alt: `Question ${subQuestion.questionNumber}` })] }), subQuestion.questionText && (_jsx("p", { className: "mb-3 text-[17px] font-bold text-[#001590]", children: subQuestion.questionText })), _jsx("div", { className: "flex flex-col gap-2", children: subQuestion.options.map((option) => (_jsxs("button", { type: "button", onClick: () => !isReviewMode && onSelect(option.id), disabled: isReviewMode, className: `flex items-center gap-3 rounded-lg border-2 px-3 py-2 text-left transition-colors ${getOptionStyle(option.id)} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: [_jsxs("span", { className: "text-sm font-medium text-gray-600", children: [option.label, "."] }), _jsx("span", { className: "flex-1 text-sm text-gray-700", children: option.text }), _jsx("div", { className: `flex h-5 w-5 items-center justify-center rounded-full border-2 ${getRadioStyle(option.id)}`, children: isReviewMode ? (getReviewIcon(option.id)) : (selectedOptionId === option.id && (_jsx("div", { className: "h-2 w-2 rounded-full bg-white" }))) })] }, option.id))) })] }));
73
- }
74
- export function MoversPictureChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode = false, }) {
75
- return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode })] }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: subQuestions.map((subQuestion) => (_jsx(SubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, selectedOptionId: answers[subQuestion.id], onSelect: (optionId) => onAnswerChange(subQuestion.id, optionId), isReviewMode: isReviewMode }, subQuestion.id))) })] }));
76
- }
@@ -1,2 +0,0 @@
1
- import type { MoversPictureFillBlankChooseRendererProps } from '../../types';
2
- export declare function MoversPictureFillBlankChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode, }: MoversPictureFillBlankChooseRendererProps): import("react").JSX.Element;
@@ -1,68 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState } from 'react';
4
- import { ZoomIn } from 'lucide-react';
5
- import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
6
- import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
7
- import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
8
- // Image with zoom functionality
9
- function QuestionImage({ imageUrl, alt }) {
10
- const [isZoomed, setIsZoomed] = useState(false);
11
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative flex items-center justify-center", children: [_jsx(ResolvedImage, { src: imageUrl, alt: alt, className: "max-h-[150px] cursor-pointer rounded-lg object-contain shadow-md", onClick: () => setIsZoomed(true) }), _jsx("button", { type: "button", onClick: () => setIsZoomed(true), className: "absolute right-1 top-1 rounded-full bg-white/80 p-1 shadow-md hover:bg-white", "aria-label": "Zoom image", children: _jsx(ZoomIn, { className: "h-3 w-3 text-gray-600" }) })] }), isZoomed && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70", onClick: () => setIsZoomed(false), children: _jsx(ResolvedImage, { src: imageUrl, alt: `${alt} (zoomed)`, className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
12
- }
13
- // Render question text with blank highlight
14
- function QuestionWithBlank({ question, selectedAnswer, isReviewMode, isCorrect, }) {
15
- // Split by {0} placeholder
16
- const parts = question.split('{0}');
17
- const getBlankStyle = () => {
18
- if (!isReviewMode || !selectedAnswer) {
19
- return 'border-blue-400 text-blue-600';
20
- }
21
- return isCorrect
22
- ? 'border-green-500 text-green-600'
23
- : 'border-red-500 text-red-600';
24
- };
25
- return (_jsxs("p", { className: "text-sm font-medium text-gray-700", children: [parts[0], _jsx("span", { className: `mx-1 inline-block min-w-[60px] border-b-2 border-dashed px-2 text-center font-semibold ${getBlankStyle()}`, children: selectedAnswer || '______' }), parts[1]] }));
26
- }
27
- // Single Sub-Question Component
28
- function SubQuestionItem({ subQuestion, selectedOptionId, onSelect, isReviewMode, id, }) {
29
- const selectedOption = subQuestion.options.find((o) => o.id === selectedOptionId);
30
- // Review mode states
31
- const isUserCorrect = isReviewMode && selectedOptionId === subQuestion.correctOptionId;
32
- const getOptionStyle = (optionId) => {
33
- if (!isReviewMode) {
34
- return selectedOptionId === optionId
35
- ? 'border-blue-500 bg-blue-50'
36
- : 'border-gray-300 bg-white hover:border-blue-300';
37
- }
38
- // Review mode
39
- const isSelected = selectedOptionId === optionId;
40
- const isCorrect = subQuestion.correctOptionId === optionId;
41
- if (isCorrect) {
42
- // ✅ Green if user answered correctly
43
- // ⚪ Blue if user didn't answer or was wrong (show correct answer)
44
- return isUserCorrect
45
- ? 'border-green-500 bg-green-50'
46
- : 'border-blue-500 bg-blue-50';
47
- }
48
- if (isSelected && !isCorrect) {
49
- // ❌ Red for wrong answer
50
- return 'border-red-500 bg-red-50';
51
- }
52
- return 'border-gray-300 bg-white';
53
- };
54
- const getTextStyle = (optionId) => {
55
- if (!isReviewMode)
56
- return 'text-gray-700';
57
- const isSelected = selectedOptionId === optionId;
58
- const isCorrect = subQuestion.correctOptionId === optionId;
59
- if (isCorrect || isSelected) {
60
- return 'text-gray-800 font-bold';
61
- }
62
- return 'text-gray-600';
63
- };
64
- return (_jsxs("div", { id: id, className: "rounded-lg border border-gray-200 bg-white p-4 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white", children: subQuestion.questionNumber }), _jsx(QuestionImage, { imageUrl: subQuestion.imageUrl, alt: `Question ${subQuestion.questionNumber}` })] }), _jsx("div", { className: "mb-3", children: _jsx(QuestionWithBlank, { question: subQuestion.question, selectedAnswer: selectedOption?.text, isReviewMode: isReviewMode, isCorrect: selectedOptionId === subQuestion.correctOptionId }) }), _jsx("div", { className: "flex flex-wrap gap-2", children: subQuestion.options.map((option) => (_jsxs("button", { type: "button", onClick: () => !isReviewMode && onSelect(option.id), disabled: isReviewMode, className: `rounded-lg border-2 px-3 py-1.5 text-sm transition-colors ${getOptionStyle(option.id)} ${getTextStyle(option.id)} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: [option.label, ". ", option.text] }, option.id))) })] }));
65
- }
66
- export function MoversPictureFillBlankChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode = false, }) {
67
- return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode })] }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: subQuestions.map((subQuestion) => (_jsx(SubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, selectedOptionId: answers[subQuestion.id], onSelect: (optionId) => onAnswerChange(subQuestion.id, optionId), isReviewMode: isReviewMode }, subQuestion.id))) })] }));
68
- }
@@ -1,16 +0,0 @@
1
- import type { QuestionPart } from '../../../utils/question-transformers';
2
- interface SpeakingGNInterviewRendererProps {
3
- part: QuestionPart;
4
- answers: Record<string, unknown>;
5
- onAnswerChange: (questionId: string, value: unknown) => void;
6
- isReviewMode?: boolean;
7
- onExit: () => void;
8
- onPartComplete?: () => void;
9
- onPartBack?: () => void;
10
- speakingTheme?: string;
11
- teacherVideoUrl?: string;
12
- onTeacherIntroPlayed?: () => void;
13
- skipTeacherVideo?: boolean;
14
- }
15
- export declare function SpeakingGNInterviewRenderer(props: SpeakingGNInterviewRendererProps): import("react").JSX.Element;
16
- export {};
@@ -1,212 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- /**
4
- * SpeakingGNInterviewRenderer
5
- *
6
- * Renderer for GN_SPEAKING_INTERVIEW (GN Speaking Part 1 & Part 2).
7
- * Simulates 2 candidates: virtual (pre-recorded) + real (student records).
8
- *
9
- * Flow per question:
10
- * - If targetCandidate === 'VIRTUAL' -> auto-play virtual answer, no mic
11
- * - If targetCandidate === 'REAL' -> show mic, student records
12
- *
13
- * Part 2 extension: When content.imageUrl exists, displays a booklet
14
- * image (collage) above the question text for Discussion with Pictures.
15
- *
16
- * UI: Summer Sky theme with two game-style candidate avatars at bottom,
17
- * question text shown inside a teal card with hide/show question toggle badge,
18
- * audio player for examiner question.
19
- */
20
- import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
21
- import Image from 'next/image';
22
- import { usePresignedFileUrl } from '../../../../../../shared/lib/hooks';
23
- import { useSpeakingRendererSetup } from '../../../hooks/useSpeakingRendererSetup';
24
- import { getSpeakingLayout } from '../../../../../../components/themes';
25
- // Summer Sky theme assets (shared GN/KFS badges)
26
- import questionBadge from '../../../../../../components/themes/summer-sky/assets/images/question-badge-sunset.png';
27
- import redBadge from '../../../../../../components/themes/summer-sky/assets/images/red-badge-sunset.png';
28
- import blueBadge from '../../../../../../components/themes/summer-sky/assets/images/blue-badge-sunset.png';
29
- import redWrapper from '../../../../../../components/themes/summer-sky/assets/images/red-wrapper-sunset.png';
30
- import blueWrapper from '../../../../../../components/themes/summer-sky/assets/images/blue-wrapper-sunset.png';
31
- import bingoAvatar from '../../../../../../components/themes/summer-sky/assets/images/robot-avatar.png';
32
- import userAvatar from '../../../../../../components/themes/summer-sky/assets/images/student-avatar.png';
33
- import icPlay from '../../../../../../components/themes/summer-sky/assets/images/ic-play-sunset.png';
34
- import icPlayViolet from '../../../../../../components/themes/summer-sky/assets/images/ic-play-violet.webp';
35
- import nextSmall from '../../../../../../components/themes/summer-sky/assets/images/next-small.webp';
36
- function ProgressDots({ total, currentIndex, answeredIds, questionIds, virtualIndices }) {
37
- return (_jsx("div", { className: "flex items-center gap-1.5 flex-wrap justify-center", children: Array.from({ length: total }, (_, i) => {
38
- const isCurrent = i === currentIndex;
39
- const isAnswered = answeredIds.has(questionIds[i]);
40
- const isVirtual = virtualIndices.has(i);
41
- return (_jsx("div", { className: `h-2.5 w-2.5 rounded-full border-2 transition-all ${isCurrent
42
- ? 'scale-125 border-yellow-300 bg-yellow-400 shadow-lg'
43
- : isAnswered
44
- ? 'border-green-400 bg-green-400'
45
- : isVirtual
46
- ? 'border-white/30 bg-white/10'
47
- : 'border-white/50 bg-white/20'}`, title: isVirtual ? 'Câu HS ảo' : `Câu ${i + 1}` }, i));
48
- }) }));
49
- }
50
- // ============================================
51
- // Main component
52
- // ============================================
53
- export function SpeakingGNInterviewRenderer(props) {
54
- const [isQuestionVisible, setIsQuestionVisible] = useState(true);
55
- const [isVirtualPlaying, setIsVirtualPlaying] = useState(false);
56
- const virtualAudioRef = useRef(null);
57
- // Get group payload for virtual candidate config
58
- const groupPayload = props.part.groupPayload;
59
- const virtualName = groupPayload?.virtualStudentName || 'Học sinh AI';
60
- // Determine which questions are virtual
61
- const virtualIndices = useMemo(() => {
62
- const indices = new Set();
63
- props.part.questions.forEach((q, i) => {
64
- const content = q.content;
65
- if (content?.targetCandidate === 'VIRTUAL') {
66
- indices.add(i);
67
- }
68
- });
69
- return indices;
70
- }, [props.part.questions]);
71
- // Setup with mic always enabled - we'll conditionally show/hide based on virtual/real
72
- const setup = useSpeakingRendererSetup({
73
- ...props,
74
- maxDurationMs: 60000, // 60 seconds
75
- hasMic: true,
76
- });
77
- const Layout = getSpeakingLayout('SUMMER_SKY');
78
- const content = setup.currentQuestion?.content;
79
- const isVirtualTurn = content?.targetCandidate === 'VIRTUAL';
80
- const isRealTurn = !isVirtualTurn;
81
- // Resolve presigned URLs
82
- const { previewUrl: virtualAnswerAudioUrl } = usePresignedFileUrl(content?.virtualAnswer?.audioUrl ?? '');
83
- const { previewUrl: bookletImageUrl } = usePresignedFileUrl(content?.imageUrl ?? '');
84
- const hasBookletImage = !!content?.imageUrl && !!bookletImageUrl;
85
- // Stop virtual audio when navigating to a different question
86
- useEffect(() => {
87
- if (virtualAudioRef.current) {
88
- virtualAudioRef.current.pause();
89
- virtualAudioRef.current.currentTime = 0;
90
- }
91
- setIsVirtualPlaying(false);
92
- }, [setup.currentQuestion?.id]);
93
- // Play virtual answer audio
94
- const handlePlayVirtualAnswer = useCallback(() => {
95
- if (!virtualAnswerAudioUrl)
96
- return;
97
- if (isVirtualPlaying && virtualAudioRef.current) {
98
- virtualAudioRef.current.pause();
99
- setIsVirtualPlaying(false);
100
- return;
101
- }
102
- if (!virtualAudioRef.current) {
103
- virtualAudioRef.current = new Audio(virtualAnswerAudioUrl);
104
- virtualAudioRef.current.onended = () => setIsVirtualPlaying(false);
105
- virtualAudioRef.current.onerror = () => setIsVirtualPlaying(false);
106
- }
107
- else {
108
- virtualAudioRef.current.src = virtualAnswerAudioUrl;
109
- }
110
- virtualAudioRef.current.play();
111
- setIsVirtualPlaying(true);
112
- }, [virtualAnswerAudioUrl, isVirtualPlaying]);
113
- // Cleanup audio on unmount
114
- useEffect(() => {
115
- return () => {
116
- if (virtualAudioRef.current) {
117
- virtualAudioRef.current.pause();
118
- virtualAudioRef.current = null;
119
- }
120
- };
121
- }, []);
122
- // Auto-play virtual answer after teacher audio ends (1s delay)
123
- const handleTeacherAudioEnded = useCallback(() => {
124
- if (!isVirtualTurn || !virtualAnswerAudioUrl)
125
- return;
126
- const timer = setTimeout(() => {
127
- handlePlayVirtualAnswer();
128
- }, 1000);
129
- return () => clearTimeout(timer);
130
- }, [isVirtualTurn, virtualAnswerAudioUrl, handlePlayVirtualAnswer]);
131
- if (!setup.currentQuestion || !content)
132
- return null;
133
- // Progress tracking
134
- const answeredIds = new Set(props.part.questions.map((q) => q.id).filter((id) => !!props.answers[id]));
135
- const questionIds = props.part.questions.map((q) => q.id);
136
- const headerRight = (_jsx(ProgressDots, { total: props.part.questions.length, currentIndex: setup.nav.currentIndex, answeredIds: answeredIds, questionIds: questionIds, virtualIndices: virtualIndices }));
137
- return (_jsxs(Layout, { onExit: props.onExit, partName: props.part.name || `Part ${props.part.partNo}`, instruction: props.part.instructions || 'LISTEN AND ANSWER', audioUrl: content.audioUrl ?? '', questionNumber: setup.nav.questionNumberInPart, onPrev: setup.handlePrev, onNext: setup.handleNext, showPrev: setup.nav.showPrev, showNext: setup.nav.showNext, canGoPrev: setup.nav.canGoPrev, canGoNext: setup.nav.canGoNext, onAudioPlayingChange: setup.onAudioPlayingChange, recorder: props.isReviewMode || isVirtualTurn ? null : setup.recorder, showExistingBadge: isRealTurn && setup.showExistingBadge, teacherVideoUrl: props.teacherVideoUrl, onTeacherVideoEnded: props.onTeacherIntroPlayed, skipTeacherVideo: props.skipTeacherVideo, headerRight: headerRight, onAudioEnded: handleTeacherAudioEnded, children: [_jsxs("div", { className: "w-full h-full flex flex-col items-center relative", children: [_jsx("div", { className: "w-full flex-1", style: { minHeight: 0 }, children: _jsx("div", { className: "mx-auto", style: { width: '850px', maxWidth: '90%', height: hasBookletImage ? 'auto' : 'calc(100% - 100px)' }, children: _jsxs("div", { className: `w-full ${hasBookletImage ? '' : 'h-full'} flex flex-col items-center`, style: hasBookletImage ? {} : { paddingTop: '30px' }, children: [isQuestionVisible && content.questionText && (_jsxs("div", { className: "relative flex flex-col justify-center items-center", style: {
138
- width: '882px',
139
- maxWidth: '90%',
140
- maxHeight: '80%',
141
- paddingLeft: '77px',
142
- paddingRight: '77px',
143
- paddingTop: '26px',
144
- paddingBottom: '26px',
145
- backgroundColor: 'rgba(232, 136, 154, 0.15)',
146
- borderRadius: '20px',
147
- }, children: [_jsxs("div", { className: "absolute cursor-pointer", style: { top: '-19px' }, onClick: () => setIsQuestionVisible(false), children: [_jsx(Image, { src: questionBadge, alt: "", style: { width: '169px', height: '38px' } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center select-none", children: _jsx("span", { className: "font-normal text-center leading-5 text-white", style: { fontSize: '18px' }, children: "\u00E1\u00BA\u00A8n c\u00C3\u00A2u h\u00E1\u00BB\u008Fi" }) })] }), _jsx("div", { className: "max-w-full", children: _jsx("div", { className: "text-black font-bold leading-[26px] text-center max-w-full", style: { fontSize: '18px', fontFamily: '"Open Sans", sans-serif' }, children: _jsx("p", { children: content.questionText }) }) })] })), !isQuestionVisible && (_jsxs("div", { className: "cursor-pointer", onClick: () => setIsQuestionVisible(true), children: [_jsx(Image, { src: questionBadge, alt: "", style: { width: '169px', height: '38px' } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center select-none", style: { position: 'relative', top: '-30px' }, children: _jsx("span", { className: "font-normal text-center leading-5 text-white", style: { fontSize: '18px' }, children: "Hi\u00E1\u00BB\u2021n c\u00C3\u00A2u h\u00E1\u00BB\u008Fi" }) })] })), hasBookletImage && (_jsx("div", { className: "flex justify-center", style: { marginTop: '12px' }, children: _jsx("div", { className: "relative overflow-hidden", style: {
148
- maxWidth: '100%',
149
- borderRadius: '16px',
150
- border: '3px solid rgba(230, 99, 93, 0.3)',
151
- boxShadow: '0 4px 15px rgba(0,0,0,0.08)',
152
- }, children: _jsx("img", { src: bookletImageUrl, alt: "Booklet", style: {
153
- width: '100%',
154
- height: '100%',
155
- objectFit: 'cover',
156
- } }) }) }))] }) }) }), _jsxs("div", { className: "flex justify-between select-none items-end", style: { width: '990px', maxWidth: '95%', paddingBottom: '40px', paddingLeft: '20px', paddingRight: '20px' }, children: [_jsxs("div", { className: `relative select-none transition-opacity duration-300 ${isVirtualTurn ? 'opacity-100' : 'opacity-50 grayscale'}`, children: [_jsx("div", { children: _jsxs("div", { className: "relative flex", children: [_jsx(Image, { src: redBadge, alt: "", style: { height: '57px', width: '258px' } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center", style: { paddingTop: '12px' }, children: _jsx("div", { className: "text-white leading-5 font-normal text-center m-0 w-full select-none", children: _jsx("p", { className: "m-0 truncate select-none", style: { fontSize: '18px', paddingLeft: '60px', paddingRight: '60px' }, children: virtualName }) }) })] }) }), _jsxs("div", { className: "absolute", style: { top: '7px', right: '-58px' }, children: [_jsx(Image, { src: redWrapper, alt: "", className: "relative", style: { width: '115px', height: '84px', zIndex: 0 } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center w-full h-full", children: _jsxs("div", { className: "relative", style: { width: '68px', height: '68px' }, children: [_jsx(Image, { src: bingoAvatar, alt: virtualName, width: 68, height: 68, className: "object-cover rounded-full select-none", style: { width: '68px', height: '68px' }, draggable: false }), _jsx("div", { className: "flex items-center justify-center absolute w-full h-full top-0 rounded-full text-white cursor-pointer", onClick: isVirtualTurn ? handlePlayVirtualAnswer : undefined, children: _jsx(Image, { src: icPlay, alt: "play", width: 16, height: 16, className: "opacity-80" }) })] }) })] }), isVirtualPlaying && (_jsx("div", { className: "absolute pointer-events-none", style: { top: '0px', right: '-130px', width: '70px', height: '84px', display: 'flex', alignItems: 'center' }, children: _jsxs("div", { className: "relative", style: { width: '70px', height: '70px' }, children: [_jsx("div", { style: {
157
- position: 'absolute',
158
- left: '0px',
159
- top: '50%',
160
- transform: 'translateY(-50%)',
161
- width: '20px',
162
- height: '34px',
163
- borderRight: '3px solid rgba(30, 64, 175, 0.95)',
164
- borderRadius: '0 50% 50% 0',
165
- animation: 'soundWavePulse 1s ease-in-out infinite',
166
- animationDelay: '0s',
167
- } }), _jsx("div", { style: {
168
- position: 'absolute',
169
- left: '12px',
170
- top: '50%',
171
- transform: 'translateY(-50%)',
172
- width: '28px',
173
- height: '50px',
174
- borderRight: '3px solid rgba(30, 64, 175, 0.7)',
175
- borderRadius: '0 50% 50% 0',
176
- animation: 'soundWavePulse 1s ease-in-out infinite',
177
- animationDelay: '0.2s',
178
- } }), _jsx("div", { style: {
179
- position: 'absolute',
180
- left: '24px',
181
- top: '50%',
182
- transform: 'translateY(-50%)',
183
- width: '36px',
184
- height: '66px',
185
- borderRight: '3px solid rgba(30, 64, 175, 0.45)',
186
- borderRadius: '0 50% 50% 0',
187
- animation: 'soundWavePulse 1s ease-in-out infinite',
188
- animationDelay: '0.4s',
189
- } })] }) }))] }), isVirtualPlaying && (_jsx("div", { className: "flex-1 flex justify-center items-center text-center", style: { paddingLeft: '40px', paddingRight: '40px', paddingBottom: '40px' }, children: _jsxs("p", { className: "m-0 select-none", style: {
190
- fontSize: '16px',
191
- fontWeight: 700,
192
- fontStyle: 'italic',
193
- color: '#1a1a2e',
194
- lineHeight: '1.5',
195
- fontFamily: '"Open Sans", sans-serif',
196
- }, children: ["Ng\u00C6\u00B0\u00E1\u00BB\u009Di ch\u00C6\u00A1i kh\u00C3\u00A1c \u00C4\u2018ang tr\u00E1\u00BA\u00A3 l\u00E1\u00BB\u009Di.", _jsx("br", {}), "Vui l\u00C3\u00B2ng nghe xong \u0111\u1EC3 ti\u1EBFp t\u1EE5c."] }) })), isVirtualTurn && !isVirtualPlaying && (_jsxs("div", { className: "flex-1 flex flex-col justify-center items-center text-center", style: { paddingLeft: '40px', paddingRight: '40px', paddingBottom: '40px' }, children: [_jsxs("p", { className: "m-0 whitespace-nowrap", style: { color: '#1a1a2e', fontSize: '16px', fontWeight: 700, fontStyle: 'italic', fontFamily: '"Open Sans", sans-serif' }, children: ["\u00E1\u00BA\u00A4n bi\u00E1\u00BB\u0192u t\u00C6\u00B0\u00E1\u00BB\u00A3ng", ' ', _jsx(Image, { src: icPlayViolet, alt: "", width: 20, height: 20, className: "inline-block" }), ' ', "tr\u00EAn avatar \u0111\u1EC3 nghe l\u1EA1i."] }), _jsxs("div", { className: "flex items-center", style: { gap: '4px' }, children: [_jsx("p", { className: "m-0", style: { color: '#1a1a2e', fontSize: '16px', fontWeight: 700, fontStyle: 'italic', fontFamily: '"Open Sans", sans-serif' }, children: "\u1EA4n n\u00FAt" }), _jsx(Image, { src: nextSmall, alt: "next", width: 34, height: 34 }), _jsx("p", { className: "m-0", style: { color: '#1a1a2e', fontSize: '16px', fontWeight: 700, fontStyle: 'italic', fontFamily: '"Open Sans", sans-serif' }, children: "\u0111\u1EC3 ti\u1EBFp t\u1EE5c." })] })] })), _jsxs("div", { className: `relative select-none transition-opacity duration-300 ${isRealTurn ? 'opacity-100' : 'opacity-50 grayscale'}`, children: [_jsx("div", { children: _jsxs("div", { className: "relative flex", children: [_jsx(Image, { src: blueBadge, alt: "", style: { height: '57px', width: '258px' } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center", style: { paddingTop: '12px' }, children: _jsx("div", { className: "text-white leading-5 font-normal text-center m-0 w-full select-none", children: _jsx("p", { className: "m-0 truncate select-none", style: { fontSize: '18px', paddingLeft: '60px', paddingRight: '60px' }, children: "B\u1EA1n" }) }) })] }) }), _jsxs("div", { className: "absolute", style: { top: '7px', left: '-58px' }, children: [_jsx(Image, { src: blueWrapper, alt: "", className: "relative", style: { width: '115px', height: '84px', zIndex: 0 } }), _jsx("div", { className: "absolute inset-0 flex justify-center items-center w-full h-full", children: _jsx("div", { className: "relative", style: { width: '68px', height: '68px' }, children: _jsx(Image, { src: userAvatar, alt: "B\u1EA1n", width: 68, height: 68, className: "object-cover rounded-full select-none", style: { width: '68px', height: '68px' }, draggable: false }) }) })] })] })] })] }), _jsx("style", { jsx: true, children: `
197
- @keyframes soundWavePulse {
198
- 0% {
199
- opacity: 0.2;
200
- transform: translateY(-50%) scaleX(0.7);
201
- }
202
- 50% {
203
- opacity: 1;
204
- transform: translateY(-50%) scaleX(1);
205
- }
206
- 100% {
207
- opacity: 0.2;
208
- transform: translateY(-50%) scaleX(0.7);
209
- }
210
- }
211
- ` })] }));
212
- }
@@ -1,32 +0,0 @@
1
- import type { ValidationRef } from './look-and-choose-answer.type';
2
- export interface GNSpeakingInterviewData {
3
- /** How admin provides the question prompt */
4
- inputType: 'AUDIO' | 'TEXT';
5
- /** Audio file URL — required when inputType is 'AUDIO' */
6
- audioUrl?: string;
7
- /** Question text — required when inputType is 'TEXT', backend converts via TTS */
8
- questionText?: string;
9
- /** Which candidate this question targets */
10
- targetCandidate: 'A' | 'B';
11
- /** Virtual student's pre-recorded answer text */
12
- virtualAnswerText?: string;
13
- /** Virtual student's pre-recorded answer audio URL */
14
- virtualAnswerAudioUrl?: string;
15
- /** Whether this is an Extended Response question */
16
- isExtendedResponse?: boolean;
17
- /** Optional sample answers for AI grading reference (for real candidate questions) */
18
- sampleAnswers?: string[];
19
- /** Explanation for review */
20
- explanation?: string;
21
- /** Points per question (0 for virtual) */
22
- points?: number;
23
- }
24
- export interface GNSpeakingInterviewCreatorProps {
25
- initialData?: GNSpeakingInterviewData;
26
- onSave?: (data: GNSpeakingInterviewData) => void;
27
- onCancel?: () => void;
28
- onChange?: (data: GNSpeakingInterviewData) => void;
29
- externalErrors?: string[];
30
- onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void;
31
- validationRef?: React.MutableRefObject<ValidationRef | null>;
32
- }
@@ -1,47 +0,0 @@
1
- import { ValidationRef } from './look-and-choose-answer.type';
2
- export type { ValidationRef };
3
- export interface LookPictureFillWordHintSubQuestion {
4
- id: string;
5
- imageUrl: string;
6
- word: string;
7
- correctAnswer: string;
8
- points?: number;
9
- groupNumber?: number;
10
- }
11
- export interface LookPictureFillWordHintGroup {
12
- number: number;
13
- questionCount: number;
14
- }
15
- export interface LookPictureFillWordHintData {
16
- subQuestions: LookPictureFillWordHintSubQuestion[];
17
- hintLetters?: string[];
18
- hintLettersByGroup?: Record<number, string[]>;
19
- caseSensitive?: boolean;
20
- groups?: LookPictureFillWordHintGroup[];
21
- }
22
- export interface LookPictureFillWordHintCreatorProps {
23
- initialData?: LookPictureFillWordHintData;
24
- onSave?: (data: LookPictureFillWordHintData) => void;
25
- onSaveToQuestionBank?: (data: LookPictureFillWordHintData) => void;
26
- onCancel?: () => void;
27
- onChange?: (data: LookPictureFillWordHintData) => void;
28
- onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void;
29
- externalErrors?: string[];
30
- groups?: LookPictureFillWordHintGroup[];
31
- questionIndexInPart?: number;
32
- partId?: string;
33
- validationRef?: React.MutableRefObject<ValidationRef | null>;
34
- }
35
- export interface LookPictureFillWordHintQuestionData {
36
- subQuestions: LookPictureFillWordHintSubQuestion[];
37
- hintLetters?: string[];
38
- hintLettersByGroup?: Record<number, string[]>;
39
- caseSensitive?: boolean;
40
- groups?: LookPictureFillWordHintGroup[];
41
- }
42
- export interface LookPictureFillWordHintClientProps {
43
- questionData: LookPictureFillWordHintQuestionData;
44
- onSubmit?: (answers: Record<string, string>) => void;
45
- isReviewMode?: boolean;
46
- userAnswer?: Record<string, string>;
47
- }
@@ -1,2 +0,0 @@
1
- import type { GNSpeakingInterviewCreatorProps } from '../../_shared/types/gn-speaking-interview.type';
2
- export declare function GNSpeakingInterviewCreator({ initialData, onSave, onChange, externalErrors, validationRef, }: GNSpeakingInterviewCreatorProps): import("react").JSX.Element;