@tinyweb_dev/oe-exam-sdk 0.1.28 → 0.1.30

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 (796) hide show
  1. package/README.md +4 -4
  2. package/dist/api/contest-rooms.js +54 -1
  3. package/dist/api/contest-rooms.types.js +1 -1
  4. package/dist/api/exam-create.js +179 -1
  5. package/dist/api/exam-create.types.js +1 -1
  6. package/dist/api/exam-entry.js +68 -1
  7. package/dist/api/exam-entry.types.js +1 -1
  8. package/dist/api/exam-questions.js +149 -1
  9. package/dist/api/exam-questions.types.js +1 -1
  10. package/dist/api/exam-taking.js +84 -1
  11. package/dist/api/exam-taking.types.d.ts +7 -0
  12. package/dist/api/exam-taking.types.js +1 -1
  13. package/dist/api/index.js +8 -1
  14. package/dist/api/result-review.js +62 -1
  15. package/dist/api/result-review.types.js +16 -1
  16. package/dist/components/CueCardEditor.js +58 -1
  17. package/dist/components/common/ResolvedImage.js +15 -1
  18. package/dist/components/exams/CompletionDialog.js +8 -1
  19. package/dist/components/exams/CreateExamInfoForm.js +84 -1
  20. package/dist/components/exams/CreateExamPageContainer.js +110 -1
  21. package/dist/components/exams/ExamCreator.js +287 -1
  22. package/dist/components/exams/ExamPartTabs.js +138 -1
  23. package/dist/components/exams/ExamPreviewDialog.d.ts +6 -7
  24. package/dist/components/exams/ExamPreviewDialog.js +121 -1
  25. package/dist/components/exams/ExamPreviewPartContent.d.ts +18 -0
  26. package/dist/components/exams/ExamPreviewPartContent.js +27 -0
  27. package/dist/components/exams/ExamPreviewSidebar.d.ts +17 -0
  28. package/dist/components/exams/ExamPreviewSidebar.js +37 -0
  29. package/dist/components/exams/ExamQuestionGrid.js +37 -1
  30. package/dist/components/exams/ExamQuestionsPageContainer.js +112 -1
  31. package/dist/components/exams/ExamViewDialog.js +61 -1
  32. package/dist/components/exams/PartAudioUploader.js +9 -1
  33. package/dist/components/exams/TemplateSelector.js +76 -1
  34. package/dist/components/exams/UnsavedChangesDialog.js +7 -1
  35. package/dist/components/exams/api.js +3 -1
  36. package/dist/components/exams/create-exam.texts.js +1 -1
  37. package/dist/components/exams/create-exam.validation.js +18 -1
  38. package/dist/components/exams/entry/EntryRestartDialog.js +11 -1
  39. package/dist/components/exams/entry/StudentExamEntryPageContainer.js +358 -1
  40. package/dist/components/exams/entry/exam-entry.states.js +26 -1
  41. package/dist/components/exams/entry/exam-entry.utils.js +55 -1
  42. package/dist/components/exams/entry/fullscreen-loading.js +18 -1
  43. package/dist/components/exams/entry/index.js +4 -1
  44. package/dist/components/exams/exam-preview.types.d.ts +30 -0
  45. package/dist/components/exams/exam-preview.types.js +62 -0
  46. package/dist/components/exams/exam-question-status.js +45 -1
  47. package/dist/components/exams/exam-template.utils.js +18 -1
  48. package/dist/components/exams/index.d.ts +1 -0
  49. package/dist/components/exams/index.js +19 -1
  50. package/dist/components/exams/rooms/StudentContestRoomsPageContainer.js +183 -1
  51. package/dist/components/exams/rooms/contest-rooms.utils.js +93 -1
  52. package/dist/components/exams/rooms/index.js +2 -1
  53. package/dist/components/exams/take/ExamTakingApiContext.js +25 -1
  54. package/dist/components/exams/take/ExamTakingPageContainer.js +955 -1
  55. package/dist/components/exams/take/GenericQuestionRenderer.js +14 -1
  56. package/dist/components/exams/take/components/QuestionRenderer.js +207 -1
  57. package/dist/components/exams/take/components/index.js +11 -1
  58. package/dist/components/exams/take/components/question-renderers/ArticlesViewer.js +8 -1
  59. package/dist/components/exams/take/components/question-renderers/MoversAnswerTheQuestionRenderer.js +30 -1
  60. package/dist/components/exams/take/components/question-renderers/MoversChooseAdjectiveRenderer.js +63 -1
  61. package/dist/components/exams/take/components/question-renderers/MoversChooseBestAnswerRenderer.js +136 -1
  62. package/dist/components/exams/take/components/question-renderers/MoversColoringRenderer.js +379 -1
  63. package/dist/components/exams/take/components/question-renderers/MoversCrossOutWordGroupRenderer.d.ts +20 -0
  64. package/dist/components/exams/take/components/question-renderers/MoversCrossOutWordGroupRenderer.js +141 -0
  65. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +131 -1
  66. package/dist/components/exams/take/components/question-renderers/MoversGridFillRenderer.js +76 -1
  67. package/dist/components/exams/take/components/question-renderers/MoversLabelThePictureRenderer.js +68 -1
  68. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +42 -1
  69. package/dist/components/exams/take/components/question-renderers/MoversMatchByWritingAnswerRenderer.js +131 -1
  70. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +76 -1
  71. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +68 -1
  72. package/dist/components/exams/take/components/question-renderers/MoversReadingPassageRenderer.js +62 -1
  73. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.d.ts +1 -1
  74. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.js +51 -1
  75. package/dist/components/exams/take/components/question-renderers/MoversWordFillParagraphRenderer.js +171 -1
  76. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +198 -1
  77. package/dist/components/exams/take/components/question-renderers/MoversWordOrderAndMatchGroupRenderer.d.ts +15 -0
  78. package/dist/components/exams/take/components/question-renderers/MoversWordOrderAndMatchGroupRenderer.js +36 -0
  79. package/dist/components/exams/take/components/question-renderers/MoversWordOrderingRenderer.js +92 -1
  80. package/dist/components/exams/take/components/question-renderers/MoversWriteSentencesRenderer.js +11 -1
  81. package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.js +56 -1
  82. package/dist/components/exams/take/components/question-renderers/index.d.ts +2 -0
  83. package/dist/components/exams/take/components/question-renderers/index.js +25 -1
  84. package/dist/components/exams/take/components/speaking/SpeakingAudioPlayer.js +85 -1
  85. package/dist/components/exams/take/components/speaking/SpeakingContentFrame.js +10 -1
  86. package/dist/components/exams/take/components/speaking/SpeakingExamLayout.js +15 -1
  87. package/dist/components/exams/take/components/speaking/SpeakingHeader.js +6 -1
  88. package/dist/components/exams/take/components/speaking/SpeakingInstructionBar.js +8 -1
  89. package/dist/components/exams/take/components/speaking/SpeakingMicButton.js +59 -1
  90. package/dist/components/exams/take/components/speaking/SpeakingNavButton.js +7 -1
  91. package/dist/components/exams/take/components/speaking/SpeakingPartBadge.js +5 -1
  92. package/dist/components/exams/take/components/speaking/SpeakingReadDisplayedContent.module.css +120 -0
  93. package/dist/components/exams/take/components/speaking/SpeakingRecordingPreview.js +73 -1
  94. package/dist/components/exams/take/components/speaking/SpeakingReportErrorButton.js +8 -1
  95. package/dist/components/exams/take/components/speaking/SpeakingSpontaneousQA.module.css +344 -0
  96. package/dist/components/exams/take/components/speaking/SpeakingVideoIntro.js +32 -1
  97. package/dist/components/exams/take/components/speaking/index.js +1 -1
  98. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseAnswerGroupRenderer.js +63 -1
  99. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseObjectsRenderer.js +95 -1
  100. package/dist/components/exams/take/components/speaking/renderers/SpeakingCompareImagesRenderer.js +35 -1
  101. package/dist/components/exams/take/components/speaking/renderers/SpeakingConversationRenderer.js +147 -1
  102. package/dist/components/exams/take/components/speaking/renderers/SpeakingCueCardRenderer.js +232 -1
  103. package/dist/components/exams/take/components/speaking/renderers/SpeakingDescribeImageRenderer.js +193 -1
  104. package/dist/components/exams/take/components/speaking/renderers/SpeakingDragObjectsRenderer.js +155 -1
  105. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +212 -1
  106. package/dist/components/exams/take/components/speaking/renderers/SpeakingInfoExchangeRenderer.js +77 -1
  107. package/dist/components/exams/take/components/speaking/renderers/SpeakingListenAndSpeakAnswerRenderer.js +64 -1
  108. package/dist/components/exams/take/components/speaking/renderers/SpeakingOddOneOutRenderer.js +69 -1
  109. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionListRenderer.js +64 -1
  110. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.js +92 -1
  111. package/dist/components/exams/take/components/speaking/renderers/SpeakingReadDisplayedContentRenderer.js +202 -1
  112. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQARenderer.js +339 -1
  113. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQaGroupRenderer.d.ts +19 -0
  114. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQaGroupRenderer.js +76 -0
  115. package/dist/components/exams/take/components/speaking/renderers/SpeakingStoryImagesRenderer.js +56 -1
  116. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQACambridgeLayout.d.ts +24 -0
  117. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQACambridgeLayout.js +120 -0
  118. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQAInlineAudioPlayer.d.ts +8 -0
  119. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQAInlineAudioPlayer.js +94 -0
  120. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQASummerSkyAudioPlayer.d.ts +8 -0
  121. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQASummerSkyAudioPlayer.js +101 -0
  122. package/dist/components/exams/take/components/speaking/renderers/index.d.ts +1 -0
  123. package/dist/components/exams/take/components/speaking/renderers/index.js +14 -1
  124. package/dist/components/exams/take/exam-taking.utils.d.ts +13 -0
  125. package/dist/components/exams/take/exam-taking.utils.js +203 -1
  126. package/dist/components/exams/take/hooks/index.js +2 -1
  127. package/dist/components/exams/take/hooks/useAnswerAutosave.js +71 -1
  128. package/dist/components/exams/take/hooks/useAttemptSubmit.js +38 -1
  129. package/dist/components/exams/take/hooks/useAutoSave.js +83 -1
  130. package/dist/components/exams/take/hooks/useExamCountdown.js +35 -1
  131. package/dist/components/exams/take/hooks/useExamTimer.js +97 -1
  132. package/dist/components/exams/take/hooks/useProctoringCamera.js +118 -1
  133. package/dist/components/exams/take/hooks/useProctoringSnapshot.js +76 -1
  134. package/dist/components/exams/take/hooks/useSpeakingConversationAudio.js +178 -1
  135. package/dist/components/exams/take/hooks/useSpeakingNavigation.js +51 -1
  136. package/dist/components/exams/take/hooks/useSpeakingRecorder.js +406 -1
  137. package/dist/components/exams/take/hooks/useSpeakingRendererSetup.js +136 -1
  138. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRecorder.d.ts +11 -0
  139. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRecorder.js +352 -0
  140. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRendererSetup.d.ts +42 -0
  141. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRendererSetup.js +166 -0
  142. package/dist/components/exams/take/hooks/useToeicAudio.js +35 -1
  143. package/dist/components/exams/take/index.js +6 -1
  144. package/dist/components/exams/take/types/speaking-cue-card.types.js +1 -1
  145. package/dist/components/exams/take/types/speaking.types.js +7 -1
  146. package/dist/components/exams/take/types.js +4 -1
  147. package/dist/components/exams/take/utils/answer-transformers.js +452 -1
  148. package/dist/components/exams/take/utils/cambridge-yle-inline-speaking.d.ts +21 -0
  149. package/dist/components/exams/take/utils/cambridge-yle-inline-speaking.js +44 -0
  150. package/dist/components/exams/take/utils/coloring-assignments.js +40 -1
  151. package/dist/components/exams/take/utils/cross-out-word-group.transformer.d.ts +21 -0
  152. package/dist/components/exams/take/utils/cross-out-word-group.transformer.js +83 -0
  153. package/dist/components/exams/take/utils/question-transformers.d.ts +43 -2
  154. package/dist/components/exams/take/utils/question-transformers.js +1137 -1
  155. package/dist/components/features/exam-entry/entry-state-cards.js +19 -1
  156. package/dist/components/features/exam-entry/index.js +2 -1
  157. package/dist/components/features/exam-entry/themed/CambridgeYleWaitingRoom.js +121 -1
  158. package/dist/components/features/exam-entry/themed/ThemedWaitingRoom.js +37 -1
  159. package/dist/components/features/exam-entry/themed/ToeicWaitingRoom.js +15 -1
  160. package/dist/components/features/exam-entry/themed/cambridge-yle-waiting-parts.js +80 -1
  161. package/dist/components/features/exam-entry/themed/components/CloseButton.js +6 -1
  162. package/dist/components/features/exam-entry/themed/components/ExamInfoPanel.js +17 -1
  163. package/dist/components/features/exam-entry/themed/components/ModeSelector.js +6 -1
  164. package/dist/components/features/exam-entry/themed/components/StartButton.js +12 -1
  165. package/dist/components/features/exam-entry/themed/components/index.js +4 -1
  166. package/dist/components/features/exam-entry/themed/index.js +3 -1
  167. package/dist/components/index.d.ts +1 -0
  168. package/dist/components/index.js +43 -1
  169. package/dist/components/questions/_shared/config/question-types.config.js +362 -1
  170. package/dist/components/questions/_shared/constants/color-palette.js +21 -1
  171. package/dist/components/questions/_shared/hooks/useAnswerGroupQuestionGroup.js +105 -1
  172. package/dist/components/questions/_shared/hooks/useBasicQuestionGroup.js +222 -1
  173. package/dist/components/questions/_shared/hooks/useCompareImagesGroup.js +140 -1
  174. package/dist/components/questions/_shared/hooks/useImageQuestionGroup.js +123 -1
  175. package/dist/components/questions/_shared/hooks/useInfoExchangeGroup.js +50 -1
  176. package/dist/components/questions/_shared/hooks/useQuestionFormState.js +54 -1
  177. package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +123 -1
  178. package/dist/components/questions/_shared/hooks/useQuestionListGroup.js +121 -1
  179. package/dist/components/questions/_shared/hooks/useQuestionOnChange.js +70 -1
  180. package/dist/components/questions/_shared/hooks/useSceneQuestionGroup.js +194 -1
  181. package/dist/components/questions/_shared/index.js +7 -1
  182. package/dist/components/questions/_shared/types/answer-the-question.type.js +1 -1
  183. package/dist/components/questions/_shared/types/arrange-letters-into-words.type.js +1 -1
  184. package/dist/components/questions/_shared/types/choose-correct-adjective.type.js +3 -1
  185. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.d.ts +1 -0
  186. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.js +1 -1
  187. package/dist/components/questions/_shared/types/color-region.config.js +1 -1
  188. package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +2 -0
  189. package/dist/components/questions/_shared/types/cross-out-word-group.type.js +1 -1
  190. package/dist/components/questions/_shared/types/fill-in-blank.type.js +1 -1
  191. package/dist/components/questions/_shared/types/fill-missing-words-in-grid.type.js +1 -1
  192. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +1 -1
  193. package/dist/components/questions/_shared/types/index.d.ts +1 -0
  194. package/dist/components/questions/_shared/types/index.js +14 -1
  195. package/dist/components/questions/_shared/types/label-the-picture.type.js +1 -1
  196. package/dist/components/questions/_shared/types/listen-and-choose-from-answer-group.type.js +1 -1
  197. package/dist/components/questions/_shared/types/listen-and-choose-objects-in-scene.type.js +1 -1
  198. package/dist/components/questions/_shared/types/listen-and-drag-objects-into-scene.type.js +1 -1
  199. package/dist/components/questions/_shared/types/listen-and-speak-answer.type.js +1 -1
  200. package/dist/components/questions/_shared/types/listen-and-speak-compare-images.type.js +1 -1
  201. package/dist/components/questions/_shared/types/listen-and-speak-image-group.type.js +1 -1
  202. package/dist/components/questions/_shared/types/listen-and-speak-info-exchange.type.js +1 -1
  203. package/dist/components/questions/_shared/types/listen-and-speak-odd-one-out.type.js +3 -1
  204. package/dist/components/questions/_shared/types/listen-and-speak-question-list.type.js +1 -1
  205. package/dist/components/questions/_shared/types/listen-and-speak-with-story-images.type.js +3 -1
  206. package/dist/components/questions/_shared/types/listen-and-tick-answer.type.js +1 -1
  207. package/dist/components/questions/_shared/types/listening-drawline.type.js +1 -1
  208. package/dist/components/questions/_shared/types/look-and-choose-answer.type.js +1 -1
  209. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +1 -1
  210. package/dist/components/questions/_shared/types/match-by-writing-answer.type.js +1 -1
  211. package/dist/components/questions/_shared/types/multiple-choice.type.d.ts +5 -0
  212. package/dist/components/questions/_shared/types/multiple-choice.type.js +1 -1
  213. package/dist/components/questions/_shared/types/question-group.type.js +11 -1
  214. package/dist/components/questions/_shared/types/read-and-color-objects.type.js +1 -1
  215. package/dist/components/questions/_shared/types/read-displayed-content.type.js +1 -1
  216. package/dist/components/questions/_shared/types/read-passage-and-answer-questions.type.js +1 -1
  217. package/dist/components/questions/_shared/types/speaking-describe-image.type.js +1 -1
  218. package/dist/components/questions/_shared/types/spontaneous-qa-group.type.d.ts +37 -0
  219. package/dist/components/questions/_shared/types/spontaneous-qa-group.type.js +1 -0
  220. package/dist/components/questions/_shared/types/spontaneous-qa.type.js +1 -1
  221. package/dist/components/questions/_shared/types/true-false-group.type.js +1 -1
  222. package/dist/components/questions/_shared/types/word-fill-paragraph-with-options.type.js +1 -1
  223. package/dist/components/questions/_shared/types/word-fill-paragraph.type.js +1 -1
  224. package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +20 -11
  225. package/dist/components/questions/_shared/types/word-fill-structured-form.type.js +1 -1
  226. package/dist/components/questions/_shared/types/word-order-and-match-group.type.d.ts +38 -0
  227. package/dist/components/questions/_shared/types/word-order-and-match-group.type.js +1 -0
  228. package/dist/components/questions/_shared/types/word-ordering.type.js +1 -1
  229. package/dist/components/questions/_shared/types/write-a-short-letter.type.js +1 -1
  230. package/dist/components/questions/_shared/types/write-correct-verb-form.type.js +3 -1
  231. package/dist/components/questions/_shared/types/write-sentences.type.js +1 -1
  232. package/dist/components/questions/_shared/types/write-short-paragraph.type.js +1 -1
  233. package/dist/components/questions/_shared/utils/answer-builder.js +79 -1
  234. package/dist/components/questions/_shared/utils/createColorRegionRegistration.js +39 -1
  235. package/dist/components/questions/_shared/utils/id-generator.js +3 -1
  236. package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +30 -0
  237. package/dist/components/questions/_shared/utils/parseFillBlankStem.js +69 -0
  238. package/dist/components/questions/_shared/utils/question-validation.js +21 -1
  239. package/dist/components/questions/components/ColorNode.js +85 -1
  240. package/dist/components/questions/components/ColorRegionClient.js +545 -1
  241. package/dist/components/questions/components/ColorRegionCreator.js +420 -1
  242. package/dist/components/questions/components/ColorRegionNode.js +59 -1
  243. package/dist/components/questions/components/CreatorGuide.js +103 -1
  244. package/dist/components/questions/components/NameNode.js +26 -1
  245. package/dist/components/questions/components/QuestionBankOption.js +46 -1
  246. package/dist/components/questions/components/QuestionBasicInfoForm.js +9 -1
  247. package/dist/components/questions/components/QuestionCommonFields.js +33 -1
  248. package/dist/components/questions/components/QuestionSearchDropdown.js +258 -1
  249. package/dist/components/questions/components/QuestionTypeSelector.js +32 -1
  250. package/dist/components/questions/components/QuestionTypeSpecificForms.js +6 -1
  251. package/dist/components/questions/components/RegionNode.js +94 -1
  252. package/dist/components/questions/components/index.js +14 -1
  253. package/dist/components/questions/creator/QuestionCreator.js +90 -1
  254. package/dist/components/questions/creator/QuestionGroupCreator.js +119 -1
  255. package/dist/components/questions/creator/dedicated-component-router.js +79 -1
  256. package/dist/components/questions/creator/index.js +3 -1
  257. package/dist/components/questions/creator/question-type-registry.js +90 -1
  258. package/dist/components/questions/groups/ArticlesGroupCard.js +121 -1
  259. package/dist/components/questions/groups/BasicQuestionGroupCard.js +50 -1
  260. package/dist/components/questions/groups/DocumentGroupCard.js +114 -1
  261. package/dist/components/questions/groups/MatchAnswerGroupCard.js +25 -1
  262. package/dist/components/questions/index.d.ts +1 -0
  263. package/dist/components/questions/index.js +11 -1
  264. package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +2 -0
  265. package/dist/components/questions/question-bank/EditQuestionBankDialog.js +114 -0
  266. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +23 -0
  267. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +75 -0
  268. package/dist/components/questions/question-bank/difficulty.d.ts +15 -0
  269. package/dist/components/questions/question-bank/difficulty.js +33 -0
  270. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +5 -0
  271. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +101 -0
  272. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +5 -0
  273. package/dist/components/questions/question-bank/editor-adapters/index.js +4 -0
  274. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +6 -0
  275. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +140 -0
  276. package/dist/components/questions/question-bank/editor-adapters/types.d.ts +1 -0
  277. package/dist/components/questions/question-bank/editor-adapters/types.js +1 -0
  278. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +8 -0
  279. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +6 -0
  280. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +5 -0
  281. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +114 -0
  282. package/dist/components/questions/question-bank/index.d.ts +4 -0
  283. package/dist/components/questions/question-bank/index.js +3 -0
  284. package/dist/components/questions/question-bank/types.d.ts +59 -0
  285. package/dist/components/questions/question-bank/types.js +1 -0
  286. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +37 -1
  287. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +351 -1
  288. package/dist/components/questions/types/answer-the-question/register.js +67 -1
  289. package/dist/components/questions/types/answer-the-question/transform.js +36 -1
  290. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +141 -1
  291. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +118 -1
  292. package/dist/components/questions/types/arrange-letters-into-words/index.js +2 -1
  293. package/dist/components/questions/types/arrange-letters-into-words/register.js +4 -1
  294. package/dist/components/questions/types/arrange-letters-into-words/transform.js +24 -1
  295. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +74 -1
  296. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +169 -1
  297. package/dist/components/questions/types/choose-correct-adjective/index.js +2 -1
  298. package/dist/components/questions/types/choose-correct-adjective/register.js +55 -1
  299. package/dist/components/questions/types/choose-correct-adjective/transform.js +16 -1
  300. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +149 -1
  301. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +568 -1
  302. package/dist/components/questions/types/choose-the-correct-answer/index.js +3 -1
  303. package/dist/components/questions/types/choose-the-correct-answer/normalize.d.ts +9 -0
  304. package/dist/components/questions/types/choose-the-correct-answer/normalize.js +88 -1
  305. package/dist/components/questions/types/choose-the-correct-answer/register.js +99 -1
  306. package/dist/components/questions/types/choose-the-correct-answer/transform.js +70 -1
  307. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +22 -1
  308. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +163 -1
  309. package/dist/components/questions/types/choose-the-correct-answer-group/index.js +3 -1
  310. package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +94 -1
  311. package/dist/components/questions/types/choose-the-correct-answer-group/register.js +36 -1
  312. package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +55 -1
  313. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +27 -1
  314. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +231 -1
  315. package/dist/components/questions/types/cross-out-word-group/index.js +5 -1
  316. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.d.ts +1 -1
  317. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +110 -1
  318. package/dist/components/questions/types/cross-out-word-group/register.js +36 -1
  319. package/dist/components/questions/types/cross-out-word-group/transform.js +67 -1
  320. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +275 -1
  321. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +464 -1
  322. package/dist/components/questions/types/fill-in-blank/index.js +2 -1
  323. package/dist/components/questions/types/fill-in-blank/register.js +148 -1
  324. package/dist/components/questions/types/fill-in-blank/transform.js +88 -1
  325. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +117 -1
  326. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +671 -1
  327. package/dist/components/questions/types/fill-missing-words-in-grid/index.js +2 -1
  328. package/dist/components/questions/types/fill-missing-words-in-grid/register.js +37 -1
  329. package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +15 -1
  330. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +262 -1
  331. package/dist/components/questions/types/gn-speaking-interview/register.js +121 -1
  332. package/dist/components/questions/types/gn-speaking-interview/transform.js +48 -1
  333. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +16 -1
  334. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +27 -1
  335. package/dist/components/questions/types/image-object-matching/index.js +2 -1
  336. package/dist/components/questions/types/image-object-matching/register.js +3 -1
  337. package/dist/components/questions/types/image-object-matching/transform.js +2 -1
  338. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +102 -1
  339. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +344 -1
  340. package/dist/components/questions/types/label-the-picture/index.js +2 -1
  341. package/dist/components/questions/types/label-the-picture/register.js +54 -1
  342. package/dist/components/questions/types/label-the-picture/transform.js +28 -1
  343. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +78 -1
  344. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +232 -1
  345. package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +2 -1
  346. package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +82 -1
  347. package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +27 -1
  348. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +70 -1
  349. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +386 -1
  350. package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +2 -1
  351. package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +100 -1
  352. package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +33 -1
  353. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +106 -1
  354. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +457 -1
  355. package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +2 -1
  356. package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +110 -1
  357. package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +35 -1
  358. package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +8 -1
  359. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +22 -1
  360. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +291 -1
  361. package/dist/components/questions/types/listen-and-speak-answer/index.js +2 -1
  362. package/dist/components/questions/types/listen-and-speak-answer/register.js +84 -1
  363. package/dist/components/questions/types/listen-and-speak-answer/transform.js +27 -1
  364. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +32 -1
  365. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +295 -1
  366. package/dist/components/questions/types/listen-and-speak-compare-images/register.js +79 -1
  367. package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +27 -1
  368. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +34 -1
  369. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +285 -1
  370. package/dist/components/questions/types/listen-and-speak-image-group/register.js +81 -1
  371. package/dist/components/questions/types/listen-and-speak-image-group/transform.js +26 -1
  372. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +38 -1
  373. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +385 -1
  374. package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +87 -1
  375. package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +32 -1
  376. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +26 -1
  377. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +247 -1
  378. package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +59 -1
  379. package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +18 -1
  380. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +26 -1
  381. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +256 -1
  382. package/dist/components/questions/types/listen-and-speak-question-list/register.js +81 -1
  383. package/dist/components/questions/types/listen-and-speak-question-list/transform.js +26 -1
  384. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +26 -1
  385. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +230 -1
  386. package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +56 -1
  387. package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +16 -1
  388. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +72 -1
  389. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +230 -1
  390. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
  391. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +66 -1
  392. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +42 -1
  393. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +96 -1
  394. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +238 -1
  395. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +2 -1
  396. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +76 -1
  397. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +19 -1
  398. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +134 -1
  399. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +617 -1
  400. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +2 -1
  401. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +82 -1
  402. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +29 -1
  403. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +38 -1
  404. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +359 -1
  405. package/dist/components/questions/types/match-by-writing-answer/index.js +3 -1
  406. package/dist/components/questions/types/match-by-writing-answer/register.js +58 -1
  407. package/dist/components/questions/types/match-by-writing-answer/transform.js +61 -1
  408. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +16 -1
  409. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +23 -1
  410. package/dist/components/questions/types/read-and-color-objects/index.js +2 -1
  411. package/dist/components/questions/types/read-and-color-objects/register.js +3 -1
  412. package/dist/components/questions/types/read-and-color-objects/transform.js +36 -1
  413. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +125 -1
  414. package/dist/components/questions/types/read-displayed-content/register.js +64 -1
  415. package/dist/components/questions/types/read-displayed-content/transform.js +12 -1
  416. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +65 -1
  417. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +511 -1
  418. package/dist/components/questions/types/read-passage-and-answer-questions/index.js +2 -1
  419. package/dist/components/questions/types/read-passage-and-answer-questions/register.js +58 -1
  420. package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +28 -1
  421. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +373 -1
  422. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +41 -1
  423. package/dist/components/questions/types/speaking-conversation/register.js +110 -1
  424. package/dist/components/questions/types/speaking-conversation/transform.js +34 -1
  425. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +74 -1
  426. package/dist/components/questions/types/speaking-cue-card/register.js +52 -1
  427. package/dist/components/questions/types/speaking-cue-card/transform.js +12 -1
  428. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +10 -1
  429. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +161 -1
  430. package/dist/components/questions/types/speaking-describe-image/index.js +2 -1
  431. package/dist/components/questions/types/speaking-describe-image/register.js +69 -1
  432. package/dist/components/questions/types/speaking-describe-image/transform.js +16 -1
  433. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +234 -1
  434. package/dist/components/questions/types/spontaneous-qa/register.js +93 -1
  435. package/dist/components/questions/types/spontaneous-qa/transform.js +34 -1
  436. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.d.ts +2 -0
  437. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +9 -0
  438. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.d.ts +2 -0
  439. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +179 -0
  440. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.d.ts +5 -0
  441. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.js +43 -0
  442. package/dist/components/questions/types/spontaneous-qa-group/flatten.d.ts +14 -0
  443. package/dist/components/questions/types/spontaneous-qa-group/flatten.js +69 -0
  444. package/dist/components/questions/types/spontaneous-qa-group/index.d.ts +2 -0
  445. package/dist/components/questions/types/spontaneous-qa-group/index.js +2 -0
  446. package/dist/components/questions/types/spontaneous-qa-group/register.d.ts +2 -0
  447. package/dist/components/questions/types/spontaneous-qa-group/register.js +139 -0
  448. package/dist/components/questions/types/spontaneous-qa-group/transform.d.ts +2 -0
  449. package/dist/components/questions/types/spontaneous-qa-group/transform.js +52 -0
  450. package/dist/components/questions/types/true-false/TrueFalseClient.js +75 -1
  451. package/dist/components/questions/types/true-false/TrueFalseCreator.js +244 -1
  452. package/dist/components/questions/types/true-false/index.js +2 -1
  453. package/dist/components/questions/types/true-false/register.js +77 -1
  454. package/dist/components/questions/types/true-false/transform.js +32 -1
  455. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +25 -1
  456. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +129 -1
  457. package/dist/components/questions/types/true-false-group/index.js +5 -1
  458. package/dist/components/questions/types/true-false-group/map-true-false-group-data.js +69 -1
  459. package/dist/components/questions/types/true-false-group/register.js +36 -1
  460. package/dist/components/questions/types/true-false-group/transform.js +43 -1
  461. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +233 -1
  462. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +631 -1
  463. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +28 -1
  464. package/dist/components/questions/types/word-fill-paragraph/index.js +2 -1
  465. package/dist/components/questions/types/word-fill-paragraph/register.js +136 -1
  466. package/dist/components/questions/types/word-fill-paragraph/transform.js +56 -1
  467. package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.js +86 -1
  468. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +246 -1
  469. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.d.ts +2 -0
  470. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +484 -1
  471. package/dist/components/questions/types/word-fill-structured-form/index.js +3 -1
  472. package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.js +113 -1
  473. package/dist/components/questions/types/word-fill-structured-form/register.js +36 -1
  474. package/dist/components/questions/types/word-fill-structured-form/transform.js +77 -1
  475. package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.js +110 -1
  476. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.d.ts +3 -0
  477. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +190 -0
  478. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.d.ts +3 -0
  479. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +182 -0
  480. package/dist/components/questions/types/word-order-and-match-group/index.d.ts +4 -0
  481. package/dist/components/questions/types/word-order-and-match-group/index.js +4 -0
  482. package/dist/components/questions/types/word-order-and-match-group/register.d.ts +2 -0
  483. package/dist/components/questions/types/word-order-and-match-group/register.js +121 -0
  484. package/dist/components/questions/types/word-order-and-match-group/transform.d.ts +2 -0
  485. package/dist/components/questions/types/word-order-and-match-group/transform.js +70 -0
  486. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +84 -1
  487. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +192 -1
  488. package/dist/components/questions/types/word-ordering/index.js +2 -1
  489. package/dist/components/questions/types/word-ordering/register.js +46 -1
  490. package/dist/components/questions/types/word-ordering/transform.js +24 -1
  491. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +99 -1
  492. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +320 -1
  493. package/dist/components/questions/types/write-a-short-letter/index.js +2 -1
  494. package/dist/components/questions/types/write-a-short-letter/register.js +68 -1
  495. package/dist/components/questions/types/write-a-short-letter/transform.js +25 -1
  496. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +61 -1
  497. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +196 -1
  498. package/dist/components/questions/types/write-correct-verb-form/index.js +2 -1
  499. package/dist/components/questions/types/write-correct-verb-form/register.js +62 -1
  500. package/dist/components/questions/types/write-correct-verb-form/transform.js +17 -1
  501. package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +22 -1
  502. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +174 -1
  503. package/dist/components/questions/types/write-sentences/index.js +2 -1
  504. package/dist/components/questions/types/write-sentences/register.js +58 -1
  505. package/dist/components/questions/types/write-sentences/transform.js +28 -1
  506. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +96 -1
  507. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +161 -1
  508. package/dist/components/questions/types/write-short-paragraph/index.js +2 -1
  509. package/dist/components/questions/types/write-short-paragraph/register.js +4 -1
  510. package/dist/components/questions/types/write-short-paragraph/transform.js +21 -1
  511. package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.js +11 -1
  512. package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +8 -1
  513. package/dist/components/questions/viewer/QuestionGroupViewer.js +36 -1
  514. package/dist/components/questions/viewer/QuestionViewer.js +692 -1
  515. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +2 -1
  516. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +82 -1
  517. package/dist/components/questions/viewer/TrueFalseGroupViewer.js +11 -1
  518. package/dist/components/questions/viewer/WordFillStructuredFormViewer.js +14 -1
  519. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +3 -1
  520. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +95 -1
  521. package/dist/components/questions/viewer/index.js +8 -1
  522. package/dist/components/results/ResultReviewPageContainer.js +220 -1
  523. package/dist/components/results/ReviewQuestionRenderer.js +55 -1
  524. package/dist/components/results/hooks/useResultReviewPolling.js +76 -1
  525. package/dist/components/results/index.js +22 -1
  526. package/dist/components/results/renderers/QuestionExplanations.js +19 -1
  527. package/dist/components/results/renderers/ReviewChooseAdjectiveRenderer.js +94 -1
  528. package/dist/components/results/renderers/ReviewChooseBestAnswerRenderer.js +75 -1
  529. package/dist/components/results/renderers/ReviewColoringRenderer.js +110 -1
  530. package/dist/components/results/renderers/ReviewListenAndWriteRenderer.js +48 -1
  531. package/dist/components/results/renderers/ReviewListenChooseAnswerGroupRenderer.js +87 -1
  532. package/dist/components/results/renderers/ReviewListenChooseObjectsRenderer.js +104 -1
  533. package/dist/components/results/renderers/ReviewListenDragObjectsRenderer.js +123 -1
  534. package/dist/components/results/renderers/ReviewListeningHeader.js +104 -1
  535. package/dist/components/results/renderers/ReviewSpeakingAIPanel.js +116 -1
  536. package/dist/components/results/renderers/ReviewSpeakingMedia.js +48 -1
  537. package/dist/components/results/renderers/ReviewSpeakingQuestionItem.js +42 -1
  538. package/dist/components/results/renderers/ReviewSpeakingRenderer.js +12 -1
  539. package/dist/components/results/renderers/ReviewSpeakingRenderer.types.js +85 -1
  540. package/dist/components/results/renderers/review-question-body-dedicated.js +104 -1
  541. package/dist/components/results/renderers/review-question-body-movers.js +148 -1
  542. package/dist/components/results/renderers/review-speaking-map.js +226 -1
  543. package/dist/components/results/renderers/review-spontaneous-qa-group.d.ts +4 -0
  544. package/dist/components/results/renderers/review-spontaneous-qa-group.js +74 -0
  545. package/dist/components/results/report/BadgeTitle.js +5 -1
  546. package/dist/components/results/report/ExamSkillRow.js +20 -1
  547. package/dist/components/results/report/OceanEduExamReport.js +58 -1
  548. package/dist/components/results/report/OceanEduSpeakingReport.js +62 -1
  549. package/dist/components/results/report/OverallAssessmentSection.js +17 -1
  550. package/dist/components/results/report/ResultErrorState.js +18 -1
  551. package/dist/components/results/report/ResultLoadingState.js +10 -1
  552. package/dist/components/results/report/ResultNotPublicState.js +27 -1
  553. package/dist/components/results/report/SpeakingReportParts.js +14 -1
  554. package/dist/components/results/report/SpeakingReportShared.js +86 -1
  555. package/dist/components/results/report/SpeakingRubricSection.js +171 -1
  556. package/dist/components/results/report/speaking-report.utils.js +198 -1
  557. package/dist/components/results/result-review.utils.js +6 -1
  558. package/dist/components/results/review-data.js +222 -1
  559. package/dist/components/results/review-renderer.utils.js +97 -1
  560. package/dist/components/results/review-status.utils.js +36 -1
  561. package/dist/components/results/review-types.js +1 -1
  562. package/dist/components/results/speaking/SpeakingResultAudioPlayer.js +77 -1
  563. package/dist/components/results/speaking/SpeakingReviewResult.js +48 -1
  564. package/dist/components/results/utils/review-score.utils.js +72 -1
  565. package/dist/components/results/utils/speaking-summary.js +224 -1
  566. package/dist/components/results/utils/transform-speaking-review.js +183 -1
  567. package/dist/components/shared/RichTextEditor.d.ts +9 -0
  568. package/dist/components/shared/RichTextEditor.js +47 -0
  569. package/dist/components/shared/audio/SpeakingAudioPlayer.js +100 -1
  570. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +140 -1
  571. package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +10 -1
  572. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.d.ts +1 -1
  573. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +18 -1
  574. package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +11 -1
  575. package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +11 -1
  576. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.d.ts +2 -1
  577. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +19 -1
  578. package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +13 -1
  579. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.d.ts +1 -1
  580. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +3 -1
  581. package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +6 -1
  582. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +5 -1
  583. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +9 -1
  584. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.d.ts +2 -1
  585. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +61 -1
  586. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.d.ts +1 -1
  587. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +25 -1
  588. package/dist/components/themes/cambridge-yle/index.js +13 -1
  589. package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +25 -1
  590. package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +89 -1
  591. package/dist/components/themes/english-certification/EcWordFillParagraph.js +56 -1
  592. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +192 -1
  593. package/dist/components/themes/english-certification/EcWritingTask.js +60 -1
  594. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +108 -1
  595. package/dist/components/themes/english-certification/EnglishCertificationBrand.js +11 -1
  596. package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +34 -1
  597. package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +15 -1
  598. package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +19 -1
  599. package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +166 -1
  600. package/dist/components/themes/english-certification/EnglishCertificationHeader.js +31 -1
  601. package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.js +79 -1
  602. package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +71 -1
  603. package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +79 -1
  604. package/dist/components/themes/english-certification/EnglishCertificationPartHeader.js +47 -1
  605. package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +77 -1
  606. package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +25 -1
  607. package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +36 -1
  608. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +81 -1
  609. package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +95 -1
  610. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +18 -1
  611. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +32 -1
  612. package/dist/components/themes/english-certification/english-cert-scroll.js +163 -1
  613. package/dist/components/themes/english-certification/english-certification-theme.js +58 -1
  614. package/dist/components/themes/english-certification/grouped-question-utils.js +243 -1
  615. package/dist/components/themes/english-certification/index.js +24 -1
  616. package/dist/components/themes/index.js +25 -1
  617. package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +170 -1
  618. package/dist/components/themes/summer-sky/SummerSkyExitModal.js +21 -1
  619. package/dist/components/themes/summer-sky/SummerSkyLayout.js +221 -1
  620. package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +18 -1
  621. package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +193 -1
  622. package/dist/components/themes/types.js +1 -1
  623. package/dist/components/ui/alert-dialog.js +26 -1
  624. package/dist/components/ui/alert.js +22 -1
  625. package/dist/components/ui/avatar.js +12 -1
  626. package/dist/components/ui/badge.js +38 -1
  627. package/dist/components/ui/button.js +35 -1
  628. package/dist/components/ui/calendar.js +76 -1
  629. package/dist/components/ui/card.js +16 -1
  630. package/dist/components/ui/carousel.js +91 -1
  631. package/dist/components/ui/checkbox.js +9 -1
  632. package/dist/components/ui/collapsible.js +13 -1
  633. package/dist/components/ui/command.js +34 -1
  634. package/dist/components/ui/confirm-dialog.js +49 -1
  635. package/dist/components/ui/dialog.js +23 -1
  636. package/dist/components/ui/drawer.js +35 -1
  637. package/dist/components/ui/dropdown-menu.js +33 -1
  638. package/dist/components/ui/file-upload.js +155 -1
  639. package/dist/components/ui/form.js +62 -1
  640. package/dist/components/ui/hover-card.js +10 -1
  641. package/dist/components/ui/image-preview.js +29 -1
  642. package/dist/components/ui/input.js +8 -1
  643. package/dist/components/ui/label.js +9 -1
  644. package/dist/components/ui/language-switcher.js +15 -1
  645. package/dist/components/ui/multi-select.js +90 -1
  646. package/dist/components/ui/points-input.js +33 -1
  647. package/dist/components/ui/popover.js +26 -1
  648. package/dist/components/ui/progress.js +16 -1
  649. package/dist/components/ui/radio-group.js +12 -1
  650. package/dist/components/ui/scroll-area.js +11 -1
  651. package/dist/components/ui/select.js +38 -1
  652. package/dist/components/ui/separator.js +8 -1
  653. package/dist/components/ui/sheet.js +40 -1
  654. package/dist/components/ui/single-select.js +76 -1
  655. package/dist/components/ui/skeleton.js +6 -1
  656. package/dist/components/ui/switch.js +8 -1
  657. package/dist/components/ui/table.js +20 -1
  658. package/dist/components/ui/tabs.js +17 -1
  659. package/dist/components/ui/textarea.js +8 -1
  660. package/dist/components/ui/tooltip.js +11 -1
  661. package/dist/index.d.ts +3 -0
  662. package/dist/index.js +24 -1
  663. package/dist/shared/constants/ApiConstant.d.ts +1 -0
  664. package/dist/shared/constants/ApiConstant.js +278 -1
  665. package/dist/shared/constants/QueryKeyConstant.js +112 -1
  666. package/dist/shared/constants/exam-level.enum.js +41 -1
  667. package/dist/shared/constants/landings/placement-test.constants.js +431 -1
  668. package/dist/shared/constants/question-skills.js +277 -1
  669. package/dist/shared/constants/routes.js +81 -1
  670. package/dist/shared/index.js +10 -1
  671. package/dist/shared/lib/hooks/index.js +10 -1
  672. package/dist/shared/lib/hooks/useAlertDialog.js +57 -1
  673. package/dist/shared/lib/hooks/useAudioPlayCounter.js +30 -1
  674. package/dist/shared/lib/hooks/useAudioPreview.js +81 -1
  675. package/dist/shared/lib/hooks/useAudioUpload.js +24 -1
  676. package/dist/shared/lib/hooks/useConfirmDialog.js +89 -1
  677. package/dist/shared/lib/hooks/useDebouncedCallback.js +32 -1
  678. package/dist/shared/lib/hooks/useDelayedAutoPlay.js +12 -1
  679. package/dist/shared/lib/hooks/useFileUpload.js +24 -1
  680. package/dist/shared/lib/hooks/useImageUrl.js +5 -1
  681. package/dist/shared/lib/hooks/usePresignedFileUrl.js +108 -1
  682. package/dist/shared/lib/hooks/useReactHookForm.js +31 -1
  683. package/dist/shared/lib/hooks/useToast.js +62 -1
  684. package/dist/shared/lib/html-content.js +22 -1
  685. package/dist/shared/lib/i18n/index.js +54 -1
  686. package/dist/shared/lib/i18n/messages/en/admin.d.ts +11 -4
  687. package/dist/shared/lib/i18n/messages/en/admin.js +2111 -1
  688. package/dist/shared/lib/i18n/messages/en/auth.js +86 -1
  689. package/dist/shared/lib/i18n/messages/en/common.js +140 -1
  690. package/dist/shared/lib/i18n/messages/en/file-upload.js +18 -1
  691. package/dist/shared/lib/i18n/messages/en/student.js +133 -1
  692. package/dist/shared/lib/i18n/messages/en/terms.js +37 -1
  693. package/dist/shared/lib/i18n/messages/en.d.ts +11 -4
  694. package/dist/shared/lib/i18n/messages/en.js +15 -1
  695. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +11 -4
  696. package/dist/shared/lib/i18n/messages/vi/admin.js +2111 -1
  697. package/dist/shared/lib/i18n/messages/vi/auth.js +86 -1
  698. package/dist/shared/lib/i18n/messages/vi/common.js +140 -1
  699. package/dist/shared/lib/i18n/messages/vi/file-upload.js +18 -1
  700. package/dist/shared/lib/i18n/messages/vi/student.js +133 -1
  701. package/dist/shared/lib/i18n/messages/vi/terms.js +37 -1
  702. package/dist/shared/lib/i18n/messages/vi.d.ts +11 -4
  703. package/dist/shared/lib/i18n/messages/vi.js +15 -1
  704. package/dist/shared/lib/i18n/types.js +1 -1
  705. package/dist/shared/lib/stores/examQuestionStore.js +212 -1
  706. package/dist/shared/lib/stores/examTakingStore.js +240 -1
  707. package/dist/shared/lib/stores/gradingTransientStore.js +39 -1
  708. package/dist/shared/lib/stores/localeStore.js +10 -1
  709. package/dist/shared/lib/themes/config/starters.config.js +71 -1
  710. package/dist/shared/lib/themes/index.js +49 -1
  711. package/dist/shared/lib/themes/types.js +2 -1
  712. package/dist/shared/lib/toast.js +43 -1
  713. package/dist/shared/lib/utils/public-page.js +44 -1
  714. package/dist/shared/lib/utils/question-reverse-transform.js +438 -1
  715. package/dist/shared/lib/utils/question-transform-types.js +1 -1
  716. package/dist/shared/lib/utils/question-transform-validation.js +194 -1
  717. package/dist/shared/lib/utils/question-transform.js +199 -1
  718. package/dist/shared/lib/utils.js +168 -1
  719. package/dist/shared/lib/validation/choose-correct-answer.validation.js +111 -1
  720. package/dist/shared/lib/validation/label-the-picture.validation.js +19 -1
  721. package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +46 -1
  722. package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +21 -1
  723. package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +34 -1
  724. package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +40 -1
  725. package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +45 -1
  726. package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +19 -1
  727. package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +39 -1
  728. package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +32 -1
  729. package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +19 -1
  730. package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +28 -1
  731. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +12 -1
  732. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +47 -1
  733. package/dist/shared/lib/validation/read-and-color-objects.validation.js +29 -1
  734. package/dist/shared/lib/validation/read-displayed-content.validation.js +28 -1
  735. package/dist/shared/lib/validation/speaking-conversation.validation.js +75 -1
  736. package/dist/shared/lib/validation/speaking-describe-image.validation.js +31 -1
  737. package/dist/shared/lib/validation/spontaneous-qa.validation.js +48 -1
  738. package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +38 -1
  739. package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +39 -1
  740. package/dist/shared/lib/validation/word-fill-paragraph.validation.js +43 -1
  741. package/dist/shared/lib/validation/word-ordering.validation.js +33 -1
  742. package/dist/shared/types/branch.types.js +6 -1
  743. package/dist/shared/types/common.types.js +49 -1
  744. package/dist/shared/types/entities/exam-schedule.types.js +5 -1
  745. package/dist/shared/types/entities/exam.types.js +1 -1
  746. package/dist/shared/types/entities/question.types.js +4 -1
  747. package/dist/shared/types/entities/result.types.js +4 -1
  748. package/dist/shared/types/entities/user.types.js +4 -1
  749. package/dist/shared/types/exam-taking.types.js +2 -1
  750. package/dist/shared/types/history.types.js +34 -1
  751. package/dist/shared/types/index.js +1 -1
  752. package/dist/shared/types/questions/choose-correct-adjective.js +4 -1
  753. package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +1 -0
  754. package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -1
  755. package/dist/shared/types/questions/choose-the-correct-answer.js +9 -1
  756. package/dist/shared/types/questions/cross-out-word-group.d.ts +2 -0
  757. package/dist/shared/types/questions/cross-out-word-group.js +1 -1
  758. package/dist/shared/types/questions/fill-missing-words-in-grid.js +11 -1
  759. package/dist/shared/types/questions/index.d.ts +1 -0
  760. package/dist/shared/types/questions/index.js +46 -1
  761. package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
  762. package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
  763. package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
  764. package/dist/shared/types/questions/listen-and-speak-info-exchange.js +3 -1
  765. package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +3 -1
  766. package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
  767. package/dist/shared/types/questions/listen-and-speak-with-story-images.js +3 -1
  768. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +5 -1
  769. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +9 -1
  770. package/dist/shared/types/questions/look-picture-fill-word-hint.js +7 -1
  771. package/dist/shared/types/questions/read-displayed-content.js +1 -1
  772. package/dist/shared/types/questions/speaking-conversation.js +7 -1
  773. package/dist/shared/types/questions/speaking-describe-image.js +1 -1
  774. package/dist/shared/types/questions/spontaneous-qa.js +1 -1
  775. package/dist/shared/types/questions/word-order-and-match-group.d.ts +33 -0
  776. package/dist/shared/types/questions/word-order-and-match-group.js +1 -0
  777. package/dist/shared/types/questions/write-correct-verb-form.js +12 -1
  778. package/dist/shared/types/role.types.js +1 -1
  779. package/dist/shared/types/structure-management.js +28 -1
  780. package/dist/shared/types/student.types.js +57 -1
  781. package/dist/shared/types/teacher-dashboard-rooms.js +2 -1
  782. package/package.json +184 -166
  783. package/dist/mcp/config.d.ts +0 -12
  784. package/dist/mcp/config.js +0 -1
  785. package/dist/mcp/http-client.d.ts +0 -6
  786. package/dist/mcp/http-client.js +0 -1
  787. package/dist/mcp/index.d.ts +0 -6
  788. package/dist/mcp/index.js +0 -2
  789. package/dist/mcp/tools/_helpers.d.ts +0 -4
  790. package/dist/mcp/tools/_helpers.js +0 -1
  791. package/dist/mcp/tools/exams.d.ts +0 -2
  792. package/dist/mcp/tools/exams.js +0 -1
  793. package/dist/mcp/tools/index.d.ts +0 -2
  794. package/dist/mcp/tools/index.js +0 -1
  795. package/dist/mcp/tools/results.d.ts +0 -2
  796. package/dist/mcp/tools/results.js +0 -1
