@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
@@ -38,7 +38,6 @@ export function ExamCreator(props) {
38
38
  const clearQuestionData = useExamQuestionStore((state) => state.clearQuestionData);
39
39
  const markQuestionCompleted = useExamQuestionStore((state) => state.markQuestionCompleted);
40
40
  const getQuestionData = useExamQuestionStore((state) => state.getQuestionData);
41
- const setSharedHintLetters = useExamQuestionStore((state) => state.setSharedHintLetters);
42
41
  const [validationErrors, setValidationErrors] = useState({});
43
42
  const [isSavingQuestion, setIsSavingQuestion] = useState(false);
44
43
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
@@ -96,14 +95,13 @@ export function ExamCreator(props) {
96
95
  upsertQuestionData(index, savedQuestion);
97
96
  markQuestionCompleted(index, true);
98
97
  savedQuestionsRef.current[index] = savedQuestion;
99
- hydrateSharedHintLetters(index, savedQuestion, template, setSharedHintLetters);
100
98
  const questionBank = question.questionBank;
101
99
  if (questionBank?.id)
102
100
  setExistingQuestionBanks((prev) => ({ ...prev, [index]: questionBank }));
103
101
  });
104
102
  const timer = window.setTimeout(() => { justInitializedRef.current = false; }, 1000);
105
103
  return () => window.clearTimeout(timer);
106
- }, [initialQuestions, initialized, markQuestionCompleted, setSharedHintLetters, template, upsertQuestionData]);
104
+ }, [initialQuestions, initialized, markQuestionCompleted, template, upsertQuestionData]);
107
105
  useEffect(() => {
108
106
  setCurrentQuestionHasUnsavedChanges(getQuestionStatus(examId, currentQuestionIndex + 1) === QuestionStatus.UNSAVED);
109
107
  }, [currentQuestionIndex, examId]);
@@ -302,19 +300,6 @@ function validateQuestionBank(setting, existingBank, setCodeError, setTitleError
302
300
  setTitleError(titleError);
303
301
  return !codeError && !titleError;
304
302
  }
305
- function hydrateSharedHintLetters(index, question, template, setSharedHintLetters) {
306
- if (question.type !== 'LOOK_PICTURE_FILL_WORD_HINT' || !question.partId)
307
- return;
308
- const answer = question.answer;
309
- const groupNumber = question.questionGroup?.groupNumber;
310
- if (!answer?.hintLetters?.length || !groupNumber)
311
- return;
312
- const part = getPartByQuestionIndex(template, index);
313
- const config = part ? getEffectiveQuestionConfig(part, index) : undefined;
314
- const sectionName = getConfigSectionName(config);
315
- const partId = sectionName ? `${question.partId}_${sectionName}` : question.partId;
316
- setSharedHintLetters(partId, groupNumber, answer.hintLetters);
317
- }
318
303
  function getConfigSectionName(config) {
319
304
  return config && 'sectionName' in config ? config.sectionName : undefined;
320
305
  }
@@ -614,18 +614,6 @@ function ExamTakingPageContainerInner({ roomId, api, onNavigate, resultPath = (a
614
614
  map.set(region.id, question.id);
615
615
  });
616
616
  }
