@tinyweb_dev/oe-exam-sdk 0.1.27 → 0.1.29

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 (809) hide show
  1. package/README.md +79 -6
  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.d.ts +1 -0
  310. package/dist/components/questions/types/choose-the-correct-answer-group/index.js +3 -1
  311. package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.d.ts +4 -0
  312. package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +94 -0
  313. package/dist/components/questions/types/choose-the-correct-answer-group/register.js +36 -1
  314. package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +55 -1
  315. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +27 -1
  316. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +231 -1
  317. package/dist/components/questions/types/cross-out-word-group/index.d.ts +1 -0
  318. package/dist/components/questions/types/cross-out-word-group/index.js +5 -1
  319. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.d.ts +6 -0
  320. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +110 -0
  321. package/dist/components/questions/types/cross-out-word-group/register.js +36 -1
  322. package/dist/components/questions/types/cross-out-word-group/transform.js +67 -1
  323. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +275 -1
  324. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +464 -1
  325. package/dist/components/questions/types/fill-in-blank/index.js +2 -1
  326. package/dist/components/questions/types/fill-in-blank/register.js +148 -1
  327. package/dist/components/questions/types/fill-in-blank/transform.js +88 -1
  328. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +117 -1
  329. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +671 -1
  330. package/dist/components/questions/types/fill-missing-words-in-grid/index.js +2 -1
  331. package/dist/components/questions/types/fill-missing-words-in-grid/register.js +37 -1
  332. package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +15 -1
  333. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +262 -1
  334. package/dist/components/questions/types/gn-speaking-interview/register.js +121 -1
  335. package/dist/components/questions/types/gn-speaking-interview/transform.js +48 -1
  336. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +16 -1
  337. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +27 -1
  338. package/dist/components/questions/types/image-object-matching/index.js +2 -1
  339. package/dist/components/questions/types/image-object-matching/register.js +3 -1
  340. package/dist/components/questions/types/image-object-matching/transform.js +2 -1
  341. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +102 -1
  342. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +344 -1
  343. package/dist/components/questions/types/label-the-picture/index.js +2 -1
  344. package/dist/components/questions/types/label-the-picture/register.js +54 -1
  345. package/dist/components/questions/types/label-the-picture/transform.js +28 -1
  346. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +78 -1
  347. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +232 -1
  348. package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +2 -1
  349. package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +82 -1
  350. package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +27 -1
  351. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +70 -1
  352. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +386 -1
  353. package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +2 -1
  354. package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +100 -1
  355. package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +33 -1
  356. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +106 -1
  357. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +457 -1
  358. package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +2 -1
  359. package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +110 -1
  360. package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +35 -1
  361. package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +8 -1
  362. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +22 -1
  363. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +291 -1
  364. package/dist/components/questions/types/listen-and-speak-answer/index.js +2 -1
  365. package/dist/components/questions/types/listen-and-speak-answer/register.js +84 -1
  366. package/dist/components/questions/types/listen-and-speak-answer/transform.js +27 -1
  367. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +32 -1
  368. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +295 -1
  369. package/dist/components/questions/types/listen-and-speak-compare-images/register.js +79 -1
  370. package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +27 -1
  371. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +34 -1
  372. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +285 -1
  373. package/dist/components/questions/types/listen-and-speak-image-group/register.js +81 -1
  374. package/dist/components/questions/types/listen-and-speak-image-group/transform.js +26 -1
  375. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +38 -1
  376. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +385 -1
  377. package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +87 -1
  378. package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +32 -1
  379. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +26 -1
  380. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +247 -1
  381. package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +59 -1
  382. package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +18 -1
  383. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +26 -1
  384. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +256 -1
  385. package/dist/components/questions/types/listen-and-speak-question-list/register.js +81 -1
  386. package/dist/components/questions/types/listen-and-speak-question-list/transform.js +26 -1
  387. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +26 -1
  388. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +230 -1
  389. package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +56 -1
  390. package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +16 -1
  391. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +72 -1
  392. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +230 -1
  393. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
  394. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +66 -1
  395. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +42 -1
  396. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +96 -1
  397. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +238 -1
  398. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +2 -1
  399. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +76 -1
  400. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +19 -1
  401. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +134 -1
  402. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +617 -1
  403. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +2 -1
  404. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +82 -1
  405. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +29 -1
  406. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +38 -1
  407. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +359 -1
  408. package/dist/components/questions/types/match-by-writing-answer/index.js +3 -1
  409. package/dist/components/questions/types/match-by-writing-answer/register.js +58 -1
  410. package/dist/components/questions/types/match-by-writing-answer/transform.js +61 -1
  411. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +16 -1
  412. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +23 -1
  413. package/dist/components/questions/types/read-and-color-objects/index.js +2 -1
  414. package/dist/components/questions/types/read-and-color-objects/register.js +3 -1
  415. package/dist/components/questions/types/read-and-color-objects/transform.js +36 -1
  416. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +125 -1
  417. package/dist/components/questions/types/read-displayed-content/register.js +64 -1
  418. package/dist/components/questions/types/read-displayed-content/transform.js +12 -1
  419. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +65 -1
  420. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +511 -1
  421. package/dist/components/questions/types/read-passage-and-answer-questions/index.js +2 -1
  422. package/dist/components/questions/types/read-passage-and-answer-questions/register.js +58 -1
  423. package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +28 -1
  424. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +373 -1
  425. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +41 -1
  426. package/dist/components/questions/types/speaking-conversation/register.js +110 -1
  427. package/dist/components/questions/types/speaking-conversation/transform.js +34 -1
  428. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +74 -1
  429. package/dist/components/questions/types/speaking-cue-card/register.js +52 -1
  430. package/dist/components/questions/types/speaking-cue-card/transform.js +12 -1
  431. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +10 -1
  432. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +161 -1
  433. package/dist/components/questions/types/speaking-describe-image/index.js +2 -1
  434. package/dist/components/questions/types/speaking-describe-image/register.js +69 -1
  435. package/dist/components/questions/types/speaking-describe-image/transform.js +16 -1
  436. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +234 -1
  437. package/dist/components/questions/types/spontaneous-qa/register.js +93 -1
  438. package/dist/components/questions/types/spontaneous-qa/transform.js +34 -1
  439. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.d.ts +2 -0
  440. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +9 -0
  441. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.d.ts +2 -0
  442. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +179 -0
  443. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.d.ts +5 -0
  444. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.js +43 -0
  445. package/dist/components/questions/types/spontaneous-qa-group/flatten.d.ts +14 -0
  446. package/dist/components/questions/types/spontaneous-qa-group/flatten.js +69 -0
  447. package/dist/components/questions/types/spontaneous-qa-group/index.d.ts +2 -0
  448. package/dist/components/questions/types/spontaneous-qa-group/index.js +2 -0
  449. package/dist/components/questions/types/spontaneous-qa-group/register.d.ts +2 -0
  450. package/dist/components/questions/types/spontaneous-qa-group/register.js +139 -0
  451. package/dist/components/questions/types/spontaneous-qa-group/transform.d.ts +2 -0
  452. package/dist/components/questions/types/spontaneous-qa-group/transform.js +52 -0
  453. package/dist/components/questions/types/true-false/TrueFalseClient.js +75 -1
  454. package/dist/components/questions/types/true-false/TrueFalseCreator.js +244 -1
  455. package/dist/components/questions/types/true-false/index.js +2 -1
  456. package/dist/components/questions/types/true-false/register.js +77 -1
  457. package/dist/components/questions/types/true-false/transform.js +32 -1
  458. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +25 -1
  459. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +129 -1
  460. package/dist/components/questions/types/true-false-group/index.d.ts +1 -0
  461. package/dist/components/questions/types/true-false-group/index.js +5 -1
  462. package/dist/components/questions/types/true-false-group/map-true-false-group-data.d.ts +4 -0
  463. package/dist/components/questions/types/true-false-group/map-true-false-group-data.js +69 -0
  464. package/dist/components/questions/types/true-false-group/register.js +36 -1
  465. package/dist/components/questions/types/true-false-group/transform.js +43 -1
  466. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +233 -1
  467. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +631 -1
  468. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +28 -1
  469. package/dist/components/questions/types/word-fill-paragraph/index.js +2 -1
  470. package/dist/components/questions/types/word-fill-paragraph/register.js +136 -1
  471. package/dist/components/questions/types/word-fill-paragraph/transform.js +56 -1
  472. package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.js +86 -1
  473. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +246 -1
  474. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.d.ts +2 -0
  475. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +484 -1
  476. package/dist/components/questions/types/word-fill-structured-form/index.d.ts +1 -0
  477. package/dist/components/questions/types/word-fill-structured-form/index.js +3 -1
  478. package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.d.ts +7 -0
  479. package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.js +113 -0
  480. package/dist/components/questions/types/word-fill-structured-form/register.js +36 -1
  481. package/dist/components/questions/types/word-fill-structured-form/transform.js +77 -1
  482. package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.js +110 -1
  483. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.d.ts +3 -0
  484. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +190 -0
  485. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.d.ts +3 -0
  486. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +182 -0
  487. package/dist/components/questions/types/word-order-and-match-group/index.d.ts +4 -0
  488. package/dist/components/questions/types/word-order-and-match-group/index.js +4 -0
  489. package/dist/components/questions/types/word-order-and-match-group/register.d.ts +2 -0
  490. package/dist/components/questions/types/word-order-and-match-group/register.js +121 -0
  491. package/dist/components/questions/types/word-order-and-match-group/transform.d.ts +2 -0
  492. package/dist/components/questions/types/word-order-and-match-group/transform.js +70 -0
  493. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +84 -1
  494. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +192 -1
  495. package/dist/components/questions/types/word-ordering/index.js +2 -1
  496. package/dist/components/questions/types/word-ordering/register.js +46 -1
  497. package/dist/components/questions/types/word-ordering/transform.js +24 -1
  498. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +99 -1
  499. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +320 -1
  500. package/dist/components/questions/types/write-a-short-letter/index.js +2 -1
  501. package/dist/components/questions/types/write-a-short-letter/register.js +68 -1
  502. package/dist/components/questions/types/write-a-short-letter/transform.js +25 -1
  503. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +61 -1
  504. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +196 -1
  505. package/dist/components/questions/types/write-correct-verb-form/index.js +2 -1
  506. package/dist/components/questions/types/write-correct-verb-form/register.js +62 -1
  507. package/dist/components/questions/types/write-correct-verb-form/transform.js +17 -1
  508. package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +22 -1
  509. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +174 -1
  510. package/dist/components/questions/types/write-sentences/index.js +2 -1
  511. package/dist/components/questions/types/write-sentences/register.js +58 -1
  512. package/dist/components/questions/types/write-sentences/transform.js +28 -1
  513. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +96 -1
  514. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +161 -1
  515. package/dist/components/questions/types/write-short-paragraph/index.js +2 -1
  516. package/dist/components/questions/types/write-short-paragraph/register.js +4 -1
  517. package/dist/components/questions/types/write-short-paragraph/transform.js +21 -1
  518. package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.d.ts +8 -0
  519. package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.js +11 -0
  520. package/dist/components/questions/viewer/CrossOutWordGroupViewer.d.ts +7 -0
  521. package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +8 -0
  522. package/dist/components/questions/viewer/QuestionGroupViewer.js +36 -1
  523. package/dist/components/questions/viewer/QuestionViewer.js +692 -1
  524. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +5 -0
  525. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +82 -0
  526. package/dist/components/questions/viewer/TrueFalseGroupViewer.d.ts +8 -0
  527. package/dist/components/questions/viewer/TrueFalseGroupViewer.js +11 -0
  528. package/dist/components/questions/viewer/WordFillStructuredFormViewer.d.ts +9 -0
  529. package/dist/components/questions/viewer/WordFillStructuredFormViewer.js +14 -0
  530. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +6 -0
  531. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +95 -0
  532. package/dist/components/questions/viewer/index.d.ts +6 -0
  533. package/dist/components/questions/viewer/index.js +8 -1
  534. package/dist/components/results/ResultReviewPageContainer.js +220 -1
  535. package/dist/components/results/ReviewQuestionRenderer.js +55 -1
  536. package/dist/components/results/hooks/useResultReviewPolling.js +76 -1
  537. package/dist/components/results/index.js +22 -1
  538. package/dist/components/results/renderers/QuestionExplanations.js +19 -1
  539. package/dist/components/results/renderers/ReviewChooseAdjectiveRenderer.js +94 -1
  540. package/dist/components/results/renderers/ReviewChooseBestAnswerRenderer.js +75 -1
  541. package/dist/components/results/renderers/ReviewColoringRenderer.js +110 -1
  542. package/dist/components/results/renderers/ReviewListenAndWriteRenderer.js +48 -1
  543. package/dist/components/results/renderers/ReviewListenChooseAnswerGroupRenderer.js +87 -1
  544. package/dist/components/results/renderers/ReviewListenChooseObjectsRenderer.js +104 -1
  545. package/dist/components/results/renderers/ReviewListenDragObjectsRenderer.js +123 -1
  546. package/dist/components/results/renderers/ReviewListeningHeader.js +104 -1
  547. package/dist/components/results/renderers/ReviewSpeakingAIPanel.js +116 -1
  548. package/dist/components/results/renderers/ReviewSpeakingMedia.js +48 -1
  549. package/dist/components/results/renderers/ReviewSpeakingQuestionItem.js +42 -1
  550. package/dist/components/results/renderers/ReviewSpeakingRenderer.js +12 -1
  551. package/dist/components/results/renderers/ReviewSpeakingRenderer.types.js +85 -1
  552. package/dist/components/results/renderers/review-question-body-dedicated.js +104 -1
  553. package/dist/components/results/renderers/review-question-body-movers.js +148 -1
  554. package/dist/components/results/renderers/review-speaking-map.js +226 -1
  555. package/dist/components/results/renderers/review-spontaneous-qa-group.d.ts +4 -0
  556. package/dist/components/results/renderers/review-spontaneous-qa-group.js +74 -0
  557. package/dist/components/results/report/BadgeTitle.js +5 -1
  558. package/dist/components/results/report/ExamSkillRow.js +20 -1
  559. package/dist/components/results/report/OceanEduExamReport.js +58 -1
  560. package/dist/components/results/report/OceanEduSpeakingReport.js +62 -1
  561. package/dist/components/results/report/OverallAssessmentSection.js +17 -1
  562. package/dist/components/results/report/ResultErrorState.js +18 -1
  563. package/dist/components/results/report/ResultLoadingState.js +10 -1
  564. package/dist/components/results/report/ResultNotPublicState.js +27 -1
  565. package/dist/components/results/report/SpeakingReportParts.js +14 -1
  566. package/dist/components/results/report/SpeakingReportShared.js +86 -1
  567. package/dist/components/results/report/SpeakingRubricSection.js +171 -1
  568. package/dist/components/results/report/speaking-report.utils.js +198 -1
  569. package/dist/components/results/result-review.utils.js +6 -1
  570. package/dist/components/results/review-data.js +222 -1
  571. package/dist/components/results/review-renderer.utils.js +97 -1
  572. package/dist/components/results/review-status.utils.js +36 -1
  573. package/dist/components/results/review-types.js +1 -1
  574. package/dist/components/results/speaking/SpeakingResultAudioPlayer.js +77 -1
  575. package/dist/components/results/speaking/SpeakingReviewResult.js +48 -1
  576. package/dist/components/results/utils/review-score.utils.js +72 -1
  577. package/dist/components/results/utils/speaking-summary.js +224 -1
  578. package/dist/components/results/utils/transform-speaking-review.js +183 -1
  579. package/dist/components/shared/RichTextEditor.d.ts +9 -0
  580. package/dist/components/shared/RichTextEditor.js +47 -0
  581. package/dist/components/shared/audio/SpeakingAudioPlayer.js +100 -1
  582. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +140 -1
  583. package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +10 -1
  584. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.d.ts +1 -1
  585. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +18 -1
  586. package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +11 -1
  587. package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +11 -1
  588. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.d.ts +2 -1
  589. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +19 -1
  590. package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +13 -1
  591. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.d.ts +1 -1
  592. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +3 -1
  593. package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +6 -1
  594. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +5 -1
  595. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +9 -1
  596. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.d.ts +2 -1
  597. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +61 -1
  598. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.d.ts +1 -1
  599. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +25 -1
  600. package/dist/components/themes/cambridge-yle/index.js +13 -1
  601. package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +25 -1
  602. package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +89 -1
  603. package/dist/components/themes/english-certification/EcWordFillParagraph.js +56 -1
  604. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +192 -1
  605. package/dist/components/themes/english-certification/EcWritingTask.js +60 -1
  606. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +108 -1
  607. package/dist/components/themes/english-certification/EnglishCertificationBrand.js +11 -1
  608. package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +34 -1
  609. package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +15 -1
  610. package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +19 -1
  611. package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +166 -1
  612. package/dist/components/themes/english-certification/EnglishCertificationHeader.js +31 -1
  613. package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.js +79 -1
  614. package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +71 -1
  615. package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +79 -1
  616. package/dist/components/themes/english-certification/EnglishCertificationPartHeader.js +47 -1
  617. package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +77 -1
  618. package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +25 -1
  619. package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +36 -1
  620. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +81 -1
  621. package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +95 -1
  622. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +18 -1
  623. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +32 -1
  624. package/dist/components/themes/english-certification/english-cert-scroll.js +163 -1
  625. package/dist/components/themes/english-certification/english-certification-theme.js +58 -1
  626. package/dist/components/themes/english-certification/grouped-question-utils.js +243 -1
  627. package/dist/components/themes/english-certification/index.js +24 -1
  628. package/dist/components/themes/index.js +25 -1
  629. package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +170 -1
  630. package/dist/components/themes/summer-sky/SummerSkyExitModal.js +21 -1
  631. package/dist/components/themes/summer-sky/SummerSkyLayout.js +221 -1
  632. package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +18 -1
  633. package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +193 -1
  634. package/dist/components/themes/types.js +1 -1
  635. package/dist/components/ui/alert-dialog.js +26 -1
  636. package/dist/components/ui/alert.js +22 -1
  637. package/dist/components/ui/avatar.js +12 -1
  638. package/dist/components/ui/badge.js +38 -1
  639. package/dist/components/ui/button.js +35 -1
  640. package/dist/components/ui/calendar.js +76 -1
  641. package/dist/components/ui/card.js +16 -1
  642. package/dist/components/ui/carousel.js +91 -1
  643. package/dist/components/ui/checkbox.js +9 -1
  644. package/dist/components/ui/collapsible.js +13 -1
  645. package/dist/components/ui/command.js +34 -1
  646. package/dist/components/ui/confirm-dialog.js +49 -1
  647. package/dist/components/ui/dialog.js +23 -1
  648. package/dist/components/ui/drawer.js +35 -1
  649. package/dist/components/ui/dropdown-menu.js +33 -1
  650. package/dist/components/ui/file-upload.js +155 -1
  651. package/dist/components/ui/form.js +62 -1
  652. package/dist/components/ui/hover-card.js +10 -1
  653. package/dist/components/ui/image-preview.js +29 -1
  654. package/dist/components/ui/input.js +8 -1
  655. package/dist/components/ui/label.js +9 -1
  656. package/dist/components/ui/language-switcher.js +15 -1
  657. package/dist/components/ui/multi-select.js +90 -1
  658. package/dist/components/ui/points-input.js +33 -1
  659. package/dist/components/ui/popover.js +26 -1
  660. package/dist/components/ui/progress.js +16 -1
  661. package/dist/components/ui/radio-group.js +12 -1
  662. package/dist/components/ui/scroll-area.js +11 -1
  663. package/dist/components/ui/select.js +38 -1
  664. package/dist/components/ui/separator.js +8 -1
  665. package/dist/components/ui/sheet.js +40 -1
  666. package/dist/components/ui/single-select.js +76 -1
  667. package/dist/components/ui/skeleton.js +6 -1
  668. package/dist/components/ui/switch.js +8 -1
  669. package/dist/components/ui/table.js +20 -1
  670. package/dist/components/ui/tabs.js +17 -1
  671. package/dist/components/ui/textarea.js +8 -1
  672. package/dist/components/ui/tooltip.js +11 -1
  673. package/dist/index.d.ts +3 -1
  674. package/dist/index.js +24 -1
  675. package/dist/shared/constants/ApiConstant.d.ts +1 -0
  676. package/dist/shared/constants/ApiConstant.js +278 -1
  677. package/dist/shared/constants/QueryKeyConstant.js +112 -1
  678. package/dist/shared/constants/exam-level.enum.js +41 -1
  679. package/dist/shared/constants/landings/placement-test.constants.js +431 -1
  680. package/dist/shared/constants/question-skills.js +277 -1
  681. package/dist/shared/constants/routes.js +81 -1
  682. package/dist/shared/index.js +10 -1
  683. package/dist/shared/lib/hooks/index.js +10 -1
  684. package/dist/shared/lib/hooks/useAlertDialog.js +57 -1
  685. package/dist/shared/lib/hooks/useAudioPlayCounter.js +30 -1
  686. package/dist/shared/lib/hooks/useAudioPreview.js +81 -1
  687. package/dist/shared/lib/hooks/useAudioUpload.js +24 -1
  688. package/dist/shared/lib/hooks/useConfirmDialog.js +89 -1
  689. package/dist/shared/lib/hooks/useDebouncedCallback.js +32 -1
  690. package/dist/shared/lib/hooks/useDelayedAutoPlay.js +12 -1
  691. package/dist/shared/lib/hooks/useFileUpload.js +24 -1
  692. package/dist/shared/lib/hooks/useImageUrl.js +5 -1
  693. package/dist/shared/lib/hooks/usePresignedFileUrl.js +108 -1
  694. package/dist/shared/lib/hooks/useReactHookForm.js +31 -1
  695. package/dist/shared/lib/hooks/useToast.js +62 -1
  696. package/dist/shared/lib/html-content.js +22 -1
  697. package/dist/shared/lib/i18n/index.js +54 -1
  698. package/dist/shared/lib/i18n/messages/en/admin.d.ts +11 -4
  699. package/dist/shared/lib/i18n/messages/en/admin.js +2111 -1
  700. package/dist/shared/lib/i18n/messages/en/auth.js +86 -1
  701. package/dist/shared/lib/i18n/messages/en/common.js +140 -1
  702. package/dist/shared/lib/i18n/messages/en/file-upload.js +18 -1
  703. package/dist/shared/lib/i18n/messages/en/student.js +133 -1
  704. package/dist/shared/lib/i18n/messages/en/terms.js +37 -1
  705. package/dist/shared/lib/i18n/messages/en.d.ts +11 -4
  706. package/dist/shared/lib/i18n/messages/en.js +15 -1
  707. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +11 -4
  708. package/dist/shared/lib/i18n/messages/vi/admin.js +2111 -1
  709. package/dist/shared/lib/i18n/messages/vi/auth.js +86 -1
  710. package/dist/shared/lib/i18n/messages/vi/common.js +140 -1
  711. package/dist/shared/lib/i18n/messages/vi/file-upload.js +18 -1
  712. package/dist/shared/lib/i18n/messages/vi/student.js +133 -1
  713. package/dist/shared/lib/i18n/messages/vi/terms.js +37 -1
  714. package/dist/shared/lib/i18n/messages/vi.d.ts +11 -4
  715. package/dist/shared/lib/i18n/messages/vi.js +15 -1
  716. package/dist/shared/lib/i18n/types.js +1 -1
  717. package/dist/shared/lib/stores/examQuestionStore.js +212 -1
  718. package/dist/shared/lib/stores/examTakingStore.js +240 -1
  719. package/dist/shared/lib/stores/gradingTransientStore.js +39 -1
  720. package/dist/shared/lib/stores/localeStore.js +10 -1
  721. package/dist/shared/lib/themes/config/starters.config.js +71 -1
  722. package/dist/shared/lib/themes/index.js +49 -1
  723. package/dist/shared/lib/themes/types.js +2 -1
  724. package/dist/shared/lib/toast.js +43 -1
  725. package/dist/shared/lib/utils/public-page.js +44 -1
  726. package/dist/shared/lib/utils/question-reverse-transform.js +438 -1
  727. package/dist/shared/lib/utils/question-transform-types.js +1 -1
  728. package/dist/shared/lib/utils/question-transform-validation.js +194 -1
  729. package/dist/shared/lib/utils/question-transform.js +199 -1
  730. package/dist/shared/lib/utils.js +168 -1
  731. package/dist/shared/lib/validation/choose-correct-answer.validation.js +111 -1
  732. package/dist/shared/lib/validation/label-the-picture.validation.js +19 -1
  733. package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +46 -1
  734. package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +21 -1
  735. package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +34 -1
  736. package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +40 -1
  737. package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +45 -1
  738. package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +19 -1
  739. package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +39 -1
  740. package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +32 -1
  741. package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +19 -1
  742. package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +28 -1
  743. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +12 -1
  744. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +47 -1
  745. package/dist/shared/lib/validation/read-and-color-objects.validation.js +29 -1
  746. package/dist/shared/lib/validation/read-displayed-content.validation.js +28 -1
  747. package/dist/shared/lib/validation/speaking-conversation.validation.js +75 -1
  748. package/dist/shared/lib/validation/speaking-describe-image.validation.js +31 -1
  749. package/dist/shared/lib/validation/spontaneous-qa.validation.js +48 -1
  750. package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +38 -1
  751. package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +39 -1
  752. package/dist/shared/lib/validation/word-fill-paragraph.validation.js +43 -1
  753. package/dist/shared/lib/validation/word-ordering.validation.js +33 -1
  754. package/dist/shared/types/branch.types.js +6 -1
  755. package/dist/shared/types/common.types.d.ts +1 -1
  756. package/dist/shared/types/common.types.js +49 -1
  757. package/dist/shared/types/entities/exam-schedule.types.js +5 -1
  758. package/dist/shared/types/entities/exam.types.js +1 -1
  759. package/dist/shared/types/entities/question.types.js +4 -1
  760. package/dist/shared/types/entities/result.types.js +4 -1
  761. package/dist/shared/types/entities/user.types.js +4 -1
  762. package/dist/shared/types/exam-taking.types.js +2 -1
  763. package/dist/shared/types/history.types.js +34 -1
  764. package/dist/shared/types/index.js +1 -1
  765. package/dist/shared/types/questions/choose-correct-adjective.js +4 -1
  766. package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +1 -0
  767. package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -1
  768. package/dist/shared/types/questions/choose-the-correct-answer.js +9 -1
  769. package/dist/shared/types/questions/cross-out-word-group.d.ts +2 -0
  770. package/dist/shared/types/questions/cross-out-word-group.js +1 -1
  771. package/dist/shared/types/questions/fill-missing-words-in-grid.js +11 -1
  772. package/dist/shared/types/questions/index.d.ts +1 -0
  773. package/dist/shared/types/questions/index.js +46 -1
  774. package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
  775. package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
  776. package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
  777. package/dist/shared/types/questions/listen-and-speak-info-exchange.js +3 -1
  778. package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +3 -1
  779. package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
  780. package/dist/shared/types/questions/listen-and-speak-with-story-images.js +3 -1
  781. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +5 -1
  782. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +9 -1
  783. package/dist/shared/types/questions/look-picture-fill-word-hint.js +7 -1
  784. package/dist/shared/types/questions/read-displayed-content.js +1 -1
  785. package/dist/shared/types/questions/speaking-conversation.js +7 -1
  786. package/dist/shared/types/questions/speaking-describe-image.js +1 -1
  787. package/dist/shared/types/questions/spontaneous-qa.js +1 -1
  788. package/dist/shared/types/questions/word-order-and-match-group.d.ts +33 -0
  789. package/dist/shared/types/questions/word-order-and-match-group.js +1 -0
  790. package/dist/shared/types/questions/write-correct-verb-form.js +12 -1
  791. package/dist/shared/types/role.types.js +1 -1
  792. package/dist/shared/types/structure-management.js +28 -1
  793. package/dist/shared/types/student.types.js +57 -1
  794. package/dist/shared/types/teacher-dashboard-rooms.js +2 -1
  795. package/package.json +184 -165
  796. package/dist/mcp/config.d.ts +0 -12
  797. package/dist/mcp/config.js +0 -1
  798. package/dist/mcp/http-client.d.ts +0 -6
  799. package/dist/mcp/http-client.js +0 -1
  800. package/dist/mcp/index.d.ts +0 -6
  801. package/dist/mcp/index.js +0 -2
  802. package/dist/mcp/tools/_helpers.d.ts +0 -4
  803. package/dist/mcp/tools/_helpers.js +0 -1
  804. package/dist/mcp/tools/exams.d.ts +0 -2
  805. package/dist/mcp/tools/exams.js +0 -1
  806. package/dist/mcp/tools/index.d.ts +0 -2
  807. package/dist/mcp/tools/index.js +0 -1
  808. package/dist/mcp/tools/results.d.ts +0 -2
  809. package/dist/mcp/tools/results.js +0 -1
