@tinyweb_dev/oe-exam-sdk 0.1.1 → 0.1.3
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.
- package/dist/api/exam-create.js +1 -179
- package/dist/api/exam-create.types.js +1 -1
- package/dist/api/exam-questions.d.ts +1 -1
- package/dist/api/exam-questions.js +1 -98
- package/dist/api/exam-questions.types.d.ts +45 -1
- package/dist/api/exam-questions.types.js +1 -1
- package/dist/api/exam-taking.js +1 -73
- package/dist/api/exam-taking.types.js +1 -1
- package/dist/api/index.js +1 -6
- package/dist/api/result-review.js +1 -50
- package/dist/api/result-review.types.js +1 -1
- package/dist/components/CueCardEditor.js +1 -58
- package/dist/components/common/ResolvedImage.js +1 -15
- package/dist/components/exams/CompletionDialog.d.ts +8 -0
- package/dist/components/exams/CompletionDialog.js +1 -0
- package/dist/components/exams/CreateExamInfoForm.d.ts +4 -1
- package/dist/components/exams/CreateExamInfoForm.js +1 -35
- package/dist/components/exams/CreateExamPageContainer.d.ts +3 -0
- package/dist/components/exams/CreateExamPageContainer.js +1 -103
- package/dist/components/exams/ExamCreator.d.ts +9 -3
- package/dist/components/exams/ExamCreator.js +1 -89
- package/dist/components/exams/ExamPartTabs.d.ts +1 -1
- package/dist/components/exams/ExamPartTabs.js +1 -40
- package/dist/components/exams/ExamPreviewDialog.d.ts +20 -0
- package/dist/components/exams/ExamPreviewDialog.js +1 -0
- package/dist/components/exams/ExamQuestionGrid.d.ts +1 -1
- package/dist/components/exams/ExamQuestionGrid.js +1 -18
- package/dist/components/exams/ExamQuestionsPageContainer.d.ts +3 -0
- package/dist/components/exams/ExamQuestionsPageContainer.js +1 -90
- package/dist/components/exams/ExamViewDialog.d.ts +24 -0
- package/dist/components/exams/ExamViewDialog.js +1 -0
- package/dist/components/exams/PartAudioUploader.js +1 -9
- package/dist/components/exams/TemplateSelector.js +1 -66
- package/dist/components/exams/UnsavedChangesDialog.d.ts +8 -0
- package/dist/components/exams/UnsavedChangesDialog.js +1 -0
- package/dist/components/exams/api.d.ts +1 -1
- package/dist/components/exams/api.js +1 -3
- package/dist/components/exams/create-exam.texts.d.ts +58 -0
- package/dist/components/exams/create-exam.texts.js +1 -0
- package/dist/components/exams/create-exam.validation.js +1 -18
- package/dist/components/exams/exam-question-status.d.ts +9 -0
- package/dist/components/exams/exam-question-status.js +1 -0
- package/dist/components/exams/exam-template.utils.js +1 -18
- package/dist/components/exams/index.d.ts +11 -1
- package/dist/components/exams/index.js +1 -10
- package/dist/components/exams/take/ExamTakingPageContainer.js +1 -153
- package/dist/components/exams/take/GenericQuestionRenderer.js +1 -14
- package/dist/components/exams/take/exam-taking.utils.js +1 -88
- package/dist/components/exams/take/hooks/useSpeakingRecorder.js +1 -24
- package/dist/components/exams/take/index.js +1 -2
- package/dist/components/exams/take/types.js +1 -1
- package/dist/components/index.js +1 -42
- package/dist/components/questions/_shared/config/question-types.config.js +1 -333
- package/dist/components/questions/_shared/constants/color-palette.js +1 -21
- package/dist/components/questions/_shared/hooks/useAnswerGroupQuestionGroup.js +1 -105
- package/dist/components/questions/_shared/hooks/useBasicQuestionGroup.js +1 -222
- package/dist/components/questions/_shared/hooks/useCompareImagesGroup.js +1 -140
- package/dist/components/questions/_shared/hooks/useImageQuestionGroup.js +1 -123
- package/dist/components/questions/_shared/hooks/useInfoExchangeGroup.js +1 -50
- package/dist/components/questions/_shared/hooks/useQuestionFormState.js +1 -54
- package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +1 -123
- package/dist/components/questions/_shared/hooks/useQuestionListGroup.js +1 -121
- package/dist/components/questions/_shared/hooks/useQuestionOnChange.js +1 -70
- package/dist/components/questions/_shared/hooks/useSceneQuestionGroup.js +1 -194
- package/dist/components/questions/_shared/index.js +1 -7
- package/dist/components/questions/_shared/types/answer-the-question.type.js +1 -1
- package/dist/components/questions/_shared/types/arrange-letters-into-words.type.js +1 -1
- package/dist/components/questions/_shared/types/choose-correct-adjective.type.js +1 -3
- package/dist/components/questions/_shared/types/color-region.config.js +1 -1
- package/dist/components/questions/_shared/types/fill-in-blank.type.js +1 -1
- package/dist/components/questions/_shared/types/fill-missing-words-in-grid.type.js +1 -1
- package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +1 -1
- package/dist/components/questions/_shared/types/index.js +1 -12
- package/dist/components/questions/_shared/types/label-the-picture.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-choose-from-answer-group.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-choose-objects-in-scene.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-drag-objects-into-scene.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-answer.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-compare-images.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-image-group.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-info-exchange.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-odd-one-out.type.js +1 -3
- package/dist/components/questions/_shared/types/listen-and-speak-question-list.type.js +1 -1
- package/dist/components/questions/_shared/types/listen-and-speak-with-story-images.type.js +1 -3
- package/dist/components/questions/_shared/types/listen-and-tick-answer.type.js +1 -1
- package/dist/components/questions/_shared/types/listening-drawline.type.js +1 -1
- package/dist/components/questions/_shared/types/look-and-choose-answer.type.js +1 -1
- package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +1 -1
- package/dist/components/questions/_shared/types/match-by-writing-answer.type.js +1 -1
- package/dist/components/questions/_shared/types/multiple-choice.type.js +1 -1
- package/dist/components/questions/_shared/types/question-group.type.js +1 -11
- package/dist/components/questions/_shared/types/read-and-color-objects.type.js +1 -1
- package/dist/components/questions/_shared/types/read-displayed-content.type.js +1 -1
- package/dist/components/questions/_shared/types/read-passage-and-answer-questions.type.js +1 -1
- package/dist/components/questions/_shared/types/speaking-describe-image.type.js +1 -1
- package/dist/components/questions/_shared/types/spontaneous-qa.type.js +1 -1
- package/dist/components/questions/_shared/types/word-fill-paragraph-with-options.type.js +1 -1
- package/dist/components/questions/_shared/types/word-fill-paragraph.type.js +1 -1
- package/dist/components/questions/_shared/types/word-fill-structured-form.type.js +1 -1
- package/dist/components/questions/_shared/types/word-ordering.type.js +1 -1
- package/dist/components/questions/_shared/types/write-a-short-letter.type.js +1 -1
- package/dist/components/questions/_shared/types/write-correct-verb-form.type.js +1 -3
- package/dist/components/questions/_shared/types/write-sentences.type.js +1 -1
- package/dist/components/questions/_shared/types/write-short-paragraph.type.js +1 -1
- package/dist/components/questions/_shared/utils/answer-builder.js +1 -79
- package/dist/components/questions/_shared/utils/createColorRegionRegistration.js +1 -39
- package/dist/components/questions/_shared/utils/id-generator.js +1 -3
- package/dist/components/questions/_shared/utils/question-validation.js +1 -21
- package/dist/components/questions/components/ColorNode.js +1 -85
- package/dist/components/questions/components/ColorRegionClient.js +1 -545
- package/dist/components/questions/components/ColorRegionCreator.js +1 -420
- package/dist/components/questions/components/ColorRegionNode.js +1 -59
- package/dist/components/questions/components/CreatorGuide.js +1 -103
- package/dist/components/questions/components/NameNode.js +1 -26
- package/dist/components/questions/components/QuestionBankOption.js +1 -46
- package/dist/components/questions/components/QuestionBasicInfoForm.js +1 -9
- package/dist/components/questions/components/QuestionCommonFields.js +1 -33
- package/dist/components/questions/components/QuestionSearchDropdown.js +1 -258
- package/dist/components/questions/components/QuestionTypeSelector.js +1 -32
- package/dist/components/questions/components/QuestionTypeSpecificForms.js +1 -6
- package/dist/components/questions/components/RegionNode.js +1 -94
- package/dist/components/questions/components/index.js +1 -14
- package/dist/components/questions/creator/QuestionCreator.js +1 -90
- package/dist/components/questions/creator/QuestionGroupCreator.js +1 -119
- package/dist/components/questions/creator/dedicated-component-router.js +1 -79
- package/dist/components/questions/creator/index.js +1 -3
- package/dist/components/questions/creator/question-type-registry.js +1 -80
- package/dist/components/questions/groups/ArticlesGroupCard.js +1 -121
- package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -50
- package/dist/components/questions/groups/DocumentGroupCard.js +1 -114
- package/dist/components/questions/groups/MatchAnswerGroupCard.js +1 -25
- package/dist/components/questions/index.js +1 -10
- package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +1 -37
- package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +1 -351
- package/dist/components/questions/types/answer-the-question/register.js +1 -67
- package/dist/components/questions/types/answer-the-question/transform.js +1 -36
- package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +1 -141
- package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +1 -118
- package/dist/components/questions/types/arrange-letters-into-words/index.js +1 -2
- package/dist/components/questions/types/arrange-letters-into-words/register.js +1 -4
- package/dist/components/questions/types/arrange-letters-into-words/transform.js +1 -24
- package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -64
- package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +1 -169
- package/dist/components/questions/types/choose-correct-adjective/index.js +1 -2
- package/dist/components/questions/types/choose-correct-adjective/register.js +1 -55
- package/dist/components/questions/types/choose-correct-adjective/transform.js +1 -16
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +1 -131
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +1 -581
- package/dist/components/questions/types/choose-the-correct-answer/index.js +1 -2
- package/dist/components/questions/types/choose-the-correct-answer/register.js +1 -101
- package/dist/components/questions/types/choose-the-correct-answer/transform.js +1 -43
- package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +1 -275
- package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +1 -448
- package/dist/components/questions/types/fill-in-blank/index.js +1 -2
- package/dist/components/questions/types/fill-in-blank/register.js +1 -138
- package/dist/components/questions/types/fill-in-blank/transform.js +1 -59
- package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +1 -117
- package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +1 -671
- package/dist/components/questions/types/fill-missing-words-in-grid/index.js +1 -2
- package/dist/components/questions/types/fill-missing-words-in-grid/register.js +1 -37
- package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +1 -15
- package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +1 -262
- package/dist/components/questions/types/gn-speaking-interview/register.js +1 -121
- package/dist/components/questions/types/gn-speaking-interview/transform.js +1 -48
- package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +1 -16
- package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +1 -27
- package/dist/components/questions/types/image-object-matching/index.js +1 -2
- package/dist/components/questions/types/image-object-matching/register.js +1 -3
- package/dist/components/questions/types/image-object-matching/transform.js +1 -2
- package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +1 -102
- package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +1 -344
- package/dist/components/questions/types/label-the-picture/index.js +1 -2
- package/dist/components/questions/types/label-the-picture/register.js +1 -54
- package/dist/components/questions/types/label-the-picture/transform.js +1 -28
- package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +1 -78
- package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +1 -232
- package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +1 -2
- package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +1 -82
- package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +1 -27
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +1 -70
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +1 -386
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +1 -2
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +1 -100
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +1 -33
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +1 -106
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +1 -457
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +1 -2
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +1 -110
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +1 -35
- package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +1 -8
- package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -22
- package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +1 -291
- package/dist/components/questions/types/listen-and-speak-answer/index.js +1 -2
- package/dist/components/questions/types/listen-and-speak-answer/register.js +1 -84
- package/dist/components/questions/types/listen-and-speak-answer/transform.js +1 -27
- package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -32
- package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +1 -295
- package/dist/components/questions/types/listen-and-speak-compare-images/register.js +1 -79
- package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +1 -27
- package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -34
- package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +1 -285
- package/dist/components/questions/types/listen-and-speak-image-group/register.js +1 -81
- package/dist/components/questions/types/listen-and-speak-image-group/transform.js +1 -26
- package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -38
- package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +1 -385
- package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +1 -87
- package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +1 -32
- package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -26
- package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +1 -247
- package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +1 -59
- package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +1 -18
- package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -26
- package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +1 -256
- package/dist/components/questions/types/listen-and-speak-question-list/register.js +1 -81
- package/dist/components/questions/types/listen-and-speak-question-list/transform.js +1 -26
- package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -26
- package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +1 -230
- package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +1 -56
- package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +1 -16
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +1 -72
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +1 -230
- package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
- package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +1 -66
- package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +1 -42
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +1 -96
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +1 -238
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +1 -2
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +1 -76
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +1 -19
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +1 -134
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +1 -617
- package/dist/components/questions/types/look-picture-fill-word-hint/index.js +1 -2
- package/dist/components/questions/types/look-picture-fill-word-hint/register.js +1 -82
- package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +1 -29
- package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +1 -38
- package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +1 -359
- package/dist/components/questions/types/match-by-writing-answer/index.js +1 -3
- package/dist/components/questions/types/match-by-writing-answer/register.js +1 -58
- package/dist/components/questions/types/match-by-writing-answer/transform.js +1 -61
- package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +1 -16
- package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +1 -23
- package/dist/components/questions/types/read-and-color-objects/index.js +1 -2
- package/dist/components/questions/types/read-and-color-objects/register.js +1 -3
- package/dist/components/questions/types/read-and-color-objects/transform.js +1 -36
- package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +1 -125
- package/dist/components/questions/types/read-displayed-content/register.js +1 -64
- package/dist/components/questions/types/read-displayed-content/transform.js +1 -12
- package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -64
- package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +1 -511
- package/dist/components/questions/types/read-passage-and-answer-questions/index.js +1 -2
- package/dist/components/questions/types/read-passage-and-answer-questions/register.js +1 -58
- package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +1 -28
- package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +1 -373
- package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +1 -41
- package/dist/components/questions/types/speaking-conversation/register.js +1 -110
- package/dist/components/questions/types/speaking-conversation/transform.js +1 -34
- package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +1 -74
- package/dist/components/questions/types/speaking-cue-card/register.js +1 -52
- package/dist/components/questions/types/speaking-cue-card/transform.js +1 -12
- package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -10
- package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +1 -161
- package/dist/components/questions/types/speaking-describe-image/index.js +1 -2
- package/dist/components/questions/types/speaking-describe-image/register.js +1 -69
- package/dist/components/questions/types/speaking-describe-image/transform.js +1 -16
- package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +1 -234
- package/dist/components/questions/types/spontaneous-qa/register.js +1 -93
- package/dist/components/questions/types/spontaneous-qa/transform.js +1 -34
- package/dist/components/questions/types/true-false/TrueFalseClient.js +1 -75
- package/dist/components/questions/types/true-false/TrueFalseCreator.js +1 -244
- package/dist/components/questions/types/true-false/index.js +1 -2
- package/dist/components/questions/types/true-false/register.js +1 -77
- package/dist/components/questions/types/true-false/transform.js +1 -32
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +1 -233
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +1 -631
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +1 -28
- package/dist/components/questions/types/word-fill-paragraph/index.js +1 -2
- package/dist/components/questions/types/word-fill-paragraph/register.js +1 -136
- package/dist/components/questions/types/word-fill-paragraph/transform.js +1 -56
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -138
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +1 -261
- package/dist/components/questions/types/word-fill-structured-form/index.js +1 -2
- package/dist/components/questions/types/word-fill-structured-form/register.js +1 -67
- package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -40
- package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -84
- package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +1 -192
- package/dist/components/questions/types/word-ordering/index.js +1 -2
- package/dist/components/questions/types/word-ordering/register.js +1 -46
- package/dist/components/questions/types/word-ordering/transform.js +1 -24
- package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +1 -98
- package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +1 -320
- package/dist/components/questions/types/write-a-short-letter/index.js +1 -2
- package/dist/components/questions/types/write-a-short-letter/register.js +1 -68
- package/dist/components/questions/types/write-a-short-letter/transform.js +1 -25
- package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +1 -61
- package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +1 -196
- package/dist/components/questions/types/write-correct-verb-form/index.js +1 -2
- package/dist/components/questions/types/write-correct-verb-form/register.js +1 -62
- package/dist/components/questions/types/write-correct-verb-form/transform.js +1 -17
- package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +1 -22
- package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +1 -174
- package/dist/components/questions/types/write-sentences/index.js +1 -2
- package/dist/components/questions/types/write-sentences/register.js +1 -58
- package/dist/components/questions/types/write-sentences/transform.js +1 -28
- package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -96
- package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +1 -161
- package/dist/components/questions/types/write-short-paragraph/index.js +1 -2
- package/dist/components/questions/types/write-short-paragraph/register.js +1 -4
- package/dist/components/questions/types/write-short-paragraph/transform.js +1 -21
- package/dist/components/questions/viewer/QuestionGroupViewer.js +1 -36
- package/dist/components/questions/viewer/QuestionViewer.js +1 -446
- package/dist/components/questions/viewer/index.js +1 -2
- package/dist/components/results/ResultReviewPageContainer.js +1 -98
- package/dist/components/results/ReviewQuestionRenderer.js +1 -72
- package/dist/components/results/index.js +1 -2
- package/dist/components/results/result-review.utils.js +1 -6
- package/dist/components/results/review-data.js +1 -150
- package/dist/components/results/review-renderer.utils.js +1 -97
- package/dist/components/results/review-types.js +1 -1
- package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +1 -138
- package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +1 -12
- package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +1 -18
- package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +1 -11
- package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +1 -11
- package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +1 -9
- package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +1 -13
- package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +1 -8
- package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +1 -6
- package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +1 -5
- package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +1 -9
- package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +1 -41
- package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +1 -25
- package/dist/components/themes/cambridge-yle/index.js +1 -13
- package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +1 -24
- package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +1 -88
- package/dist/components/themes/english-certification/EcWordFillParagraph.js +1 -55
- package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -156
- package/dist/components/themes/english-certification/EcWritingTask.js +1 -34
- package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +1 -114
- package/dist/components/themes/english-certification/EnglishCertificationBrand.js +1 -11
- package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +1 -21
- package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +1 -15
- package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +1 -19
- package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +1 -148
- package/dist/components/themes/english-certification/EnglishCertificationHeader.js +1 -31
- package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +1 -71
- package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +1 -33
- package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +1 -16
- package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +1 -22
- package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +1 -37
- package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +1 -72
- package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +1 -90
- package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +1 -18
- package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +1 -29
- package/dist/components/themes/english-certification/english-certification-theme.js +1 -58
- package/dist/components/themes/english-certification/grouped-question-utils.js +1 -218
- package/dist/components/themes/english-certification/index.js +1 -21
- package/dist/components/themes/index.js +1 -6
- package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +1 -170
- package/dist/components/themes/summer-sky/SummerSkyLayout.js +1 -221
- package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +1 -18
- package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +1 -194
- package/dist/components/themes/types.js +1 -1
- package/dist/components/ui/alert-dialog.js +1 -26
- package/dist/components/ui/alert.js +1 -22
- package/dist/components/ui/avatar.js +1 -12
- package/dist/components/ui/badge.js +1 -38
- package/dist/components/ui/button.js +1 -35
- package/dist/components/ui/calendar.js +1 -76
- package/dist/components/ui/card.js +1 -16
- package/dist/components/ui/carousel.js +1 -91
- package/dist/components/ui/checkbox.js +1 -9
- package/dist/components/ui/collapsible.js +1 -13
- package/dist/components/ui/command.js +1 -34
- package/dist/components/ui/confirm-dialog.js +1 -49
- package/dist/components/ui/dialog.js +1 -23
- package/dist/components/ui/drawer.js +1 -35
- package/dist/components/ui/dropdown-menu.js +1 -33
- package/dist/components/ui/file-upload.js +1 -155
- package/dist/components/ui/form.js +1 -62
- package/dist/components/ui/hover-card.js +1 -10
- package/dist/components/ui/image-preview.js +1 -29
- package/dist/components/ui/input.js +1 -8
- package/dist/components/ui/label.js +1 -9
- package/dist/components/ui/language-switcher.js +1 -15
- package/dist/components/ui/multi-select.js +1 -90
- package/dist/components/ui/points-input.js +1 -33
- package/dist/components/ui/popover.js +1 -26
- package/dist/components/ui/progress.js +1 -16
- package/dist/components/ui/radio-group.js +1 -12
- package/dist/components/ui/scroll-area.js +1 -11
- package/dist/components/ui/select.js +1 -38
- package/dist/components/ui/separator.js +1 -8
- package/dist/components/ui/sheet.js +1 -40
- package/dist/components/ui/single-select.js +1 -76
- package/dist/components/ui/skeleton.js +1 -6
- package/dist/components/ui/switch.js +1 -8
- package/dist/components/ui/table.js +1 -20
- package/dist/components/ui/tabs.js +1 -17
- package/dist/components/ui/textarea.js +1 -8
- package/dist/components/ui/tooltip.js +1 -11
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -19
- package/dist/mcp/config.js +1 -32
- package/dist/mcp/http-client.js +1 -48
- package/dist/mcp/index.js +1 -29
- package/dist/mcp/tools/_helpers.js +1 -25
- package/dist/mcp/tools/exams.js +1 -439
- package/dist/mcp/tools/index.js +1 -6
- package/dist/mcp/tools/results.js +1 -19
- package/dist/shared/constants/ApiConstant.js +1 -276
- package/dist/shared/constants/QueryKeyConstant.js +1 -112
- package/dist/shared/constants/exam-level.enum.js +1 -41
- package/dist/shared/constants/landings/placement-test.constants.js +1 -431
- package/dist/shared/constants/question-skills.js +1 -267
- package/dist/shared/constants/routes.js +1 -81
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +1 -7
- package/dist/shared/lib/hooks/index.js +1 -10
- package/dist/shared/lib/hooks/useAlertDialog.js +1 -57
- package/dist/shared/lib/hooks/useAudioPlayCounter.js +1 -30
- package/dist/shared/lib/hooks/useAudioPreview.js +1 -81
- package/dist/shared/lib/hooks/useAudioUpload.js +1 -24
- package/dist/shared/lib/hooks/useConfirmDialog.js +1 -89
- package/dist/shared/lib/hooks/useDebouncedCallback.js +1 -32
- package/dist/shared/lib/hooks/useDelayedAutoPlay.js +1 -12
- package/dist/shared/lib/hooks/useFileUpload.js +1 -24
- package/dist/shared/lib/hooks/useImageUrl.js +1 -5
- package/dist/shared/lib/hooks/usePresignedFileUrl.js +1 -10
- package/dist/shared/lib/hooks/useReactHookForm.js +1 -31
- package/dist/shared/lib/hooks/useToast.js +1 -62
- package/dist/shared/lib/i18n/index.js +1 -54
- package/dist/shared/lib/i18n/messages/en/admin.js +1 -2104
- package/dist/shared/lib/i18n/messages/en/auth.js +1 -86
- package/dist/shared/lib/i18n/messages/en/common.js +1 -140
- package/dist/shared/lib/i18n/messages/en/file-upload.js +1 -18
- package/dist/shared/lib/i18n/messages/en/student.js +1 -133
- package/dist/shared/lib/i18n/messages/en/terms.js +1 -37
- package/dist/shared/lib/i18n/messages/en.js +1 -15
- package/dist/shared/lib/i18n/messages/vi/admin.js +1 -2104
- package/dist/shared/lib/i18n/messages/vi/auth.js +1 -86
- package/dist/shared/lib/i18n/messages/vi/common.js +1 -140
- package/dist/shared/lib/i18n/messages/vi/file-upload.js +1 -18
- package/dist/shared/lib/i18n/messages/vi/student.js +1 -133
- package/dist/shared/lib/i18n/messages/vi/terms.js +1 -37
- package/dist/shared/lib/i18n/messages/vi.js +1 -15
- package/dist/shared/lib/i18n/types.js +1 -1
- package/dist/shared/lib/stores/examQuestionStore.js +1 -212
- package/dist/shared/lib/stores/localeStore.js +1 -10
- package/dist/shared/lib/utils/public-page.js +1 -44
- package/dist/shared/lib/utils/question-reverse-transform.d.ts +6 -0
- package/dist/shared/lib/utils/question-reverse-transform.js +1 -0
- package/dist/shared/lib/utils/question-transform-types.js +1 -1
- package/dist/shared/lib/utils/question-transform-validation.d.ts +6 -0
- package/dist/shared/lib/utils/question-transform-validation.js +1 -0
- package/dist/shared/lib/utils/question-transform.d.ts +6 -2
- package/dist/shared/lib/utils/question-transform.js +1 -174
- package/dist/shared/lib/utils.js +1 -168
- package/dist/shared/lib/validation/choose-correct-answer.validation.js +1 -111
- package/dist/shared/lib/validation/label-the-picture.validation.js +1 -19
- package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +1 -46
- package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +1 -21
- package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +1 -34
- package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +1 -40
- package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +1 -45
- package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +1 -19
- package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +1 -39
- package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +1 -32
- package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +1 -19
- package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +1 -28
- package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +1 -12
- package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +1 -47
- package/dist/shared/lib/validation/read-and-color-objects.validation.js +1 -29
- package/dist/shared/lib/validation/read-displayed-content.validation.js +1 -28
- package/dist/shared/lib/validation/speaking-conversation.validation.js +1 -75
- package/dist/shared/lib/validation/speaking-describe-image.validation.js +1 -31
- package/dist/shared/lib/validation/spontaneous-qa.validation.js +1 -48
- package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +1 -38
- package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +1 -39
- package/dist/shared/lib/validation/word-fill-paragraph.validation.js +1 -43
- package/dist/shared/lib/validation/word-ordering.validation.js +1 -33
- package/dist/shared/types/branch.types.js +1 -6
- package/dist/shared/types/common.types.js +1 -50
- package/dist/shared/types/entities/exam-schedule.types.js +1 -5
- package/dist/shared/types/entities/exam.types.js +1 -1
- package/dist/shared/types/entities/question.types.js +1 -4
- package/dist/shared/types/entities/result.types.js +1 -4
- package/dist/shared/types/entities/user.types.js +1 -4
- package/dist/shared/types/exam-taking.types.js +1 -2
- package/dist/shared/types/history.types.js +1 -34
- package/dist/shared/types/index.js +1 -1
- package/dist/shared/types/questions/choose-correct-adjective.js +1 -4
- package/dist/shared/types/questions/choose-the-correct-answer.js +1 -9
- package/dist/shared/types/questions/fill-missing-words-in-grid.js +1 -11
- package/dist/shared/types/questions/index.js +1 -40
- package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
- package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
- package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
- package/dist/shared/types/questions/listen-and-speak-info-exchange.js +1 -3
- package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +1 -3
- package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
- package/dist/shared/types/questions/listen-and-speak-with-story-images.js +1 -3
- package/dist/shared/types/questions/look-picture-choose-correct-answer.js +1 -5
- package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +1 -9
- package/dist/shared/types/questions/look-picture-fill-word-hint.js +1 -7
- package/dist/shared/types/questions/read-displayed-content.js +1 -1
- package/dist/shared/types/questions/speaking-conversation.js +1 -7
- package/dist/shared/types/questions/speaking-describe-image.js +1 -1
- package/dist/shared/types/questions/spontaneous-qa.js +1 -1
- package/dist/shared/types/questions/write-correct-verb-form.js +1 -12
- package/dist/shared/types/role.types.js +1 -1
- package/dist/shared/types/structure-management.js +1 -28
- package/dist/shared/types/student.types.js +1 -54
- package/dist/shared/types/teacher-dashboard-rooms.js +1 -2
- package/package.json +12 -3
|
@@ -1,58 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const matchByWritingAnswerRegistration = {
|
|
3
|
-
component: MatchByWritingAnswerCreator,
|
|
4
|
-
transformInitialData: (initialData) => {
|
|
5
|
-
const content = initialData?.content;
|
|
6
|
-
const answer = initialData?.answer;
|
|
7
|
-
const questionGroup = initialData?.questionGroup;
|
|
8
|
-
const groupPayload = questionGroup?.payload || {};
|
|
9
|
-
const groupNumber = questionGroup?.groupNumber || 1;
|
|
10
|
-
// Extract shared options from group payload
|
|
11
|
-
const options = groupPayload?.options || answer?.options || [];
|
|
12
|
-
const groupImageUrl = groupPayload?.groupImageUrl || answer?.groupImageUrl || '';
|
|
13
|
-
const groupTitle = groupPayload?.groupTitle || answer?.groupTitle || '';
|
|
14
|
-
return {
|
|
15
|
-
question: content?.question || answer?.question || '',
|
|
16
|
-
imageUrl: content?.imageUrl || answer?.imageUrl || '',
|
|
17
|
-
correctAnswer: answer?.answer || answer?.correctAnswer || '',
|
|
18
|
-
points: initialData?.points || 1,
|
|
19
|
-
groupNumber: answer?.groupNumber || groupNumber,
|
|
20
|
-
isExample: initialData?.isExample || answer?.isExample || false,
|
|
21
|
-
askerName: content?.askerName || answer?.askerName || '',
|
|
22
|
-
answererName: content?.answererName || answer?.answererName || '',
|
|
23
|
-
options,
|
|
24
|
-
groupImageUrl,
|
|
25
|
-
groupTitle,
|
|
26
|
-
explanation: initialData?.explanation || answer?.explanation || '',
|
|
27
|
-
};
|
|
28
|
-
},
|
|
29
|
-
getExtraProps: (ctx) => ({
|
|
30
|
-
groups: ctx.groups,
|
|
31
|
-
groupConfig: ctx.groupConfig,
|
|
32
|
-
questionConfig: ctx.questionConfig,
|
|
33
|
-
viewMode: ctx.viewMode,
|
|
34
|
-
questionIndexInPart: ctx.questionIndexInPart,
|
|
35
|
-
partId: ctx.partId,
|
|
36
|
-
validationRef: ctx.validationRef,
|
|
37
|
-
}),
|
|
38
|
-
wrapOnSave: (data, ctx) => ({
|
|
39
|
-
type: ctx.questionType,
|
|
40
|
-
content: ctx.state.content,
|
|
41
|
-
points: data?.points ?? ctx.state.points ?? 1,
|
|
42
|
-
level: ctx.state.level,
|
|
43
|
-
difficulty: ctx.state.difficulty,
|
|
44
|
-
skill: ctx.state.skill,
|
|
45
|
-
answer: data,
|
|
46
|
-
explanation: data?.explanation || '',
|
|
47
|
-
}),
|
|
48
|
-
wrapOnChange: (data, ctx) => ({
|
|
49
|
-
type: ctx.questionType,
|
|
50
|
-
content: ctx.state.content,
|
|
51
|
-
points: data?.points ?? ctx.state.points ?? 1,
|
|
52
|
-
level: ctx.state.level,
|
|
53
|
-
difficulty: ctx.state.difficulty,
|
|
54
|
-
skill: ctx.state.skill,
|
|
55
|
-
answer: data,
|
|
56
|
-
explanation: data?.explanation || '',
|
|
57
|
-
}),
|
|
58
|
-
};
|
|
1
|
+
import{MatchByWritingAnswerCreator as e}from"./MatchByWritingAnswerCreator";export const matchByWritingAnswerRegistration={component:e,transformInitialData:e=>{const t=e?.content,n=e?.answer,a=e?.questionGroup,o=a?.payload||{},i=a?.groupNumber||1,r=o?.options||n?.options||[],s=o?.groupImageUrl||n?.groupImageUrl||"",p=o?.groupTitle||n?.groupTitle||"";return{question:t?.question||n?.question||"",imageUrl:t?.imageUrl||n?.imageUrl||"",correctAnswer:n?.answer||n?.correctAnswer||"",points:e?.points||1,groupNumber:n?.groupNumber||i,isExample:e?.isExample||n?.isExample||!1,askerName:t?.askerName||n?.askerName||"",answererName:t?.answererName||n?.answererName||"",options:r,groupImageUrl:s,groupTitle:p,explanation:e?.explanation||n?.explanation||""}},getExtraProps:e=>({groups:e.groups,groupConfig:e.groupConfig,questionConfig:e.questionConfig,viewMode:e.viewMode,questionIndexInPart:e.questionIndexInPart,partId:e.partId,validationRef:e.validationRef}),wrapOnSave:(e,t)=>({type:t.questionType,content:t.state.content,points:e?.points??t.state.points??1,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:e,explanation:e?.explanation||""}),wrapOnChange:(e,t)=>({type:t.questionType,content:t.state.content,points:e?.points??t.state.points??1,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:e,explanation:e?.explanation||""})};
|
|
@@ -1,61 +1 @@
|
|
|
1
|
-
function
|
|
2
|
-
if (!Array.isArray(options)) {
|
|
3
|
-
return [];
|
|
4
|
-
}
|
|
5
|
-
return options.map((option) => ({
|
|
6
|
-
answer: typeof option?.answer === 'string' ? option.answer : '',
|
|
7
|
-
content: typeof option?.content === 'string' ? option.content : '',
|
|
8
|
-
imageUrl: typeof option?.imageUrl === 'string' ? option.imageUrl : '',
|
|
9
|
-
}));
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Transform MATCH_BY_WRITING_ANSWER creator data → API format
|
|
13
|
-
*
|
|
14
|
-
* API format:
|
|
15
|
-
* content: { question, imageUrl }
|
|
16
|
-
* correctAnswer: { answer }
|
|
17
|
-
* questionGroup.payload: { options: [{ answer, imageUrl }] }
|
|
18
|
-
*/
|
|
19
|
-
export function transformMatchByWritingAnswer(question) {
|
|
20
|
-
const answerData = question.answer;
|
|
21
|
-
if (!answerData) {
|
|
22
|
-
return { apiContent: {}, apiCorrectAnswer: {} };
|
|
23
|
-
}
|
|
24
|
-
const apiContent = {
|
|
25
|
-
question: answerData.question || '',
|
|
26
|
-
};
|
|
27
|
-
// Add question image if present
|
|
28
|
-
if (answerData.imageUrl) {
|
|
29
|
-
apiContent.imageUrl = answerData.imageUrl;
|
|
30
|
-
}
|
|
31
|
-
// Add conversation names if present (viewMode = conversation)
|
|
32
|
-
if (answerData.askerName) {
|
|
33
|
-
apiContent.askerName = answerData.askerName;
|
|
34
|
-
}
|
|
35
|
-
if (answerData.answererName) {
|
|
36
|
-
apiContent.answererName = answerData.answererName;
|
|
37
|
-
}
|
|
38
|
-
const apiCorrectAnswer = {
|
|
39
|
-
answer: answerData.correctAnswer || '',
|
|
40
|
-
};
|
|
41
|
-
const normalizedOptions = normalizeMatchByWritingAnswerOptions(answerData.options);
|
|
42
|
-
// Build imageData to store shared options and group metadata in questionGroup.payload
|
|
43
|
-
const imageData = {};
|
|
44
|
-
if (normalizedOptions.length > 0) {
|
|
45
|
-
imageData.options = normalizedOptions;
|
|
46
|
-
}
|
|
47
|
-
if (answerData.groupImageUrl) {
|
|
48
|
-
imageData.groupImageUrl = answerData.groupImageUrl;
|
|
49
|
-
}
|
|
50
|
-
if (answerData.groupTitle) {
|
|
51
|
-
imageData.groupTitle = answerData.groupTitle;
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
apiContent,
|
|
55
|
-
apiCorrectAnswer,
|
|
56
|
-
totalPoints: answerData.points || 1,
|
|
57
|
-
imageData: imageData,
|
|
58
|
-
groupNumber: answerData.groupNumber || 1,
|
|
59
|
-
isExample: answerData.isExample || false,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
1
|
+
export function transformMatchByWritingAnswer(r){const e=r.answer;if(!e)return{apiContent:{},apiCorrectAnswer:{}};const t={question:e.question||""};e.imageUrl&&(t.imageUrl=e.imageUrl),e.askerName&&(t.askerName=e.askerName),e.answererName&&(t.answererName=e.answererName);const a={answer:e.correctAnswer||""},n=(o=e.options,Array.isArray(o)?o.map(r=>({answer:"string"==typeof r?.answer?r.answer:"",content:"string"==typeof r?.content?r.content:"",imageUrl:"string"==typeof r?.imageUrl?r.imageUrl:""})):[]);var o;const s={};return n.length>0&&(s.options=n),e.groupImageUrl&&(s.groupImageUrl=e.groupImageUrl),e.groupTitle&&(s.groupTitle=e.groupTitle),{apiContent:t,apiCorrectAnswer:a,totalPoints:e.points||1,imageData:s,groupNumber:e.groupNumber||1,isExample:e.isExample||!1}}
|
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { ColorRegionClient } from '../../components/ColorRegionClient';
|
|
4
|
-
const readAndColorObjectsConfig = {
|
|
5
|
-
creatorTitle: 'Đọc và tô màu',
|
|
6
|
-
creatorSubtitle: 'Tạo câu hỏi tô màu với hình ảnh và vùng màu',
|
|
7
|
-
instructionsLabel: 'Hướng dẫn tô màu',
|
|
8
|
-
instructionsTips: [],
|
|
9
|
-
instructionPlaceholder: '',
|
|
10
|
-
previewTitle: 'Read and Color Objects (Preview)',
|
|
11
|
-
clientTitle: 'Read and Color',
|
|
12
|
-
clientSubtitle: 'Đọc hướng dẫn và tô màu các vật thể trong hình',
|
|
13
|
-
};
|
|
14
|
-
export function ReadAndColorObjectsClient(props) {
|
|
15
|
-
return _jsx(ColorRegionClient, { ...props, config: readAndColorObjectsConfig });
|
|
16
|
-
}
|
|
1
|
+
"use client";import{jsx as t}from"react/jsx-runtime";import{ColorRegionClient as n}from"../../components/ColorRegionClient";const e={creatorTitle:"Đọc và tô màu",creatorSubtitle:"Tạo câu hỏi tô màu với hình ảnh và vùng màu",instructionsLabel:"Hướng dẫn tô màu",instructionsTips:[],instructionPlaceholder:"",previewTitle:"Read and Color Objects (Preview)",clientTitle:"Read and Color",clientSubtitle:"Đọc hướng dẫn và tô màu các vật thể trong hình"};export function ReadAndColorObjectsClient(i){return t(n,{...i,config:e})}
|
package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js
CHANGED
|
@@ -1,23 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { ColorRegionCreator } from '../../components/ColorRegionCreator';
|
|
4
|
-
import { ReadAndColorObjectsClient } from './ReadAndColorObjectsClient';
|
|
5
|
-
const readAndColorObjectsConfig = {
|
|
6
|
-
creatorTitle: 'Đọc và tô màu',
|
|
7
|
-
creatorSubtitle: 'Tạo câu hỏi tô màu với hình ảnh và vùng màu',
|
|
8
|
-
instructionsLabel: 'Hướng dẫn tô màu',
|
|
9
|
-
instructionsRequired: false,
|
|
10
|
-
instructionsTips: [
|
|
11
|
-
'Upload hình ảnh nền cần tô màu',
|
|
12
|
-
'Thêm các màu sắc và tạo vùng tương ứng trên hình ảnh',
|
|
13
|
-
'Kéo thả các vùng để điều chỉnh vị trí',
|
|
14
|
-
'Thêm hướng dẫn tô màu cho mỗi câu lệnh (ví dụ: "Colour the sun yellow")',
|
|
15
|
-
],
|
|
16
|
-
instructionPlaceholder: 'Colour the sun yellow',
|
|
17
|
-
previewTitle: 'Read and Color Objects (Preview)',
|
|
18
|
-
clientTitle: 'Read and Color',
|
|
19
|
-
clientSubtitle: 'Đọc hướng dẫn và tô màu các vật thể trong hình',
|
|
20
|
-
};
|
|
21
|
-
export function ReadAndColorObjectsCreator(props) {
|
|
22
|
-
return (_jsx(ColorRegionCreator, { ...props, config: readAndColorObjectsConfig, ClientComponent: ReadAndColorObjectsClient }));
|
|
23
|
-
}
|
|
1
|
+
"use client";import{jsx as n}from"react/jsx-runtime";import{ColorRegionCreator as t}from"../../components/ColorRegionCreator";import{ReadAndColorObjectsClient as o}from"./ReadAndColorObjectsClient";const e={creatorTitle:"Đọc và tô màu",creatorSubtitle:"Tạo câu hỏi tô màu với hình ảnh và vùng màu",instructionsLabel:"Hướng dẫn tô màu",instructionsRequired:!1,instructionsTips:["Upload hình ảnh nền cần tô màu","Thêm các màu sắc và tạo vùng tương ứng trên hình ảnh","Kéo thả các vùng để điều chỉnh vị trí",'Thêm hướng dẫn tô màu cho mỗi câu lệnh (ví dụ: "Colour the sun yellow")'],instructionPlaceholder:"Colour the sun yellow",previewTitle:"Read and Color Objects (Preview)",clientTitle:"Read and Color",clientSubtitle:"Đọc hướng dẫn và tô màu các vật thể trong hình"};export function ReadAndColorObjectsCreator(r){return n(t,{...r,config:e,ClientComponent:o})}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './ReadAndColorObjectsClient';
|
|
1
|
+
export*from"./ReadAndColorObjectsCreator";export*from"./ReadAndColorObjectsClient";
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createColorRegionRegistration } from '../../_shared/utils/createColorRegionRegistration';
|
|
3
|
-
export const readAndColorObjectsRegistration = createColorRegionRegistration(ReadAndColorObjectsCreator);
|
|
1
|
+
import{ReadAndColorObjectsCreator as o}from"./ReadAndColorObjectsCreator";import{createColorRegionRegistration as r}from"../../_shared/utils/createColorRegionRegistration";export const readAndColorObjectsRegistration=r(o);
|
|
@@ -1,36 +1 @@
|
|
|
1
|
-
export const transformReadAndColorObjects =
|
|
2
|
-
const answerData = question.answer;
|
|
3
|
-
if (!answerData?.backgroundImageUrl) {
|
|
4
|
-
return { apiContent: {}, apiCorrectAnswer: {} };
|
|
5
|
-
}
|
|
6
|
-
const apiContent = {
|
|
7
|
-
backgroundImageUrl: answerData.backgroundImageUrl,
|
|
8
|
-
colorNodes: (answerData.colorNodes || []).map((node) => ({
|
|
9
|
-
id: node.id,
|
|
10
|
-
color: node.color,
|
|
11
|
-
...(node.label ? { label: node.label } : {}),
|
|
12
|
-
})),
|
|
13
|
-
regionNodes: (answerData.regionNodes || []).map((region) => ({
|
|
14
|
-
id: region.id,
|
|
15
|
-
x: region.x,
|
|
16
|
-
y: region.y,
|
|
17
|
-
width: region.width,
|
|
18
|
-
height: region.height,
|
|
19
|
-
color: region.color,
|
|
20
|
-
linkedColorNodeId: region.linkedColorNodeId,
|
|
21
|
-
})),
|
|
22
|
-
instructions: answerData.instructions || [],
|
|
23
|
-
};
|
|
24
|
-
const answers = (answerData.regionNodes || []).reduce((acc, region) => {
|
|
25
|
-
if (region.id && region.color) {
|
|
26
|
-
acc[region.id] = region.color;
|
|
27
|
-
}
|
|
28
|
-
return acc;
|
|
29
|
-
}, {});
|
|
30
|
-
return {
|
|
31
|
-
apiContent,
|
|
32
|
-
apiCorrectAnswer: {
|
|
33
|
-
answers,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
};
|
|
1
|
+
export const transformReadAndColorObjects=o=>{const r=o.answer;if(!r?.backgroundImageUrl)return{apiContent:{},apiCorrectAnswer:{}};return{apiContent:{backgroundImageUrl:r.backgroundImageUrl,colorNodes:(r.colorNodes||[]).map(o=>({id:o.id,color:o.color,...o.label?{label:o.label}:{}})),regionNodes:(r.regionNodes||[]).map(o=>({id:o.id,x:o.x,y:o.y,width:o.width,height:o.height,color:o.color,linkedColorNodeId:o.linkedColorNodeId})),instructions:r.instructions||[]},apiCorrectAnswer:{answers:(r.regionNodes||[]).reduce((o,r)=>(r.id&&r.color&&(o[r.id]=r.color),o),{})}}};
|
package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js
CHANGED
|
@@ -1,125 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useRef, useEffect } from 'react';
|
|
4
|
-
import { Label } from '../../../../components/ui/label';
|
|
5
|
-
import { Textarea } from '../../../../components/ui/textarea';
|
|
6
|
-
import { PointsInput } from '../../../../components/ui/points-input';
|
|
7
|
-
import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
|
|
8
|
-
import { useDebouncedCallback } from '../../../../shared/lib/hooks';
|
|
9
|
-
import { useReactHookForm } from '../../../../shared/lib/hooks/useReactHookForm';
|
|
10
|
-
import { BookOpen, FileText, Info, MessageSquare } from 'lucide-react';
|
|
11
|
-
import { CreatorGuide } from '../../components/CreatorGuide';
|
|
12
|
-
import { readDisplayedContentFormSchema, } from '../../../../shared/lib/validation/read-displayed-content.validation';
|
|
13
|
-
export function ReadDisplayedContentCreator({ initialData, onSave, onChange, externalErrors, validationRef, }) {
|
|
14
|
-
const apiData = initialData;
|
|
15
|
-
const form = useReactHookForm({
|
|
16
|
-
defaultValues: {
|
|
17
|
-
referenceText: apiData?.referenceText || apiData?.content?.referenceText || apiData?.correctAnswer?.expectedAnswers || '',
|
|
18
|
-
explanation: apiData?.explanation || '',
|
|
19
|
-
points: apiData?.points ?? 5,
|
|
20
|
-
},
|
|
21
|
-
zodSchema: readDisplayedContentFormSchema,
|
|
22
|
-
mode: 'onBlur',
|
|
23
|
-
});
|
|
24
|
-
const previousInitialDataRef = useRef(initialData);
|
|
25
|
-
const isInitializingRef = useRef(false);
|
|
26
|
-
const onChangeRef = useRef(onChange);
|
|
27
|
-
const previousPayloadRef = useRef('');
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
onChangeRef.current = onChange;
|
|
30
|
-
}, [onChange]);
|
|
31
|
-
const debouncedOnChange = useDebouncedCallback((data) => {
|
|
32
|
-
onChangeRef.current?.(data);
|
|
33
|
-
}, 300);
|
|
34
|
-
const watchedReferenceText = form.watch('referenceText');
|
|
35
|
-
const watchedExplanation = form.watch('explanation');
|
|
36
|
-
const watchedPoints = form.watch('points');
|
|
37
|
-
// Expose validation ref for external trigger
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (validationRef) {
|
|
40
|
-
validationRef.current = {
|
|
41
|
-
triggerValidation: async () => {
|
|
42
|
-
return await form.trigger();
|
|
43
|
-
},
|
|
44
|
-
getFormData: () => ({
|
|
45
|
-
referenceText: watchedReferenceText,
|
|
46
|
-
explanation: watchedExplanation,
|
|
47
|
-
points: watchedPoints,
|
|
48
|
-
}),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
}, [validationRef, form, watchedReferenceText, watchedExplanation, watchedPoints]);
|
|
52
|
-
// Reset form when initialData changes externally
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
const apiD = initialData;
|
|
55
|
-
const normalizedInitialData = {
|
|
56
|
-
referenceText: apiD?.referenceText || apiD?.content?.referenceText || apiD?.correctAnswer?.expectedAnswers || '',
|
|
57
|
-
explanation: apiD?.explanation || '',
|
|
58
|
-
points: apiD?.points ?? 5,
|
|
59
|
-
};
|
|
60
|
-
const initialDataChanged = JSON.stringify(previousInitialDataRef.current) !== JSON.stringify(initialData);
|
|
61
|
-
if (!initialDataChanged) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
previousInitialDataRef.current = initialData;
|
|
65
|
-
const currentFormData = {
|
|
66
|
-
referenceText: watchedReferenceText,
|
|
67
|
-
explanation: watchedExplanation,
|
|
68
|
-
points: watchedPoints,
|
|
69
|
-
};
|
|
70
|
-
const isEchoFromOnChange = currentFormData.points === normalizedInitialData.points &&
|
|
71
|
-
currentFormData.explanation === normalizedInitialData.explanation &&
|
|
72
|
-
currentFormData.referenceText === normalizedInitialData.referenceText;
|
|
73
|
-
const wasJustSaved = initialData?.isCompleted === true;
|
|
74
|
-
if (isEchoFromOnChange && wasJustSaved) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const shouldReset = !isEchoFromOnChange;
|
|
78
|
-
if (shouldReset) {
|
|
79
|
-
isInitializingRef.current = true;
|
|
80
|
-
form.reset(normalizedInitialData);
|
|
81
|
-
setTimeout(() => {
|
|
82
|
-
isInitializingRef.current = false;
|
|
83
|
-
}, 150);
|
|
84
|
-
}
|
|
85
|
-
}, [initialData, form, watchedReferenceText, watchedExplanation, watchedPoints]);
|
|
86
|
-
// Debounced onChange
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
if (isInitializingRef.current) {
|
|
89
|
-
const currentPayload = JSON.stringify({
|
|
90
|
-
referenceText: watchedReferenceText,
|
|
91
|
-
explanation: watchedExplanation,
|
|
92
|
-
points: watchedPoints,
|
|
93
|
-
});
|
|
94
|
-
previousPayloadRef.current = currentPayload;
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const payload = {
|
|
98
|
-
referenceText: watchedReferenceText,
|
|
99
|
-
explanation: watchedExplanation,
|
|
100
|
-
points: watchedPoints,
|
|
101
|
-
};
|
|
102
|
-
const payloadString = JSON.stringify(payload);
|
|
103
|
-
if (previousPayloadRef.current !== payloadString) {
|
|
104
|
-
previousPayloadRef.current = payloadString;
|
|
105
|
-
debouncedOnChange(payload);
|
|
106
|
-
}
|
|
107
|
-
}, [
|
|
108
|
-
watchedReferenceText,
|
|
109
|
-
watchedExplanation,
|
|
110
|
-
watchedPoints,
|
|
111
|
-
debouncedOnChange,
|
|
112
|
-
]);
|
|
113
|
-
const handleSave = form.handleSubmit((data) => {
|
|
114
|
-
onSave?.({
|
|
115
|
-
...data,
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(CreatorGuide, { colorScheme: "blue", steps: [
|
|
119
|
-
{ text: 'Nhập đoạn văn bản mà học sinh sẽ đọc to (reference text)', highlight: true },
|
|
120
|
-
{ text: 'Thêm giải thích (tùy chọn)' },
|
|
121
|
-
], tips: [
|
|
122
|
-
'Học sinh sẽ nhìn thấy đoạn văn trên màn hình và đọc to.',
|
|
123
|
-
'AI sẽ so sánh giọng đọc của học sinh với văn bản gốc (Phonetic Distance).',
|
|
124
|
-
] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white", children: [_jsx(CardHeader, { className: "px-4 py-3", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100", children: _jsx(FileText, { className: "h-4 w-4 text-gray-600" }) }), _jsxs("div", { children: [_jsx(CardTitle, { className: "text-base font-bold text-gray-900", children: "\u0110o\u1EA1n v\u0103n b\u1EA3n c\u1EA7n \u0111\u1ECDc" }), _jsx("p", { className: "text-xs text-gray-500", children: "T\u1EA1o c\u00E2u h\u1ECFi \u0111\u1ECDc \u0111o\u1EA1n v\u0103n" })] })] }) }) }), _jsxs(CardContent, { className: "space-y-3 px-4 pb-4", children: [_jsx("div", { className: "flex items-center gap-6", children: _jsx(PointsInput, { ...form.register('points', { valueAsNumber: true }), error: form.hasError('points') ? form.getFieldError('points') : undefined }) }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "referenceText", className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-indigo-500" }), _jsx("span", { className: "flex items-center gap-1", children: "\u0110o\u1EA1n v\u0103n b\u1EA3n" }), _jsx("span", { className: "text-sm font-normal text-red-500", children: "*" })] }), _jsx(Textarea, { id: "referenceText", ...form.register('referenceText'), placeholder: "VD: The fat cat sat on a red mat. It has a small bell on its neck. The bell rings when the cat jumps.", rows: 4, className: `min-h-[120px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 resize-none ${form.hasError('referenceText') ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), form.hasError('referenceText') && (_jsx("p", { className: "text-sm text-red-600", children: form.getFieldError('referenceText') })), _jsxs("div", { className: "mt-2 flex items-start gap-3 rounded-xl border border-blue-100 bg-gradient-to-r from-blue-50 to-indigo-50 p-4 text-sm text-blue-800", children: [_jsx(Info, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-indigo-500" }), _jsx("p", { children: "\u0110\u00E2y l\u00E0 \u0111o\u1EA1n v\u0103n s\u1EBD hi\u1EC3n th\u1ECB tr\u00EAn m\u00E0n h\u00ECnh cho h\u1ECDc sinh \u0111\u1ECDc to. AI s\u1EBD so s\u00E1nh ph\u00E1t \u00E2m c\u1EE7a h\u1ECDc sinh v\u1EDBi \u0111o\u1EA1n v\u0103n n\u00E0y." })] })] }), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100", children: _jsx("span", { className: "text-lg", children: "\u274C" }) }), _jsxs("div", { className: "text-sm", children: [_jsx("p", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("ul", { className: "mt-1 list-inside list-disc text-red-700", children: externalErrors.map((error, index) => (_jsx("li", { children: error }, index))) })] })] }))] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white", children: [_jsx(CardHeader, { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm", children: _jsx(BookOpen, { className: "h-3.5 w-3.5 text-white" }) }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-base font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" }), _jsx("span", { className: "inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600", children: "Kh\u00F4ng b\u1EAFt bu\u1ED9c" })] }), _jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Gi\u1EA3i th\u00EDch cho \u0111\u00E1p \u00E1n \u0111\u00FAng \u2014 hi\u1EC3n th\u1ECB sau khi h\u1ECDc sinh ho\u00E0n th\u00E0nh c\u00E2u h\u1ECFi" })] })] }) }), _jsx(CardContent, { className: "px-4 pb-4", children: _jsx(Textarea, { value: watchedExplanation || '', onChange: (e) => form.setValue('explanation', e.target.value, { shouldValidate: true }), placeholder: "VD: \u0110o\u1EA1n v\u0103n t\u1EADp trung v\u00E0o c\u00E1c \u00E2m ng\u1EAFn /\u00E6/, /e/, /\u026A/...", rows: 3, className: "min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none" }) })] })] }));
|
|
125
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useRef as t,useEffect as n}from"react";import{Label as i}from"../../../../components/ui/label";import{Textarea as s}from"../../../../components/ui/textarea";import{PointsInput as a}from"../../../../components/ui/points-input";import{Card as c,CardContent as o,CardHeader as l,CardTitle as d}from"../../../../components/ui/card";import{useDebouncedCallback as h}from"../../../../shared/lib/hooks";import{useReactHookForm as m}from"../../../../shared/lib/hooks/useReactHookForm";import{BookOpen as x,FileText as p,Info as f,MessageSquare as g}from"lucide-react";import{CreatorGuide as u}from"../../components/CreatorGuide";import{readDisplayedContentFormSchema as b}from"../../../../shared/lib/validation/read-displayed-content.validation";export function ReadDisplayedContentCreator({initialData:N,onSave:v,onChange:y,externalErrors:w,validationRef:T}){const j=N,S=m({defaultValues:{referenceText:j?.referenceText||j?.content?.referenceText||j?.correctAnswer?.expectedAnswers||"",explanation:j?.explanation||"",points:j?.points??5},zodSchema:b,mode:"onBlur"}),k=t(N),A=t(!1),C=t(y),D=t("");n(()=>{C.current=y},[y]);const E=h(e=>{C.current?.(e)},300),V=S.watch("referenceText"),F=S.watch("explanation"),J=S.watch("points");n(()=>{T&&(T.current={triggerValidation:async()=>await S.trigger(),getFormData:()=>({referenceText:V,explanation:F,points:J})})},[T,S,V,F,J]),n(()=>{const e=N,r={referenceText:e?.referenceText||e?.content?.referenceText||e?.correctAnswer?.expectedAnswers||"",explanation:e?.explanation||"",points:e?.points??5};if(!(JSON.stringify(k.current)!==JSON.stringify(N)))return;k.current=N;const t=J===r.points&&F===r.explanation&&V===r.referenceText;if(t&&!0===N?.isCompleted)return;!t&&(A.current=!0,S.reset(r),setTimeout(()=>{A.current=!1},150))},[N,S,V,F,J]),n(()=>{if(A.current){const e=JSON.stringify({referenceText:V,explanation:F,points:J});return void(D.current=e)}const e={referenceText:V,explanation:F,points:J},r=JSON.stringify(e);D.current!==r&&(D.current=r,E(e))},[V,F,J,E]);S.handleSubmit(e=>{v?.({...e})});return r("div",{className:"space-y-4",children:[e(u,{colorScheme:"blue",steps:[{text:"Nhập đoạn văn bản mà học sinh sẽ đọc to (reference text)",highlight:!0},{text:"Thêm giải thích (tùy chọn)"}],tips:["Học sinh sẽ nhìn thấy đoạn văn trên màn hình và đọc to.","AI sẽ so sánh giọng đọc của học sinh với văn bản gốc (Phonetic Distance)."]}),r(c,{className:"overflow-hidden border-0 bg-white",children:[e(l,{className:"px-4 py-3",children:e("div",{className:"flex items-center justify-between",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100",children:e(p,{className:"h-4 w-4 text-gray-600"})}),r("div",{children:[e(d,{className:"text-base font-bold text-gray-900",children:"Đoạn văn bản cần đọc"}),e("p",{className:"text-xs text-gray-500",children:"Tạo câu hỏi đọc đoạn văn"})]})]})})}),r(o,{className:"space-y-3 px-4 pb-4",children:[e("div",{className:"flex items-center gap-6",children:e(a,{...S.register("points",{valueAsNumber:!0}),error:S.hasError("points")?S.getFieldError("points"):void 0})}),r("div",{className:"space-y-2",children:[r(i,{htmlFor:"referenceText",className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(g,{className:"h-4 w-4 text-indigo-500"}),e("span",{className:"flex items-center gap-1",children:"Đoạn văn bản"}),e("span",{className:"text-sm font-normal text-red-500",children:"*"})]}),e(s,{id:"referenceText",...S.register("referenceText"),placeholder:"VD: The fat cat sat on a red mat. It has a small bell on its neck. The bell rings when the cat jumps.",rows:4,className:"min-h-[120px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 resize-none "+(S.hasError("referenceText")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),S.hasError("referenceText")&&e("p",{className:"text-sm text-red-600",children:S.getFieldError("referenceText")}),r("div",{className:"mt-2 flex items-start gap-3 rounded-xl border border-blue-100 bg-gradient-to-r from-blue-50 to-indigo-50 p-4 text-sm text-blue-800",children:[e(f,{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-indigo-500"}),e("p",{children:"Đây là đoạn văn sẽ hiển thị trên màn hình cho học sinh đọc to. AI sẽ so sánh phát âm của học sinh với đoạn văn này."})]})]}),w&&w.length>0&&r("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100",children:e("span",{className:"text-lg",children:"❌"})}),r("div",{className:"text-sm",children:[e("p",{className:"font-semibold text-red-800",children:"Lỗi:"}),e("ul",{className:"mt-1 list-inside list-disc text-red-700",children:w.map((r,t)=>e("li",{children:r},t))})]})]})]})]}),r(c,{className:"overflow-hidden border-0 bg-white",children:[e(l,{className:"px-4 py-3",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm",children:e(x,{className:"h-3.5 w-3.5 text-white"})}),r("div",{children:[r("div",{className:"flex items-center gap-2",children:[e(d,{className:"text-base font-semibold text-gray-800",children:"Giải thích"}),e("span",{className:"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600",children:"Không bắt buộc"})]}),e("p",{className:"text-xs text-gray-500 mt-0.5",children:"Giải thích cho đáp án đúng — hiển thị sau khi học sinh hoàn thành câu hỏi"})]})]})}),e(o,{className:"px-4 pb-4",children:e(s,{value:F||"",onChange:e=>S.setValue("explanation",e.target.value,{shouldValidate:!0}),placeholder:"VD: Đoạn văn tập trung vào các âm ngắn /æ/, /e/, /ɪ/...",rows:3,className:"min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none"})})]})]})}
|
|
@@ -1,64 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const readDisplayedContentRegistration = {
|
|
3
|
-
component: ReadDisplayedContentCreator,
|
|
4
|
-
transformInitialData: (initialData) => {
|
|
5
|
-
let creatorData = initialData?.answer;
|
|
6
|
-
const content = initialData?.content;
|
|
7
|
-
const answer = initialData?.answer || initialData?.correctAnswer || initialData?.correct_answer;
|
|
8
|
-
const referenceTextValue = answer?.referenceText || answer?.expectedAnswers || content?.referenceText || '';
|
|
9
|
-
const points = initialData?.total_points
|
|
10
|
-
? parseFloat(initialData.total_points)
|
|
11
|
-
: (initialData?.points || content?.points || answer?.points || 5);
|
|
12
|
-
const explanation = initialData?.explanation || content?.explanation || answer?.explanation || '';
|
|
13
|
-
if (content && typeof content === 'object' && (content.referenceText !== undefined || answer?.expectedAnswers !== undefined)) {
|
|
14
|
-
creatorData = {
|
|
15
|
-
referenceText: referenceTextValue,
|
|
16
|
-
explanation,
|
|
17
|
-
points,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
else if (answer && typeof answer === 'object') {
|
|
21
|
-
creatorData = {
|
|
22
|
-
...answer,
|
|
23
|
-
referenceText: referenceTextValue,
|
|
24
|
-
explanation,
|
|
25
|
-
points,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
return creatorData;
|
|
29
|
-
},
|
|
30
|
-
getExtraProps: (ctx) => ({
|
|
31
|
-
onUnsavedChangesChange: ctx.onUnsavedChangesChange,
|
|
32
|
-
validationRef: ctx.validationRef,
|
|
33
|
-
}),
|
|
34
|
-
wrapOnSave: (data, ctx) => ({
|
|
35
|
-
type: ctx.questionType,
|
|
36
|
-
content: {
|
|
37
|
-
...(typeof ctx.state.content === 'object' && ctx.state.content !== null ? ctx.state.content : {}),
|
|
38
|
-
referenceText: data.referenceText,
|
|
39
|
-
},
|
|
40
|
-
points: data?.points ?? ctx.state.points ?? 5,
|
|
41
|
-
level: ctx.state.level,
|
|
42
|
-
difficulty: ctx.state.difficulty,
|
|
43
|
-
skill: ctx.state.skill,
|
|
44
|
-
answer: {
|
|
45
|
-
expectedAnswers: data.referenceText,
|
|
46
|
-
},
|
|
47
|
-
explanation: data?.explanation || '',
|
|
48
|
-
}),
|
|
49
|
-
wrapOnChange: (data, ctx) => ({
|
|
50
|
-
type: ctx.questionType,
|
|
51
|
-
content: {
|
|
52
|
-
...(typeof ctx.state.content === 'object' && ctx.state.content !== null ? ctx.state.content : {}),
|
|
53
|
-
referenceText: data.referenceText,
|
|
54
|
-
},
|
|
55
|
-
points: data?.points ?? ctx.state.points ?? 5,
|
|
56
|
-
level: ctx.state.level,
|
|
57
|
-
difficulty: ctx.state.difficulty,
|
|
58
|
-
skill: ctx.state.skill,
|
|
59
|
-
answer: {
|
|
60
|
-
expectedAnswers: data.referenceText,
|
|
61
|
-
},
|
|
62
|
-
explanation: data?.explanation || '',
|
|
63
|
-
}),
|
|
64
|
-
};
|
|
1
|
+
import{ReadDisplayedContentCreator as e}from"./ReadDisplayedContentCreator";export const readDisplayedContentRegistration={component:e,transformInitialData:e=>{let t=e?.answer;const n=e?.content,a=e?.answer||e?.correctAnswer||e?.correct_answer,o=a?.referenceText||a?.expectedAnswers||n?.referenceText||"",s=e?.total_points?parseFloat(e.total_points):e?.points||n?.points||a?.points||5,r=e?.explanation||n?.explanation||a?.explanation||"";return!n||"object"!=typeof n||void 0===n.referenceText&&void 0===a?.expectedAnswers?a&&"object"==typeof a&&(t={...a,referenceText:o,explanation:r,points:s}):t={referenceText:o,explanation:r,points:s},t},getExtraProps:e=>({onUnsavedChangesChange:e.onUnsavedChangesChange,validationRef:e.validationRef}),wrapOnSave:(e,t)=>({type:t.questionType,content:{..."object"==typeof t.state.content&&null!==t.state.content?t.state.content:{},referenceText:e.referenceText},points:e?.points??t.state.points??5,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:{expectedAnswers:e.referenceText},explanation:e?.explanation||""}),wrapOnChange:(e,t)=>({type:t.questionType,content:{..."object"==typeof t.state.content&&null!==t.state.content?t.state.content:{},referenceText:e.referenceText},points:e?.points??t.state.points??5,level:t.state.level,difficulty:t.state.difficulty,skill:t.state.skill,answer:{expectedAnswers:e.referenceText},explanation:e?.explanation||""})};
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
export const transformReadDisplayedContent
|
|
2
|
-
const contentData = question.content;
|
|
3
|
-
const answerData = question.answer;
|
|
4
|
-
const referenceText = contentData?.referenceText || answerData?.referenceText || answerData?.expectedAnswers || '';
|
|
5
|
-
const apiContent = {
|
|
6
|
-
referenceText,
|
|
7
|
-
};
|
|
8
|
-
return {
|
|
9
|
-
apiContent,
|
|
10
|
-
apiCorrectAnswer: {},
|
|
11
|
-
};
|
|
12
|
-
};
|
|
1
|
+
export const transformReadDisplayedContent=e=>{const n=e.content,r=e.answer;return{apiContent:{referenceText:n?.referenceText||r?.referenceText||r?.expectedAnswers||""},apiCorrectAnswer:{}}};
|
|
@@ -1,64 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import { cn } from '../../../../shared/lib/utils';
|
|
5
|
-
import { Check, X, BookOpen, FileText, ClipboardList, Lightbulb } from 'lucide-react';
|
|
6
|
-
export function ReadPassageAndAnswerQuestionsClient({ questionData, userAnswer, isReviewMode = false, onSubmit, autoFillCorrectAnswers = false, explanation: explanationProp, }) {
|
|
7
|
-
const { passage, passageTitle, instructions, singleQuestion, explanation: dataExplanation } = questionData;
|
|
8
|
-
const explanation = explanationProp || dataExplanation;
|
|
9
|
-
// Single answer state
|
|
10
|
-
const [selectedAnswer, setSelectedAnswer] = useState(() => {
|
|
11
|
-
if (autoFillCorrectAnswers && singleQuestion) {
|
|
12
|
-
return singleQuestion.correctAnswer;
|
|
13
|
-
}
|
|
14
|
-
return typeof userAnswer === 'number' ? userAnswer : -1;
|
|
15
|
-
});
|
|
16
|
-
const previousUserAnswerRef = useRef(JSON.stringify(userAnswer));
|
|
17
|
-
// Sync userAnswer when it changes
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (autoFillCorrectAnswers)
|
|
20
|
-
return;
|
|
21
|
-
const currentUserAnswerStr = JSON.stringify(userAnswer);
|
|
22
|
-
if (previousUserAnswerRef.current !== currentUserAnswerStr) {
|
|
23
|
-
previousUserAnswerRef.current = currentUserAnswerStr;
|
|
24
|
-
setSelectedAnswer(typeof userAnswer === 'number' ? userAnswer : -1);
|
|
25
|
-
}
|
|
26
|
-
}, [userAnswer, autoFillCorrectAnswers]);
|
|
27
|
-
// Handle answer change
|
|
28
|
-
const handleAnswerChange = (value) => {
|
|
29
|
-
if (isReviewMode)
|
|
30
|
-
return;
|
|
31
|
-
setSelectedAnswer(value);
|
|
32
|
-
onSubmit?.(value);
|
|
33
|
-
};
|
|
34
|
-
// If no singleQuestion data, show empty state
|
|
35
|
-
if (!singleQuestion) {
|
|
36
|
-
return (_jsx("div", { className: "text-center text-gray-500 py-8", children: "Kh\u00F4ng c\u00F3 c\u00E2u h\u1ECFi n\u00E0o" }));
|
|
37
|
-
}
|
|
38
|
-
const isCorrect = isReviewMode && selectedAnswer === singleQuestion.correctAnswer;
|
|
39
|
-
const isWrong = isReviewMode && selectedAnswer >= 0 && selectedAnswer !== singleQuestion.correctAnswer;
|
|
40
|
-
const hasAnswered = selectedAnswer >= 0;
|
|
41
|
-
return (_jsxs("div", { className: "space-y-5", children: [instructions && (_jsx("div", { className: "overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 shadow-sm", children: _jsxs("div", { className: "flex items-center gap-3 px-5 py-4", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm", children: _jsx(FileText, { className: "h-4 w-4" }) }), _jsx("p", { className: "text-sm font-medium text-blue-900", children: instructions })] }) })), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-sm", children: _jsx(BookOpen, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "\u0110o\u1EA1n v\u0103n \u0111\u1ECDc hi\u1EC3u" })] }), _jsxs("div", { className: "p-5 space-y-4", children: [passageTitle && (_jsx("h3", { className: "text-center text-lg font-bold text-gray-900 border-b border-gray-100 pb-3", children: passageTitle })), _jsx("div", { className: "rounded-lg bg-gradient-to-br from-slate-50 to-gray-50 p-5 border border-gray-100", children: _jsx("p", { className: "whitespace-pre-wrap text-base leading-relaxed text-gray-700", children: passage }) })] })] }), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: cn('flex items-center justify-between border-b px-5 py-3', isReviewMode && isCorrect && 'border-green-200 bg-gradient-to-r from-green-50 to-emerald-50', isReviewMode && isWrong && 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50', !isReviewMode && 'border-gray-100 bg-gradient-to-r from-gray-50 to-white'), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-8 w-8 items-center justify-center rounded-lg text-sm font-bold text-white shadow-sm', isReviewMode && isCorrect && 'bg-gradient-to-br from-green-500 to-emerald-600', isReviewMode && isWrong && 'bg-gradient-to-br from-red-500 to-rose-600', !isReviewMode && 'bg-gradient-to-br from-indigo-500 to-purple-600'), children: _jsx(ClipboardList, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-800", children: singleQuestion.question })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold', isCorrect ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'), children: [isCorrect ? _jsx(Check, { className: "h-3.5 w-3.5" }) : _jsx(X, { className: "h-3.5 w-3.5" }), isCorrect ? 'Đúng' : 'Sai'] }))] }), _jsxs("div", { className: "p-5 space-y-2.5", children: [singleQuestion.options.map((option, optIndex) => {
|
|
42
|
-
const isSelected = selectedAnswer === optIndex;
|
|
43
|
-
const isCorrectOption = optIndex === singleQuestion.correctAnswer;
|
|
44
|
-
const letter = String.fromCharCode(65 + optIndex);
|
|
45
|
-
return (_jsxs("button", { type: "button", onClick: () => handleAnswerChange(optIndex), disabled: isReviewMode, className: cn('group flex w-full items-center gap-3 rounded-lg border-2 p-3.5 text-left transition-all', isReviewMode
|
|
46
|
-
? isCorrectOption
|
|
47
|
-
? 'border-green-400 bg-green-50'
|
|
48
|
-
: isSelected
|
|
49
|
-
? 'border-red-400 bg-red-50'
|
|
50
|
-
: 'border-gray-200 bg-gray-50'
|
|
51
|
-
: isSelected
|
|
52
|
-
? 'border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100'
|
|
53
|
-
: 'border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm'), children: [_jsx("div", { className: cn('flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all', isReviewMode
|
|
54
|
-
? isCorrectOption
|
|
55
|
-
? 'bg-green-500 text-white'
|
|
56
|
-
: isSelected
|
|
57
|
-
? 'bg-red-500 text-white'
|
|
58
|
-
: 'bg-gray-200 text-gray-600'
|
|
59
|
-
: isSelected
|
|
60
|
-
? 'bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm'
|
|
61
|
-
: 'bg-gray-100 text-gray-600 group-hover:bg-gray-200'), children: letter }), _jsx("span", { className: cn('flex-1 text-sm font-medium', isReviewMode && isCorrectOption ? 'text-green-800' :
|
|
62
|
-
isReviewMode && isSelected && !isCorrectOption ? 'text-red-800' : 'text-gray-700'), children: option }), isReviewMode && (isCorrectOption || isSelected) && (_jsx("div", { className: cn('flex h-6 w-6 items-center justify-center rounded-full', isCorrectOption ? 'bg-green-500' : 'bg-red-500'), children: isCorrectOption ? _jsx(Check, { className: "h-4 w-4 text-white" }) : _jsx(X, { className: "h-4 w-4 text-white" }) }))] }, optIndex));
|
|
63
|
-
}), !isReviewMode && !hasAnswered && (_jsxs("div", { className: "rounded-lg border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-3 flex items-center gap-2 mt-3", children: [_jsx("div", { className: "flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-amber-400 text-white", children: _jsx("span", { className: "text-xs font-bold", children: "!" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng ch\u1ECDn m\u1ED9t \u0111\u00E1p \u00E1n" })] })), isReviewMode && isWrong && (_jsx("div", { className: "rounded-lg bg-gradient-to-r from-green-50 to-emerald-50 p-4 border border-green-200 mt-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Check, { className: "h-4 w-4 text-green-600" }), _jsxs("span", { className: "text-sm text-green-700", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", _jsxs("strong", { children: [String.fromCharCode(65 + singleQuestion.correctAnswer), ". ", singleQuestion.options[singleQuestion.correctAnswer]] })] })] }) }))] })] }), isReviewMode && explanation && (_jsxs("div", { className: "overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-br from-blue-50 to-indigo-50 shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-blue-100 bg-white/50 px-4 py-3", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm", children: _jsx(Lightbulb, { className: "h-4 w-4" }) }), _jsx("h4", { className: "text-sm font-semibold text-gray-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-sm text-gray-700 leading-relaxed", children: explanation }) })] }))] }));
|
|
64
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t,useEffect as s,useRef as a}from"react";import{cn as n}from"../../../../shared/lib/utils";import{Check as d,X as i,BookOpen as o,FileText as l,ClipboardList as c,Lightbulb as g}from"lucide-react";export function ReadPassageAndAnswerQuestionsClient({questionData:m,userAnswer:b,isReviewMode:h=!1,onSubmit:x,autoFillCorrectAnswers:f=!1,explanation:u}){const{passage:p,passageTitle:w,instructions:y,singleQuestion:N,explanation:v}=m,j=u||v,[A,C]=t(()=>f&&N?N.correctAnswer:"number"==typeof b?b:-1),S=a(JSON.stringify(b));s(()=>{if(f)return;const e=JSON.stringify(b);S.current!==e&&(S.current=e,C("number"==typeof b?b:-1))},[b,f]);if(!N)return e("div",{className:"text-center text-gray-500 py-8",children:"Không có câu hỏi nào"});const k=h&&A===N.correctAnswer,q=h&&A>=0&&A!==N.correctAnswer,J=A>=0;return r("div",{className:"space-y-5",children:[y&&e("div",{className:"overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 shadow-sm",children:r("div",{className:"flex items-center gap-3 px-5 py-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm",children:e(l,{className:"h-4 w-4"})}),e("p",{className:"text-sm font-medium text-blue-900",children:y})]})}),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Đoạn văn đọc hiểu"})]}),r("div",{className:"p-5 space-y-4",children:[w&&e("h3",{className:"text-center text-lg font-bold text-gray-900 border-b border-gray-100 pb-3",children:w}),e("div",{className:"rounded-lg bg-gradient-to-br from-slate-50 to-gray-50 p-5 border border-gray-100",children:e("p",{className:"whitespace-pre-wrap text-base leading-relaxed text-gray-700",children:p})})]})]}),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:n("flex items-center justify-between border-b px-5 py-3",h&&k&&"border-green-200 bg-gradient-to-r from-green-50 to-emerald-50",h&&q&&"border-red-200 bg-gradient-to-r from-red-50 to-rose-50",!h&&"border-gray-100 bg-gradient-to-r from-gray-50 to-white"),children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-8 w-8 items-center justify-center rounded-lg text-sm font-bold text-white shadow-sm",h&&k&&"bg-gradient-to-br from-green-500 to-emerald-600",h&&q&&"bg-gradient-to-br from-red-500 to-rose-600",!h&&"bg-gradient-to-br from-indigo-500 to-purple-600"),children:e(c,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-800",children:N.question})]}),h&&J&&r("div",{className:n("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",k?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(k?d:i,{className:"h-3.5 w-3.5"}),k?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-2.5",children:[N.options.map((t,s)=>{const a=A===s,o=s===N.correctAnswer,l=String.fromCharCode(65+s);return r("button",{type:"button",onClick:()=>{return e=s,void(h||(C(e),x?.(e)));var e},disabled:h,className:n("group flex w-full items-center gap-3 rounded-lg border-2 p-3.5 text-left transition-all",h?o?"border-green-400 bg-green-50":a?"border-red-400 bg-red-50":"border-gray-200 bg-gray-50":a?"border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100":"border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm"),children:[e("div",{className:n("flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all",h?o?"bg-green-500 text-white":a?"bg-red-500 text-white":"bg-gray-200 text-gray-600":a?"bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm":"bg-gray-100 text-gray-600 group-hover:bg-gray-200"),children:l}),e("span",{className:n("flex-1 text-sm font-medium",h&&o?"text-green-800":h&&a&&!o?"text-red-800":"text-gray-700"),children:t}),h&&(o||a)&&e("div",{className:n("flex h-6 w-6 items-center justify-center rounded-full",o?"bg-green-500":"bg-red-500"),children:e(o?d:i,{className:"h-4 w-4 text-white"})})]},s)}),!h&&!J&&r("div",{className:"rounded-lg border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-3 flex items-center gap-2 mt-3",children:[e("div",{className:"flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-amber-400 text-white",children:e("span",{className:"text-xs font-bold",children:"!"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng chọn một đáp án"})]}),h&&q&&e("div",{className:"rounded-lg bg-gradient-to-r from-green-50 to-emerald-50 p-4 border border-green-200 mt-3",children:r("div",{className:"flex items-center gap-2",children:[e(d,{className:"h-4 w-4 text-green-600"}),r("span",{className:"text-sm text-green-700",children:["Đáp án đúng: ",r("strong",{children:[String.fromCharCode(65+N.correctAnswer),". ",N.options[N.correctAnswer]]})]})]})})]})]}),h&&j&&r("div",{className:"overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-br from-blue-50 to-indigo-50 shadow-sm",children:[r("div",{className:"flex items-center gap-2 border-b border-blue-100 bg-white/50 px-4 py-3",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",children:e(g,{className:"h-4 w-4"})}),e("h4",{className:"text-sm font-semibold text-gray-800",children:"Giải thích"})]}),e("div",{className:"p-4",children:e("p",{className:"text-sm text-gray-700 leading-relaxed",children:j})})]})]})}
|