@@ -1 +1,131 @@
1
- "use client";import{jsx as e,Fragment as r,jsxs as t}from"react/jsx-runtime";import{Check as s,ChevronDown as a,X as n}from"lucide-react";import{ResolvedImage as i}from"../../../../../components/common/ResolvedImage";import o from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import l from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";function c({opt:s,isUsed:a}){const n=Boolean(s.imageUrl?.trim()),o=Boolean(s.content?.trim()),l=!n&&!o,d=o?s.content:s.answer;return l?e("div",{className:["group relative flex min-h-[56px] items-center rounded-xl border-2 px-4 py-3 shadow-sm transition-all duration-300",a?"border-emerald-400 bg-emerald-50/50 opacity-60 scale-[0.98] shadow-emerald-100/50":"border-slate-200 bg-white hover:border-indigo-300 hover:shadow-md hover:shadow-indigo-100/50"].join(" "),children:e("span",{className:"min-w-0 flex-1 text-sm font-semibold leading-snug break-words transition-colors "+(a?"text-emerald-700":"text-slate-700"),children:s.answer})}):t("div",{className:["group relative flex min-h-[180px] flex-col gap-3 rounded-2xl border-2 p-3 shadow-sm transition-all duration-300",a?"border-emerald-400 bg-emerald-50/40 opacity-60 scale-[0.98] shadow-emerald-100/50":"border-slate-200 bg-white/95 hover:-translate-y-1 hover:border-indigo-300 hover:shadow-lg hover:shadow-indigo-100/50"].join(" "),children:[s.answer!==d&&e("div",{className:"flex items-start justify-start gap-2",children:e("div",{className:"relative inline-flex min-h-[40px] min-w-[40px] items-center justify-center rounded-xl px-3 py-1.5 font-extrabold text-white shadow-sm transition-all duration-300 "+(a?"bg-gradient-to-br from-emerald-400 to-emerald-600":"bg-gradient-to-br from-indigo-500 to-violet-600"),children:e("span",{className:"text-sm text-center leading-tight break-words line-clamp-2",children:s.answer})})}),n?t(r,{children:[e("div",{className:"flex flex-1 items-center justify-center overflow-hidden rounded-xl border p-2 transition-all duration-300 "+(a?"border-emerald-200/50 bg-emerald-100/30 grayscale-[40%]":"border-slate-100 bg-gradient-to-br from-slate-50 to-white"),children:e(i,{src:s.imageUrl,alt:s.answer,className:"h-28 w-full rounded-xl object-contain sm:h-32"})}),e("div",{className:"min-w-0",children:e("div",{className:"truncate text-center text-sm font-semibold transition-colors "+(a?"text-emerald-700":"text-slate-700"),children:d||`Picture ${s.answer}`})})]}):e("div",{className:"flex flex-1 items-center justify-center rounded-xl border border-slate-100 bg-gradient-to-br from-slate-50 to-white px-4 py-5 text-center",children:e("span",{className:"text-sm font-semibold leading-snug "+(a?"text-emerald-700":"text-slate-700"),children:d})})]})}function m({value:r,onChange:s,disabled:n,options:i}){const o=r.trim().toUpperCase();return t("div",{className:"group relative min-w-[160px] sm:min-w-[210px]",children:[t("select",{value:o,onChange:e=>s(e.target.value),disabled:n,className:"h-[48px] w-full appearance-none rounded-2xl border border-slate-200 bg-white px-4 pr-11 text-sm font-semibold text-slate-700 shadow-sm outline-none transition-all duration-200 hover:border-indigo-300 focus:border-indigo-500 focus:ring-4 focus:ring-indigo-100/50 disabled:cursor-not-allowed disabled:opacity-60","aria-label":"Chọn đáp án đúng",children:[e("option",{value:"",children:"Chọn đáp án"}),i.map(r=>e("option",{value:r.answer.toUpperCase(),children:r.content||r.answer},r.answer))]}),e("div",{className:"pointer-events-none absolute right-2.5 top-1/2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full bg-slate-100 text-slate-500 transition-colors group-focus-within:bg-indigo-100 group-focus-within:text-indigo-600",children:e(a,{className:"h-3.5 w-3.5",strokeWidth:2.5})})]})}function p({question:r,rawAnswer:s,displayValue:a,isDisabled:n,isExampleQ:o,onAnswerChange:l,isReviewMode:d,correctAnswer:c,answerStatus:p,options:u}){return t("div",{className:["group relative overflow-hidden rounded-[14px] border p-4 shadow-sm transition-all duration-200 flex flex-col gap-4",o?"border-amber-200 bg-gradient-to-br from-amber-50 to-orange-50/50 shadow-amber-100/40":"border-slate-200/80 bg-white hover:-translate-y-0.5 hover:border-indigo-200 hover:shadow-md hover:shadow-indigo-100/50"].join(" "),children:[t("div",{className:"flex items-start gap-4",children:[e("span",{className:"flex h-[38px] w-[38px] shrink-0 items-center justify-center rounded-[10px] text-[15px] font-extrabold text-white shadow-sm "+(o?"bg-gradient-to-br from-amber-400 to-orange-500":"bg-gradient-to-br from-indigo-500 to-violet-600"),children:r.questionNumber}),t("div",{className:"flex flex-1 flex-col gap-2 pt-1",children:[o&&e("span",{className:"w-fit rounded-full border border-amber-300 bg-amber-100 px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider text-amber-700",children:"Example"}),e("div",{className:"text-[15px] font-medium leading-relaxed text-slate-800 break-words",children:r.question})]})]}),r.imageUrl&&e("div",{className:"flex w-full justify-center",children:e(i,{src:r.imageUrl,alt:`Q${r.questionNumber}`,className:"h-30 w-auto min-w-[5rem] rounded-xl border border-slate-100 bg-slate-50 object-contain p-1.5 shadow-sm sm:h-30"})}),e("div",{className:"mt-1 flex w-full items-center justify-end border-t border-slate-100/80 pt-3",children:d&&!o?e(h,{userAnswer:a,correctAnswer:c,status:p??"unanswered"}):e("div",{className:"w-full sm:w-auto",children:e(m,{value:s,onChange:e=>l(r.id,e),disabled:n,options:u})})})]})}function h({userAnswer:a,correctAnswer:i,status:o}){return t("div",{className:`flex w-full sm:w-auto items-center justify-center gap-2 rounded-xl border px-5 py-2 text-[15px] shadow-sm transition-colors ${"correct"===o?"border-emerald-200 bg-emerald-50 text-emerald-700":"incorrect"===o?"border-red-200 bg-red-50 text-red-700":"border-slate-200 bg-slate-50 text-slate-700"}`,children:["correct"===o&&t(r,{children:[e(s,{className:"h-4 w-4 shrink-0",strokeWidth:3}),e("span",{className:"font-medium opacity-90",children:"Đáp án:"}),e("span",{className:"ml-1 rounded-md bg-white px-2.5 py-0.5 border border-emerald-100 font-bold shadow-sm",children:a||"Trống"})]}),"unanswered"===o&&t("div",{className:"flex items-center gap-2",children:[e("span",{className:"font-medium opacity-80",children:"Đáp án:"}),e("span",{className:"rounded-md bg-white px-2.5 py-0.5 border border-slate-200 font-bold shadow-sm",children:i})]}),"incorrect"===o&&t("div",{className:"flex items-center gap-2",children:[e(n,{className:"h-4 w-4 shrink-0",strokeWidth:3}),e("span",{className:"font-medium opacity-90",children:"Đáp án:"}),e("span",{className:"line-through decoration-red-400/80 decoration-2 rounded-md bg-white/60 px-2 py-0.5 border border-red-100/50 font-semibold opacity-70",children:a||"Trống"}),e("span",{className:"text-red-400 font-bold",children:"→"}),e("span",{className:"rounded-md bg-white px-2.5 py-0.5 border border-red-200 font-bold shadow-sm",children:i})]})]})}export function MoversMatchByWritingAnswerRenderer({partNumber:a,partName:m,questionCount:h,instruction:u,audioUrl:x,options:g,questions:b,answers:w,onAnswerChange:f,isReviewMode:v=!1,viewMode:N="DEFAULT",groupImageUrl:y,correctAnswerTextMap:C={},isCorrectMap:j={}}){const A=e=>{if(!w[e])return"unanswered";const r=j[e];return!0===r?"correct":!1===r?"incorrect":"unanswered"},k=e=>{if(!e)return"";const r=e.trim().toUpperCase(),t=g.find(e=>e.answer.toUpperCase()===r);return t?t.content||t.answer:e};if("CONVERSATION"===N)return t("div",{className:"flex h-full flex-col gap-4 overflow-y-auto p-3 sm:gap-6 sm:p-6",children:[e(o,{partNumber:a,questionCount:h,partName:m,isReviewMode:v}),e(l,{instruction:u,isReviewMode:v}),x&&e("div",{className:"shrink-0",children:e(d,{audioSrc:x,compact:!0})}),y&&e(i,{src:y,alt:"Group illustration",className:"max-h-[200px] rounded-lg object-contain shadow-md"}),g.length>0&&e("div",{className:"grid grid-cols-2 gap-2 rounded-xl border border-slate-200 bg-slate-50 p-3 sm:grid-cols-4",children:g.map((r,s)=>t("div",{className:"flex items-center gap-2 rounded-lg border border-slate-200 bg-white p-2",children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-violet-600 text-xs font-bold text-white",children:r.answer}),e("span",{className:"flex-1 text-sm text-slate-700",children:r.content||r.answer})]},s))}),e("div",{className:"flex flex-col gap-3",children:b.filter(e=>!e.isExample).map(a=>{const i=A(a.id),o=w[a.id]||"",l=k(o),d=C[a.id];return t("div",{id:`question-${a.id}`,className:"flex flex-col gap-2",children:[t("div",{className:"flex items-start gap-2",children:[t("span",{className:"w-12 shrink-0 text-xs font-semibold text-slate-500",children:[a.askerName,":"]}),e("div",{className:"max-w-[80%] rounded-2xl rounded-tl-none bg-slate-100 px-4 py-2 text-sm text-slate-800",children:a.question})]}),e("div",{className:"flex items-center justify-end gap-2",children:t("div",{className:"flex max-w-[80%] items-center gap-2 rounded-2xl rounded-tr-none border border-indigo-200 bg-indigo-50 px-4 py-2",children:[t("span",{className:"shrink-0 text-xs font-semibold text-indigo-600",children:[a.answererName,":"]}),v?t("span",{className:"flex items-center gap-1 text-sm font-bold",children:["correct"===i&&e("span",{className:"text-slate-800",children:l}),"unanswered"===i&&e("span",{className:"text-indigo-600",children:d}),"incorrect"===i&&t(r,{children:[e("span",{className:"text-red-500 line-through",children:l}),e("span",{className:"text-slate-400",children:"→"}),e("span",{className:"text-indigo-600",children:d})]}),e("div",{className:"flex h-5 w-5 items-center justify-center rounded-full text-white "+("correct"===i?"bg-emerald-500":"incorrect"===i?"bg-red-500":"bg-indigo-500"),children:e("incorrect"===i?n:s,{className:"h-3 w-3",strokeWidth:3})})]}):t("select",{value:o.trim().toUpperCase(),onChange:e=>f(a.id,e.target.value),disabled:v,className:"min-w-[140px] rounded-lg border border-indigo-300 bg-white px-3 py-2 text-sm font-bold text-slate-700 outline-none focus:border-indigo-500",children:[e("option",{value:"",children:"Chọn đáp án"}),g.map(r=>e("option",{value:r.answer.toUpperCase(),children:r.content||r.answer},r.answer))]})]})})]},a.id)})})]});const U=new Set(Object.values(w).filter(e=>"string"==typeof e&&Boolean(e)).map(e=>e.trim().toUpperCase()));b.forEach(e=>{e.isExample&&e.exampleAnswer&&U.add(e.exampleAnswer.trim().toUpperCase())});const q=b.filter(e=>e.isExample),M=b.filter(e=>!e.isExample);return t("div",{className:"flex flex-col h-full gap-5 sm:gap-6 overflow-y-auto custom-scrollbar",children:[t("div",{className:"flex flex-col gap-4 sm:gap-5 p-3 sm:px-6 sm:pt-2",children:[e(o,{partNumber:a,questionCount:h,partName:m,isReviewMode:v}),e(l,{instruction:u,isReviewMode:v}),x&&e("div",{className:"shrink-0",children:e(d,{audioSrc:x,compact:!0})}),y&&e("div",{className:"flex items-center justify-center rounded-2xl border border-slate-200/80 bg-white p-3 shadow-sm",children:e(i,{src:y,alt:"Group illustration",className:"max-h-[300px] rounded-xl object-contain shadow-md"})}),g.length>0&&t("div",{className:"rounded-[20px] border border-slate-200/80 bg-gradient-to-br from-white via-white to-slate-50 p-4 sm:p-5 shadow-lg shadow-slate-100/70",children:[e("div",{className:"mb-4 flex items-center justify-between gap-3",children:e("div",{children:e("h3",{className:"text-sm font-bold uppercase tracking-[0.18em] text-slate-500",children:"Answer bank"})})}),e("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4",children:g.map((r,t)=>e(c,{opt:r,isUsed:U.has(r.answer.toUpperCase())},t))})]}),q.length>0&&e("div",{className:"flex flex-col gap-4 mt-2",children:q.map(r=>{const t=w[r.id]||"",s=r.exampleAnswer||k(t);return e("div",{id:`question-${r.id}`,className:"w-full",children:e(p,{question:r,rawAnswer:t,displayValue:s,isDisabled:!0,isExampleQ:!0,onAnswerChange:f,isReviewMode:v,correctAnswer:C[r.id],answerStatus:void 0,options:g})},r.id)})})]}),q.length>0&&M.length>0&&e("div",{className:"px-3 sm:px-6",children:e("hr",{className:"border-t border-slate-200/60 my-2"})}),e("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6",children:M.map(r=>{const t=v,s=w[r.id]||"",a=k(s);return e("div",{id:`question-${r.id}`,className:"w-full",children:e(p,{question:r,rawAnswer:s,displayValue:a,isDisabled:t,isExampleQ:!1,onAnswerChange:f,isReviewMode:v,correctAnswer:C[r.id],answerStatus:v?A(r.id):void 0,options:g})},r.id)})})]})}
1
+ /**
2
+ * MATCH_BY_WRITING_ANSWER Renderer - Shared options grid + choose matching answer
3
+ * Supports DEFAULT (image-based options) and CONVERSATION (dialogue) modes
4
+ * Used in Movers P3/P6, Flyers P7
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
8
+ import { Check, ChevronDown, X } from 'lucide-react';
9
+ import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
10
+ import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
11
+ import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
12
+ import CambridgeYleAudioPlayer from '../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer';
13
+ // ---------------------------------------------------------------------------
14
+ // Option card — left column palette
15
+ // ---------------------------------------------------------------------------
16
+ function OptionCard({ opt, isUsed, }) {
17
+ const hasImage = Boolean(opt.imageUrl?.trim());
18
+ const hasContent = Boolean(opt.content?.trim());
19
+ const isAnswerOnly = !hasImage && !hasContent;
20
+ const displayText = hasContent ? opt.content : opt.answer;
21
+ if (isAnswerOnly) {
22
+ return (_jsx("div", { className: [
23
+ 'group relative flex min-h-[56px] items-center rounded-xl border-2 px-4 py-3 shadow-sm transition-all duration-300',
24
+ isUsed
25
+ ? 'border-emerald-400 bg-emerald-50/50 opacity-60 scale-[0.98] shadow-emerald-100/50'
26
+ : 'border-slate-200 bg-white hover:border-indigo-300 hover:shadow-md hover:shadow-indigo-100/50',
27
+ ].join(' '), children: _jsx("span", { className: `min-w-0 flex-1 text-sm font-semibold leading-snug break-words transition-colors ${isUsed ? 'text-emerald-700' : 'text-slate-700'}`, children: opt.answer }) }));
28
+ }
29
+ return (_jsxs("div", { className: [
30
+ 'group relative flex min-h-[180px] flex-col gap-3 rounded-2xl border-2 p-3 shadow-sm transition-all duration-300',
31
+ isUsed
32
+ ? 'border-emerald-400 bg-emerald-50/40 opacity-60 scale-[0.98] shadow-emerald-100/50'
33
+ : 'border-slate-200 bg-white/95 hover:-translate-y-1 hover:border-indigo-300 hover:shadow-lg hover:shadow-indigo-100/50',
34
+ ].join(' '), children: [opt.answer !== displayText && (_jsx("div", { className: "flex items-start justify-start gap-2", children: _jsx("div", { className: `relative inline-flex min-h-[40px] min-w-[40px] items-center justify-center rounded-xl px-3 py-1.5 font-extrabold text-white shadow-sm transition-all duration-300 ${isUsed
35
+ ? 'bg-gradient-to-br from-emerald-400 to-emerald-600'
36
+ : 'bg-gradient-to-br from-indigo-500 to-violet-600'}`, children: _jsx("span", { className: "text-sm text-center leading-tight break-words line-clamp-2", children: opt.answer }) }) })), hasImage ? (_jsxs(_Fragment, { children: [_jsx("div", { className: `flex flex-1 items-center justify-center overflow-hidden rounded-xl border p-2 transition-all duration-300 ${isUsed ? 'border-emerald-200/50 bg-emerald-100/30 grayscale-[40%]' : 'border-slate-100 bg-gradient-to-br from-slate-50 to-white'}`, children: _jsx(ResolvedImage, { src: opt.imageUrl, alt: opt.answer, className: "h-28 w-full rounded-xl object-contain sm:h-32" }) }), _jsx("div", { className: "min-w-0", children: _jsx("div", { className: `truncate text-center text-sm font-semibold transition-colors ${isUsed ? 'text-emerald-700' : 'text-slate-700'}`, children: displayText || `Picture ${opt.answer}` }) })] })) : (_jsx("div", { className: "flex flex-1 items-center justify-center rounded-xl border border-slate-100 bg-gradient-to-br from-slate-50 to-white px-4 py-5 text-center", children: _jsx("span", { className: `text-sm font-semibold leading-snug ${isUsed ? 'text-emerald-700' : 'text-slate-700'}`, children: displayText }) }))] }));
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Answer selector — choose correct answer
40
+ // ---------------------------------------------------------------------------
41
+ function AnswerSelector({ value, onChange, disabled, options, }) {
42
+ const normalizedValue = value.trim().toUpperCase();
43
+ return (_jsxs("div", { className: "group relative min-w-[160px] sm:min-w-[210px]", children: [_jsxs("select", { value: normalizedValue, onChange: (e) => onChange(e.target.value), disabled: disabled, className: "h-[48px] w-full appearance-none rounded-2xl border border-slate-200 bg-white px-4 pr-11 text-sm font-semibold text-slate-700 shadow-sm outline-none transition-all duration-200 hover:border-indigo-300 focus:border-indigo-500 focus:ring-4 focus:ring-indigo-100/50 disabled:cursor-not-allowed disabled:opacity-60", "aria-label": "Ch\u1ECDn \u0111\u00E1p \u00E1n \u0111\u00FAng", children: [_jsx("option", { value: "", children: "Ch\u1ECDn \u0111\u00E1p \u00E1n" }), options.map((opt) => (_jsx("option", { value: opt.answer.toUpperCase(), children: opt.content || opt.answer }, opt.answer)))] }), _jsx("div", { className: "pointer-events-none absolute right-2.5 top-1/2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full bg-slate-100 text-slate-500 transition-colors group-focus-within:bg-indigo-100 group-focus-within:text-indigo-600", children: _jsx(ChevronDown, { className: "h-3.5 w-3.5", strokeWidth: 2.5 }) })] }));
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // Question row — right column
47
+ // ---------------------------------------------------------------------------
48
+ function QuestionRow({ question, rawAnswer, displayValue, isDisabled, isExampleQ, onAnswerChange, isReviewMode, correctAnswer, answerStatus, options, }) {
49
+ return (_jsxs("div", { className: [
50
+ 'group relative overflow-hidden rounded-[14px] border p-4 shadow-sm transition-all duration-200 flex flex-col gap-4',
51
+ isExampleQ
52
+ ? 'border-amber-200 bg-gradient-to-br from-amber-50 to-orange-50/50 shadow-amber-100/40'
53
+ : 'border-slate-200/80 bg-white hover:-translate-y-0.5 hover:border-indigo-200 hover:shadow-md hover:shadow-indigo-100/50',
54
+ ].join(' '), children: [_jsxs("div", { className: "flex items-start gap-4", children: [_jsx("span", { className: `flex h-[38px] w-[38px] shrink-0 items-center justify-center rounded-[10px] text-[15px] font-extrabold text-white shadow-sm ${isExampleQ
55
+ ? 'bg-gradient-to-br from-amber-400 to-orange-500'
56
+ : 'bg-gradient-to-br from-indigo-500 to-violet-600'}`, children: question.questionNumber }), _jsxs("div", { className: "flex flex-1 flex-col gap-2 pt-1", children: [isExampleQ && (_jsx("span", { className: "w-fit rounded-full border border-amber-300 bg-amber-100 px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider text-amber-700", children: "Example" })), _jsx("div", { className: "text-[15px] font-medium leading-relaxed text-slate-800 break-words", children: question.question })] })] }), question.imageUrl && (_jsx("div", { className: "flex w-full justify-center", children: _jsx(ResolvedImage, { src: question.imageUrl, alt: `Q${question.questionNumber}`, className: "h-30 w-auto min-w-[5rem] rounded-xl border border-slate-100 bg-slate-50 object-contain p-1.5 shadow-sm sm:h-30" }) })), _jsx("div", { className: "mt-1 flex w-full items-center justify-end border-t border-slate-100/80 pt-3", children: isReviewMode && !isExampleQ ? (_jsx(ReviewAnswer, { userAnswer: displayValue, correctAnswer: correctAnswer, status: answerStatus ?? 'unanswered' })) : (_jsx("div", { className: "w-full sm:w-auto", children: _jsx(AnswerSelector, { value: rawAnswer, onChange: (value) => onAnswerChange(question.id, value), disabled: isDisabled, options: options }) })) })] }));
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Review answer display
60
+ // ---------------------------------------------------------------------------
61
+ function ReviewAnswer({ userAnswer, correctAnswer, status, }) {
62
+ const badgeCls = status === 'correct'
63
+ ? 'border-emerald-200 bg-emerald-50 text-emerald-700'
64
+ : status === 'incorrect'
65
+ ? 'border-red-200 bg-red-50 text-red-700'
66
+ : 'border-slate-200 bg-slate-50 text-slate-700';
67
+ return (_jsxs("div", { className: `flex w-full sm:w-auto items-center justify-center gap-2 rounded-xl border px-5 py-2 text-[15px] shadow-sm transition-colors ${badgeCls}`, children: [status === 'correct' && (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-4 w-4 shrink-0", strokeWidth: 3 }), _jsx("span", { className: "font-medium opacity-90", children: "\u0110\u00E1p \u00E1n:" }), _jsx("span", { className: "ml-1 rounded-md bg-white px-2.5 py-0.5 border border-emerald-100 font-bold shadow-sm", children: userAnswer || 'Trống' })] })), status === 'unanswered' && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium opacity-80", children: "\u0110\u00E1p \u00E1n:" }), _jsx("span", { className: "rounded-md bg-white px-2.5 py-0.5 border border-slate-200 font-bold shadow-sm", children: correctAnswer })] })), status === 'incorrect' && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(X, { className: "h-4 w-4 shrink-0", strokeWidth: 3 }), _jsx("span", { className: "font-medium opacity-90", children: "\u0110\u00E1p \u00E1n:" }), _jsx("span", { className: "line-through decoration-red-400/80 decoration-2 rounded-md bg-white/60 px-2 py-0.5 border border-red-100/50 font-semibold opacity-70", children: userAnswer || 'Trống' }), _jsx("span", { className: "text-red-400 font-bold", children: "\u2192" }), _jsx("span", { className: "rounded-md bg-white px-2.5 py-0.5 border border-red-200 font-bold shadow-sm", children: correctAnswer })] }))] }));
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // Main renderer
71
+ // ---------------------------------------------------------------------------
72
+ export function MoversMatchByWritingAnswerRenderer({ partNumber, partName, questionCount, instruction, audioUrl, options, questions, answers, onAnswerChange, isReviewMode = false, viewMode = 'DEFAULT', groupImageUrl, correctAnswerTextMap = {}, isCorrectMap = {}, }) {
73
+ const getAnswerStatus = (questionId) => {
74
+ const userAnswer = answers[questionId];
75
+ if (!userAnswer)
76
+ return 'unanswered';
77
+ const isCorrect = isCorrectMap[questionId];
78
+ if (isCorrect === true)
79
+ return 'correct';
80
+ if (isCorrect === false)
81
+ return 'incorrect';
82
+ return 'unanswered';
83
+ };
84
+ // Helper to get original text for display instead of uppercase
85
+ const getOriginalAnswerText = (val) => {
86
+ if (!val)
87
+ return '';
88
+ const upperVal = val.trim().toUpperCase();
89
+ const opt = options.find((o) => o.answer.toUpperCase() === upperVal);
90
+ return opt ? (opt.content || opt.answer) : val;
91
+ };
92
+ // --------------------- CONVERSATION MODE ---------------------
93
+ if (viewMode === 'CONVERSATION') {
94
+ return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-3 sm:gap-6 sm:p-6", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode }), audioUrl && (_jsx("div", { className: "shrink-0", children: _jsx(CambridgeYleAudioPlayer, { audioSrc: audioUrl, compact: true }) })), groupImageUrl && (_jsx(ResolvedImage, { src: groupImageUrl, alt: "Group illustration", className: "max-h-[200px] rounded-lg object-contain shadow-md" })), options.length > 0 && (_jsx("div", { className: "grid grid-cols-2 gap-2 rounded-xl border border-slate-200 bg-slate-50 p-3 sm:grid-cols-4", children: options.map((opt, idx) => (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-slate-200 bg-white p-2", children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-violet-600 text-xs font-bold text-white", children: opt.answer }), _jsx("span", { className: "flex-1 text-sm text-slate-700", children: opt.content || opt.answer })] }, idx))) })), _jsx("div", { className: "flex flex-col gap-3", children: questions
95
+ .filter((q) => !q.isExample)
96
+ .map((question) => {
97
+ const status = getAnswerStatus(question.id);
98
+ const rawUserAnswer = answers[question.id] || '';
99
+ const userAnswer = getOriginalAnswerText(rawUserAnswer);
100
+ const correctAnswer = correctAnswerTextMap[question.id];
101
+ return (_jsxs("div", { id: `question-${question.id}`, className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsxs("span", { className: "w-12 shrink-0 text-xs font-semibold text-slate-500", children: [question.askerName, ":"] }), _jsx("div", { className: "max-w-[80%] rounded-2xl rounded-tl-none bg-slate-100 px-4 py-2 text-sm text-slate-800", children: question.question })] }), _jsx("div", { className: "flex items-center justify-end gap-2", children: _jsxs("div", { className: "flex max-w-[80%] items-center gap-2 rounded-2xl rounded-tr-none border border-indigo-200 bg-indigo-50 px-4 py-2", children: [_jsxs("span", { className: "shrink-0 text-xs font-semibold text-indigo-600", children: [question.answererName, ":"] }), isReviewMode ? (_jsxs("span", { className: "flex items-center gap-1 text-sm font-bold", children: [status === 'correct' && _jsx("span", { className: "text-slate-800", children: userAnswer }), status === 'unanswered' && _jsx("span", { className: "text-indigo-600", children: correctAnswer }), status === 'incorrect' && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-red-500 line-through", children: userAnswer }), _jsx("span", { className: "text-slate-400", children: "\u2192" }), _jsx("span", { className: "text-indigo-600", children: correctAnswer })] })), _jsx("div", { className: `flex h-5 w-5 items-center justify-center rounded-full text-white ${status === 'correct'
102
+ ? 'bg-emerald-500'
103
+ : status === 'incorrect'
104
+ ? 'bg-red-500'
105
+ : 'bg-indigo-500'}`, children: status === 'incorrect' ? (_jsx(X, { className: "h-3 w-3", strokeWidth: 3 })) : (_jsx(Check, { className: "h-3 w-3", strokeWidth: 3 })) })] })) : (_jsxs("select", { value: rawUserAnswer.trim().toUpperCase(), onChange: (e) => onAnswerChange(question.id, e.target.value), disabled: isReviewMode, className: "min-w-[140px] rounded-lg border border-indigo-300 bg-white px-3 py-2 text-sm font-bold text-slate-700 outline-none focus:border-indigo-500", children: [_jsx("option", { value: "", children: "Ch\u1ECDn \u0111\u00E1p \u00E1n" }), options.map((opt) => (_jsx("option", { value: opt.answer.toUpperCase(), children: opt.content || opt.answer }, opt.answer)))] }))] }) })] }, question.id));
106
+ }) })] }));
107
+ }
108
+ // Collect used answer letters for visual state
109
+ const usedAnswers = new Set(Object.values(answers)
110
+ .filter((v) => typeof v === 'string' && Boolean(v))
111
+ .map((v) => v.trim().toUpperCase()));
112
+ // Also include example answers as "used"
113
+ questions.forEach((q) => {
114
+ if (q.isExample && q.exampleAnswer)
115
+ usedAnswers.add(q.exampleAnswer.trim().toUpperCase());
116
+ });
117
+ // Separate example questions and actual questions
118
+ const exampleQuestions = questions.filter((q) => q.isExample);
119
+ const actualQuestions = questions.filter((q) => !q.isExample);
120
+ // --------------------- DEFAULT MODE — Top/Bottom layout ---------------------
121
+ return (_jsxs("div", { className: "flex flex-col h-full gap-5 sm:gap-6 overflow-y-auto custom-scrollbar", children: [_jsxs("div", { className: "flex flex-col gap-4 sm:gap-5 p-3 sm:px-6 sm:pt-2", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode }), audioUrl && (_jsx("div", { className: "shrink-0", children: _jsx(CambridgeYleAudioPlayer, { audioSrc: audioUrl, compact: true }) })), groupImageUrl && (_jsx("div", { className: "flex items-center justify-center rounded-2xl border border-slate-200/80 bg-white p-3 shadow-sm", children: _jsx(ResolvedImage, { src: groupImageUrl, alt: "Group illustration", className: "max-h-[300px] rounded-xl object-contain shadow-md" }) })), options.length > 0 && (_jsxs("div", { className: "rounded-[20px] border border-slate-200/80 bg-gradient-to-br from-white via-white to-slate-50 p-4 sm:p-5 shadow-lg shadow-slate-100/70", children: [_jsx("div", { className: "mb-4 flex items-center justify-between gap-3", children: _jsx("div", { children: _jsx("h3", { className: "text-sm font-bold uppercase tracking-[0.18em] text-slate-500", children: "Answer bank" }) }) }), _jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4", children: options.map((opt, idx) => (_jsx(OptionCard, { opt: opt, isUsed: usedAnswers.has(opt.answer.toUpperCase()) }, idx))) })] })), exampleQuestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-4 mt-2", children: exampleQuestions.map((question) => {
122
+ const rawAnswer = answers[question.id] || '';
123
+ const displayValue = question.exampleAnswer || getOriginalAnswerText(rawAnswer);
124
+ return (_jsx("div", { id: `question-${question.id}`, className: "w-full", children: _jsx(QuestionRow, { question: question, rawAnswer: rawAnswer, displayValue: displayValue, isDisabled: true, isExampleQ: true, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, correctAnswer: correctAnswerTextMap[question.id], answerStatus: undefined, options: options }) }, question.id));
125
+ }) }))] }), exampleQuestions.length > 0 && actualQuestions.length > 0 && (_jsx("div", { className: "px-3 sm:px-6", children: _jsx("hr", { className: "border-t border-slate-200/60 my-2" }) })), _jsx("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6", children: actualQuestions.map((question) => {
126
+ const isDisabled = isReviewMode;
127
+ const rawAnswer = answers[question.id] || '';
128
+ const displayValue = getOriginalAnswerText(rawAnswer);
129
+ return (_jsx("div", { id: `question-${question.id}`, className: "w-full", children: _jsx(QuestionRow, { question: question, rawAnswer: rawAnswer, displayValue: displayValue, isDisabled: isDisabled, isExampleQ: false, onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, correctAnswer: correctAnswerTextMap[question.id], answerStatus: isReviewMode ? getAnswerStatus(question.id) : undefined, options: options }) }, question.id));
130
+ }) })] }));
131
+ }
@@ -1 +1,76 @@
1
- "use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as o}from"react";import{ZoomIn as i,Check as n,X as s}from"lucide-react";import{ResolvedImage as l}from"../../../../../components/common/ResolvedImage";import d from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import a from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";function c({imageUrl:n,alt:s}){const[d,a]=o(!1);return r(t,{children:[r("div",{className:"relative flex items-center justify-center",children:[e(l,{src:n,alt:s,className:"max-h-[180px] cursor-pointer rounded-lg object-contain shadow-md",onClick:()=>a(!0)}),e("button",{type:"button",onClick:()=>a(!0),className:"absolute right-2 top-2 rounded-full bg-white/80 p-1.5 shadow-md hover:bg-white","aria-label":"Zoom image",children:e(i,{className:"h-4 w-4 text-gray-600"})})]}),d&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70",onClick:()=>a(!1),children:e(l,{src:n,alt:`${s} (zoomed)`,className:"max-h-[90vh] max-w-[90vw] rounded-lg object-contain",showLoadingState:!1})})]})}function m({subQuestion:t,selectedOptionId:o,onSelect:i,isReviewMode:l,id:d}){const a=l&&o===t.correctOptionId,m=e=>{if(!l)return o===e?"border-blue-500 bg-[#f4f9ff]":"border-blue-200 bg-white hover:border-blue-300 hover:bg-blue-50/30";const r=o===e,i=t.correctOptionId===e;return i?a?"border-green-500 bg-green-50":"border-blue-500 bg-blue-50":r&&!i?"border-red-500 bg-red-50":"border-blue-200 bg-white"},u=e=>{if(!l)return o===e?"border-blue-500 bg-blue-500":"border-gray-300 bg-white";const r=o===e,i=t.correctOptionId===e;return i?a?"border-green-500 bg-green-500":"border-blue-500 bg-blue-500":r&&!i?"border-red-500 bg-red-500":"border-gray-300 bg-white"},b=r=>{if(!l)return null;const i=o===r,d=t.correctOptionId===r;return d?e(n,{className:"h-4 w-4 text-white"}):i&&!d?e(s,{className:"h-4 w-4 text-white"}):null};return r("div",{id:d,className:"rounded-lg border border-gray-200 bg-white p-4 shadow-sm",children:[r("div",{className:"mb-3 flex items-start gap-3",children:[e("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:t.questionNumber}),e(c,{imageUrl:t.imageUrl,alt:`Question ${t.questionNumber}`})]}),t.questionText&&e("p",{className:"mb-3 text-[17px] font-bold text-[#001590]",children:t.questionText}),e("div",{className:"flex flex-col gap-2",children:t.options.map(t=>r("button",{type:"button",onClick:()=>!l&&i(t.id),disabled:l,className:`flex items-center gap-3 rounded-lg border-2 px-3 py-2 text-left transition-colors ${m(t.id)} ${l?"cursor-default":"cursor-pointer"}`,children:[r("span",{className:"text-sm font-medium text-gray-600",children:[t.label,"."]}),e("span",{className:"flex-1 text-sm text-gray-700",children:t.text}),e("div",{className:`flex h-5 w-5 items-center justify-center rounded-full border-2 ${u(t.id)}`,children:l?b(t.id):o===t.id&&e("div",{className:"h-2 w-2 rounded-full bg-white"})})]},t.id))})]})}export function MoversPictureChooseRenderer({partNumber:t,partName:o,questionCount:i,instruction:n,subQuestions:s,answers:l,onAnswerChange:c,isReviewMode:u=!1}){return r("div",{className:"flex h-full flex-col gap-4 overflow-y-auto p-6",children:[r("div",{className:"flex flex-col gap-4",children:[e(d,{partNumber:t,questionCount:i,partName:o,isReviewMode:u}),e(a,{instruction:n,isReviewMode:u})]}),e("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-2",children:s.map(r=>e(m,{id:`question-${r.id}`,subQuestion:r,selectedOptionId:l[r.id],onSelect:e=>c(r.id,e),isReviewMode:u},r.id))})]})}
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 +1,68 @@
1
- "use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as o}from"react";import{ZoomIn as i}from"lucide-react";import{ResolvedImage as n}from"../../../../../components/common/ResolvedImage";import s from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";function l({imageUrl:s,alt:d}){const[l,a]=o(!1);return r(t,{children:[r("div",{className:"relative flex items-center justify-center",children:[e(n,{src:s,alt:d,className:"max-h-[150px] cursor-pointer rounded-lg object-contain shadow-md",onClick:()=>a(!0)}),e("button",{type:"button",onClick:()=>a(!0),className:"absolute right-1 top-1 rounded-full bg-white/80 p-1 shadow-md hover:bg-white","aria-label":"Zoom image",children:e(i,{className:"h-3 w-3 text-gray-600"})})]}),l&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70",onClick:()=>a(!1),children:e(n,{src:s,alt:`${d} (zoomed)`,className:"max-h-[90vh] max-w-[90vw] rounded-lg object-contain",showLoadingState:!1})})]})}function a({question:t,selectedAnswer:o,isReviewMode:i,isCorrect:n}){const s=t.split("{0}");return r("p",{className:"text-sm font-medium text-gray-700",children:[s[0],e("span",{className:"mx-1 inline-block min-w-[60px] border-b-2 border-dashed px-2 text-center font-semibold "+(i&&o?n?"border-green-500 text-green-600":"border-red-500 text-red-600":"border-blue-400 text-blue-600"),children:o||"______"}),s[1]]})}function c({subQuestion:t,selectedOptionId:o,onSelect:i,isReviewMode:n,id:s}){const d=t.options.find(e=>e.id===o),c=n&&o===t.correctOptionId,m=e=>{if(!n)return o===e?"border-blue-500 bg-blue-50":"border-gray-300 bg-white hover:border-blue-300";const r=o===e,i=t.correctOptionId===e;return i?c?"border-green-500 bg-green-50":"border-blue-500 bg-blue-50":r&&!i?"border-red-500 bg-red-50":"border-gray-300 bg-white"},u=e=>{if(!n)return"text-gray-700";const r=o===e;return t.correctOptionId===e||r?"text-gray-800 font-bold":"text-gray-600"};return r("div",{id:s,className:"rounded-lg border border-gray-200 bg-white p-4 shadow-sm",children:[r("div",{className:"mb-3 flex items-start gap-3",children:[e("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:t.questionNumber}),e(l,{imageUrl:t.imageUrl,alt:`Question ${t.questionNumber}`})]}),e("div",{className:"mb-3",children:e(a,{question:t.question,selectedAnswer:d?.text,isReviewMode:n,isCorrect:o===t.correctOptionId})}),e("div",{className:"flex flex-wrap gap-2",children:t.options.map(e=>r("button",{type:"button",onClick:()=>!n&&i(e.id),disabled:n,className:`rounded-lg border-2 px-3 py-1.5 text-sm transition-colors ${m(e.id)} ${u(e.id)} ${n?"cursor-default":"cursor-pointer"}`,children:[e.label,". ",e.text]},e.id))})]})}export function MoversPictureFillBlankChooseRenderer({partNumber:t,partName:o,questionCount:i,instruction:n,subQuestions:l,answers:a,onAnswerChange:m,isReviewMode:u=!1}){return r("div",{className:"flex h-full flex-col gap-4 overflow-y-auto p-6",children:[r("div",{className:"flex flex-col gap-4",children:[e(s,{partNumber:t,questionCount:i,partName:o,isReviewMode:u}),e(d,{instruction:n,isReviewMode:u})]}),e("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-2",children:l.map(r=>e(c,{id:`question-${r.id}`,subQuestion:r,selectedOptionId:a[r.id],onSelect:e=>m(r.id,e),isReviewMode:u},r.id))})]})}
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 +1,62 @@
1
- "use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as s}from"react";import{Check as a,X as i,ZoomIn as l}from"lucide-react";import{ResolvedImage as o}from"../../../../../components/common/ResolvedImage";import n from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";function c({imageUrl:a}){const[i,n]=s(!1);return r(t,{children:[r("div",{className:"relative flex items-center justify-center",children:[e(o,{src:a,alt:"Passage illustration",className:"max-h-[200px] cursor-pointer rounded-lg object-contain shadow-md",onClick:()=>n(!0)}),e("button",{type:"button",onClick:()=>n(!0),className:"absolute right-2 top-2 rounded-full bg-white/80 p-1.5 shadow-md hover:bg-white","aria-label":"Zoom image",children:e(l,{className:"h-4 w-4 text-gray-600"})})]}),i&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70",onClick:()=>n(!1),children:e(o,{src:a,alt:"Passage illustration (zoomed)",className:"max-h-[90vh] max-w-[90vw] rounded-lg object-contain",showLoadingState:!1})})]})}function m({title:t,passage:s,imageUrl:a}){return r("div",{className:"rounded-lg border-2 border-amber-200 bg-amber-50 p-4",children:[t&&e("h3",{className:"mb-3 text-center text-lg font-bold text-amber-800",children:t}),a&&e("div",{className:"mb-3",children:e(c,{imageUrl:a})}),e("div",{className:"prose prose-sm max-w-none text-gray-700",children:s.split("\n").map((r,t)=>e("p",{className:"mb-2 last:mb-0",children:r},t))})]})}function u({question:t,selectedOptionId:s,onSelect:l,isReviewMode:o,correctOptionId:n,id:d}){const c=n||t.correctOptionId,m=!!s,u=s===c,b=e=>{if(!o)return s===e?"border-blue-500 bg-blue-50":"border-gray-300 bg-white hover:border-blue-300";const r=s===e;return r&&u?"border-green-500 bg-green-50":r&&!u?"border-red-500 bg-red-50":!(c===e)||u&&m?"border-gray-300 bg-white":"border-blue-500 bg-blue-50"};return r("div",{id:d,className:"mb-4",children:[r("p",{className:"mb-2 text-base font-semibold text-gray-800",children:[t.questionNumber,". ",t.questionText]}),e("div",{className:"flex flex-col gap-2 pl-2",children:t.options.map(t=>{const n=s===t.id,d=c===t.id,p=o&&n&&u,g=o&&n&&!u,h=o&&d&&(!u||!m);return r("button",{type:"button",onClick:()=>!o&&l(t.id),disabled:o,className:`flex items-center gap-3 rounded-lg border-2 px-3 py-2 text-left transition-colors ${b(t.id)} ${o?"cursor-default":"cursor-pointer"}`,children:[r("span",{className:"text-sm font-medium text-gray-600",children:[t.label,"."]}),e("span",{className:"flex-1 text-sm text-gray-700",children:t.text}),p&&e("div",{className:"flex h-6 w-6 items-center justify-center rounded-full bg-green-500",children:e(a,{className:"h-4 w-4 text-white",strokeWidth:3})}),g&&e("div",{className:"flex h-6 w-6 items-center justify-center rounded-full bg-red-500",children:e(i,{className:"h-4 w-4 text-white",strokeWidth:3})}),h&&e("div",{className:"flex h-6 w-6 items-center justify-center rounded-full bg-blue-500",children:e(a,{className:"h-4 w-4 text-white",strokeWidth:3})}),!o&&e("div",{className:"flex h-5 w-5 items-center justify-center rounded-full border-2 "+(n?"border-blue-500 bg-blue-500":"border-gray-300 bg-white"),children:n&&e("div",{className:"h-2 w-2 rounded-full bg-white"})}),o&&!p&&!g&&!h&&e("div",{className:"flex h-5 w-5 items-center justify-center rounded-full border-2 border-gray-300 bg-white"})]},t.id)})})]})}export function MoversReadingPassageRenderer({partNumber:t,partName:s,questionCount:a,instruction:i,passageTitle:l,passage:o,passageImageUrl:c,questions:b,answers:p,onAnswerChange:g,isReviewMode:h=!1,correctOptionIdMap:f}){return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative",children:[r("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-4",children:[e(n,{partNumber:t,questionCount:a,partName:s,isReviewMode:h}),e(d,{instruction:i,isReviewMode:h})]}),e("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100",children:e("div",{className:"max-h-[35vh] overflow-y-auto custom-scrollbar pr-2",children:e(m,{title:l,passage:o,imageUrl:c})})}),e("div",{className:"flex flex-col gap-4 p-3 sm:pb-6 sm:px-6",children:b.map(r=>e(u,{id:`question-${r.id}`,question:r,selectedOptionId:p[r.id],onSelect:e=>g(r.id,e),isReviewMode:h,correctOptionId:f?.[r.id]},r.id))})]})}
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 { Check, X, 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
+ // Passage Image with zoom
9
+ function PassageImage({ imageUrl }) {
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: "Passage illustration", className: "max-h-[200px] 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: "Passage illustration (zoomed)", className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
12
+ }
13
+ // Passage Section Component
14
+ function PassageSection({ title, passage, imageUrl, }) {
15
+ return (_jsxs("div", { className: "rounded-lg border-2 border-amber-200 bg-amber-50 p-4", children: [title && (_jsx("h3", { className: "mb-3 text-center text-lg font-bold text-amber-800", children: title })), imageUrl && (_jsx("div", { className: "mb-3", children: _jsx(PassageImage, { imageUrl: imageUrl }) })), _jsx("div", { className: "prose prose-sm max-w-none text-gray-700", children: passage.split('\n').map((paragraph, index) => (_jsx("p", { className: "mb-2 last:mb-0", children: paragraph }, index))) })] }));
16
+ }
17
+ // Single Question Component
18
+ function QuestionItem({ question, selectedOptionId, onSelect, isReviewMode, correctOptionId, id, }) {
19
+ // Use passed correctOptionId (from map) or fallback to question.correctOptionId
20
+ const actualCorrectId = correctOptionId || question.correctOptionId;
21
+ const hasStudentAnswered = !!selectedOptionId;
22
+ // Determine if student's answer is correct for this sub-question
23
+ const isStudentCorrect = selectedOptionId === actualCorrectId;
24
+ const getOptionStyle = (optionId) => {
25
+ if (!isReviewMode) {
26
+ return selectedOptionId === optionId
27
+ ? 'border-blue-500 bg-blue-50'
28
+ : 'border-gray-300 bg-white hover:border-blue-300';
29
+ }
30
+ // Review mode
31
+ const isSelected = selectedOptionId === optionId;
32
+ const isCorrectOption = actualCorrectId === optionId;
33
+ // Student answered correctly
34
+ if (isSelected && isStudentCorrect) {
35
+ return 'border-green-500 bg-green-50';
36
+ }
37
+ // Student answered wrong - highlight their wrong selection
38
+ if (isSelected && !isStudentCorrect) {
39
+ return 'border-red-500 bg-red-50';
40
+ }
41
+ // Show correct answer (blue border) when student was wrong or didn't answer
42
+ if (isCorrectOption && (!isStudentCorrect || !hasStudentAnswered)) {
43
+ return 'border-blue-500 bg-blue-50';
44
+ }
45
+ return 'border-gray-300 bg-white';
46
+ };
47
+ return (_jsxs("div", { id: id, className: "mb-4", children: [_jsxs("p", { className: "mb-2 text-base font-semibold text-gray-800", children: [question.questionNumber, ". ", question.questionText] }), _jsx("div", { className: "flex flex-col gap-2 pl-2", children: question.options.map((option) => {
48
+ const isSelected = selectedOptionId === option.id;
49
+ const isCorrectOption = actualCorrectId === option.id;
50
+ // Determine which icon to show (review mode only)
51
+ // Green tick: Student selected correct
52
+ const showGreenTick = isReviewMode && isSelected && isStudentCorrect;
53
+ // Red X: Student selected wrong
54
+ const showRedX = isReviewMode && isSelected && !isStudentCorrect;
55
+ // Blue tick: This is correct answer but student was wrong or didn't answer
56
+ const showBlueTick = isReviewMode && isCorrectOption && (!isStudentCorrect || !hasStudentAnswered);
57
+ return (_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 }), showGreenTick && (_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-green-500", children: _jsx(Check, { className: "h-4 w-4 text-white", strokeWidth: 3 }) })), showRedX && (_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-red-500", children: _jsx(X, { className: "h-4 w-4 text-white", strokeWidth: 3 }) })), showBlueTick && (_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-blue-500", children: _jsx(Check, { className: "h-4 w-4 text-white", strokeWidth: 3 }) })), !isReviewMode && (_jsx("div", { className: `flex h-5 w-5 items-center justify-center rounded-full border-2 ${isSelected ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'}`, children: isSelected && _jsx("div", { className: "h-2 w-2 rounded-full bg-white" }) })), isReviewMode && !showGreenTick && !showRedX && !showBlueTick && (_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full border-2 border-gray-300 bg-white" }))] }, option.id));
58
+ }) })] }));
59
+ }
60
+ export function MoversReadingPassageRenderer({ partNumber, partName, questionCount, instruction, passageTitle, passage, passageImageUrl, questions, answers, onAnswerChange, isReviewMode = false, correctOptionIdMap, }) {
61
+ return (_jsxs("div", { className: "flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative", children: [_jsxs("div", { className: "flex flex-col gap-4 p-3 sm:px-6 sm:pt-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode })] }), _jsx("div", { className: "flex flex-col gap-4 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100", children: _jsx("div", { className: "max-h-[35vh] overflow-y-auto custom-scrollbar pr-2", children: _jsx(PassageSection, { title: passageTitle, passage: passage, imageUrl: passageImageUrl }) }) }), _jsx("div", { className: "flex flex-col gap-4 p-3 sm:pb-6 sm:px-6", children: questions.map((question) => (_jsx(QuestionItem, { id: `question-${question.id}`, question: question, selectedOptionId: answers[question.id], onSelect: (optionId) => onAnswerChange(question.id, optionId), isReviewMode: isReviewMode, correctOptionId: correctOptionIdMap?.[question.id] }, question.id))) })] }));
62
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * TRUE_FALSE Renderer - Display questions with True/False buttons
3
- * Used in Starters P5
3
+ * - Full-width 1-line-per-question layout
4
4
  */