@@ -1 +1,77 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useCallback as r,useRef as a,useState as n}from"react";import{Loader2 as i,Mic as s,Pause as l,Play as o,RefreshCw as d}from"lucide-react";import{usePresignedFileUrl as u}from"../../../shared/lib/hooks/usePresignedFileUrl";import{cn as c}from"../../../shared/lib/utils";function m(e){if(!isFinite(e)||isNaN(e))return"--:--";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`}export function SpeakingResultAudioPlayer({audioKey:h,variant:b="student",token:g=null}){const{previewUrl:p,isLoading:x,error:f}=u(h),w=a(null),[y,N]=n(!1),[v,k]=n(0),[_,A]=n(0),j=r(()=>{const e=w.current;e&&p&&(y?e.pause():e.play().catch(e=>{console.error("Audio play failed:",e)}))},[y,p]),T=r(e=>{const t=w.current;if(!t)return;const r=Number(e.target.value);t.currentTime=r,k(r)},[]),P=r(()=>{const e=w.current;e&&k(e.currentTime)},[]),M=r(()=>{const e=w.current;e&&A(e.duration||0)},[]),S=r(()=>{N(!1),k(0);const e=w.current;e&&(e.currentTime=0)},[]),U=_>0?v/_*100:0,$="admin"===b;return t("div",x?{className:c("flex items-center justify-center gap-2 rounded-xl px-4 py-3.5",$?"bg-gray-100":"bg-gradient-to-r from-[#2874A6] to-[#3498DB]"),children:[e(i,{className:c("h-4 w-4 animate-spin",$?"text-gray-500":"text-white/80")}),e("span",{className:c("text-sm font-medium",$?"text-gray-600":"text-white/80"),children:"Đang tải âm thanh..."})]}:f||!p?{className:"flex items-center gap-2.5 rounded-xl border border-red-200 bg-red-50 px-4 py-3",children:[e(d,{className:"h-4 w-4 text-red-400"}),e("span",{className:"text-sm font-medium text-red-600",children:"Không thể phát âm thanh"})]}:{className:"overflow-hidden rounded-2xl border border-gray-100 bg-white shadow-[0_2px_12px_rgba(0,0,0,0.02)] transition-all hover:shadow-[0_4px_16px_rgba(0,0,0,0.04)] ring-1 ring-gray-900/5",children:[e("audio",{ref:w,src:p,onPlay:()=>N(!0),onPause:()=>N(!1),onTimeUpdate:P,onLoadedMetadata:M,onEnded:S,preload:"metadata"}),t("div",{className:"flex items-center gap-3 px-4 py-3",children:[e("div",{className:c("flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-all",y?"bg-blue-50 ring-4 ring-blue-50/50":"bg-gray-50"),children:e(s,{className:c("h-4 w-4 transition-transform",y?"text-[#2874A6] animate-pulse":"text-gray-400")})}),e("button",{type:"button",onClick:j,className:c("flex h-10 w-10 shrink-0 items-center justify-center rounded-full shadow-sm transition-all active:scale-95",$?y?"bg-gray-600 text-white hover:bg-gray-700":"bg-gray-500 text-white hover:bg-gray-600":y?"bg-[#1A5276] text-white hover:bg-[#154360]":"bg-[#2874A6] text-white hover:bg-[#1A5276]"),"aria-label":y?"Tạm dừng":"Phát",children:y?e(l,{className:"h-4 w-4"}):e(o,{className:"h-4 w-4 ml-0.5"})}),t("div",{className:"flex flex-1 flex-col gap-1.5 px-2",children:[t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-[10px] font-bold tabular-nums text-gray-500 tracking-wide",children:m(v)}),e("span",{className:"text-[10px] font-bold tabular-nums text-gray-400 tracking-wide",children:_>0?m(_):"--:--"})]}),t("div",{className:"relative flex h-2 items-center",children:[e("input",{type:"range",min:0,max:_||1,step:.1,value:v,onChange:T,className:c("absolute inset-0 z-10 h-1.5 w-full cursor-pointer appearance-none rounded-full bg-transparent","[&::-webkit-slider-thumb]:h-3.5 [&::-webkit-slider-thumb]:w-3.5","[&::-webkit-slider-thumb]:appearance-none","[&::-webkit-slider-thumb]:rounded-full","[&::-webkit-slider-thumb]:bg-white","[&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(0,0,0,0.2)]","[&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-gray-200","[&::-webkit-slider-thumb]:transition-transform","[&::-webkit-slider-thumb]:hover:scale-110"),"aria-label":"Tiến trình phát"}),e("div",{className:"pointer-events-none absolute left-0 right-0 h-1.5 rounded-full bg-gray-100"}),e("div",{className:c("pointer-events-none absolute left-0 h-1.5 rounded-full transition-all duration-100 ease-linear",$?"bg-blue-500":"bg-gradient-to-r from-[#2874A6] to-[#3498DB]"),style:{width:`${U}%`}})]})]})]})]})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useRef, useState } from 'react';
4
+ import { Loader2, Mic, Pause, Play, RefreshCw } from 'lucide-react';
5
+ import { usePresignedFileUrl } from '../../../shared/lib/hooks/usePresignedFileUrl';
6
+ import { cn } from '../../../shared/lib/utils';
7
+ function formatTime(seconds) {
8
+ if (!isFinite(seconds) || isNaN(seconds))
9
+ return '--:--';
10
+ const mins = Math.floor(seconds / 60);
11
+ const secs = Math.floor(seconds % 60);
12
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
13
+ }
14
+ export function SpeakingResultAudioPlayer({ audioKey, variant = 'student', token: _token = null, }) {
15
+ // Default SDK hook is a pass-through; hosts can wrap usePresignedFileUrl for token-aware resolve.
16
+ void _token;
17
+ const { previewUrl, isLoading, error } = usePresignedFileUrl(audioKey);
18
+ const audioRef = useRef(null);
19
+ const [isPlaying, setIsPlaying] = useState(false);
20
+ const [currentTime, setCurrentTime] = useState(0);
21
+ const [duration, setDuration] = useState(0);
22
+ const handlePlayPause = useCallback(() => {
23
+ const audio = audioRef.current;
24
+ if (!audio || !previewUrl)
25
+ return;
26
+ if (isPlaying) {
27
+ audio.pause();
28
+ }
29
+ else {
30
+ audio.play().catch((err) => {
31
+ console.error('Audio play failed:', err);
32
+ });
33
+ }
34
+ }, [isPlaying, previewUrl]);
35
+ const handleSeek = useCallback((e) => {
36
+ const audio = audioRef.current;
37
+ if (!audio)
38
+ return;
39
+ const newTime = Number(e.target.value);
40
+ audio.currentTime = newTime;
41
+ setCurrentTime(newTime);
42
+ }, []);
43
+ const handleTimeUpdate = useCallback(() => {
44
+ const audio = audioRef.current;
45
+ if (!audio)
46
+ return;
47
+ setCurrentTime(audio.currentTime);
48
+ }, []);
49
+ const handleLoadedMetadata = useCallback(() => {
50
+ const audio = audioRef.current;
51
+ if (!audio)
52
+ return;
53
+ setDuration(audio.duration || 0);
54
+ }, []);
55
+ const handleEnded = useCallback(() => {
56
+ setIsPlaying(false);
57
+ setCurrentTime(0);
58
+ const audio = audioRef.current;
59
+ if (audio)
60
+ audio.currentTime = 0;
61
+ }, []);
62
+ const progressPercent = duration > 0 ? (currentTime / duration) * 100 : 0;
63
+ const isAdminVariant = variant === 'admin';
64
+ if (isLoading) {
65
+ return (_jsxs("div", { className: cn('flex items-center justify-center gap-2 rounded-xl px-4 py-3.5', isAdminVariant ? 'bg-gray-100' : 'bg-gradient-to-r from-[#2874A6] to-[#3498DB]'), children: [_jsx(Loader2, { className: cn('h-4 w-4 animate-spin', isAdminVariant ? 'text-gray-500' : 'text-white/80') }), _jsx("span", { className: cn('text-sm font-medium', isAdminVariant ? 'text-gray-600' : 'text-white/80'), children: "\u0110ang t\u1EA3i \u00E2m thanh..." })] }));
66
+ }
67
+ if (error || !previewUrl) {
68
+ return (_jsxs("div", { className: "flex items-center gap-2.5 rounded-xl border border-red-200 bg-red-50 px-4 py-3", children: [_jsx(RefreshCw, { className: "h-4 w-4 text-red-400" }), _jsx("span", { className: "text-sm font-medium text-red-600", children: "Kh\u00F4ng th\u1EC3 ph\u00E1t \u00E2m thanh" })] }));
69
+ }
70
+ return (_jsxs("div", { className: "overflow-hidden rounded-2xl border border-gray-100 bg-white shadow-[0_2px_12px_rgba(0,0,0,0.02)] transition-all hover:shadow-[0_4px_16px_rgba(0,0,0,0.04)] ring-1 ring-gray-900/5", children: [_jsx("audio", { ref: audioRef, src: previewUrl, onPlay: () => setIsPlaying(true), onPause: () => setIsPlaying(false), onTimeUpdate: handleTimeUpdate, onLoadedMetadata: handleLoadedMetadata, onEnded: handleEnded, preload: "metadata" }), _jsxs("div", { className: "flex items-center gap-3 px-4 py-3", children: [_jsx("div", { className: cn('flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-all', isPlaying ? 'bg-blue-50 ring-4 ring-blue-50/50' : 'bg-gray-50'), children: _jsx(Mic, { className: cn('h-4 w-4 transition-transform', isPlaying ? 'text-[#2874A6] animate-pulse' : 'text-gray-400') }) }), _jsx("button", { type: "button", onClick: handlePlayPause, className: cn('flex h-10 w-10 shrink-0 items-center justify-center rounded-full shadow-sm transition-all active:scale-95', isAdminVariant
71
+ ? isPlaying
72
+ ? 'bg-gray-600 text-white hover:bg-gray-700'
73
+ : 'bg-gray-500 text-white hover:bg-gray-600'
74
+ : isPlaying
75
+ ? 'bg-[#1A5276] text-white hover:bg-[#154360]'
76
+ : 'bg-[#2874A6] text-white hover:bg-[#1A5276]'), "aria-label": isPlaying ? 'Tạm dừng' : 'Phát', children: isPlaying ? _jsx(Pause, { className: "h-4 w-4" }) : _jsx(Play, { className: "h-4 w-4 ml-0.5" }) }), _jsxs("div", { className: "flex flex-1 flex-col gap-1.5 px-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-[10px] font-bold tabular-nums text-gray-500 tracking-wide", children: formatTime(currentTime) }), _jsx("span", { className: "text-[10px] font-bold tabular-nums text-gray-400 tracking-wide", children: duration > 0 ? formatTime(duration) : '--:--' })] }), _jsxs("div", { className: "relative flex h-2 items-center", children: [_jsx("input", { type: "range", min: 0, max: duration || 1, step: 0.1, value: currentTime, onChange: handleSeek, className: cn('absolute inset-0 z-10 h-1.5 w-full cursor-pointer appearance-none rounded-full bg-transparent', '[&::-webkit-slider-thumb]:h-3.5 [&::-webkit-slider-thumb]:w-3.5', '[&::-webkit-slider-thumb]:appearance-none', '[&::-webkit-slider-thumb]:rounded-full', '[&::-webkit-slider-thumb]:bg-white', '[&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(0,0,0,0.2)]', '[&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-gray-200', '[&::-webkit-slider-thumb]:transition-transform', '[&::-webkit-slider-thumb]:hover:scale-110'), "aria-label": "Ti\u1EBFn tr\u00ECnh ph\u00E1t" }), _jsx("div", { className: "pointer-events-none absolute left-0 right-0 h-1.5 rounded-full bg-gray-100" }), _jsx("div", { className: cn('pointer-events-none absolute left-0 h-1.5 rounded-full transition-all duration-100 ease-linear', isAdminVariant ? 'bg-blue-500' : 'bg-gradient-to-r from-[#2874A6] to-[#3498DB]'), style: { width: `${progressPercent}%` } })] })] })] })] }));
77
+ }
@@ -1 +1,48 @@
1
- "use client";import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{useMemo as s,useState as r}from"react";import{AlertTriangle as i,ChevronLeft as n,Download as l,Loader2 as o,Sparkles as d}from"lucide-react";import{OceanEduSpeakingReport as c}from"../report/OceanEduSpeakingReport";export const SPEAKING_REVIEW_POLL_INTERVAL_MS=5e3;export function SpeakingReviewResult({reviewData:m,studentName:h,studentCode:u,branchName:f,examDateText:p,examTitle:x,showDetailedResults:b,speakingRubric:g,reviewUrl:v,assetBaseUrl:w,canExportPdf:N=!1,isExporting:y,hasPendingQuestions:E=!1,onBack:A,onExportPdf:D,topActionsSlot:k,beforeReportSlot:R,afterReportSlot:S}){const[F,P]=r(!1),T=y??F,j=s(()=>{if(p)return p;if(m.submittedAt){const e=new Date(m.submittedAt);if(!Number.isNaN(e.getTime()))return e.toLocaleDateString("vi-VN")}return(new Date).toLocaleDateString("vi-VN")},[p,m.submittedAt]);return e("div",{className:"min-h-screen bg-[#e0e0e0] py-4 md:py-6",children:t("div",{className:"mx-auto flex w-full max-w-[1160px] flex-col gap-4 px-0 sm:px-4",children:[t("div",{className:"flex items-center justify-between gap-3 px-3 print:hidden sm:px-0",children:[t("button",{type:"button",onClick:()=>{A?A():"undefined"!=typeof window&&window.history.back()},className:"inline-flex items-center gap-2 rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:border-slate-300 hover:bg-slate-50",children:[e(n,{className:"h-4 w-4"}),"Quay lại"]}),t("div",{className:"flex items-center gap-2",children:[N&&D?t("button",{type:"button",onClick:()=>{(async()=>{if(D){void 0===y&&P(!0);try{await D()}finally{void 0===y&&P(!1)}}})()},disabled:T,className:"group relative inline-flex items-center gap-2.5 overflow-hidden rounded-xl bg-gradient-to-r from-[#00AEEF] via-[#0099D6] to-[#00AEEF] bg-[length:200%_100%] px-5 py-3 text-sm font-bold text-white shadow-lg shadow-[#00AEEF]/30 transition-all duration-300 hover:bg-[position:100%_0] hover:shadow-xl hover:shadow-[#00AEEF]/40 hover:scale-[1.02] active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:hover:shadow-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#00AEEF] focus-visible:ring-offset-2",children:[e("span",{className:"absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent transition-transform duration-1000 group-hover:translate-x-full"}),t(a,T?{children:[e(o,{className:"relative z-10 h-4 w-4 animate-spin"}),e("span",{className:"relative z-10",children:"Đang xuất..."})]}:{children:[e(l,{className:"relative z-10 h-4 w-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:scale-110"}),e("span",{className:"relative z-10",children:"Xuất PDF"})]})]}):null,k]})]}),E?t("div",{className:"flex items-center gap-3 rounded-2xl border border-[#b3dfff] bg-gradient-to-r from-[#e8f6ff] to-[#f0f8ff] px-5 py-4 shadow-sm",children:[e("div",{className:"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#d0edff]",children:e(d,{className:"h-5 w-5 animate-pulse text-[#00AEEF]"})}),t("div",{className:"flex-1",children:[e("p",{className:"text-sm font-bold text-[#0054A6]",children:"AI đang chấm điểm..."}),t("p",{className:"text-xs text-[#0078c8]",children:["Trang sẽ tự động cập nhật sau mỗi ",5," giây cho đến khi hoàn tất."]})]})]}):null,m.isPendingGrading?t("div",{className:"flex items-center gap-3 rounded-2xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 px-5 py-4 shadow-sm",children:[e("div",{className:"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-amber-100",children:e(i,{className:"h-5 w-5 text-amber-600"})}),t("div",{children:[e("p",{className:"text-sm font-bold text-amber-800",children:"Đang chờ chấm điểm"}),e("p",{className:"text-xs text-amber-600",children:"Giáo viên sẽ chấm điểm bài thi của bạn sớm nhất có thể."})]})]}):null,R,e(c,{reviewData:m,studentName:h??m.studentName,studentCode:u,branchName:f,examDateText:j,examTitle:x,showDetailedResults:b,reviewUrl:v,speakingRubric:g,assetBaseUrl:w}),S]})})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useMemo, useState } from 'react';
4
+ import { AlertTriangle, ChevronLeft, Download, Loader2, Sparkles, } from 'lucide-react';
5
+ import { OceanEduSpeakingReport } from '../report/OceanEduSpeakingReport';
6
+ export const SPEAKING_REVIEW_POLL_INTERVAL_MS = 5000;
7
+ /**
8
+ * Speaking review page shell (toolbar + banners + report).
9
+ * Source: oe-exam-fe/.../speaking-review/page.tsx (SDK-owned portion only).
10
+ */
11
+ export function SpeakingReviewResult({ reviewData, studentName, studentCode, branchName, examDateText, examTitle, showDetailedResults, speakingRubric, reviewUrl, assetBaseUrl, canExportPdf = false, isExporting: isExportingProp, hasPendingQuestions = false, onBack, onExportPdf, topActionsSlot, beforeReportSlot, afterReportSlot, }) {
12
+ const [isExportingLocal, setIsExportingLocal] = useState(false);
13
+ const isExporting = isExportingProp ?? isExportingLocal;
14
+ const resolvedExamDateText = useMemo(() => {
15
+ if (examDateText)
16
+ return examDateText;
17
+ if (reviewData.submittedAt) {
18
+ const date = new Date(reviewData.submittedAt);
19
+ if (!Number.isNaN(date.getTime())) {
20
+ return date.toLocaleDateString('vi-VN');
21
+ }
22
+ }
23
+ return new Date().toLocaleDateString('vi-VN');
24
+ }, [examDateText, reviewData.submittedAt]);
25
+ const handleBack = () => {
26
+ if (onBack) {
27
+ onBack();
28
+ return;
29
+ }
30
+ if (typeof window !== 'undefined') {
31
+ window.history.back();
32
+ }
33
+ };
34
+ const handleExportPdf = async () => {
35
+ if (!onExportPdf)
36
+ return;
37
+ if (isExportingProp === undefined)
38
+ setIsExportingLocal(true);
39
+ try {
40
+ await onExportPdf();
41
+ }
42
+ finally {
43
+ if (isExportingProp === undefined)
44
+ setIsExportingLocal(false);
45
+ }
46
+ };
47
+ return (_jsx("div", { className: "min-h-screen bg-[#e0e0e0] py-4 md:py-6", children: _jsxs("div", { className: "mx-auto flex w-full max-w-[1160px] flex-col gap-4 px-0 sm:px-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 px-3 print:hidden sm:px-0", children: [_jsxs("button", { type: "button", onClick: handleBack, className: "inline-flex items-center gap-2 rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:border-slate-300 hover:bg-slate-50", children: [_jsx(ChevronLeft, { className: "h-4 w-4" }), "Quay l\u1EA1i"] }), _jsxs("div", { className: "flex items-center gap-2", children: [canExportPdf && onExportPdf ? (_jsxs("button", { type: "button", onClick: () => void handleExportPdf(), disabled: isExporting, className: "group relative inline-flex items-center gap-2.5 overflow-hidden rounded-xl bg-gradient-to-r from-[#00AEEF] via-[#0099D6] to-[#00AEEF] bg-[length:200%_100%] px-5 py-3 text-sm font-bold text-white shadow-lg shadow-[#00AEEF]/30 transition-all duration-300 hover:bg-[position:100%_0] hover:shadow-xl hover:shadow-[#00AEEF]/40 hover:scale-[1.02] active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:hover:shadow-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#00AEEF] focus-visible:ring-offset-2", children: [_jsx("span", { className: "absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent transition-transform duration-1000 group-hover:translate-x-full" }), isExporting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "relative z-10 h-4 w-4 animate-spin" }), _jsx("span", { className: "relative z-10", children: "\u0110ang xu\u1EA5t..." })] })) : (_jsxs(_Fragment, { children: [_jsx(Download, { className: "relative z-10 h-4 w-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:scale-110" }), _jsx("span", { className: "relative z-10", children: "Xu\u1EA5t PDF" })] }))] })) : null, topActionsSlot] })] }), hasPendingQuestions ? (_jsxs("div", { className: "flex items-center gap-3 rounded-2xl border border-[#b3dfff] bg-gradient-to-r from-[#e8f6ff] to-[#f0f8ff] px-5 py-4 shadow-sm", children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#d0edff]", children: _jsx(Sparkles, { className: "h-5 w-5 animate-pulse text-[#00AEEF]" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-bold text-[#0054A6]", children: "AI \u0111ang ch\u1EA5m \u0111i\u1EC3m..." }), _jsxs("p", { className: "text-xs text-[#0078c8]", children: ["Trang s\u1EBD t\u1EF1 \u0111\u1ED9ng c\u1EADp nh\u1EADt sau m\u1ED7i ", SPEAKING_REVIEW_POLL_INTERVAL_MS / 1000, " gi\u00E2y cho \u0111\u1EBFn khi ho\u00E0n t\u1EA5t."] })] })] })) : null, reviewData.isPendingGrading ? (_jsxs("div", { className: "flex items-center gap-3 rounded-2xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 px-5 py-4 shadow-sm", children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-amber-100", children: _jsx(AlertTriangle, { className: "h-5 w-5 text-amber-600" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-bold text-amber-800", children: "\u0110ang ch\u1EDD ch\u1EA5m \u0111i\u1EC3m" }), _jsx("p", { className: "text-xs text-amber-600", children: "Gi\u00E1o vi\u00EAn s\u1EBD ch\u1EA5m \u0111i\u1EC3m b\u00E0i thi c\u1EE7a b\u1EA1n s\u1EDBm nh\u1EA5t c\u00F3 th\u1EC3." })] })] })) : null, beforeReportSlot, _jsx(OceanEduSpeakingReport, { reviewData: reviewData, studentName: studentName ?? reviewData.studentName, studentCode: studentCode, branchName: branchName, examDateText: resolvedExamDateText, examTitle: examTitle, showDetailedResults: showDetailedResults, reviewUrl: reviewUrl, speakingRubric: speakingRubric, assetBaseUrl: assetBaseUrl }), afterReportSlot] }) }));
48
+ }
@@ -1 +1,72 @@
1
- export const ReviewScoreBand={EXCELLENT:90,GOOD:80,FAIR:65,AVERAGE:50};export function formatScore(n,e=1){if(null==n||Number.isNaN(n))return"—";return n.toFixed(e).replace(/\.0+$/,"").replace(/(\.\d*[1-9])0+$/,"$1")}export function formatTotalScore(n){return null!=n&&Number.isFinite(n)?n<10?n.toFixed(1):String(Math.round(n)):"—"}export function getScoreStroke(n,e,i){if(i||null==n||e<=0)return"conic-gradient(#cbd5e1 0% 100%, #eef5ff 100% 100%)";const t=Math.max(0,Math.min(100,n/e*100));return`conic-gradient(#00AEEF 0% ${t}%, #eef5ff ${t}% 100%)`}export function getScoreLabel(n,e,i){if(i||null==n||e<=0)return"Đang chấm điểm";const t=n/e*100;return t>=ReviewScoreBand.EXCELLENT?"Xuất sắc":t>=ReviewScoreBand.GOOD?"Giỏi":t>=ReviewScoreBand.FAIR?"Khá":t>=ReviewScoreBand.AVERAGE?"Trung bình":"Cần cố gắng"}export function getScoreMessage(n,e,i){if(i)return"Bài làm của bạn đang có câu hỏi tự luận chờ giáo viên chấm điểm. Điểm số sẽ được cập nhật sớm nhất.";if(null==n||e<=0)return"Đừng nản nhé! Hãy xem lại chi tiết bài làm phía dưới và ôn lại kiến thức nhé.";const t=n/e*100;return t>=ReviewScoreBand.EXCELLENT?"Xuất sắc! Bạn nắm rất vững kiến thức. Xem lại chi tiết phía dưới nhé.":t>=ReviewScoreBand.GOOD?"Làm tốt lắm! Xem lại chi tiết bài làm phía dưới để hoàn thiện hơn nhé.":t>=ReviewScoreBand.FAIR?"Khá tốt! Hãy xem lại các câu chưa đúng phía dưới để tiến bộ hơn nhé.":t>=ReviewScoreBand.AVERAGE?"Bạn đã cố gắng! Xem lại kỹ phần chi tiết phía dưới để cải thiện nhé.":"Đừng nản nhé! Hãy xem lại chi tiết bài làm phía dưới và ôn lại kiến thức nhé."}
1
+ /**
2
+ * Score display helpers for the general (non-speaking) exam result report.
3
+ * Source thresholds mirror oe-exam-fe OceanEduExamReport.
4
+ */
5
+ /** Percentage bands for general exam total-score labels / messages. */
6
+ export const ReviewScoreBand = {
7
+ EXCELLENT: 90,
8
+ GOOD: 80,
9
+ FAIR: 65,
10
+ AVERAGE: 50,
11
+ };
12
+ export function formatScore(score, digits = 1) {
13
+ if (score == null || Number.isNaN(score))
14
+ return '—';
15
+ const fixed = score.toFixed(digits);
16
+ return fixed.replace(/\.0+$/, '').replace(/(\.\d*[1-9])0+$/, '$1');
17
+ }
18
+ /** Format total score for "ĐIỂM TỔNG" display. */
19
+ export function formatTotalScore(score) {
20
+ if (score == null || !Number.isFinite(score))
21
+ return '—';
22
+ if (score < 10)
23
+ return score.toFixed(1);
24
+ return String(Math.round(score));
25
+ }
26
+ export function getScoreStroke(totalScore, maxScore, isPendingGrading) {
27
+ if (isPendingGrading || totalScore == null || maxScore <= 0) {
28
+ return 'conic-gradient(#cbd5e1 0% 100%, #eef5ff 100% 100%)';
29
+ }
30
+ const percentage = Math.max(0, Math.min(100, (totalScore / maxScore) * 100));
31
+ return `conic-gradient(#00AEEF 0% ${percentage}%, #eef5ff ${percentage}% 100%)`;
32
+ }
33
+ export function getScoreLabel(totalScore, maxScore, isPendingGrading) {
34
+ if (isPendingGrading || totalScore == null || maxScore <= 0)
35
+ return 'Đang chấm điểm';
36
+ const percentage = (totalScore / maxScore) * 100;
37
+ if (percentage >= ReviewScoreBand.EXCELLENT)
38
+ return 'Xuất sắc';
39
+ if (percentage >= ReviewScoreBand.GOOD)
40
+ return 'Giỏi';
41
+ if (percentage >= ReviewScoreBand.FAIR)
42
+ return 'Khá';
43
+ if (percentage >= ReviewScoreBand.AVERAGE)
44
+ return 'Trung bình';
45
+ return 'Cần cố gắng';
46
+ }
47
+ /**
48
+ * Score-aware mascot message. Mirrors {@link getScoreLabel} thresholds so the
49
+ * encouragement text matches the actual result.
50
+ */
51
+ export function getScoreMessage(totalScore, maxScore, isPendingGrading) {
52
+ if (isPendingGrading) {
53
+ return 'Bài làm của bạn đang có câu hỏi tự luận chờ giáo viên chấm điểm. Điểm số sẽ được cập nhật sớm nhất.';
54
+ }
55
+ if (totalScore == null || maxScore <= 0) {
56
+ return 'Đừng nản nhé! Hãy xem lại chi tiết bài làm phía dưới và ôn lại kiến thức nhé.';
57
+ }
58
+ const percentage = (totalScore / maxScore) * 100;
59
+ if (percentage >= ReviewScoreBand.EXCELLENT) {
60
+ return 'Xuất sắc! Bạn nắm rất vững kiến thức. Xem lại chi tiết phía dưới nhé.';
61
+ }
62
+ if (percentage >= ReviewScoreBand.GOOD) {
63
+ return 'Làm tốt lắm! Xem lại chi tiết bài làm phía dưới để hoàn thiện hơn nhé.';
64
+ }
65
+ if (percentage >= ReviewScoreBand.FAIR) {
66
+ return 'Khá tốt! Hãy xem lại các câu chưa đúng phía dưới để tiến bộ hơn nhé.';
67
+ }
68
+ if (percentage >= ReviewScoreBand.AVERAGE) {
69
+ return 'Bạn đã cố gắng! Xem lại kỹ phần chi tiết phía dưới để cải thiện nhé.';
70
+ }
71
+ return 'Đừng nản nhé! Hãy xem lại chi tiết bài làm phía dưới và ôn lại kiến thức nhé.';
72
+ }
@@ -1 +1,224 @@
1
- export const SPEAKING_SKILL_COLORS={pronunciation:"#4CAF50",fluency:"#2196F3",vocabulary:"#FF9800",grammar:"#9C27B0",coherence:"#00BCD4"};function n(n){return null!=n&&Number.isFinite(n)?Math.round(Math.max(0,Math.min(100,n))):0}function t(n,t){if(t<=0)return null;return n.reduce((n,t)=>n+("number"==typeof t&&Number.isFinite(t)?t:0),0)/t}function e(n){return n&&"object"==typeof n?n:null}function c(n){const t=e(n);return e(t?.pronunciation)}export function deriveSkillScores(n){const r=function(n){return n.parts.flatMap(n=>n.questions)}(n),i=r.filter(n=>!n.isExample),o=i.length;return{pronunciation:t(i.map(n=>{const t=c(n.aiAssessment)?.pronunciationScore;return"number"==typeof t?t:null}),o),fluency:t(i.map(n=>{const t=c(n.aiAssessment)?.fluencyScore;return"number"==typeof t?t:null}),o),vocabulary:t(i.map(n=>{const t=e(n.llmAssessment)?.contentScore;return"number"==typeof t?t:null}),o),grammar:t(i.map(n=>{const t=c(n.aiAssessment)?.accuracyScore;return"number"==typeof t?t:null}),o),coherence:t(i.map(n=>{const t=c(n.aiAssessment)?.prosodyScore;return"number"==typeof t?t:null}),o)}}export function buildSkillMetrics(t){return[{key:"pronunciation",label:"Pronunciation",sublabel:"Phát âm",score:n(t.pronunciation),color:SPEAKING_SKILL_COLORS.pronunciation},{key:"fluency",label:"Fluency",sublabel:"Độ trôi chảy",score:n(t.fluency),color:SPEAKING_SKILL_COLORS.fluency},{key:"grammar",label:"Accuracy",sublabel:"Chính xác phát âm",score:n(t.grammar),color:SPEAKING_SKILL_COLORS.grammar},{key:"coherence",label:"Prosody",sublabel:"Ngữ điệu",score:n(t.coherence),color:SPEAKING_SKILL_COLORS.coherence},{key:"vocabulary",label:"Content",sublabel:"Nội dung",score:n(t.vocabulary),color:SPEAKING_SKILL_COLORS.vocabulary}]}export function deriveSkillMetrics(n){return buildSkillMetrics(deriveSkillScores(n))}export function deriveQuestionSkillMetrics(n){const t=c(n.aiAssessment),r=e(n.llmAssessment);return buildSkillMetrics({pronunciation:"number"==typeof t?.pronunciationScore?t.pronunciationScore:null,fluency:"number"==typeof t?.fluencyScore?t.fluencyScore:null,vocabulary:"number"==typeof r?.contentScore?r.contentScore:null,grammar:"number"==typeof t?.accuracyScore?t.accuracyScore:null,coherence:"number"==typeof t?.prosodyScore?t.prosodyScore:null})}export function getOverallStatusText(n,t,e){if(e||null==n)return"Đang chờ hoàn tất chấm điểm. Kết quả tổng quan sẽ được cập nhật ngay khi có đủ dữ liệu.";const c=t>0?n/t*100:0;return c>=85?"Trình độ rất tốt. Tiếp tục phát huy nhé!":c>=70?"Kết quả tốt. Hãy tiếp tục luyện tập để bứt phá hơn nữa!":c>=50?"Bạn đang tiến bộ tốt. Hãy luyện tập thêm để cải thiện toàn diện hơn.":"Cần luyện tập thêm để nâng cao kỹ năng nói và sự tự tin khi giao tiếp."}export function getScoreLabel(n,t,e){if(e||null==n)return"ĐANG CHỜ";const c=t>0?n/t*100:0;return c>=85?"XUẤT SẮC":c>=70?"TỐT":c>=50?"KHÁ":"CẦN CỐ GẮNG HƠN"}export function deriveFeedback(n){if(n.isPendingGrading)return"Bài thi đang chờ hệ thống hoặc giáo viên hoàn tất chấm điểm. Kết quả chi tiết sẽ được cập nhật sớm nhất có thể.";const t=n.maxScore>0?(n.totalScore??0)/n.maxScore*100:0;return t>=85?"Tuyệt vời! Bạn đã thể hiện khả năng nói tiếng Anh rất tốt. Hãy tiếp tục phát huy và chinh phục những thử thách cao hơn nhé!":t>=70?"Bạn đã có nền tảng nói tiếng Anh khá tốt. Tiếp tục luyện phát âm, mở rộng vốn từ và duy trì sự tự tin khi trả lời.":t>=50?"Bạn cần cố gắng hơn nữa. Hãy dành thêm thời gian luyện phát âm rõ ràng hơn và trả lời mạch lạc hơn ở từng phần thi.":"Bạn cần cố gắng nhiều hơn. Hãy luyện tập từng ngày để nâng cao khả năng nói, sự trôi chảy và mức độ tự tin khi giao tiếp bằng tiếng Anh."}export function deriveSummaryPoints(n,t){const e=Object.fromEntries(t.map(n=>[n.key,n.score])),c=[];return(e.pronunciation??0)>=75?c.push({icon:"check",text:"Phát âm rõ ràng, tự nhiên, ngữ điệu khá tốt."}):c.push({icon:"check",text:"Cần luyện thêm phát âm từng âm và nhấn trọng âm để nói rõ hơn."}),(e.grammar??0)>=75?c.push({icon:"check",text:"Phát âm từng âm chuẩn xác, ít mắc lỗi sai âm."}):c.push({icon:"check",text:"Cần luyện phát âm chuẩn từng âm tiết, đặc biệt các âm tiếng Anh dễ nhầm."}),(e.fluency??0)>=75?c.push({icon:"check",text:"Diễn đạt trôi chảy, tốc độ nói khá tốt."}):c.push({icon:"check",text:"Cần tăng độ trôi chảy và giảm các khoảng ngập ngừng khi trả lời."}),(e.coherence??0)>=75?c.push({icon:"check",text:"Ngữ điệu tự nhiên, nhấn nhá và nhịp điệu khi nói khá tốt."}):c.push({icon:"check",text:"Nên luyện ngữ điệu lên xuống tự nhiên hơn và chú ý nhịp điệu khi nói."}),(e.vocabulary??0)>=75?c.push({icon:"check",text:"Nội dung trả lời bám sát câu hỏi và đầy đủ ý chính."}):c.push({icon:"check",text:"Cần trả lời đúng trọng tâm câu hỏi và đầy đủ ý chính hơn."}),c.push({icon:"star",text:getOverallStatusText(n.totalScore,n.maxScore,n.isPendingGrading),highlight:!0}),c.slice(0,6)}
1
+ /**
2
+ * Shared logic for Speaking Review "NHẬN XÉT TỔNG QUAN TỪ AI".
3
+ * Source: oe-exam-fe/.../speaking-review/_utils/speaking-summary.ts
4
+ */
5
+ export const SPEAKING_SKILL_COLORS = {
6
+ pronunciation: '#4CAF50',
7
+ fluency: '#2196F3',
8
+ vocabulary: '#FF9800',
9
+ grammar: '#9C27B0',
10
+ coherence: '#00BCD4',
11
+ };
12
+ const SCORE_THRESHOLD_EXCELLENT = 85;
13
+ const SCORE_THRESHOLD_GOOD = 70;
14
+ const SCORE_THRESHOLD_FAIR = 50;
15
+ const METRIC_POSITIVE_THRESHOLD = 75;
16
+ function clampScore(score) {
17
+ if (score == null || !Number.isFinite(score))
18
+ return 0;
19
+ return Math.round(Math.max(0, Math.min(100, score)));
20
+ }
21
+ function averageAllQuestions(values, totalGradable) {
22
+ if (totalGradable <= 0)
23
+ return null;
24
+ const sum = values.reduce((acc, v) => acc + (typeof v === 'number' && Number.isFinite(v) ? v : 0), 0);
25
+ return sum / totalGradable;
26
+ }
27
+ function getAllQuestions(reviewData) {
28
+ return reviewData.parts.flatMap((part) => part.questions);
29
+ }
30
+ function asRecord(value) {
31
+ if (!value || typeof value !== 'object')
32
+ return null;
33
+ return value;
34
+ }
35
+ function getPronunciationScores(aiAssessment) {
36
+ const ai = asRecord(aiAssessment);
37
+ return asRecord(ai?.['pronunciation']);
38
+ }
39
+ export function deriveSkillScores(reviewData) {
40
+ const questions = getAllQuestions(reviewData);
41
+ const gradable = questions.filter((q) => !q.isExample);
42
+ const total = gradable.length;
43
+ return {
44
+ pronunciation: averageAllQuestions(gradable.map((q) => {
45
+ const score = getPronunciationScores(q.aiAssessment)?.['pronunciationScore'];
46
+ return typeof score === 'number' ? score : null;
47
+ }), total),
48
+ fluency: averageAllQuestions(gradable.map((q) => {
49
+ const score = getPronunciationScores(q.aiAssessment)?.['fluencyScore'];
50
+ return typeof score === 'number' ? score : null;
51
+ }), total),
52
+ vocabulary: averageAllQuestions(gradable.map((q) => {
53
+ const score = asRecord(q.llmAssessment)?.['contentScore'];
54
+ return typeof score === 'number' ? score : null;
55
+ }), total),
56
+ grammar: averageAllQuestions(gradable.map((q) => {
57
+ const score = getPronunciationScores(q.aiAssessment)?.['accuracyScore'];
58
+ return typeof score === 'number' ? score : null;
59
+ }), total),
60
+ coherence: averageAllQuestions(gradable.map((q) => {
61
+ const score = getPronunciationScores(q.aiAssessment)?.['prosodyScore'];
62
+ return typeof score === 'number' ? score : null;
63
+ }), total),
64
+ };
65
+ }
66
+ export function buildSkillMetrics(scores) {
67
+ return [
68
+ {
69
+ key: 'pronunciation',
70
+ label: 'Pronunciation',
71
+ sublabel: 'Phát âm',
72
+ score: clampScore(scores.pronunciation),
73
+ color: SPEAKING_SKILL_COLORS.pronunciation,
74
+ },
75
+ {
76
+ key: 'fluency',
77
+ label: 'Fluency',
78
+ sublabel: 'Độ trôi chảy',
79
+ score: clampScore(scores.fluency),
80
+ color: SPEAKING_SKILL_COLORS.fluency,
81
+ },
82
+ {
83
+ key: 'grammar',
84
+ label: 'Accuracy',
85
+ sublabel: 'Chính xác phát âm',
86
+ score: clampScore(scores.grammar),
87
+ color: SPEAKING_SKILL_COLORS.grammar,
88
+ },
89
+ {
90
+ key: 'coherence',
91
+ label: 'Prosody',
92
+ sublabel: 'Ngữ điệu',
93
+ score: clampScore(scores.coherence),
94
+ color: SPEAKING_SKILL_COLORS.coherence,
95
+ },
96
+ {
97
+ key: 'vocabulary',
98
+ label: 'Content',
99
+ sublabel: 'Nội dung',
100
+ score: clampScore(scores.vocabulary),
101
+ color: SPEAKING_SKILL_COLORS.vocabulary,
102
+ },
103
+ ];
104
+ }
105
+ export function deriveSkillMetrics(reviewData) {
106
+ return buildSkillMetrics(deriveSkillScores(reviewData));
107
+ }
108
+ export function deriveQuestionSkillMetrics(question) {
109
+ const pronunciation = getPronunciationScores(question.aiAssessment);
110
+ const llm = asRecord(question.llmAssessment);
111
+ return buildSkillMetrics({
112
+ pronunciation: typeof pronunciation?.['pronunciationScore'] === 'number'
113
+ ? pronunciation['pronunciationScore']
114
+ : null,
115
+ fluency: typeof pronunciation?.['fluencyScore'] === 'number'
116
+ ? pronunciation['fluencyScore']
117
+ : null,
118
+ vocabulary: typeof llm?.['contentScore'] === 'number'
119
+ ? llm['contentScore']
120
+ : null,
121
+ grammar: typeof pronunciation?.['accuracyScore'] === 'number'
122
+ ? pronunciation['accuracyScore']
123
+ : null,
124
+ coherence: typeof pronunciation?.['prosodyScore'] === 'number'
125
+ ? pronunciation['prosodyScore']
126
+ : null,
127
+ });
128
+ }
129
+ export function getOverallStatusText(totalScore, maxScore, isPendingGrading) {
130
+ if (isPendingGrading || totalScore == null) {
131
+ return 'Đang chờ hoàn tất chấm điểm. Kết quả tổng quan sẽ được cập nhật ngay khi có đủ dữ liệu.';
132
+ }
133
+ const pct = maxScore > 0 ? (totalScore / maxScore) * 100 : 0;
134
+ if (pct >= SCORE_THRESHOLD_EXCELLENT)
135
+ return 'Trình độ rất tốt. Tiếp tục phát huy nhé!';
136
+ if (pct >= SCORE_THRESHOLD_GOOD)
137
+ return 'Kết quả tốt. Hãy tiếp tục luyện tập để bứt phá hơn nữa!';
138
+ if (pct >= SCORE_THRESHOLD_FAIR)
139
+ return 'Bạn đang tiến bộ tốt. Hãy luyện tập thêm để cải thiện toàn diện hơn.';
140
+ return 'Cần luyện tập thêm để nâng cao kỹ năng nói và sự tự tin khi giao tiếp.';
141
+ }
142
+ export function getScoreLabel(totalScore, maxScore, isPendingGrading) {
143
+ if (isPendingGrading || totalScore == null)
144
+ return 'ĐANG CHỜ';
145
+ const pct = maxScore > 0 ? (totalScore / maxScore) * 100 : 0;
146
+ if (pct >= SCORE_THRESHOLD_EXCELLENT)
147
+ return 'XUẤT SẮC';
148
+ if (pct >= SCORE_THRESHOLD_GOOD)
149
+ return 'TỐT';
150
+ if (pct >= SCORE_THRESHOLD_FAIR)
151
+ return 'KHÁ';
152
+ return 'CẦN CỐ GẮNG HƠN';
153
+ }
154
+ export function deriveFeedback(reviewData) {
155
+ if (reviewData.isPendingGrading) {
156
+ return 'Bài thi đang chờ hệ thống hoặc giáo viên hoàn tất chấm điểm. Kết quả chi tiết sẽ được cập nhật sớm nhất có thể.';
157
+ }
158
+ const pct = reviewData.maxScore > 0 ? ((reviewData.totalScore ?? 0) / reviewData.maxScore) * 100 : 0;
159
+ if (pct >= SCORE_THRESHOLD_EXCELLENT) {
160
+ return 'Tuyệt vời! Bạn đã thể hiện khả năng nói tiếng Anh rất tốt. Hãy tiếp tục phát huy và chinh phục những thử thách cao hơn nhé!';
161
+ }
162
+ if (pct >= SCORE_THRESHOLD_GOOD) {
163
+ return 'Bạn đã có nền tảng nói tiếng Anh khá tốt. Tiếp tục luyện phát âm, mở rộng vốn từ và duy trì sự tự tin khi trả lời.';
164
+ }
165
+ if (pct >= SCORE_THRESHOLD_FAIR) {
166
+ return 'Bạn cần cố gắng hơn nữa. Hãy dành thêm thời gian luyện phát âm rõ ràng hơn và trả lời mạch lạc hơn ở từng phần thi.';
167
+ }
168
+ return 'Bạn cần cố gắng nhiều hơn. Hãy luyện tập từng ngày để nâng cao khả năng nói, sự trôi chảy và mức độ tự tin khi giao tiếp bằng tiếng Anh.';
169
+ }
170
+ export function deriveSummaryPoints(reviewData, metrics) {
171
+ const metricMap = Object.fromEntries(metrics.map((metric) => [metric.key, metric.score]));
172
+ const points = [];
173
+ if ((metricMap.pronunciation ?? 0) >= METRIC_POSITIVE_THRESHOLD) {
174
+ points.push({ icon: 'check', text: 'Phát âm rõ ràng, tự nhiên, ngữ điệu khá tốt.' });
175
+ }
176
+ else {
177
+ points.push({
178
+ icon: 'check',
179
+ text: 'Cần luyện thêm phát âm từng âm và nhấn trọng âm để nói rõ hơn.',
180
+ });
181
+ }
182
+ if ((metricMap.grammar ?? 0) >= METRIC_POSITIVE_THRESHOLD) {
183
+ points.push({ icon: 'check', text: 'Phát âm từng âm chuẩn xác, ít mắc lỗi sai âm.' });
184
+ }
185
+ else {
186
+ points.push({
187
+ icon: 'check',
188
+ text: 'Cần luyện phát âm chuẩn từng âm tiết, đặc biệt các âm tiếng Anh dễ nhầm.',
189
+ });
190
+ }
191
+ if ((metricMap.fluency ?? 0) >= METRIC_POSITIVE_THRESHOLD) {
192
+ points.push({ icon: 'check', text: 'Diễn đạt trôi chảy, tốc độ nói khá tốt.' });
193
+ }
194
+ else {
195
+ points.push({
196
+ icon: 'check',
197
+ text: 'Cần tăng độ trôi chảy và giảm các khoảng ngập ngừng khi trả lời.',
198
+ });
199
+ }
200
+ if ((metricMap.coherence ?? 0) >= METRIC_POSITIVE_THRESHOLD) {
201
+ points.push({ icon: 'check', text: 'Ngữ điệu tự nhiên, nhấn nhá và nhịp điệu khi nói khá tốt.' });
202
+ }
203
+ else {
204
+ points.push({
205
+ icon: 'check',
206
+ text: 'Nên luyện ngữ điệu lên xuống tự nhiên hơn và chú ý nhịp điệu khi nói.',
207
+ });
208
+ }
209
+ if ((metricMap.vocabulary ?? 0) >= METRIC_POSITIVE_THRESHOLD) {
210
+ points.push({ icon: 'check', text: 'Nội dung trả lời bám sát câu hỏi và đầy đủ ý chính.' });
211
+ }
212
+ else {
213
+ points.push({
214
+ icon: 'check',
215
+ text: 'Cần trả lời đúng trọng tâm câu hỏi và đầy đủ ý chính hơn.',
216
+ });
217
+ }
218
+ points.push({
219
+ icon: 'star',
220
+ text: getOverallStatusText(reviewData.totalScore, reviewData.maxScore, reviewData.isPendingGrading),
221
+ highlight: true,
222
+ });
223
+ return points.slice(0, 6);
224
+ }