617
- // LOOK_PICTURE_FILL_WORD_HINT: single question with {0}, {1} placeholders → synthetic IDs
618
- if (part.questionType === 'LOOK_PICTURE_FILL_WORD_HINT') {
619
- const word = content?.word;
620
- if (word && typeof word === 'string') {
621
- const placeholderRegex = /\{(\d+)\}/g;
622
- let match;
623
- while ((match = placeholderRegex.exec(word)) !== null) {
624
- const blankIndex = match[1];
625
- map.set(`${question.id}-blank-${blankIndex}`, question.id);
626
- }
627
- }
628
- }
629
617
  if (part.questionType === 'CROSS_OUT_WORD_GROUP' &&
630
618
  Array.isArray(content?.items)) {
631
619
  content.items.forEach((_, index) => {
@@ -8,9 +8,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  * 2. Transforms data to renderer-specific props
9
9
  * 3. Renders the correct component for each question type
10
10
  */
11
- import { MoversListenAndWriteRenderer, MoversChooseBestAnswerRenderer, MoversChooseAdjectiveRenderer, MoversWritingRenderer, MoversColoringRenderer, MoversPictureChooseRenderer, MoversPictureFillBlankChooseRenderer, MoversReadingPassageRenderer, MoversLabelThePictureRenderer, MoversFillWordHintRenderer, MoversGridFillRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversFillInBlankGroupRenderer, MoversCrossOutWordGroupRenderer, MoversAnswerTheQuestionRenderer, MoversWriteSentencesRenderer, MoversWordOrderingRenderer, MoversWordOrderingGroupRenderer, MoversWordFillParagraphRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderAndMatchGroupRenderer, MoversMatchingWithLinesGroupRenderer, MoversCrosswordPuzzleRenderer, FindWordsInMatrixRenderer, SortWordsIntoCategoriesRenderer, ChooseThenAnswerGroupRenderer, } from './question-renderers';
11
+ import { MoversListenAndWriteRenderer, MoversChooseBestAnswerRenderer, MoversChooseAdjectiveRenderer, MoversWritingRenderer, MoversColoringRenderer, MoversReadingPassageRenderer, MoversLabelThePictureRenderer, MoversGridFillRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversFillInBlankGroupRenderer, MoversCrossOutWordGroupRenderer, MoversAnswerTheQuestionRenderer, MoversWriteSentencesRenderer, MoversWordOrderingRenderer, MoversWordOrderingGroupRenderer, MoversWordFillParagraphRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderAndMatchGroupRenderer, MoversMatchingWithLinesGroupRenderer, MoversCrosswordPuzzleRenderer, FindWordsInMatrixRenderer, SortWordsIntoCategoriesRenderer, ChooseThenAnswerGroupRenderer, } from './question-renderers';
12
12
  import { SpeakingQuestionRenderer } from './speaking/renderers';
13
- import { transformFillInBlank, transformWriteCorrectVerbForm, transformChooseCorrectAnswer, transformChooseTheCorrectAnswerGroup, transformChooseCorrectAdjective, transformWriteShortLetter, transformColorObjects, transformPictureChoose, transformPictureFillBlankChoose, transformReadingPassage, transformLabelPicture, transformFillWordHint, transformGridFill, transformAnswerTheQuestion, transformAnswerTheQuestionGroup, transformTrueFalse, transformTrueFalseGroup, transformTrueFalseCorrectGroup, transformFillInBlankGroup, transformWordOrdering, transformWordOrderingGroupTake, transformWordFillParagraph, transformMatchByWritingAnswer, transformMatchWordToPicture, transformWriteSentences, transformWordFillStructuredForm, transformWordOrderAndMatchGroup, transformMatchingWithLinesGroup, transformCrosswordPuzzle, transformFindWordsInMatrix, transformSortWordsIntoCategories, transformChooseThenAnswerGroup, } from '../utils/question-transformers';
13
+ import { transformFillInBlank, transformWriteCorrectVerbForm, transformChooseCorrectAnswer, transformChooseTheCorrectAnswerGroup, transformChooseCorrectAdjective, transformWriteShortLetter, transformColorObjects, transformReadingPassage, transformLabelPicture, transformGridFill, transformAnswerTheQuestion, transformAnswerTheQuestionGroup, transformTrueFalse, transformTrueFalseGroup, transformTrueFalseCorrectGroup, transformFillInBlankGroup, transformWordOrdering, transformWordOrderingGroupTake, transformWordFillParagraph, transformMatchByWritingAnswer, transformMatchWordToPicture, transformWriteSentences, transformWordFillStructuredForm, transformWordOrderAndMatchGroup, transformMatchingWithLinesGroup, transformCrosswordPuzzle, transformFindWordsInMatrix, transformSortWordsIntoCategories, transformChooseThenAnswerGroup, } from '../utils/question-transformers';
14
14
  import { transformCrossOutWordGroup } from '../utils/cross-out-word-group.transformer';
15
15
  import { normalizeColoringAssignments } from '../utils/coloring-assignments';
16
16
  export function QuestionRenderer({ part, answers, onAnswerChange, isReviewMode = false, onExit, onPartComplete, onPartBack, speakingTheme, initialQuestionIndex, skipTeacherVideo, onTeacherIntroPlayed, currentQuestionIndex, compactLayout = false, }) {
@@ -88,14 +88,6 @@ export function QuestionRenderer({ part, answers, onAnswerChange, isReviewMode =
88
88
  onAnswerChange(regionId, hintItemId);
89
89
  }, isReviewMode: isReviewMode }));
90
90
  }
91
- case 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': {
92
- const data = transformPictureChoose(questions);
93
- return (_jsx(MoversPictureChooseRenderer, { partNumber: partNo, partName: part.name, questionCount: questionCount, instruction: part.instructions || data.instruction, subQuestions: data.subQuestions, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode }));
94
- }
95
- case 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER': {
96
- const data = transformPictureFillBlankChoose(questions);
97
- return (_jsx(MoversPictureFillBlankChooseRenderer, { partNumber: partNo, partName: part.name, questionCount: questionCount, instruction: part.instructions || data.instruction, subQuestions: data.subQuestions, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode }));
98
- }
99
91
  case 'READ_PASSAGE_AND_ANSWER_QUESTIONS': {
100
92
  const data = transformReadingPassage(questions);
101
93
  return (_jsx(MoversReadingPassageRenderer, { partNumber: partNo, partName: part.name, questionCount: data.questions.length, instruction: part.instructions || data.instruction, passageTitle: data.passageTitle, passage: data.passage, passageImageUrl: data.passageImageUrl, questions: getRenderQuestions(data.questions), answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode }));
@@ -104,10 +96,6 @@ export function QuestionRenderer({ part, answers, onAnswerChange, isReviewMode =
104
96
  const data = transformLabelPicture(questions);
105
97
  return (_jsx(MoversLabelThePictureRenderer, { partNumber: partNo, partName: part.name, questionCount: data.labels.length, instruction: part.instructions || data.instruction, imageUrl: data.imageUrl, wordBank: data.wordBank, labels: data.labels, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode }));
106
98
  }
107
- case 'LOOK_PICTURE_FILL_WORD_HINT': {
108
- const data = transformFillWordHint(questions);
109
- return (_jsx(MoversFillWordHintRenderer, { partNumber: partNo, partName: part.name, questionCount: data.subQuestions.length, instruction: part.instructions || data.instruction, hintLetters: data.hintLetters, subQuestions: data.subQuestions, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode }));
110
- }
111
99
  case 'FILL_MISSING_WORDS_IN_GRID': {
112
100
  const data = transformGridFill(questions);
113
101
  return (_jsx(MoversGridFillRenderer, { partNumber: partNo, partName: part.name, questionCount: questionCount, instruction: part.instructions || data.instruction, grid: data.grid, rows: data.rows, columns: data.columns, cellAnswers: {}, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, disabledCells: data.disabledCells }));
@@ -243,7 +231,6 @@ export function QuestionRenderer({ part, answers, onAnswerChange, isReviewMode =
243
231
  case 'SPONTANEOUS_QA':
244
232
  case 'SPONTANEOUS_QA_GROUP':
245
233
  case 'SPEAKING_CONVERSATION':
246
- case 'GN_SPEAKING_INTERVIEW':
247
234
  case 'SPEAKING_CUE_CARD': {
248
235
  return (_jsx(SpeakingQuestionRenderer, { part: part, answers: answers, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, onExit: onExit, onPartComplete: onPartComplete, onPartBack: onPartBack, speakingTheme: speakingTheme, initialQuestionIndex: initialQuestionIndex, skipTeacherVideo: skipTeacherVideo, onTeacherIntroPlayed: onTeacherIntroPlayed, currentQuestionIndex: currentQuestionIndex }));
249
236
  }
@@ -3,11 +3,8 @@ export { MoversColoringRenderer } from './MoversColoringRenderer';
3
3
  export { MoversChooseBestAnswerRenderer } from './MoversChooseBestAnswerRenderer';
4
4
  export { MoversChooseAdjectiveRenderer } from './MoversChooseAdjectiveRenderer';
5
5
  export { MoversWritingRenderer } from './MoversWritingRenderer';
6
- export { MoversPictureChooseRenderer } from './MoversPictureChooseRenderer';
7
- export { MoversPictureFillBlankChooseRenderer } from './MoversPictureFillBlankChooseRenderer';
8
6
  export { MoversReadingPassageRenderer } from './MoversReadingPassageRenderer';
9
7
  export { MoversLabelThePictureRenderer } from './MoversLabelThePictureRenderer';
10
- export { MoversFillWordHintRenderer } from './MoversFillWordHintRenderer';
11
8
  export { MoversGridFillRenderer } from './MoversGridFillRenderer';
12
9
  export { MoversTrueFalseRenderer } from './MoversTrueFalseRenderer';
13
10
  export { MoversTrueFalseCorrectGroupRenderer } from './MoversTrueFalseCorrectGroupRenderer';
@@ -4,12 +4,9 @@ export { MoversChooseBestAnswerRenderer } from './MoversChooseBestAnswerRenderer
4
4
  export { MoversChooseAdjectiveRenderer } from './MoversChooseAdjectiveRenderer';
5
5
  export { MoversWritingRenderer } from './MoversWritingRenderer';
6
6
  // New renderers - P1 (Simple)
7
- export { MoversPictureChooseRenderer } from './MoversPictureChooseRenderer';
8
- export { MoversPictureFillBlankChooseRenderer } from './MoversPictureFillBlankChooseRenderer';
9
7
  export { MoversReadingPassageRenderer } from './MoversReadingPassageRenderer';
10
8
  // New renderers - P2 (Medium)
11
9
  export { MoversLabelThePictureRenderer } from './MoversLabelThePictureRenderer';
12
- export { MoversFillWordHintRenderer } from './MoversFillWordHintRenderer';
13
10
  // New renderers - P3 (Complex)
14
11
  export { MoversGridFillRenderer } from './MoversGridFillRenderer';
15
12
  // Starters & Movers renderers
@@ -17,7 +17,6 @@ import { SpeakingSpontaneousQaGroupRenderer } from './SpeakingSpontaneousQaGroup
17
17
  import { SpeakingSpontaneousQaGroupTextList } from './SpeakingSpontaneousQaGroupTextList';
18
18
  import { isTextOnlySpontaneousQaGroupContent } from '../../../../../questions/types/spontaneous-qa-group/flatten';
19
19
  import { SpeakingConversationRenderer } from './SpeakingConversationRenderer';
20
- import { SpeakingGNInterviewRenderer } from './SpeakingGNInterviewRenderer';
21
20
  import { SpeakingCueCardRenderer } from './SpeakingCueCardRenderer';
22
21
  // ============================================
23
22
  // Factory
@@ -86,9 +85,6 @@ export function SpeakingQuestionRenderer({ part, answers, onAnswerChange, isRevi
86
85
  // KFS Speaking — 3-participant conversation (Interlocutor + Partner + Student)
87
86
  case 'SPEAKING_CONVERSATION':
88
87
  return _jsx(SpeakingConversationRenderer, { ...sharedProps });
89
- // GN Speaking Interview — virtual + real candidate simulation
90
- case 'GN_SPEAKING_INTERVIEW':
91
- return _jsx(SpeakingGNInterviewRenderer, { ...sharedProps });
92
88
  // IELTS Part 2 — Cue Card (Preparation + Recording)
93
89
  case 'SPEAKING_CUE_CARD':
94
90
  return _jsx(SpeakingCueCardRenderer, { ...sharedProps });
@@ -81,37 +81,6 @@ export interface SpontaneousQAContent {
81
81
  /** Backup flag — consistent with other speaking types */
82
82
  isBackup?: boolean;
83
83
  }
84
- export interface GNSpeakingInterviewContent {
85
- /** Examiner's question text */
86
- questionText: string;
87
- /** Audio URL for examiner's question (TTS or uploaded) */
88
- audioUrl?: string;
89
- /** How admin created the question */
90
- inputType: 'AUDIO' | 'TEXT';
91
- /** Which candidate this question is addressed to */
92
- targetCandidate: 'VIRTUAL' | 'REAL';
93
- /** Booklet image URL — collage for Part 2 Discussion with Pictures */
94
- imageUrl?: string;
95
- /** Virtual student's pre-recorded answer (filled by admin) */
96
- virtualAnswer?: {
97
- /** Text of the virtual student's answer */
98
- answerText: string;
99
- /** Audio URL — admin uploads or auto-generates via TTS */
100
- audioUrl?: string;
101
- };
102
- /** Whether this is an Extended Response question */
103
- isExtendedResponse?: boolean;
104
- /** Backup flag */
105
- isBackup?: boolean;
106
- }
107
- export interface GNSpeakingInterviewGroupPayload {
108
- /** Which candidate role is virtual (pre-recorded) */
109
- virtualCandidate: 'A' | 'B';
110
- /** Virtual student display name */
111
- virtualStudentName?: string;
112
- /** Virtual student avatar image URL */
113
- virtualStudentAvatar?: string;
114
- }
115
84
  /** Answer stored in examTakingStore for speaking questions */
116
85
  export interface SpeakingAnswer {
117
86
  audioUrl: string;
@@ -168,52 +168,6 @@ export interface ArticleItem {
168
168
  content: string;
169
169
  imageUrl?: string;
170
170
  }
171
- export interface PictureChooseOption {
172
- id: string;
173
- label: string;
174
- text: string;
175
- }
176
- export interface PictureChooseSubQuestion {
177
- id: string;
178
- questionNumber: number;
179
- imageUrl: string;
180
- questionText?: string;
181
- options: PictureChooseOption[];
182
- correctOptionId?: string;
183
- }
184
- export interface MoversPictureChooseRendererProps {
185
- partNumber: number;
186
- partName?: string;
187
- questionCount: number;
188
- instruction: string;
189
- subQuestions: PictureChooseSubQuestion[];
190
- answers: Record<string, string>;
191
- onAnswerChange: (subQuestionId: string, optionId: string) => void;
192
- isReviewMode?: boolean;
193
- }
194
- export interface PictureFillBlankOption {
195
- id: string;
196
- label: string;
197
- text: string;
198
- }
199
- export interface PictureFillBlankSubQuestion {
200
- id: string;
201
- questionNumber: number;
202
- imageUrl: string;
203
- question: string;
204
- options: PictureFillBlankOption[];
205
- correctOptionId?: string;
206
- }
207
- export interface MoversPictureFillBlankChooseRendererProps {
208
- partNumber: number;
209
- partName?: string;
210
- questionCount: number;
211
- instruction: string;
212
- subQuestions: PictureFillBlankSubQuestion[];
213
- answers: Record<string, string>;
214
- onAnswerChange: (subQuestionId: string, optionId: string) => void;
215
- isReviewMode?: boolean;
216
- }
217
171
  export interface ReadingPassageOption {
218
172
  id: string;
219
173
  label: string;
@@ -258,25 +212,6 @@ export interface MoversLabelThePictureRendererProps {
258
212
  onAnswerChange: (labelId: string, value: string) => void;
259
213
  isReviewMode?: boolean;
260
214
  }
261
- export interface FillWordHintSubQuestion {
262
- id: string;
263
- questionNumber: number;
264
- imageUrl: string;
265
- word: string;
266
- correctAnswer?: string;
267
- blankIndex?: number;
268
- }
269
- export interface MoversFillWordHintRendererProps {
270
- partNumber: number;
271
- partName?: string;
272
- questionCount: number;
273
- instruction: string;
274
- hintLetters: string[];
275
- subQuestions: FillWordHintSubQuestion[];
276
- answers: Record<string, string>;
277
- onAnswerChange: (subQuestionId: string, value: string) => void;
278
- isReviewMode?: boolean;
279
- }
280
215
  export interface GridCellAnswer {
281
216
  correctAnswer: string;
282
217
  }
@@ -162,34 +162,6 @@ function findColoringParentQuestion(regionId, parts) {
162
162
  }
163
163
  return null;
164
164
  }
165
- /**
166
- * Find parent question for sub-questions (LOOK_PICTURE_FILL_WORD_HINT)
167
- * Supports both old format (content.subQuestions) and new format (questionId-blank-N)
168
- */
169
- function findFillWordHintParentQuestion(subQuestionId, parts) {
170
- for (const part of parts) {
171
- if (part.questionType === 'LOOK_PICTURE_FILL_WORD_HINT') {
172
- for (const question of part.questions) {
173
- // NEW FORMAT: Check if subQuestionId matches pattern "questionId-blank-N"
174
- if (subQuestionId.startsWith(`${question.id}-blank-`)) {
175
- return {
176
- parentId: question.id,
177
- questionType: part.questionType,
178
- };
179
- }
180
- // OLD FORMAT: Check subQuestions array in content
181
- const content = question.content;
182
- if (content?.subQuestions?.some((sq) => sq.id === subQuestionId)) {
183
- return {
184
- parentId: question.id,
185
- questionType: part.questionType,
186
- };
187
- }
188
- }
189
- }
190
- }
191
- return null;
192
- }
193
165
  /**
194
166
  * Find question type by questionId
195
167
  */
@@ -327,14 +299,9 @@ export function transformAnswersForSubmission(answers, parts) {
327
299
  }
328
300
  continue;
329
301
  }
330
- // Handle synthetic sub-question IDs (from READ_PASSAGE_AND_ANSWER_QUESTIONS or LOOK_PICTURE_FILL_WORD_HINT)
302
+ // Handle synthetic sub-question IDs (from READ_PASSAGE_AND_ANSWER_QUESTIONS)
331
303
  if (isSyntheticSubQuestionId(questionId)) {
332
- // Try READ_PASSAGE_AND_ANSWER_QUESTIONS first
333
- let parent = findParentQuestion(questionId, parts);
334
- // If not found, try LOOK_PICTURE_FILL_WORD_HINT
335
- if (!parent) {
336
- parent = findFillWordHintParentQuestion(questionId, parts);
337
- }
304
+ const parent = findParentQuestion(questionId, parts);
338
305
  if (parent) {
339
306
  if (!subQuestionAnswers.has(parent.parentId)) {
340
307
  subQuestionAnswers.set(parent.parentId, {});
@@ -457,31 +424,10 @@ export function transformAnswersForSubmission(answers, parts) {
457
424
  });
458
425
  continue;
459
426
  }
460
- // Check if this is LOOK_PICTURE_FILL_WORD_HINT with new format IDs
461
- const hasBlankIds = Object.keys(subAnswers).some((key) => key.includes('-blank-'));
462
- if (hasBlankIds) {
463
- // NEW FORMAT: Convert to comma-separated string like correctAnswer
464
- // Sort by blank index and join
465
- const sortedEntries = Object.entries(subAnswers).sort(([a], [b]) => {
466
- const aMatch = a.match(/-blank-(\d+)$/);
467
- const bMatch = b.match(/-blank-(\d+)$/);
468
- const aIdx = aMatch ? parseInt(aMatch[1], 10) : 0;
469
- const bIdx = bMatch ? parseInt(bMatch[1], 10) : 0;
470
- return aIdx - bIdx;
471
- });
472
- const commaSeparated = sortedEntries.map(([, v]) => v).join(', ');
473
- result.push({
474
- questionId: parentId,
475
- answer: { answer: commaSeparated }, // Simple format: { answer: "a, e" }
476
- });
477
- }
478
- else {
479
- // OLD FORMAT or other question types: keep subAnswers format
480
- result.push({
481
- questionId: parentId,
482
- answer: { subAnswers },
483
- });
484
- }
427
+ result.push({
428
+ questionId: parentId,
429
+ answer: { subAnswers },
430
+ });
485
431
  }
486
432
  // Add grid cell answers (grouped under parent question)
487
433
  for (const [parentId, cellAnswers] of gridCellAnswers) {
@@ -4,8 +4,8 @@
4
4
  * Maps backend question types to frontend renderer props.
5
5
  * Each transformer handles specific question type data structure.
6
6
  */
7
- import type { FillBlankQuestion, ChooseBestAnswerQuestion, PictureChooseSubQuestion, PictureFillBlankSubQuestion, ReadingPassageQuestion, LabelThePictureLabel, FillWordHintSubQuestion, ColoringHintItem, ColoringRegion } from '../types';
8
- export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'ANSWER_THE_QUESTION_GROUP' | 'TRUE_FALSE' | 'TRUE_FALSE_GROUP' | 'TRUE_FALSE_CORRECT_GROUP' | 'FILL_IN_BLANK_GROUP' | 'MATCHING_WITH_LINES_GROUP' | 'CROSS_OUT_WORD_GROUP' | 'WORD_ORDERING' | 'WORD_ORDERING_GROUP' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'MATCH_WORD_TO_PICTURE' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'CROSSWORD_PUZZLE' | 'FIND_WORDS_IN_MATRIX' | 'SORT_WORDS_INTO_CATEGORIES' | 'CHOOSE_THEN_ANSWER_GROUP' | 'WORD_ORDER_AND_MATCH_GROUP' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPONTANEOUS_QA_GROUP' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD';
7
+ import type { FillBlankQuestion, ChooseBestAnswerQuestion, ReadingPassageQuestion, LabelThePictureLabel, ColoringHintItem, ColoringRegion } from '../types';
8
+ export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'ANSWER_THE_QUESTION_GROUP' | 'TRUE_FALSE' | 'TRUE_FALSE_GROUP' | 'TRUE_FALSE_CORRECT_GROUP' | 'FILL_IN_BLANK_GROUP' | 'MATCHING_WITH_LINES_GROUP' | 'CROSS_OUT_WORD_GROUP' | 'WORD_ORDERING' | 'WORD_ORDERING_GROUP' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'MATCH_WORD_TO_PICTURE' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'CROSSWORD_PUZZLE' | 'FIND_WORDS_IN_MATRIX' | 'SORT_WORDS_INTO_CATEGORIES' | 'CHOOSE_THEN_ANSWER_GROUP' | 'WORD_ORDER_AND_MATCH_GROUP' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPONTANEOUS_QA_GROUP' | 'SPEAKING_CONVERSATION' | 'SPEAKING_CUE_CARD';
9
9
  export interface ApiQuestion {
10
10
  id: string;
11
11
  content: any;
@@ -204,14 +204,6 @@ export declare function transformColorObjects(questions: ApiQuestion[]): {
204
204
  hintItems: ColoringHintItem[];
205
205
  regions: ColoringRegion[];
206
206
  };
207
- export declare function transformPictureChoose(questions: ApiQuestion[]): {
208
- subQuestions: PictureChooseSubQuestion[];
209
- instruction: string;
210
- };
211
- export declare function transformPictureFillBlankChoose(questions: ApiQuestion[]): {
212
- subQuestions: PictureFillBlankSubQuestion[];
213
- instruction: string;
214
- };
215
207
  export declare function transformReadingPassage(questions: ApiQuestion[]): {
216
208
  passage: string;
217
209
  passageTitle?: string;
@@ -225,11 +217,6 @@ export declare function transformLabelPicture(questions: ApiQuestion[]): {
225
217
  labels: LabelThePictureLabel[];
226
218
  instruction: string;
227
219
  };
228
- export declare function transformFillWordHint(questions: ApiQuestion[]): {
229
- subQuestions: FillWordHintSubQuestion[];
230
- hintLetters: string[];
231
- instruction: string;
232
- };
233
220
  export declare function transformGridFill(questions: ApiQuestion[]): {
234
221
  grid: (string | null)[][];
235
222
  rows: number;
@@ -618,49 +618,6 @@ export function transformColorObjects(questions) {
618
618
  regions,
619
619
  };
620
620
  }
621
- export function transformPictureChoose(questions) {
622
- const firstContent = questions[0]?.content;
623
- const subQuestions = questions.map((q) => {
624
- const content = q.content;
625
- return {
626
- id: q.id,
627
- questionNumber: q.question_number,
628
- imageUrl: content.imageUrl || '',
629
- questionText: content.questionText,
630
- options: (content.options || []).map((opt, idx) => ({
631
- id: opt.id || `${q.id}-opt-${idx}`,
632
- label: OPTION_LABELS[idx] || String(idx + 1),
633
- text: typeof opt === 'string' ? opt : opt.text,
634
- })),
635
- };
636
- });
637
- return {
638
- subQuestions,
639
- instruction: firstContent?.instruction || 'LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER',
640
- };
641
- }
642
- export function transformPictureFillBlankChoose(questions) {
643
- const firstContent = questions[0]?.content;
644
- const subQuestions = questions.map((q) => {
645
- const content = q.content;
646
- return {
647
- id: q.id,
648
- questionNumber: q.question_number,
649
- imageUrl: content.imageUrl || '',
650
- question: content.question || '',
651
- options: (content.options || []).map((opt, idx) => ({
652
- id: opt.id || `${q.id}-opt-${idx}`,
653
- label: OPTION_LABELS[idx] || String(idx + 1),
654
- text: typeof opt === 'string' ? opt : opt.text,
655
- })),
656
- };
657
- });
658
- return {
659
- subQuestions,
660
- instruction: firstContent?.instruction ||
661
- 'LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER',
662
- };
663
- }
664
621
  /**
665
622
  * Detect if data uses new format (separate questions with questionGroup)
666
623
  * New format: content has 'question' field (not 'questions' array)
@@ -737,106 +694,6 @@ export function transformLabelPicture(questions) {
737
694
  instruction: content?.instruction || 'LABEL THE PICTURE',
738
695
  };
739
696
  }
740
- /**
741
- * Detect if content uses new format (single word with {n} placeholders)
742
- */
743
- function isNewFillWordHintFormat(content) {
744
- return content && typeof content.word === 'string' && !content.subQuestions;
745
- }
746
- /**
747
- * Parse word string with numbered placeholders like "c{0}t, {1}lephan"
748
- * Returns array of parsed blanks with their segments
749
- */
750
- function parseNumberedPlaceholders(word) {
751
- const results = [];
752
- // Split by comma to handle multiple words like "c{0}t, {1}lephan"
753
- const wordSegments = word.split(',').map((s) => s.trim());
754
- for (const segment of wordSegments) {
755
- // Find all placeholders in this segment
756
- let match;
757
- const segmentRegex = /\{(\d+)\}/g;
758
- while ((match = segmentRegex.exec(segment)) !== null) {
759
- const placeholderIndex = parseInt(match[1], 10);
760
- // Replace {n} with _ for display
761
- const displayWord = segment.replace(match[0], '_');
762
- results.push({
763
- index: placeholderIndex,
764
- displayWord,
765
- });
766
- }
767
- }
768
- // Sort by index to ensure correct order
769
- results.sort((a, b) => a.index - b.index);
770
- return results;
771
- }
772
- export function transformFillWordHint(questions) {
773
- const firstQuestion = questions[0];
774
- const content = firstQuestion?.content;
775
- // MULTI-QUESTION FORMAT: Multiple separate questions with same group_id
776
- // Each has own id, imageUrl, and single {0} placeholder
777
- if (questions.length > 1 && questions.every((q) => isNewFillWordHintFormat(q.content))) {
778
- const hintLetters = firstQuestion.questionGroup?.payload?.hintLetters || [];
779
- const subQuestions = questions.map((q) => {
780
- const qContent = q.content;
781
- // Replace {0} with underscore for display
782
- const displayWord = qContent.word.replace(/\{\d+\}/, '_');
783
- return {
784
- id: q.id, // Use actual question ID (not synthetic)
785
- questionNumber: q.question_number,
786
- imageUrl: qContent.imageUrl || '',
787
- word: displayWord,
788
- // No blankIndex → triggers OLD FORMAT rendering (grid with individual images)
789
- };
790
- });
791
- return {
792
- subQuestions,
793
- hintLetters,
794
- instruction: content?.instruction ||
795
- 'LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER',
796
- };
797
- }
798
- // Detect format and transform accordingly
799
- if (isNewFillWordHintFormat(content)) {
800
- // NEW FORMAT: Single word with {0}, {1} placeholders
801
- const newContent = content;
802
- // Get hintLetters from questionGroup.payload (new location)
803
- const hintLetters = firstQuestion.questionGroup?.payload?.hintLetters || [];
804
- // Parse the word string to extract placeholders
805
- const placeholders = parseNumberedPlaceholders(newContent.word);
806
- // Create sub-questions for each placeholder
807
- const subQuestions = placeholders.map((p) => ({
808
- id: `${firstQuestion.id}-blank-${p.index}`,
809
- questionNumber: firstQuestion.question_number,
810
- imageUrl: newContent.imageUrl || '',
811
- word: p.displayWord,
812
- blankIndex: p.index,
813
- }));
814
- return {
815
- subQuestions,
816
- hintLetters,
817
- instruction: newContent.instruction ||
818
- 'LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER',
819
- };
820
- }
821
- // OLD FORMAT: subQuestions array with individual images
822
- const oldContent = content;
823
- const subQuestions = oldContent?.subQuestions?.map((sq, idx) => ({
824
- id: sq.id,
825
- questionNumber: firstQuestion.question_number + idx,
826
- imageUrl: sq.imageUrl || '',
827
- word: sq.word || '',
828
- })) || [];
829
- // Try hintLetters from content first, then from questionGroup.payload
830
- const hintLetters = oldContent?.hintLetters ||
831
- firstQuestion.questionGroup?.payload?.hintLetters ||
832
- [];
833
- return {
834
- subQuestions,
835
- hintLetters,
836
- instruction: oldContent?.instruction ||
837
- 'LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER',
838
- };
839
- }
840
697
  export function transformGridFill(questions) {
841
698
  const firstQuestion = questions[0];
842
699
  const content = firstQuestion?.content;
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from 'react';
2
+ interface CompactCreatorHeaderProps {
3
+ icon: ReactNode;
4
+ title: string;
5
+ points?: {
6
+ value: number;
7
+ onValueChange: (value: number) => void;
8
+ error?: string;
9
+ allowZero?: boolean;
10
+ };
11
+ example?: {
12
+ checked: boolean;
13
+ onChange: (checked: boolean) => void;
14
+ };
15
+ preview?: {
16
+ onClick: () => void;
17
+ disabled?: boolean;
18
+ };
19
+ headerExtra?: ReactNode;
20
+ extraActions?: ReactNode;
21
+ }
22
+ export declare function CompactCreatorHeader({ icon, title, points, example, preview, headerExtra, extraActions, }: CompactCreatorHeaderProps): import("react").JSX.Element;
23
+ export {};
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { CardTitle } from '../../../../../components/ui/card';
4
+ import { PointsInput } from '../../../../../components/ui/points-input';
5
+ import { CompactExampleToggle } from './CompactExampleToggle';
6
+ import { CompactPreviewButton } from './CompactPreviewButton';
7
+ export function CompactCreatorHeader({ icon, title, points, example, preview, headerExtra, extraActions, }) {
8
+ return (_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 text-gray-600", children: icon }), _jsx(CardTitle, { className: "text-sm font-bold text-gray-900", children: title })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [points && (_jsx(PointsInput, { value: points.value, onValueChange: points.onValueChange, error: points.error, allowZero: points.allowZero })), example && (_jsx(CompactExampleToggle, { checked: example.checked, onChange: example.onChange })), extraActions, headerExtra, preview && (_jsx(CompactPreviewButton, { onClick: preview.onClick, disabled: preview.disabled }))] })] }));
9
+ }
@@ -0,0 +1,6 @@
1
+ interface CompactExampleToggleProps {
2
+ checked: boolean;
3
+ onChange: (checked: boolean) => void;
4
+ }
5
+ export declare function CompactExampleToggle({ checked, onChange }: CompactExampleToggleProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Star } from 'lucide-react';
4
+ export function CompactExampleToggle({ checked, onChange }) {
5
+ return (_jsxs("button", { type: "button", onClick: () => onChange(!checked), className: `inline-flex h-8 items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors select-none ${checked
6
+ ? 'border-amber-300 bg-amber-50 text-amber-700'
7
+ : 'border-gray-200 bg-white text-gray-400 hover:text-gray-600'}`, children: [_jsx(Star, { className: `h-3.5 w-3.5 ${checked ? 'fill-amber-400 text-amber-400' : ''}` }), "Example"] }));
8
+ }
@@ -0,0 +1,7 @@
1
+ interface CompactExplanationToggleProps {
2
+ value: string;
3
+ onValueChange: (value: string) => void;
4
+ defaultVisible?: boolean;
5
+ }
6
+ export declare function CompactExplanationToggle({ value, onValueChange, defaultVisible, }: CompactExplanationToggleProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { Button } from '../../../../../components/ui/button';
5
+ import { Textarea } from '../../../../../components/ui/textarea';
6
+ import { Label } from '../../../../../components/ui/label';
7
+ import { BookOpen } from 'lucide-react';
8
+ export function CompactExplanationToggle({ value, onValueChange, defaultVisible, }) {
9
+ const [visible, setVisible] = useState(() => defaultVisible ?? Boolean(value));
10
+ if (!visible) {
11
+ return (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setVisible(true), className: "h-8 gap-1.5 border-amber-200 px-2.5 text-xs text-amber-700 hover:bg-amber-50 hover:text-amber-800", children: [_jsx(BookOpen, { className: "h-3.5 w-3.5" }), value ? 'Hiện giải thích' : 'Thêm giải thích'] }));
12
+ }
13
+ return (_jsxs("div", { className: "relative pr-10", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setVisible(false), className: "absolute right-0 top-0 z-10 h-7 px-2 text-xs text-gray-500 hover:text-gray-700", children: "\u1EA8n" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-sm font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx(Textarea, { rows: 2, value: value, onChange: (event) => onValueChange(event.target.value), placeholder: "Nh\u1EADp gi\u1EA3i th\u00EDch (t\u00F9y ch\u1ECDn)", className: "min-h-[56px] border-gray-200" })] })] }));
14
+ }