5
5
  import type { TrueFalseQuestion } from '../../utils/question-transformers';
6
6
  interface MoversTrueFalseRendererProps {
@@ -1 +1,51 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import{ResolvedImage as a}from"../../../../../components/common/ResolvedImage";import t from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import s from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";function o({question:t,answer:s,onAnswerChange:o,isReviewMode:l,correctAnswerTextMap:i,id:n}){const d=l||t.isExample,m=i[t.id],c="true"===m||"false"!==m&&void 0,g=t.isExample?t.exampleCorrectAnswer:s,p=l&&void 0!==c,x=p&&g===c,b=p&&void 0!==g&&g!==c;return r("div",{id:n,className:"flex items-start gap-3 rounded-xl p-3 "+(t.isExample?"border border-amber-300 bg-gradient-to-br from-amber-50 via-orange-50 to-white shadow-amber-100/70":""),children:[e("span",{className:"flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-sm font-bold text-white "+(t.isExample?"bg-gradient-to-br from-amber-400 to-orange-500":x?"bg-emerald-500":b?"bg-rose-500":"bg-blue-500"),children:t.questionNumber}),r("div",{className:"flex flex-1 flex-col gap-2",children:[e("div",{className:"flex items-center gap-2",children:t.isExample&&e("span",{className:"rounded-full border border-amber-300 bg-gradient-to-r from-amber-100 to-orange-100 px-2 py-0.5 text-[10px] font-extrabold uppercase tracking-widest text-amber-700 shadow-sm",children:"Example"})}),t.imageUrl&&e(a,{src:t.imageUrl,alt:`Q${t.questionNumber}`,className:"max-h-[120px] rounded-lg object-contain"}),e("p",{className:"text-base text-gray-800",children:t.question}),r("div",{className:"flex gap-3",children:[e("button",{type:"button",disabled:d,onClick:()=>o(t.id,!0),className:`rounded-lg border-2 px-5 py-2 text-sm font-semibold transition-colors ${!0===g?l&&b&&!t.isExample?"border-rose-500 bg-rose-50 text-rose-700":"border-emerald-500 bg-emerald-50 text-emerald-700":p&&!0===c&&!t.isExample?"border-emerald-500 bg-emerald-50 text-emerald-700 ring-2 ring-emerald-300":"border-gray-300 bg-white text-gray-600 hover:border-emerald-400"} ${d?"cursor-not-allowed opacity-60":""}`,children:"✓ True"}),e("button",{type:"button",disabled:d,onClick:()=>o(t.id,!1),className:`rounded-lg border-2 px-5 py-2 text-sm font-semibold transition-colors ${!1===g?l&&b&&!t.isExample?"border-rose-500 bg-rose-50 text-rose-700":"border-emerald-500 bg-emerald-50 text-emerald-700":p&&!1===c&&!t.isExample?"border-emerald-500 bg-emerald-50 text-emerald-700 ring-2 ring-emerald-300":"border-gray-300 bg-white text-gray-600 hover:border-rose-400"} ${d?"cursor-not-allowed opacity-60":""}`,children:"✗ False"})]}),b&&p&&!t.isExample&&r("p",{className:"text-sm font-medium text-emerald-600",children:["Đáp án đúng: ",c?"True":"False"]})]})]})}export function MoversTrueFalseRenderer({partNumber:l,partName:i,questionCount:n,instruction:d,imageUrl:m,questions:c,answers:g,onAnswerChange:p,isReviewMode:x=!1,correctAnswerTextMap:b={},groupContent:u}){const h=c.filter(e=>e.isExample),f=c.filter(e=>!e.isExample);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar",children:[r("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-2",children:[e(t,{partNumber:l,questionCount:n,partName:i,isReviewMode:x}),e(s,{instruction:d,isReviewMode:x}),m&&e("div",{className:"flex items-center justify-center",children:e(a,{src:m,alt:"Question illustration",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),u&&e("div",{className:"rounded-lg bg-amber-50 p-4 text-base leading-relaxed text-gray-800",dangerouslySetInnerHTML:{__html:u}}),h.length>0&&e("div",{className:"flex flex-col gap-4 mt-2",children:h.map(r=>e(o,{id:`question-${r.id}`,question:r,answer:g[r.id],onAnswerChange:p,isReviewMode:x,correctAnswerTextMap:b},r.id))})]}),h.length>0&&f.length>0&&e("div",{className:"px-3 sm:px-6",children:e("hr",{className:"border-t border-slate-200/60 my-1"})}),e("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6",children:f.map(r=>e("div",{id:`question-${r.id}`,className:"w-full rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:border-indigo-200 hover:shadow-md",children:e(o,{question:r,answer:g[r.id],onAnswerChange:p,isReviewMode:x,correctAnswerTextMap:b})},r.id))})]})}
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * TRUE_FALSE Renderer - Display questions with True/False buttons
4
+ * - Full-width 1-line-per-question layout
5
+ */
6
+ import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
7
+ import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
8
+ import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
9
+ // Single Question Component (1 Line / Full Width Row)
10
+ function QuestionItem({ question, answer, onAnswerChange, isReviewMode, correctAnswerTextMap, id, }) {
11
+ const isDisabled = isReviewMode || question.isExample;
12
+ const correctAnswerText = correctAnswerTextMap[question.id];
13
+ const correctAnswer = correctAnswerText === 'true' ? true : correctAnswerText === 'false' ? false : undefined;
14
+ const currentAnswer = question.isExample ? question.exampleCorrectAnswer : answer;
15
+ const hasCorrectAnswer = isReviewMode && correctAnswer !== undefined;
16
+ const isCorrect = hasCorrectAnswer && currentAnswer === correctAnswer;
17
+ const isWrong = hasCorrectAnswer && currentAnswer !== undefined && currentAnswer !== correctAnswer;
18
+ return (_jsxs("div", { id: id, className: `w-full rounded-2xl border p-4 sm:p-4.5 transition-all duration-200 ${question.isExample
19
+ ? 'border-amber-200 bg-gradient-to-r from-amber-50/70 via-orange-50/30 to-amber-50/50 shadow-sm'
20
+ : isCorrect
21
+ ? 'border-emerald-300 bg-emerald-50/30 shadow-sm'
22
+ : isWrong
23
+ ? 'border-rose-300 bg-rose-50/30 shadow-sm'
24
+ : currentAnswer !== undefined
25
+ ? 'border-blue-200 bg-blue-50/20 shadow-sm'
26
+ : 'border-slate-200/90 bg-white shadow-sm hover:border-blue-200 hover:shadow'}`, children: [_jsxs("div", { className: "flex flex-col md:flex-row md:items-center justify-between gap-3 sm:gap-4", children: [_jsxs("div", { className: "flex flex-1 items-start sm:items-center gap-3", children: [_jsx("span", { className: `flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-xs font-black text-white shadow-sm ${question.isExample
27
+ ? 'bg-gradient-to-br from-amber-400 to-orange-500'
28
+ : isCorrect
29
+ ? 'bg-emerald-500'
30
+ : isWrong
31
+ ? 'bg-rose-500'
32
+ : 'bg-blue-600'}`, children: question.questionNumber }), _jsxs("div", { className: "flex flex-1 flex-col sm:flex-row sm:items-center gap-2 sm:gap-3", children: [question.isExample && (_jsx("span", { className: "self-start sm:self-center rounded-full border border-amber-300 bg-amber-100/90 px-2.5 py-0.5 text-[10.5px] font-extrabold uppercase tracking-wider text-amber-800 flex-shrink-0", children: "EXAMPLE" })), question.imageUrl && (_jsx(ResolvedImage, { src: question.imageUrl, alt: `Q${question.questionNumber}`, className: "max-h-[80px] max-w-[120px] rounded-lg object-contain shadow-sm" })), _jsx("p", { className: "text-[15.5px] sm:text-[16.5px] font-medium leading-relaxed text-slate-800", children: question.question })] })] }), _jsxs("div", { className: "flex items-center gap-2.5 flex-shrink-0 self-end md:self-center pl-10 md:pl-0", children: [_jsx("button", { type: "button", disabled: isDisabled, onClick: () => onAnswerChange(question.id, true), className: `h-9 min-w-[90px] rounded-xl border-2 px-4 text-sm font-bold transition-all flex items-center justify-center gap-1 select-none ${currentAnswer === true
33
+ ? isReviewMode && isWrong && !question.isExample
34
+ ? 'border-rose-500 bg-rose-50 text-rose-700'
35
+ : 'border-emerald-500 bg-emerald-50 text-emerald-700 shadow-sm'
36
+ : hasCorrectAnswer && correctAnswer === true && !question.isExample
37
+ ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-2 ring-emerald-300'
38
+ : 'border-slate-200 bg-slate-50/80 text-slate-700 hover:border-emerald-400 hover:bg-emerald-50/50 hover:text-emerald-700'} ${isDisabled ? 'cursor-not-allowed opacity-70' : 'cursor-pointer'}`, children: "\u2713 True" }), _jsx("button", { type: "button", disabled: isDisabled, onClick: () => onAnswerChange(question.id, false), className: `h-9 min-w-[90px] rounded-xl border-2 px-4 text-sm font-bold transition-all flex items-center justify-center gap-1 select-none ${currentAnswer === false
39
+ ? isReviewMode && isWrong && !question.isExample
40
+ ? 'border-rose-500 bg-rose-50 text-rose-700'
41
+ : 'border-emerald-500 bg-emerald-50 text-emerald-700 shadow-sm'
42
+ : hasCorrectAnswer && correctAnswer === false && !question.isExample
43
+ ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-2 ring-emerald-300'
44
+ : 'border-slate-200 bg-slate-50/80 text-slate-700 hover:border-rose-400 hover:bg-rose-50/50 hover:text-rose-700'} ${isDisabled ? 'cursor-not-allowed opacity-70' : 'cursor-pointer'}`, children: "\u2717 False" })] })] }), isWrong && hasCorrectAnswer && !question.isExample && (_jsxs("div", { className: "mt-2.5 border-t border-slate-100 pt-2 flex items-center gap-2 text-xs font-semibold text-rose-600", children: [_jsxs("span", { children: ["H\u1ECDc sinh: ", currentAnswer ? 'True' : 'False'] }), _jsx("span", { children: "\u2022" }), _jsxs("span", { className: "text-emerald-700", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", correctAnswer ? 'True' : 'False'] })] }))] }));
45
+ }
46
+ export function MoversTrueFalseRenderer({ partNumber, partName, questionCount, instruction, imageUrl, questions, answers, onAnswerChange, isReviewMode = false, correctAnswerTextMap = {}, groupContent, }) {
47
+ // Separate example questions from regular questions
48
+ const exampleQuestions = questions.filter((q) => q.isExample);
49
+ const regularQuestions = questions.filter((q) => !q.isExample);
50
+ return (_jsxs("div", { className: "custom-scrollbar flex h-full flex-col gap-4 overflow-y-auto sm:gap-5 pb-6", children: [_jsxs("div", { className: "flex flex-col gap-3.5 p-3 sm:px-6 sm:pt-2", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode }), imageUrl && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(ResolvedImage, { src: imageUrl, alt: "Question illustration", className: "max-h-[300px] rounded-xl object-contain shadow-md" }) })), groupContent && (_jsx("div", { className: "rounded-xl border border-amber-200 bg-amber-50/60 p-4 text-[15.5px] leading-relaxed text-slate-800 shadow-sm", dangerouslySetInnerHTML: { __html: groupContent } })), exampleQuestions.length > 0 && (_jsx("div", { className: "mt-1 flex flex-col gap-3", children: exampleQuestions.map((question) => (_jsx(QuestionItem, { id: `question-${question.id}`, question: question, answer: answers[question.id], onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, correctAnswerTextMap: correctAnswerTextMap }, question.id))) }))] }), exampleQuestions.length > 0 && regularQuestions.length > 0 && (_jsx("div", { className: "px-3 sm:px-6", children: _jsx("hr", { className: "border-t border-dashed border-slate-200" }) })), _jsx("div", { className: "flex flex-col gap-3 px-3 sm:px-6", children: regularQuestions.map((question) => (_jsx(QuestionItem, { id: `question-${question.id}`, question: question, answer: answers[question.id], onAnswerChange: onAnswerChange, isReviewMode: isReviewMode, correctAnswerTextMap: correctAnswerTextMap }, question.id))) })] }));
51
+ }