@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,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './ChooseTheCorrectAnswerClient';
|
|
1
|
+
export*from"./ChooseTheCorrectAnswerCreator";export*from"./ChooseTheCorrectAnswerClient";
|
|
@@ -1,101 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const chooseTheCorrectAnswerRegistration = {
|
|
3
|
-
component: ChooseTheCorrectAnswerCreator,
|
|
4
|
-
transformInitialData: (initialData) => {
|
|
5
|
-
let creatorData = initialData?.answer;
|
|
6
|
-
const content = initialData?.content;
|
|
7
|
-
const answer = initialData?.answer;
|
|
8
|
-
const points = initialData?.total_points
|
|
9
|
-
? parseFloat(initialData.total_points)
|
|
10
|
-
: (initialData?.points || content?.points || answer?.points || 1);
|
|
11
|
-
const explanation = initialData?.explanation || content?.explanation || answer?.explanation || '';
|
|
12
|
-
// Extract group info from API format
|
|
13
|
-
const questionGroup = initialData?.questionGroup || {};
|
|
14
|
-
const groupPayload = questionGroup?.payload || {};
|
|
15
|
-
if (content && typeof content === 'object' && (content.question !== undefined || content.options)) {
|
|
16
|
-
const optionsStrings = content.options || [];
|
|
17
|
-
const rawCorrectAnswer = answer?.answer;
|
|
18
|
-
const normalizedCorrectAnswer = Array.isArray(rawCorrectAnswer)
|
|
19
|
-
? rawCorrectAnswer
|
|
20
|
-
: typeof rawCorrectAnswer === 'number'
|
|
21
|
-
? rawCorrectAnswer
|
|
22
|
-
: -1;
|
|
23
|
-
const isMultipleAnswers = Boolean(content?.multipleAnswers
|
|
24
|
-
?? answer?.multipleAnswers
|
|
25
|
-
?? initialData?.multipleAnswers
|
|
26
|
-
?? groupPayload?.multipleAnswers
|
|
27
|
-
?? Array.isArray(normalizedCorrectAnswer));
|
|
28
|
-
creatorData = {
|
|
29
|
-
question: content.question || '',
|
|
30
|
-
optionType: content.optionType || 'text',
|
|
31
|
-
options: optionsStrings,
|
|
32
|
-
correctAnswer: normalizedCorrectAnswer,
|
|
33
|
-
multipleAnswers: isMultipleAnswers,
|
|
34
|
-
imageUrl: content.imageUrl || '',
|
|
35
|
-
askerName: content.askerName || '',
|
|
36
|
-
answererName: content.answererName || '',
|
|
37
|
-
isExample: initialData?.isExample || answer?.isExample || false,
|
|
38
|
-
explanation,
|
|
39
|
-
points,
|
|
40
|
-
// Add group stuff
|
|
41
|
-
groupTitle: groupPayload?.title || answer?.groupTitle || '',
|
|
42
|
-
groupContent: groupPayload?.content || answer?.groupContent || '',
|
|
43
|
-
groupImageUrl: groupPayload?.imageUrl || answer?.groupImageUrl || content?.groupImageUrl || '',
|
|
44
|
-
groupNumber: questionGroup.groupNumber || answer?.groupNumber || 1,
|
|
45
|
-
articles: groupPayload?.articles || answer?.articles || undefined,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
else if (answer && typeof answer === 'object' && (answer.question !== undefined || answer.options)) {
|
|
49
|
-
creatorData = {
|
|
50
|
-
...answer,
|
|
51
|
-
multipleAnswers: Boolean(answer?.multipleAnswers ?? initialData?.multipleAnswers ?? Array.isArray(answer?.correctAnswer)),
|
|
52
|
-
optionType: answer.optionType || content?.optionType || 'text',
|
|
53
|
-
imageUrl: answer.imageUrl || content?.imageUrl || '',
|
|
54
|
-
isExample: initialData?.isExample || answer?.isExample || false,
|
|
55
|
-
explanation,
|
|
56
|
-
points,
|
|
57
|
-
// Add group stuff
|
|
58
|
-
groupTitle: groupPayload?.title || answer?.groupTitle || '',
|
|
59
|
-
groupContent: groupPayload?.content || answer?.groupContent || '',
|
|
60
|
-
groupImageUrl: groupPayload?.imageUrl || answer?.groupImageUrl || content?.groupImageUrl || '',
|
|
61
|
-
groupNumber: questionGroup.groupNumber || answer?.groupNumber || 1,
|
|
62
|
-
articles: groupPayload?.articles || answer?.articles || undefined,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
return creatorData;
|
|
66
|
-
},
|
|
67
|
-
getExtraProps: (ctx) => ({
|
|
68
|
-
optionCount: ctx.optionCount || 4,
|
|
69
|
-
optionMode: ctx.optionMode,
|
|
70
|
-
defaultValue: ctx.defaultValue,
|
|
71
|
-
defaultQuestion: ctx.defaultQuestion,
|
|
72
|
-
viewMode: ctx.viewMode,
|
|
73
|
-
onUnsavedChangesChange: ctx.onUnsavedChangesChange,
|
|
74
|
-
validationRef: ctx.validationRef,
|
|
75
|
-
groups: ctx.groups,
|
|
76
|
-
groupType: ctx.groupType,
|
|
77
|
-
articleCount: ctx.articleCount,
|
|
78
|
-
questionIndexInPart: ctx.questionIndexInPart,
|
|
79
|
-
partId: ctx.partId,
|
|
80
|
-
questionConfig: ctx.questionConfig,
|
|
81
|
-
multipleAnswers: ctx.multipleAnswers,
|
|
82
|
-
}),
|
|
83
|
-
wrapOnSave: (data, ctx) => ({
|
|
84
|
-
type: ctx.questionType,
|
|
85
|
-
content: ctx.state.content,
|
|
86
|
-
points: data?.points ?? ctx.state.points ?? 1,
|
|
87
|
-
level: ctx.state.level,
|
|
88
|
-
difficulty: ctx.state.difficulty,
|
|
89
|
-
skill: ctx.state.skill,
|
|
90
|
-
answer: data,
|
|
91
|
-
}),
|
|
92
|
-
wrapOnChange: (data, ctx) => ({
|
|
93
|
-
type: ctx.questionType,
|
|
94
|
-
content: ctx.state.content,
|
|
95
|
-
points: data?.points ?? ctx.state.points ?? 1,
|
|
96
|
-
level: ctx.state.level,
|
|
97
|
-
difficulty: ctx.state.difficulty,
|
|
98
|
-
skill: ctx.state.skill,
|
|
99
|
-
answer: data,
|
|
100
|
-
}),
|
|
101
|
-
};
|
|
1
|
+
import{ChooseTheCorrectAnswerCreator as e}from"./ChooseTheCorrectAnswerCreator";export const chooseTheCorrectAnswerRegistration={component:e,transformInitialData:e=>{let t=e?.answer;const o=e?.content,n=e?.answer,r=e?.total_points?parseFloat(e.total_points):e?.points||o?.points||n?.points||1,i=e?.explanation||o?.explanation||n?.explanation||"",s=e?.questionGroup||{},a=s?.payload||{};if(o&&"object"==typeof o&&(void 0!==o.question||o.options)){const p=o.options||[],l=n?.answer,u=Array.isArray(l)||"number"==typeof l?l:-1,g=Boolean(o?.multipleAnswers??n?.multipleAnswers??e?.multipleAnswers??a?.multipleAnswers??Array.isArray(u));t={question:o.question||"",optionType:o.optionType||"text",options:p,correctAnswer:u,multipleAnswers:g,imageUrl:o.imageUrl||"",askerName:o.askerName||"",answererName:o.answererName||"",isExample:e?.isExample||n?.isExample||!1,explanation:i,points:r,groupTitle:a?.title||n?.groupTitle||"",groupContent:a?.content||n?.groupContent||"",groupImageUrl:a?.imageUrl||n?.groupImageUrl||o?.groupImageUrl||"",groupNumber:s.groupNumber||n?.groupNumber||1,articles:a?.articles||n?.articles||void 0}}else n&&"object"==typeof n&&(void 0!==n.question||n.options)&&(t={...n,multipleAnswers:Boolean(n?.multipleAnswers??e?.multipleAnswers??Array.isArray(n?.correctAnswer)),optionType:n.optionType||o?.optionType||"text",imageUrl:n.imageUrl||o?.imageUrl||"",isExample:e?.isExample||n?.isExample||!1,explanation:i,points:r,groupTitle:a?.title||n?.groupTitle||"",groupContent:a?.content||n?.groupContent||"",groupImageUrl:a?.imageUrl||n?.groupImageUrl||o?.groupImageUrl||"",groupNumber:s.groupNumber||n?.groupNumber||1,articles:a?.articles||n?.articles||void 0});return t},getExtraProps:e=>({optionCount:e.optionCount||4,optionMode:e.optionMode,defaultValue:e.defaultValue,defaultQuestion:e.defaultQuestion,viewMode:e.viewMode,onUnsavedChangesChange:e.onUnsavedChangesChange,validationRef:e.validationRef,groups:e.groups,groupType:e.groupType,articleCount:e.articleCount,questionIndexInPart:e.questionIndexInPart,partId:e.partId,questionConfig:e.questionConfig,multipleAnswers:e.multipleAnswers}),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}),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})};
|
|
@@ -1,43 +1 @@
|
|
|
1
|
-
export const transformChooseTheCorrectAnswer = (
|
|
2
|
-
const answerData = question.answer;
|
|
3
|
-
if (!answerData?.options || answerData.correctAnswer === undefined) {
|
|
4
|
-
return { apiContent: {}, apiCorrectAnswer: {} };
|
|
5
|
-
}
|
|
6
|
-
const apiContent = {
|
|
7
|
-
question: answerData.question || '',
|
|
8
|
-
optionType: answerData.optionType || 'text',
|
|
9
|
-
options: answerData.options,
|
|
10
|
-
...(answerData.multipleAnswers ? { multipleAnswers: true } : {}),
|
|
11
|
-
};
|
|
12
|
-
// Per-question image goes into content (not group card)
|
|
13
|
-
if (answerData.imageUrl) {
|
|
14
|
-
apiContent.imageUrl = answerData.imageUrl;
|
|
15
|
-
}
|
|
16
|
-
if (answerData.askerName) {
|
|
17
|
-
apiContent.askerName = answerData.askerName;
|
|
18
|
-
}
|
|
19
|
-
if (answerData.answererName) {
|
|
20
|
-
apiContent.answererName = answerData.answererName;
|
|
21
|
-
}
|
|
22
|
-
// Build basicGroupData when any group field is present
|
|
23
|
-
const hasGroupData = !!(answerData.groupTitle || answerData.groupSubtitle || answerData.groupContent || answerData.groupImageUrl || (answerData.articles && answerData.articles.length > 0));
|
|
24
|
-
const basicGroupData = hasGroupData
|
|
25
|
-
? {
|
|
26
|
-
title: answerData.groupTitle || '',
|
|
27
|
-
subtitle: answerData.groupSubtitle || '',
|
|
28
|
-
content: answerData.groupContent || '',
|
|
29
|
-
imageUrl: answerData.groupImageUrl || '',
|
|
30
|
-
...(answerData.articles ? { articles: answerData.articles } : {}),
|
|
31
|
-
}
|
|
32
|
-
: undefined;
|
|
33
|
-
return {
|
|
34
|
-
apiContent,
|
|
35
|
-
apiCorrectAnswer: {
|
|
36
|
-
answer: answerData.correctAnswer,
|
|
37
|
-
...(answerData.multipleAnswers ? { multipleAnswers: true } : {}),
|
|
38
|
-
},
|
|
39
|
-
isExample: answerData.isExample || false,
|
|
40
|
-
basicGroupData,
|
|
41
|
-
groupNumber: answerData.groupNumber || 1,
|
|
42
|
-
};
|
|
43
|
-
};
|
|
1
|
+
export const transformChooseTheCorrectAnswer=e=>{const r=e.answer;if(!r?.options||void 0===r.correctAnswer)return{apiContent:{},apiCorrectAnswer:{}};const t={question:r.question||"",optionType:r.optionType||"text",options:r.options,...r.multipleAnswers?{multipleAnswers:!0}:{}};r.imageUrl&&(t.imageUrl=r.imageUrl),r.askerName&&(t.askerName=r.askerName),r.answererName&&(t.answererName=r.answererName);const o=!!(r.groupTitle||r.groupSubtitle||r.groupContent||r.groupImageUrl||r.articles&&r.articles.length>0)?{title:r.groupTitle||"",subtitle:r.groupSubtitle||"",content:r.groupContent||"",imageUrl:r.groupImageUrl||"",...r.articles?{articles:r.articles}:{}}:void 0;return{apiContent:t,apiCorrectAnswer:{answer:r.correctAnswer,...r.multipleAnswers?{multipleAnswers:!0}:{}},isExample:r.isExample||!1,basicGroupData:o,groupNumber:r.groupNumber||1}};
|
|
@@ -1,275 +1 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
4
|
-
import { Input } from '../../../../components/ui/input';
|
|
5
|
-
import { Check, X, PenLine, AlertTriangle, ClipboardList, Lightbulb, BookOpen, Type, Hash, } from 'lucide-react';
|
|
6
|
-
import { cn } from '../../../../shared/lib/utils';
|
|
7
|
-
import { usePresignedFileUrl } from '../../../../shared/lib/hooks';
|
|
8
|
-
// Helper: Extract placeholder indices from question text
|
|
9
|
-
function extractPlaceholderIndices(question) {
|
|
10
|
-
const regex = /\{(\d+)\}/g;
|
|
11
|
-
const indices = [];
|
|
12
|
-
let match;
|
|
13
|
-
while ((match = regex.exec(question)) !== null) {
|
|
14
|
-
const index = parseInt(match[1], 10);
|
|
15
|
-
if (!indices.includes(index)) {
|
|
16
|
-
indices.push(index);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return indices.sort((a, b) => a - b);
|
|
20
|
-
}
|
|
21
|
-
// Sub-component: Resolve presigned URL for group image
|
|
22
|
-
function GroupImage({ src, alt, className }) {
|
|
23
|
-
const { previewUrl, isLoading } = usePresignedFileUrl(src);
|
|
24
|
-
if (isLoading) {
|
|
25
|
-
return (_jsx("div", { className: "flex h-40 items-center justify-center", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-3 border-gray-200 border-t-indigo-500" }) }));
|
|
26
|
-
}
|
|
27
|
-
return (
|
|
28
|
-
/* eslint-disable-next-line @next/next/no-img-element */
|
|
29
|
-
_jsx("img", { src: previewUrl || src, alt: alt, className: cn('max-h-72 w-auto object-contain rounded-lg drop-shadow-sm', className), onError: (e) => {
|
|
30
|
-
const target = e.target;
|
|
31
|
-
target.onerror = null;
|
|
32
|
-
target.src = '/images/placeholder-image.svg';
|
|
33
|
-
} }));
|
|
34
|
-
}
|
|
35
|
-
export function FillInBlankClient({ questionData, onSubmit, isReviewMode = false, userAnswer = [], autoFillCorrectAnswers = false, explanation: explanationProp, }) {
|
|
36
|
-
// Detect if this is new format (question + answers) or legacy format (blanks array)
|
|
37
|
-
const isLegacyFormat = !questionData.question && questionData.blanks && questionData.blanks.length > 0;
|
|
38
|
-
const explanation = explanationProp || questionData.explanation;
|
|
39
|
-
// Group data - resolve from multiple possible field names
|
|
40
|
-
const isGroup = questionData.isGroup;
|
|
41
|
-
const groupTitle = questionData.groupTitle || questionData.title || '';
|
|
42
|
-
const groupContent = questionData.groupContent || '';
|
|
43
|
-
const groupImageUrl = questionData.groupImageUrl || '';
|
|
44
|
-
const groupNumber = questionData.groupNumber;
|
|
45
|
-
const hasGroupData = isGroup && (groupTitle || groupContent || groupImageUrl);
|
|
46
|
-
// Custom hooks for presigned URL (question-level image, not group image)
|
|
47
|
-
const { previewUrl: imagePreviewUrl, isLoading: isImageLoading } = usePresignedFileUrl(
|
|
48
|
-
// Only use question-level imageUrl when NOT grouped (group image is handled separately)
|
|
49
|
-
(!isGroup && questionData.imageUrl) ? questionData.imageUrl : '');
|
|
50
|
-
// For new format: extract placeholders from question
|
|
51
|
-
const placeholderIndices = useMemo(() => {
|
|
52
|
-
if (isLegacyFormat)
|
|
53
|
-
return [];
|
|
54
|
-
return extractPlaceholderIndices(questionData.question || '');
|
|
55
|
-
}, [questionData.question, isLegacyFormat]);
|
|
56
|
-
// Initialize answers based on format
|
|
57
|
-
const getInitialAnswers = () => {
|
|
58
|
-
if (autoFillCorrectAnswers) {
|
|
59
|
-
if (isLegacyFormat && questionData.blanks) {
|
|
60
|
-
return questionData.blanks.map(b => b.correctAnswer);
|
|
61
|
-
}
|
|
62
|
-
return questionData.answers || [];
|
|
63
|
-
}
|
|
64
|
-
return userAnswer || [];
|
|
65
|
-
};
|
|
66
|
-
const [answers, setAnswers] = useState(getInitialAnswers());
|
|
67
|
-
// Sync userAnswer when it changes
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (autoFillCorrectAnswers) {
|
|
70
|
-
if (isLegacyFormat && questionData.blanks) {
|
|
71
|
-
setAnswers(questionData.blanks.map(b => b.correctAnswer));
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
setAnswers(questionData.answers || []);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
else if (userAnswer) {
|
|
78
|
-
setAnswers(userAnswer);
|
|
79
|
-
}
|
|
80
|
-
}, [userAnswer, autoFillCorrectAnswers, questionData, isLegacyFormat]);
|
|
81
|
-
// Handle answer change for specific placeholder index
|
|
82
|
-
const handleAnswerChange = (index, value) => {
|
|
83
|
-
if (isReviewMode)
|
|
84
|
-
return;
|
|
85
|
-
const newAnswers = [...answers];
|
|
86
|
-
while (newAnswers.length <= index) {
|
|
87
|
-
newAnswers.push('');
|
|
88
|
-
}
|
|
89
|
-
newAnswers[index] = value;
|
|
90
|
-
setAnswers(newAnswers);
|
|
91
|
-
onSubmit?.(newAnswers);
|
|
92
|
-
};
|
|
93
|
-
// Check if answer at index is correct
|
|
94
|
-
const isAnswerCorrect = (index, userInput) => {
|
|
95
|
-
let correctAnswer;
|
|
96
|
-
if (isLegacyFormat && questionData.blanks?.[index]) {
|
|
97
|
-
correctAnswer = questionData.blanks[index].correctAnswer;
|
|
98
|
-
}
|
|
99
|
-
else if (questionData.answers?.[index]) {
|
|
100
|
-
correctAnswer = questionData.answers[index];
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
const answer = userInput.trim();
|
|
106
|
-
const correct = correctAnswer.trim();
|
|
107
|
-
if (questionData.caseSensitive) {
|
|
108
|
-
return answer === correct;
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
return answer.toLowerCase() === correct.toLowerCase();
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
// Calculate score
|
|
115
|
-
const calculateScore = () => {
|
|
116
|
-
let correct = 0;
|
|
117
|
-
let total = 0;
|
|
118
|
-
if (isLegacyFormat && questionData.blanks) {
|
|
119
|
-
total = questionData.blanks.length;
|
|
120
|
-
questionData.blanks.forEach((_, idx) => {
|
|
121
|
-
if (isAnswerCorrect(idx, answers[idx] || '')) {
|
|
122
|
-
correct++;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
total = placeholderIndices.length;
|
|
128
|
-
placeholderIndices.forEach((idx) => {
|
|
129
|
-
if (isAnswerCorrect(idx, answers[idx] || '')) {
|
|
130
|
-
correct++;
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return { correct, total };
|
|
135
|
-
};
|
|
136
|
-
const score = isReviewMode ? calculateScore() : null;
|
|
137
|
-
// =====================================================
|
|
138
|
-
// SHARED SUB-RENDERS
|
|
139
|
-
// =====================================================
|
|
140
|
-
/** Group Block – displayed above the question when isGroup */
|
|
141
|
-
const renderGroupBlock = () => {
|
|
142
|
-
if (!hasGroupData)
|
|
143
|
-
return null;
|
|
144
|
-
return (_jsxs("div", { className: "relative overflow-hidden rounded-2xl border border-indigo-100 bg-white shadow-sm ring-1 ring-black/5 transition-all", children: [_jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-indigo-50/80 via-white to-blue-50/30 opacity-70 pointer-events-none" }), _jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1.5 bg-gradient-to-b from-indigo-500 to-blue-600 rounded-l-2xl" }), _jsxs("div", { className: "relative p-6 sm:p-7", children: [_jsxs("div", { className: "flex items-start gap-4 mb-5 border-b border-indigo-50/60 pb-4", children: [_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-100 to-blue-100 shadow-inner ring-1 ring-indigo-200/50", children: _jsx(BookOpen, { className: "h-5 w-5 text-indigo-600" }) }), _jsxs("div", { className: "flex-1 pt-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [groupNumber && (_jsxs("span", { className: "inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-700 ring-1 ring-inset ring-indigo-700/10", children: ["Nh\u00F3m ", groupNumber] })), _jsx("span", { className: "inline-flex items-center rounded-md bg-orange-50 px-2 py-1 text-xs font-semibold text-orange-700 ring-1 ring-inset ring-orange-700/10", children: "\u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng" })] }), groupTitle && (_jsx("h4", { className: "text-xl font-bold text-slate-800 leading-tight tracking-tight", children: groupTitle }))] })] }), _jsxs("div", { className: "space-y-6 text-slate-700", children: [groupContent && (_jsx("div", { className: "prose prose-slate prose-p:leading-relaxed prose-p:mb-3 max-w-none text-[15px]", children: groupContent.split('\n').map((line, i) => (_jsx("p", { className: "last:mb-0", children: line }, i))) })), groupImageUrl && (_jsxs("div", { className: "mt-5 relative overflow-hidden rounded-xl border border-slate-200/60 bg-slate-50 shadow-sm transition-all hover:shadow-md", children: [_jsx("div", { className: "flex items-center justify-between border-b border-slate-200/60 bg-slate-100/50 px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-slate-300" }), _jsx("span", { className: "ml-2 text-[11px] font-semibold uppercase tracking-wider text-slate-500", children: "T\u00E0i li\u1EC7u \u0111\u00EDnh k\u00E8m" })] }) }), _jsx("div", { className: "flex items-center justify-center p-4 min-h-[160px]", children: _jsx(GroupImage, { src: groupImageUrl, alt: groupTitle || 'Hình ảnh nhóm' }) })] }))] })] })] }));
|
|
145
|
-
};
|
|
146
|
-
/** Render inline blanks within question text (new format) */
|
|
147
|
-
const renderQuestionWithBlanks = () => {
|
|
148
|
-
const question = questionData.question || '';
|
|
149
|
-
const parts = question.split(/(\{\d+\})/g);
|
|
150
|
-
return (_jsx("div", { className: "flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]", children: parts.map((part, partIndex) => {
|
|
151
|
-
const match = part.match(/\{(\d+)\}/);
|
|
152
|
-
if (match) {
|
|
153
|
-
const placeholderIndex = parseInt(match[1], 10);
|
|
154
|
-
const userInput = answers[placeholderIndex] || '';
|
|
155
|
-
const isCorrect = isReviewMode && isAnswerCorrect(placeholderIndex, userInput);
|
|
156
|
-
const isWrong = isReviewMode && userInput && !isCorrect;
|
|
157
|
-
return (_jsxs("span", { className: "relative inline-flex items-center mx-0.5", children: [_jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-md bg-orange-100 text-[10px] font-bold text-orange-600 mr-1 ring-1 ring-orange-200/60", children: placeholderIndex + 1 }), _jsx(Input, { value: userInput, onChange: (e) => handleAnswerChange(placeholderIndex, e.target.value), disabled: isReviewMode, className: cn('h-9 w-28 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200', 'focus:ring-2 focus:ring-offset-1 focus:outline-none', isReviewMode
|
|
158
|
-
? isCorrect
|
|
159
|
-
? 'border-emerald-400 bg-emerald-50 text-emerald-700'
|
|
160
|
-
: isWrong
|
|
161
|
-
? 'border-red-400 bg-red-50 text-red-700'
|
|
162
|
-
: 'border-gray-200 bg-gray-50 text-gray-500'
|
|
163
|
-
: 'border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50'), placeholder: "..." }), isReviewMode && (isCorrect || isWrong) && (_jsx("span", { className: cn('absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white', isCorrect ? 'bg-emerald-500' : 'bg-red-500'), children: isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5 text-white" })) : (_jsx(X, { className: "h-2.5 w-2.5 text-white" })) }))] }, partIndex));
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
return (_jsx("span", { className: "text-slate-800 font-medium", children: part }, partIndex));
|
|
167
|
-
}
|
|
168
|
-
}) }));
|
|
169
|
-
};
|
|
170
|
-
/** Legacy format: render blanks array */
|
|
171
|
-
const renderLegacyBlank = (text, _blankId, blankIndex) => {
|
|
172
|
-
const parts = text.split(/(\{0\})/g);
|
|
173
|
-
return (_jsx("div", { className: "flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]", children: parts.map((part, partIdx) => {
|
|
174
|
-
if (part === '{0}') {
|
|
175
|
-
const userInput = answers[blankIndex] || '';
|
|
176
|
-
const isCorrect = isReviewMode && isAnswerCorrect(blankIndex, userInput);
|
|
177
|
-
const isWrong = isReviewMode && userInput && !isCorrect;
|
|
178
|
-
return (_jsxs("span", { className: "relative inline-flex items-center mx-0.5", children: [_jsx(Input, { value: userInput, onChange: (e) => handleAnswerChange(blankIndex, e.target.value), disabled: isReviewMode, className: cn('h-9 w-32 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200', 'focus:ring-2 focus:ring-offset-1 focus:outline-none', isReviewMode
|
|
179
|
-
? isCorrect
|
|
180
|
-
? 'border-emerald-400 bg-emerald-50 text-emerald-700'
|
|
181
|
-
: isWrong
|
|
182
|
-
? 'border-red-400 bg-red-50 text-red-700'
|
|
183
|
-
: 'border-gray-200 bg-gray-50 text-gray-500'
|
|
184
|
-
: 'border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50'), placeholder: "..." }), isReviewMode && (isCorrect || isWrong) && (_jsx("span", { className: cn('absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white', isCorrect ? 'bg-emerald-500' : 'bg-red-500'), children: isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5 text-white" })) : (_jsx(X, { className: "h-2.5 w-2.5 text-white" })) }))] }, partIdx));
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
return (_jsx("span", { className: "text-slate-800 font-medium", children: part }, partIdx));
|
|
188
|
-
}
|
|
189
|
-
}) }));
|
|
190
|
-
};
|
|
191
|
-
/** Hints pills block */
|
|
192
|
-
const renderHints = () => {
|
|
193
|
-
if (isReviewMode || !questionData.showHints || !questionData.hints || questionData.hints.length === 0) {
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
return (_jsxs("div", { className: "rounded-xl border border-violet-200 bg-gradient-to-r from-violet-50/80 to-purple-50/50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-violet-100 ring-1 ring-violet-200/60", children: _jsx(Lightbulb, { className: "h-3.5 w-3.5 text-violet-600" }) }), _jsx("span", { className: "text-sm font-semibold text-violet-800", children: "G\u1EE3i \u00FD \u0111\u00E1p \u00E1n" })] }), _jsx("div", { className: "flex flex-wrap gap-2", children: questionData.hints.map((hint, index) => (_jsx("span", { className: "inline-flex items-center rounded-full border border-violet-200 bg-white px-3 py-1 text-sm font-medium text-violet-700 shadow-sm transition-all hover:border-violet-300 hover:bg-violet-50 hover:shadow", children: hint }, index))) })] }));
|
|
197
|
-
};
|
|
198
|
-
/** Case-sensitivity warning */
|
|
199
|
-
const renderCaseSensitiveNote = () => {
|
|
200
|
-
if (isReviewMode || !questionData.caseSensitive)
|
|
201
|
-
return null;
|
|
202
|
-
return (_jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50/50 px-4 py-3", children: [_jsx("div", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm", children: _jsx(Type, { className: "h-3.5 w-3.5" }) }), _jsxs("div", { children: [_jsx("span", { className: "text-sm font-semibold text-amber-800", children: "Ph\u00E2n bi\u1EC7t hoa/th\u01B0\u1EDDng" }), _jsx("span", { className: "text-sm text-amber-700 ml-1", children: "\u2013 Vui l\u00F2ng nh\u1EADp \u0111\u00FAng ch\u1EEF hoa/th\u01B0\u1EDDng" })] })] }));
|
|
203
|
-
};
|
|
204
|
-
/** Explanation card (review mode only) */
|
|
205
|
-
const renderExplanation = () => {
|
|
206
|
-
const explText = explanation || questionData.explanation;
|
|
207
|
-
if (!isReviewMode || !explText)
|
|
208
|
-
return null;
|
|
209
|
-
return (_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.5 border-b border-blue-100 bg-white/60 px-5 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-slate-800", children: "Gi\u1EA3i th\u00EDch" })] }), _jsx("div", { className: "p-5", children: _jsx("p", { className: "text-sm text-slate-700 leading-relaxed", children: explText }) })] }));
|
|
210
|
-
};
|
|
211
|
-
/** Question-level image (non-group) */
|
|
212
|
-
const renderQuestionImage = () => {
|
|
213
|
-
if (isGroup)
|
|
214
|
-
return null; // group image is rendered in group block
|
|
215
|
-
if (!imagePreviewUrl && !questionData.imageUrl)
|
|
216
|
-
return null;
|
|
217
|
-
return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-gradient-to-br from-slate-50 to-gray-100 shadow-sm", children: [_jsx("div", { className: "border-b border-gray-100 px-3 py-1.5", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "h-2 w-2 rounded-full bg-red-400" }), _jsx("div", { className: "h-2 w-2 rounded-full bg-yellow-400" }), _jsx("div", { className: "h-2 w-2 rounded-full bg-green-400" }), _jsx("span", { className: "ml-2 text-xs font-medium text-gray-500", children: "H\u00ECnh \u1EA3nh" })] }) }), _jsx("div", { className: "flex items-center justify-center p-4", children: isImageLoading ? (_jsx("div", { className: "flex h-48 items-center justify-center", children: _jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-orange-500" }) })) : (
|
|
218
|
-
/* eslint-disable-next-line @next/next/no-img-element */
|
|
219
|
-
_jsx("img", { src: imagePreviewUrl || questionData.imageUrl, alt: "Question illustration", className: "max-h-56 w-auto object-contain rounded-md", onError: (e) => {
|
|
220
|
-
const target = e.target;
|
|
221
|
-
target.onerror = null;
|
|
222
|
-
target.src = '/images/placeholder-image.svg';
|
|
223
|
-
} })) })] }));
|
|
224
|
-
};
|
|
225
|
-
// =====================================================
|
|
226
|
-
// NEW FORMAT RENDER
|
|
227
|
-
// =====================================================
|
|
228
|
-
if (!isLegacyFormat) {
|
|
229
|
-
const hasAnyAnswer = placeholderIndices.some(idx => (answers[idx] || '').trim());
|
|
230
|
-
return (_jsxs("div", { className: "space-y-4", children: [renderGroupBlock(), _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm", children: _jsx(PenLine, { className: "h-4 w-4" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-semibold text-gray-700", children: "\u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng" }), _jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-700 ring-1 ring-inset ring-orange-200/60", children: [_jsx(Hash, { className: "h-3 w-3" }), placeholderIndices.length] })] })] }), isReviewMode && score && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold', score.correct === score.total
|
|
231
|
-
? 'bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60'
|
|
232
|
-
: score.correct >= score.total / 2
|
|
233
|
-
? 'bg-yellow-100 text-yellow-700 ring-1 ring-yellow-200/60'
|
|
234
|
-
: 'bg-red-100 text-red-700 ring-1 ring-red-200/60'), children: [score.correct === score.total && _jsx(Check, { className: "h-3 w-3" }), score.correct, "/", score.total, " \u0111\u00FAng"] }))] }), _jsxs("div", { className: "p-5 space-y-4", children: [_jsx("div", { className: "rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80", children: renderQuestionWithBlanks() }), renderQuestionImage(), renderHints(), isReviewMode && (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-white overflow-hidden shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-gray-100 bg-gradient-to-r from-slate-50 to-gray-50 px-4 py-2.5", children: [_jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-slate-500 text-white", children: _jsx(ClipboardList, { className: "h-3 w-3" }) }), _jsx("h4", { className: "text-xs font-semibold text-gray-600 uppercase tracking-wider", children: "Chi ti\u1EBFt \u0111\u00E1p \u00E1n" })] }), _jsx("div", { className: "p-4 space-y-2.5", children: placeholderIndices.map((idx) => {
|
|
235
|
-
const userInput = answers[idx] || '';
|
|
236
|
-
const correctAnswer = questionData.answers?.[idx] || '';
|
|
237
|
-
const isCorrect = isAnswerCorrect(idx, userInput);
|
|
238
|
-
const hasInput = userInput.trim().length > 0;
|
|
239
|
-
return (_jsxs("div", { className: cn('rounded-lg border p-3 transition-colors', isCorrect
|
|
240
|
-
? 'border-emerald-200 bg-emerald-50/50'
|
|
241
|
-
: hasInput
|
|
242
|
-
? 'border-red-200 bg-red-50/50'
|
|
243
|
-
: 'border-gray-100 bg-gray-50/50'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-orange-100 text-xs font-bold text-orange-600 ring-1 ring-orange-200/60", children: idx + 1 }), _jsxs("span", { className: "text-sm text-gray-500", children: ["Ch\u1ED7 tr\u1ED1ng ", idx + 1] })] }), _jsx("div", { className: cn('flex items-center gap-1 text-xs font-semibold', isCorrect ? 'text-emerald-600' : hasInput ? 'text-red-600' : 'text-gray-400'), children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-3.5 w-3.5" }), " \u0110\u00FAng"] })) : hasInput ? (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-3.5 w-3.5" }), " Sai"] })) : ('Bỏ trống') })] }), _jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2 text-sm", children: [_jsxs("div", { className: "flex items-center justify-between rounded-md bg-white px-3 py-2 border border-gray-100", children: [_jsx("span", { className: "text-gray-500 text-xs", children: "\u0110\u00E3 nh\u1EADp" }), _jsx("span", { className: cn('font-semibold', isCorrect ? 'text-emerald-600' : hasInput ? 'text-red-600' : 'text-gray-400 italic'), children: userInput || '—' })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md bg-emerald-50 px-3 py-2 border border-emerald-100", children: [_jsx("span", { className: "text-gray-500 text-xs", children: "\u0110\u00E1p \u00E1n" }), _jsx("span", { className: "font-semibold text-emerald-600", children: correctAnswer })] })] })] }, idx));
|
|
244
|
-
}) })] })), !isReviewMode && !hasAnyAnswer && (_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.5", 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(AlertTriangle, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng \u0111i\u1EC1n c\u00E2u tr\u1EA3 l\u1EDDi v\u00E0o c\u00E1c ch\u1ED7 tr\u1ED1ng" })] }))] })] }), renderCaseSensitiveNote(), renderExplanation()] }));
|
|
245
|
-
}
|
|
246
|
-
// =====================================================
|
|
247
|
-
// LEGACY FORMAT RENDER
|
|
248
|
-
// =====================================================
|
|
249
|
-
return (_jsxs("div", { className: "space-y-4", children: [renderGroupBlock(), questionData.blanks?.map((blank, index) => {
|
|
250
|
-
const userInput = answers[index] || '';
|
|
251
|
-
const isCorrect = isReviewMode && isAnswerCorrect(index, userInput);
|
|
252
|
-
const hasAnswered = userInput.trim() !== '';
|
|
253
|
-
return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm", children: _jsx(PenLine, { className: "h-4 w-4" }) }), _jsxs("span", { className: "text-sm font-semibold text-gray-700", children: ["C\u00E2u ", index + 1, ": \u0110i\u1EC1n v\u00E0o ch\u1ED7 tr\u1ED1ng"] })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold', isCorrect
|
|
254
|
-
? 'bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60'
|
|
255
|
-
: 'bg-red-100 text-red-700 ring-1 ring-red-200/60'), 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-4", children: [_jsx("div", { className: "rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80", children: renderLegacyBlank(blank.text, blank.id, index) }), index === 0 && renderQuestionImage(), index === 0 && renderHints(), isReviewMode && (_jsx("div", { className: cn('rounded-xl border p-3 transition-colors', isCorrect
|
|
256
|
-
? 'border-emerald-200 bg-emerald-50/50'
|
|
257
|
-
: hasAnswered
|
|
258
|
-
? 'border-red-200 bg-red-50/50'
|
|
259
|
-
: 'border-gray-100 bg-gray-50/50'), children: _jsxs("div", { className: "space-y-2.5", children: [_jsxs("div", { className: "flex items-center justify-between rounded-md bg-white p-3 border border-gray-100", children: [_jsx("span", { className: "text-sm text-gray-500", children: "\u0110\u00E3 nh\u1EADp:" }), _jsx("span", { className: cn('text-sm font-semibold', isCorrect ? 'text-emerald-600' : hasAnswered ? 'text-red-600' : 'text-gray-400 italic'), children: userInput || '—' })] }), _jsxs("div", { className: "flex items-center justify-between rounded-md bg-emerald-50 p-3 border border-emerald-100", children: [_jsx("span", { className: "text-sm text-gray-500", children: "\u0110\u00E1p \u00E1n \u0111\u00FAng:" }), _jsx("span", { className: "text-sm font-semibold text-emerald-600", children: blank.correctAnswer })] }), _jsxs("div", { className: cn('flex items-center justify-between rounded-md p-3 border', isCorrect
|
|
260
|
-
? 'bg-emerald-50 border-emerald-200'
|
|
261
|
-
: 'bg-red-50 border-red-200'), children: [_jsx("span", { className: "text-sm text-gray-500", children: "K\u1EBFt qu\u1EA3:" }), _jsx("div", { className: cn('flex items-center gap-1.5 text-sm font-bold', isCorrect ? 'text-emerald-600' : 'text-red-600'), children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-4 w-4" }), " Ch\u00EDnh x\u00E1c"] })) : (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-4 w-4" }), " Sai"] })) })] })] }) })), !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.5", 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(AlertTriangle, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-sm text-amber-800", children: "Vui l\u00F2ng \u0111i\u1EC1n c\u00E2u tr\u1EA3 l\u1EDDi" })] }))] })] }, blank.id));
|
|
262
|
-
}), renderCaseSensitiveNote(), isReviewMode && score && (questionData.blanks?.length || 0) > 1 && (_jsx("div", { className: cn('overflow-hidden rounded-xl border shadow-sm', score.correct === score.total
|
|
263
|
-
? 'border-emerald-200 bg-gradient-to-r from-emerald-50 to-green-50'
|
|
264
|
-
: score.correct >= score.total / 2
|
|
265
|
-
? 'border-yellow-200 bg-gradient-to-r from-yellow-50 to-amber-50'
|
|
266
|
-
: 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50'), children: _jsxs("div", { className: "flex items-center justify-between px-5 py-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm', score.correct === score.total
|
|
267
|
-
? 'bg-gradient-to-br from-emerald-500 to-green-600'
|
|
268
|
-
: score.correct >= score.total / 2
|
|
269
|
-
? 'bg-gradient-to-br from-yellow-500 to-amber-600'
|
|
270
|
-
: 'bg-gradient-to-br from-red-500 to-rose-600'), children: score.correct === score.total ? (_jsx(Check, { className: "h-5 w-5" })) : (_jsx(ClipboardList, { className: "h-5 w-5" })) }), _jsxs("div", { children: [_jsx("h4", { className: "text-sm font-semibold text-gray-800", children: "T\u1ED5ng k\u1EBFt" }), _jsx("p", { className: "text-xs text-gray-500", children: "K\u1EBFt qu\u1EA3 b\u00E0i l\u00E0m c\u1EE7a b\u1EA1n" })] })] }), _jsxs("div", { className: "text-right", children: [_jsxs("div", { className: cn('text-2xl font-bold', score.correct === score.total
|
|
271
|
-
? 'text-emerald-600'
|
|
272
|
-
: score.correct >= score.total / 2
|
|
273
|
-
? 'text-yellow-600'
|
|
274
|
-
: 'text-red-600'), children: [score.correct, "/", score.total] }), _jsxs("div", { className: "text-xs text-gray-500", children: [Math.round((score.correct / score.total) * 100), "% ch\u00EDnh x\u00E1c"] })] })] }) })), renderExplanation()] }));
|
|
275
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as a,useEffect as s,useMemo as l}from"react";import{Input as n}from"../../../../components/ui/input";import{Check as i,X as d,PenLine as o,AlertTriangle as c,ClipboardList as m,Lightbulb as g,BookOpen as h,Type as b,Hash as x}from"lucide-react";import{cn as f}from"../../../../shared/lib/utils";import{usePresignedFileUrl as u}from"../../../../shared/lib/hooks";function p({src:r,alt:t,className:a}){const{previewUrl:s,isLoading:l}=u(r);return l?e("div",{className:"flex h-40 items-center justify-center",children:e("div",{className:"h-6 w-6 animate-spin rounded-full border-3 border-gray-200 border-t-indigo-500"})}):e("img",{src:s||r,alt:t,className:f("max-h-72 w-auto object-contain rounded-lg drop-shadow-sm",a),onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})}export function FillInBlankClient({questionData:N,onSubmit:w,isReviewMode:v=!1,userAnswer:y=[],autoFillCorrectAnswers:j=!1,explanation:k}){const C=!N.question&&N.blanks&&N.blanks.length>0,q=k||N.explanation,U=N.isGroup,A=N.groupTitle||N.title||"",S=N.groupContent||"",E=N.groupImageUrl||"",I=N.groupNumber,L=U&&(A||S||E),{previewUrl:F,isLoading:G}=u(!U&&N.imageUrl?N.imageUrl:""),H=l(()=>C?[]:function(e){const r=/\{(\d+)\}/g,t=[];let a;for(;null!==(a=r.exec(e));){const e=parseInt(a[1],10);t.includes(e)||t.push(e)}return t.sort((e,r)=>e-r)}(N.question||""),[N.question,C]),[T,V]=a(j?C&&N.blanks?N.blanks.map(e=>e.correctAnswer):N.answers||[]:y||[]);s(()=>{j?C&&N.blanks?V(N.blanks.map(e=>e.correctAnswer)):V(N.answers||[]):y&&V(y)},[y,j,N,C]);const B=(e,r)=>{if(v)return;const t=[...T];for(;t.length<=e;)t.push("");t[e]=r,V(t),w?.(t)},K=(e,r)=>{let t;if(C&&N.blanks?.[e])t=N.blanks[e].correctAnswer;else{if(!N.answers?.[e])return!1;t=N.answers[e]}const a=r.trim(),s=t.trim();return N.caseSensitive?a===s:a.toLowerCase()===s.toLowerCase()},M=v?(()=>{let e=0,r=0;return C&&N.blanks?(r=N.blanks.length,N.blanks.forEach((r,t)=>{K(t,T[t]||"")&&e++})):(r=H.length,H.forEach(r=>{K(r,T[r]||"")&&e++})),{correct:e,total:r}})():null,D=()=>L?r("div",{className:"relative overflow-hidden rounded-2xl border border-indigo-100 bg-white shadow-sm ring-1 ring-black/5 transition-all",children:[e("div",{className:"absolute inset-0 bg-gradient-to-br from-indigo-50/80 via-white to-blue-50/30 opacity-70 pointer-events-none"}),e("div",{className:"absolute left-0 top-0 bottom-0 w-1.5 bg-gradient-to-b from-indigo-500 to-blue-600 rounded-l-2xl"}),r("div",{className:"relative p-6 sm:p-7",children:[r("div",{className:"flex items-start gap-4 mb-5 border-b border-indigo-50/60 pb-4",children:[e("div",{className:"flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-100 to-blue-100 shadow-inner ring-1 ring-indigo-200/50",children:e(h,{className:"h-5 w-5 text-indigo-600"})}),r("div",{className:"flex-1 pt-1",children:[r("div",{className:"flex items-center gap-2 mb-1",children:[I&&r("span",{className:"inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-700 ring-1 ring-inset ring-indigo-700/10",children:["Nhóm ",I]}),e("span",{className:"inline-flex items-center rounded-md bg-orange-50 px-2 py-1 text-xs font-semibold text-orange-700 ring-1 ring-inset ring-orange-700/10",children:"Điền vào chỗ trống"})]}),A&&e("h4",{className:"text-xl font-bold text-slate-800 leading-tight tracking-tight",children:A})]})]}),r("div",{className:"space-y-6 text-slate-700",children:[S&&e("div",{className:"prose prose-slate prose-p:leading-relaxed prose-p:mb-3 max-w-none text-[15px]",children:S.split("\n").map((r,t)=>e("p",{className:"last:mb-0",children:r},t))}),E&&r("div",{className:"mt-5 relative overflow-hidden rounded-xl border border-slate-200/60 bg-slate-50 shadow-sm transition-all hover:shadow-md",children:[e("div",{className:"flex items-center justify-between border-b border-slate-200/60 bg-slate-100/50 px-4 py-2",children:r("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("div",{className:"h-2.5 w-2.5 rounded-full bg-slate-300"}),e("span",{className:"ml-2 text-[11px] font-semibold uppercase tracking-wider text-slate-500",children:"Tài liệu đính kèm"})]})}),e("div",{className:"flex items-center justify-center p-4 min-h-[160px]",children:e(p,{src:E,alt:A||"Hình ảnh nhóm"})})]})]})]})]}):null,P=()=>{const t=(N.question||"").split(/(\{\d+\})/g);return e("div",{className:"flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]",children:t.map((t,a)=>{const s=t.match(/\{(\d+)\}/);if(s){const t=parseInt(s[1],10),l=T[t]||"",o=v&&K(t,l),c=v&&l&&!o;return r("span",{className:"relative inline-flex items-center mx-0.5",children:[e("span",{className:"flex h-5 w-5 items-center justify-center rounded-md bg-orange-100 text-[10px] font-bold text-orange-600 mr-1 ring-1 ring-orange-200/60",children:t+1}),e(n,{value:l,onChange:e=>B(t,e.target.value),disabled:v,className:f("h-9 w-28 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200","focus:ring-2 focus:ring-offset-1 focus:outline-none",v?o?"border-emerald-400 bg-emerald-50 text-emerald-700":c?"border-red-400 bg-red-50 text-red-700":"border-gray-200 bg-gray-50 text-gray-500":"border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50"),placeholder:"..."}),v&&(o||c)&&e("span",{className:f("absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white",o?"bg-emerald-500":"bg-red-500"),children:e(o?i:d,{className:"h-2.5 w-2.5 text-white"})})]},a)}return e("span",{className:"text-slate-800 font-medium",children:t},a)})})},Q=(t,a,s)=>{const l=t.split(/(\{0\})/g);return e("div",{className:"flex flex-wrap items-baseline gap-x-1.5 gap-y-2 leading-loose text-[15px]",children:l.map((t,a)=>{if("{0}"===t){const t=T[s]||"",l=v&&K(s,t),o=v&&t&&!l;return r("span",{className:"relative inline-flex items-center mx-0.5",children:[e(n,{value:t,onChange:e=>B(s,e.target.value),disabled:v,className:f("h-9 w-32 text-center text-sm font-medium rounded-lg border-2 transition-all duration-200","focus:ring-2 focus:ring-offset-1 focus:outline-none",v?l?"border-emerald-400 bg-emerald-50 text-emerald-700":o?"border-red-400 bg-red-50 text-red-700":"border-gray-200 bg-gray-50 text-gray-500":"border-orange-200 bg-white hover:border-orange-300 focus:border-orange-400 focus:ring-orange-200/50"),placeholder:"..."}),v&&(l||o)&&e("span",{className:f("absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full shadow-sm ring-2 ring-white",l?"bg-emerald-500":"bg-red-500"),children:e(l?i:d,{className:"h-2.5 w-2.5 text-white"})})]},a)}return e("span",{className:"text-slate-800 font-medium",children:t},a)})})},R=()=>!v&&N.showHints&&N.hints&&0!==N.hints.length?r("div",{className:"rounded-xl border border-violet-200 bg-gradient-to-r from-violet-50/80 to-purple-50/50 p-4",children:[r("div",{className:"flex items-center gap-2 mb-3",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-lg bg-violet-100 ring-1 ring-violet-200/60",children:e(g,{className:"h-3.5 w-3.5 text-violet-600"})}),e("span",{className:"text-sm font-semibold text-violet-800",children:"Gợi ý đáp án"})]}),e("div",{className:"flex flex-wrap gap-2",children:N.hints.map((r,t)=>e("span",{className:"inline-flex items-center rounded-full border border-violet-200 bg-white px-3 py-1 text-sm font-medium text-violet-700 shadow-sm transition-all hover:border-violet-300 hover:bg-violet-50 hover:shadow",children:r},t))})]}):null,z=()=>v||!N.caseSensitive?null:r("div",{className:"flex items-center gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50/50 px-4 py-3",children:[e("div",{className:"flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",children:e(b,{className:"h-3.5 w-3.5"})}),r("div",{children:[e("span",{className:"text-sm font-semibold text-amber-800",children:"Phân biệt hoa/thường"}),e("span",{className:"text-sm text-amber-700 ml-1",children:"– Vui lòng nhập đúng chữ hoa/thường"})]})]}),J=()=>{const t=q||N.explanation;return v&&t?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.5 border-b border-blue-100 bg-white/60 px-5 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-slate-800",children:"Giải thích"})]}),e("div",{className:"p-5",children:e("p",{className:"text-sm text-slate-700 leading-relaxed",children:t})})]}):null},O=()=>U?null:F||N.imageUrl?r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-gradient-to-br from-slate-50 to-gray-100 shadow-sm",children:[e("div",{className:"border-b border-gray-100 px-3 py-1.5",children:r("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"h-2 w-2 rounded-full bg-red-400"}),e("div",{className:"h-2 w-2 rounded-full bg-yellow-400"}),e("div",{className:"h-2 w-2 rounded-full bg-green-400"}),e("span",{className:"ml-2 text-xs font-medium text-gray-500",children:"Hình ảnh"})]})}),e("div",{className:"flex items-center justify-center p-4",children:G?e("div",{className:"flex h-48 items-center justify-center",children:e("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-orange-500"})}):e("img",{src:F||N.imageUrl,alt:"Question illustration",className:"max-h-56 w-auto object-contain rounded-md",onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})})]}):null;if(!C){const a=H.some(e=>(T[e]||"").trim());return r("div",{className:"space-y-4",children:[D(),r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),r("div",{className:"flex items-center gap-2",children:[e("span",{className:"text-sm font-semibold text-gray-700",children:"Điền vào chỗ trống"}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-700 ring-1 ring-inset ring-orange-200/60",children:[e(x,{className:"h-3 w-3"}),H.length]})]})]}),v&&M&&r("div",{className:f("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold",M.correct===M.total?"bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60":M.correct>=M.total/2?"bg-yellow-100 text-yellow-700 ring-1 ring-yellow-200/60":"bg-red-100 text-red-700 ring-1 ring-red-200/60"),children:[M.correct===M.total&&e(i,{className:"h-3 w-3"}),M.correct,"/",M.total," đúng"]})]}),r("div",{className:"p-5 space-y-4",children:[e("div",{className:"rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80",children:P()}),O(),R(),v&&r("div",{className:"rounded-xl border border-gray-200 bg-white overflow-hidden shadow-sm",children:[r("div",{className:"flex items-center gap-2 border-b border-gray-100 bg-gradient-to-r from-slate-50 to-gray-50 px-4 py-2.5",children:[e("div",{className:"flex h-5 w-5 items-center justify-center rounded-full bg-slate-500 text-white",children:e(m,{className:"h-3 w-3"})}),e("h4",{className:"text-xs font-semibold text-gray-600 uppercase tracking-wider",children:"Chi tiết đáp án"})]}),e("div",{className:"p-4 space-y-2.5",children:H.map(a=>{const s=T[a]||"",l=N.answers?.[a]||"",n=K(a,s),o=s.trim().length>0;return r("div",{className:f("rounded-lg border p-3 transition-colors",n?"border-emerald-200 bg-emerald-50/50":o?"border-red-200 bg-red-50/50":"border-gray-100 bg-gray-50/50"),children:[r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded-md bg-orange-100 text-xs font-bold text-orange-600 ring-1 ring-orange-200/60",children:a+1}),r("span",{className:"text-sm text-gray-500",children:["Chỗ trống ",a+1]})]}),e("div",{className:f("flex items-center gap-1 text-xs font-semibold",n?"text-emerald-600":o?"text-red-600":"text-gray-400"),children:n?r(t,{children:[e(i,{className:"h-3.5 w-3.5"})," Đúng"]}):o?r(t,{children:[e(d,{className:"h-3.5 w-3.5"})," Sai"]}):"Bỏ trống"})]}),r("div",{className:"mt-2 grid grid-cols-2 gap-2 text-sm",children:[r("div",{className:"flex items-center justify-between rounded-md bg-white px-3 py-2 border border-gray-100",children:[e("span",{className:"text-gray-500 text-xs",children:"Đã nhập"}),e("span",{className:f("font-semibold",n?"text-emerald-600":o?"text-red-600":"text-gray-400 italic"),children:s||"—"})]}),r("div",{className:"flex items-center justify-between rounded-md bg-emerald-50 px-3 py-2 border border-emerald-100",children:[e("span",{className:"text-gray-500 text-xs",children:"Đáp án"}),e("span",{className:"font-semibold text-emerald-600",children:l})]})]})]},a)})})]}),!v&&!a&&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.5",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(c,{className:"h-3 w-3"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng điền câu trả lời vào các chỗ trống"})]})]})]}),z(),J()]})}return r("div",{className:"space-y-4",children:[D(),N.blanks?.map((a,s)=>{const l=T[s]||"",n=v&&K(s,l),m=""!==l.trim();return r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-all hover:shadow-md",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),r("span",{className:"text-sm font-semibold text-gray-700",children:["Câu ",s+1,": Điền vào chỗ trống"]})]}),v&&m&&r("div",{className:f("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-bold",n?"bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200/60":"bg-red-100 text-red-700 ring-1 ring-red-200/60"),children:[e(n?i:d,{className:"h-3.5 w-3.5"}),n?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-4",children:[e("div",{className:"rounded-xl bg-gradient-to-r from-orange-50/80 to-amber-50/50 p-5 border border-orange-100/80",children:Q(a.text,a.id,s)}),0===s&&O(),0===s&&R(),v&&e("div",{className:f("rounded-xl border p-3 transition-colors",n?"border-emerald-200 bg-emerald-50/50":m?"border-red-200 bg-red-50/50":"border-gray-100 bg-gray-50/50"),children:r("div",{className:"space-y-2.5",children:[r("div",{className:"flex items-center justify-between rounded-md bg-white p-3 border border-gray-100",children:[e("span",{className:"text-sm text-gray-500",children:"Đã nhập:"}),e("span",{className:f("text-sm font-semibold",n?"text-emerald-600":m?"text-red-600":"text-gray-400 italic"),children:l||"—"})]}),r("div",{className:"flex items-center justify-between rounded-md bg-emerald-50 p-3 border border-emerald-100",children:[e("span",{className:"text-sm text-gray-500",children:"Đáp án đúng:"}),e("span",{className:"text-sm font-semibold text-emerald-600",children:a.correctAnswer})]}),r("div",{className:f("flex items-center justify-between rounded-md p-3 border",n?"bg-emerald-50 border-emerald-200":"bg-red-50 border-red-200"),children:[e("span",{className:"text-sm text-gray-500",children:"Kết quả:"}),e("div",{className:f("flex items-center gap-1.5 text-sm font-bold",n?"text-emerald-600":"text-red-600"),children:r(t,n?{children:[e(i,{className:"h-4 w-4"})," Chính xác"]}:{children:[e(d,{className:"h-4 w-4"})," Sai"]})})]})]})}),!v&&!m&&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.5",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(c,{className:"h-3 w-3"})}),e("span",{className:"text-sm text-amber-800",children:"Vui lòng điền câu trả lời"})]})]})]},a.id)}),z(),v&&M&&(N.blanks?.length||0)>1&&e("div",{className:f("overflow-hidden rounded-xl border shadow-sm",M.correct===M.total?"border-emerald-200 bg-gradient-to-r from-emerald-50 to-green-50":M.correct>=M.total/2?"border-yellow-200 bg-gradient-to-r from-yellow-50 to-amber-50":"border-red-200 bg-gradient-to-r from-red-50 to-rose-50"),children:r("div",{className:"flex items-center justify-between px-5 py-4",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:f("flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm",M.correct===M.total?"bg-gradient-to-br from-emerald-500 to-green-600":M.correct>=M.total/2?"bg-gradient-to-br from-yellow-500 to-amber-600":"bg-gradient-to-br from-red-500 to-rose-600"),children:M.correct===M.total?e(i,{className:"h-5 w-5"}):e(m,{className:"h-5 w-5"})}),r("div",{children:[e("h4",{className:"text-sm font-semibold text-gray-800",children:"Tổng kết"}),e("p",{className:"text-xs text-gray-500",children:"Kết quả bài làm của bạn"})]})]}),r("div",{className:"text-right",children:[r("div",{className:f("text-2xl font-bold",M.correct===M.total?"text-emerald-600":M.correct>=M.total/2?"text-yellow-600":"text-red-600"),children:[M.correct,"/",M.total]}),r("div",{className:"text-xs text-gray-500",children:[Math.round(M.correct/M.total*100),"% chính xác"]})]})]})}),J()]})}
|