@tinyweb_dev/oe-exam-sdk 0.1.1 → 0.1.2
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.js +1 -98
- 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/CreateExamInfoForm.js +1 -35
- package/dist/components/exams/CreateExamPageContainer.js +1 -103
- package/dist/components/exams/ExamCreator.js +1 -89
- package/dist/components/exams/ExamPartTabs.js +1 -40
- package/dist/components/exams/ExamQuestionGrid.js +1 -18
- package/dist/components/exams/ExamQuestionsPageContainer.js +1 -90
- package/dist/components/exams/PartAudioUploader.js +1 -9
- package/dist/components/exams/TemplateSelector.js +1 -66
- package/dist/components/exams/api.js +1 -3
- package/dist/components/exams/create-exam.validation.js +1 -18
- package/dist/components/exams/exam-template.utils.js +1 -18
- 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.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.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-transform-types.js +1 -1
- 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 +4 -2
package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js
CHANGED
|
@@ -1,141 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
|
|
5
|
-
import { Check, X } from 'lucide-react';
|
|
6
|
-
// Fisher-Yates shuffle algorithm
|
|
7
|
-
function shuffleArray(array) {
|
|
8
|
-
const shuffled = [...array];
|
|
9
|
-
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
10
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
11
|
-
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
12
|
-
}
|
|
13
|
-
return shuffled;
|
|
14
|
-
}
|
|
15
|
-
export function ArrangeLettersIntoWordsClient({ questionData, onSubmit, isReviewMode = false, userAnswer, }) {
|
|
16
|
-
// Initialize state for each subQuestion
|
|
17
|
-
const [availableLetters, setAvailableLetters] = useState({});
|
|
18
|
-
const [arrangedLetters, setArrangedLetters] = useState({});
|
|
19
|
-
const [answers, setAnswers] = useState(userAnswer || {});
|
|
20
|
-
// Store presigned URLs for images: { subQuestionId: presignedUrl }
|
|
21
|
-
const [imagePreviewUrls, setImagePreviewUrls] = useState({});
|
|
22
|
-
const fetchingRef = useRef(new Set());
|
|
23
|
-
// Initialize shuffled letters for each subQuestion
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const initialAvailable = {};
|
|
26
|
-
const initialArranged = {};
|
|
27
|
-
questionData.subQuestions.forEach((sq) => {
|
|
28
|
-
// Shuffle the correctWord into individual letters
|
|
29
|
-
const letters = shuffleArray(sq.correctWord.split(''));
|
|
30
|
-
initialAvailable[sq.id] = letters;
|
|
31
|
-
initialArranged[sq.id] = [];
|
|
32
|
-
});
|
|
33
|
-
setAvailableLetters(initialAvailable);
|
|
34
|
-
setArrangedLetters(initialArranged);
|
|
35
|
-
}, [questionData.subQuestions]);
|
|
36
|
-
// Sync userAnswer when it changes (e.g., when loading from server in review mode)
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (userAnswer) {
|
|
39
|
-
setAnswers(userAnswer);
|
|
40
|
-
}
|
|
41
|
-
}, [userAnswer]);
|
|
42
|
-
// Fetch presigned URLs for images if needed
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
questionData.subQuestions.forEach((sq) => {
|
|
45
|
-
if (sq.imageUrl &&
|
|
46
|
-
!sq.imageUrl.startsWith('http') &&
|
|
47
|
-
!imagePreviewUrls[sq.id] &&
|
|
48
|
-
!fetchingRef.current.has(sq.id)) {
|
|
49
|
-
fetchingRef.current.add(sq.id);
|
|
50
|
-
setImagePreviewUrls((prev) => ({
|
|
51
|
-
...prev,
|
|
52
|
-
[sq.id]: sq.imageUrl,
|
|
53
|
-
}));
|
|
54
|
-
fetchingRef.current.delete(sq.id);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}, [questionData.subQuestions, imagePreviewUrls]);
|
|
58
|
-
// Get image preview URL for a subQuestion
|
|
59
|
-
const getImagePreviewUrl = (subQuestion) => {
|
|
60
|
-
if (!subQuestion.imageUrl)
|
|
61
|
-
return '';
|
|
62
|
-
// If it's already a full URL, use it directly
|
|
63
|
-
if (subQuestion.imageUrl.startsWith('http')) {
|
|
64
|
-
return subQuestion.imageUrl;
|
|
65
|
-
}
|
|
66
|
-
// Otherwise, use presigned URL if available
|
|
67
|
-
return imagePreviewUrls[subQuestion.id] || subQuestion.imageUrl;
|
|
68
|
-
};
|
|
69
|
-
// Update answers when arrangedLetters change
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
const newAnswers = {};
|
|
72
|
-
Object.keys(arrangedLetters).forEach((subQuestionId) => {
|
|
73
|
-
newAnswers[subQuestionId] = arrangedLetters[subQuestionId].join('');
|
|
74
|
-
});
|
|
75
|
-
setAnswers(newAnswers);
|
|
76
|
-
onSubmit?.(newAnswers);
|
|
77
|
-
}, [arrangedLetters, onSubmit]);
|
|
78
|
-
// Handle click on available letter - move to arranged
|
|
79
|
-
const handleLetterClick = (subQuestionId, letterIndex) => {
|
|
80
|
-
if (isReviewMode)
|
|
81
|
-
return;
|
|
82
|
-
// Get the letter first before updating state
|
|
83
|
-
const currentAvailable = availableLetters[subQuestionId] || [];
|
|
84
|
-
const letter = currentAvailable[letterIndex];
|
|
85
|
-
if (!letter)
|
|
86
|
-
return;
|
|
87
|
-
setAvailableLetters((prev) => {
|
|
88
|
-
const letters = [...prev[subQuestionId]];
|
|
89
|
-
letters.splice(letterIndex, 1);
|
|
90
|
-
return { ...prev, [subQuestionId]: letters };
|
|
91
|
-
});
|
|
92
|
-
setArrangedLetters((prev) => {
|
|
93
|
-
const arranged = [...(prev[subQuestionId] || [])];
|
|
94
|
-
arranged.push(letter);
|
|
95
|
-
return { ...prev, [subQuestionId]: arranged };
|
|
96
|
-
});
|
|
97
|
-
};
|
|
98
|
-
// Handle click on arranged letter - move back to available
|
|
99
|
-
const handleArrangedLetterClick = (subQuestionId, letterIndex) => {
|
|
100
|
-
if (isReviewMode)
|
|
101
|
-
return;
|
|
102
|
-
// Get the letter first before updating state
|
|
103
|
-
const currentArranged = arrangedLetters[subQuestionId] || [];
|
|
104
|
-
const letter = currentArranged[letterIndex];
|
|
105
|
-
if (!letter)
|
|
106
|
-
return;
|
|
107
|
-
setArrangedLetters((prev) => {
|
|
108
|
-
const arranged = [...prev[subQuestionId]];
|
|
109
|
-
arranged.splice(letterIndex, 1);
|
|
110
|
-
return { ...prev, [subQuestionId]: arranged };
|
|
111
|
-
});
|
|
112
|
-
setAvailableLetters((prev) => {
|
|
113
|
-
const letters = [...(prev[subQuestionId] || [])];
|
|
114
|
-
letters.push(letter);
|
|
115
|
-
return { ...prev, [subQuestionId]: letters };
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
// Check if answer is correct (case insensitive)
|
|
119
|
-
const isAnswerCorrect = (subQuestionId, userAnswerValue) => {
|
|
120
|
-
const subQuestion = questionData.subQuestions.find((sq) => sq.id === subQuestionId);
|
|
121
|
-
if (!subQuestion)
|
|
122
|
-
return false;
|
|
123
|
-
return userAnswerValue.trim().toLowerCase() === subQuestion.correctWord.trim().toLowerCase();
|
|
124
|
-
};
|
|
125
|
-
return (_jsx("div", { className: "space-y-6", children: questionData.subQuestions.map((subQuestion, sqIndex) => {
|
|
126
|
-
const userAnswerValue = answers[subQuestion.id] || '';
|
|
127
|
-
const isCorrect = isReviewMode && isAnswerCorrect(subQuestion.id, userAnswerValue);
|
|
128
|
-
const available = availableLetters[subQuestion.id] || [];
|
|
129
|
-
const arranged = arrangedLetters[subQuestion.id] || [];
|
|
130
|
-
const imagePreviewUrl = getImagePreviewUrl(subQuestion);
|
|
131
|
-
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { className: "text-lg", children: ["C\u00E2u ", sqIndex + 1] }) }), _jsxs(CardContent, { className: "space-y-4", children: [imagePreviewUrl && (_jsx("div", { className: "flex justify-center", children: _jsx("div", { className: "relative h-48 w-full max-w-md overflow-hidden rounded-lg", children: _jsx("img", { src: imagePreviewUrl, alt: `Hint for question ${sqIndex + 1}`, className: "h-full w-full object-contain", onError: () => {
|
|
132
|
-
console.error('Failed to load image:', subQuestion.imageUrl);
|
|
133
|
-
} }) }) })), _jsxs("div", { children: [_jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "Ch\u1ECDn c\u00E1c ch\u1EEF c\u00E1i:" }), _jsx("div", { className: "flex flex-wrap gap-2", children: available.map((letter, index) => (_jsx("button", { onClick: () => handleLetterClick(subQuestion.id, index), disabled: isReviewMode, className: "flex h-12 w-12 items-center justify-center rounded-full border-2 border-blue-500 bg-white text-xl font-bold text-blue-600 transition-all hover:bg-blue-50 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50", children: letter }, `${letter}-${index}`))) })] }), _jsxs("div", { children: [_jsx("p", { className: "mb-2 text-sm font-medium text-gray-700", children: "S\u1EAFp x\u1EBFp th\u00E0nh t\u1EEB:" }), _jsx("div", { className: `min-h-[60px] rounded-lg border-2 p-4 ${isReviewMode
|
|
134
|
-
? isCorrect
|
|
135
|
-
? 'border-green-500 bg-green-50'
|
|
136
|
-
: userAnswerValue.trim() !== ''
|
|
137
|
-
? 'border-red-500 bg-red-50'
|
|
138
|
-
: 'border-gray-300 bg-gray-50'
|
|
139
|
-
: 'border-gray-300 bg-gray-50'}`, children: _jsx("div", { className: "flex flex-wrap items-center gap-2", children: arranged.length === 0 ? (_jsx("span", { className: "text-gray-400", children: "G\u1EA1ch ngang \u0111\u1EC3 s\u1EAFp x\u1EBFp..." })) : (arranged.map((letter, index) => (_jsx("button", { onClick: () => handleArrangedLetterClick(subQuestion.id, index), disabled: isReviewMode, className: "flex h-12 w-12 items-center justify-center rounded-full border-2 border-gray-400 bg-white text-xl font-bold text-gray-700 transition-all hover:bg-gray-100 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50", children: letter }, `arranged-${letter}-${index}`)))) }) })] }), isReviewMode && (_jsx("div", { className: "flex items-center gap-2", children: isCorrect ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "h-5 w-5 text-green-600" }), _jsx("span", { className: "text-sm text-green-600", children: "\u0110\u00FAng!" })] })) : userAnswerValue.trim() !== '' ? (_jsxs(_Fragment, { children: [_jsx(X, { className: "h-5 w-5 text-red-600" }), _jsxs("span", { className: "text-sm text-red-600", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", _jsx("strong", { children: subQuestion.correctWord })] })] })) : null }))] })] }, subQuestion.id));
|
|
140
|
-
}) }));
|
|
141
|
-
}
|
|
1
|
+
"use client";import{jsxs as e,jsx as r,Fragment as t}from"react/jsx-runtime";import{useState as s,useEffect as n,useRef as i}from"react";import{Card as a,CardContent as l,CardHeader as d,CardTitle as o}from"../../../../components/ui/card";import{Check as c,X as m}from"lucide-react";export function ArrangeLettersIntoWordsClient({questionData:u,onSubmit:h,isReviewMode:g=!1,userAnswer:b}){const[p,f]=s({}),[x,w]=s({}),[N,y]=s(b||{}),[v,j]=s({}),U=i(new Set);n(()=>{const e={},r={};u.subQuestions.forEach(t=>{const s=function(e){const r=[...e];for(let e=r.length-1;e>0;e--){const t=Math.floor(Math.random()*(e+1));[r[e],r[t]]=[r[t],r[e]]}return r}(t.correctWord.split(""));e[t.id]=s,r[t.id]=[]}),f(e),w(r)},[u.subQuestions]),n(()=>{b&&y(b)},[b]),n(()=>{u.subQuestions.forEach(e=>{!e.imageUrl||e.imageUrl.startsWith("http")||v[e.id]||U.current.has(e.id)||(U.current.add(e.id),j(r=>({...r,[e.id]:e.imageUrl})),U.current.delete(e.id))})},[u.subQuestions,v]);n(()=>{const e={};Object.keys(x).forEach(r=>{e[r]=x[r].join("")}),y(e),h?.(e)},[x,h]);return r("div",{className:"space-y-6",children:u.subQuestions.map((s,n)=>{const i=N[s.id]||"",h=g&&((e,r)=>{const t=u.subQuestions.find(r=>r.id===e);return!!t&&r.trim().toLowerCase()===t.correctWord.trim().toLowerCase()})(s.id,i),b=p[s.id]||[],y=x[s.id]||[],j=(e=>e.imageUrl?e.imageUrl.startsWith("http")?e.imageUrl:v[e.id]||e.imageUrl:"")(s);return e(a,{children:[r(d,{children:e(o,{className:"text-lg",children:["Câu ",n+1]})}),e(l,{className:"space-y-4",children:[j&&r("div",{className:"flex justify-center",children:r("div",{className:"relative h-48 w-full max-w-md overflow-hidden rounded-lg",children:r("img",{src:j,alt:`Hint for question ${n+1}`,className:"h-full w-full object-contain",onError:()=>{console.error("Failed to load image:",s.imageUrl)}})})}),e("div",{children:[r("p",{className:"mb-2 text-sm font-medium text-gray-700",children:"Chọn các chữ cái:"}),r("div",{className:"flex flex-wrap gap-2",children:b.map((e,t)=>r("button",{onClick:()=>((e,r)=>{if(g)return;const t=(p[e]||[])[r];t&&(f(t=>{const s=[...t[e]];return s.splice(r,1),{...t,[e]:s}}),w(r=>{const s=[...r[e]||[]];return s.push(t),{...r,[e]:s}}))})(s.id,t),disabled:g,className:"flex h-12 w-12 items-center justify-center rounded-full border-2 border-blue-500 bg-white text-xl font-bold text-blue-600 transition-all hover:bg-blue-50 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50",children:e},`${e}-${t}`))})]}),e("div",{children:[r("p",{className:"mb-2 text-sm font-medium text-gray-700",children:"Sắp xếp thành từ:"}),r("div",{className:"min-h-[60px] rounded-lg border-2 p-4 "+(g?h?"border-green-500 bg-green-50":""!==i.trim()?"border-red-500 bg-red-50":"border-gray-300 bg-gray-50":"border-gray-300 bg-gray-50"),children:r("div",{className:"flex flex-wrap items-center gap-2",children:0===y.length?r("span",{className:"text-gray-400",children:"Gạch ngang để sắp xếp..."}):y.map((e,t)=>r("button",{onClick:()=>((e,r)=>{if(g)return;const t=(x[e]||[])[r];t&&(w(t=>{const s=[...t[e]];return s.splice(r,1),{...t,[e]:s}}),f(r=>{const s=[...r[e]||[]];return s.push(t),{...r,[e]:s}}))})(s.id,t),disabled:g,className:"flex h-12 w-12 items-center justify-center rounded-full border-2 border-gray-400 bg-white text-xl font-bold text-gray-700 transition-all hover:bg-gray-100 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50",children:e},`arranged-${e}-${t}`))})})]}),g&&r("div",{className:"flex items-center gap-2",children:h?e(t,{children:[r(c,{className:"h-5 w-5 text-green-600"}),r("span",{className:"text-sm text-green-600",children:"Đúng!"})]}):""!==i.trim()?e(t,{children:[r(m,{className:"h-5 w-5 text-red-600"}),e("span",{className:"text-sm text-red-600",children:["Đáp án đúng: ",r("strong",{children:s.correctWord})]})]}):null})]})]},s.id)})})}
|
package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js
CHANGED
|
@@ -1,118 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import { Button } from '../../../../components/ui/button';
|
|
5
|
-
import { Label } from '../../../../components/ui/label';
|
|
6
|
-
import { Input } from '../../../../components/ui/input';
|
|
7
|
-
import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
|
|
8
|
-
import { Pencil, Eye, Plus, Trash2 } from 'lucide-react';
|
|
9
|
-
import { toast } from 'sonner';
|
|
10
|
-
import { FileUpload } from '../../../../components/ui/file-upload';
|
|
11
|
-
import { ArrangeLettersIntoWordsClient } from './ArrangeLettersIntoWordsClient';
|
|
12
|
-
function ArrangeLettersIntoWordsCreatorContent({ initialData, onSave, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
-
onCancel, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
-
onChange, }) {
|
|
15
|
-
// State
|
|
16
|
-
const [subQuestions, setSubQuestions] = useState(initialData?.subQuestions || []);
|
|
17
|
-
// Track previous initialData to detect changes
|
|
18
|
-
const previousInitialDataRef = useRef(initialData);
|
|
19
|
-
const isInitializingRef = useRef(false);
|
|
20
|
-
// Use ref to store onChange to avoid dependency issues
|
|
21
|
-
const onChangeRef = useRef(onChange);
|
|
22
|
-
// Track previous payload to prevent unnecessary onChange calls
|
|
23
|
-
const previousPayloadRef = useRef('');
|
|
24
|
-
// Update onChange ref when it changes
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
onChangeRef.current = onChange;
|
|
27
|
-
}, [onChange]);
|
|
28
|
-
// Sync state from initialData when it changes
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
const initialDataChanged = JSON.stringify(previousInitialDataRef.current) !== JSON.stringify(initialData);
|
|
31
|
-
if (initialDataChanged) {
|
|
32
|
-
isInitializingRef.current = true;
|
|
33
|
-
previousInitialDataRef.current = initialData;
|
|
34
|
-
if (initialData) {
|
|
35
|
-
if (initialData.subQuestions !== undefined)
|
|
36
|
-
setSubQuestions(initialData.subQuestions);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
setSubQuestions([]);
|
|
40
|
-
}
|
|
41
|
-
setTimeout(() => {
|
|
42
|
-
isInitializingRef.current = false;
|
|
43
|
-
}, 100);
|
|
44
|
-
}
|
|
45
|
-
}, [initialData]);
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
// Skip onChange during initialization to prevent infinite loop
|
|
48
|
-
if (isInitializingRef.current) {
|
|
49
|
-
// Still update previous payload ref to track current state
|
|
50
|
-
const currentPayload = JSON.stringify({ subQuestions });
|
|
51
|
-
previousPayloadRef.current = currentPayload;
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Create payload
|
|
55
|
-
const payload = { subQuestions };
|
|
56
|
-
// Serialize payload for comparison
|
|
57
|
-
const payloadString = JSON.stringify(payload);
|
|
58
|
-
// Only call onChange if payload actually changed
|
|
59
|
-
if (previousPayloadRef.current !== payloadString) {
|
|
60
|
-
previousPayloadRef.current = payloadString;
|
|
61
|
-
onChangeRef.current?.(payload);
|
|
62
|
-
}
|
|
63
|
-
}, [subQuestions]);
|
|
64
|
-
// UI State
|
|
65
|
-
const [isClientMode, setIsClientMode] = useState(false);
|
|
66
|
-
// Store presigned URLs for images: { subQuestionId: presignedUrl }
|
|
67
|
-
const [imagePreviewUrls, setImagePreviewUrls] = useState({});
|
|
68
|
-
// Add new sub-question
|
|
69
|
-
const addSubQuestion = () => {
|
|
70
|
-
if (subQuestions.length >= 5) {
|
|
71
|
-
toast.error('Tối đa 5 câu hỏi con!');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const newSubQuestion = {
|
|
75
|
-
id: `subq-${Date.now()}`,
|
|
76
|
-
correctWord: '',
|
|
77
|
-
imageUrl: '',
|
|
78
|
-
};
|
|
79
|
-
setSubQuestions([...subQuestions, newSubQuestion]);
|
|
80
|
-
};
|
|
81
|
-
// Remove sub-question
|
|
82
|
-
const removeSubQuestion = (id) => {
|
|
83
|
-
if (subQuestions.length <= 1) {
|
|
84
|
-
toast.error('Tối thiểu 1 câu hỏi con!');
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
setSubQuestions(subQuestions.filter((sq) => sq.id !== id));
|
|
88
|
-
};
|
|
89
|
-
// Update sub-question field
|
|
90
|
-
const updateSubQuestion = (id, field, value) => {
|
|
91
|
-
setSubQuestions(subQuestions.map((sq) => (sq.id === id ? { ...sq, [field]: value } : sq)));
|
|
92
|
-
};
|
|
93
|
-
// Update image preview URL
|
|
94
|
-
const updateImagePreviewUrl = (subQuestionId, presignedUrl) => {
|
|
95
|
-
setImagePreviewUrls((prev) => ({
|
|
96
|
-
...prev,
|
|
97
|
-
[subQuestionId]: presignedUrl,
|
|
98
|
-
}));
|
|
99
|
-
};
|
|
100
|
-
// If in client mode, render the Client component
|
|
101
|
-
if (isClientMode) {
|
|
102
|
-
const questionData = {
|
|
103
|
-
subQuestions: subQuestions.map((sq) => ({
|
|
104
|
-
...sq,
|
|
105
|
-
imageUrl: imagePreviewUrls[sq.id] || sq.imageUrl,
|
|
106
|
-
})),
|
|
107
|
-
};
|
|
108
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Arrange Letters Into Words (Preview)" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Ch\u1EBF \u0111\u1ED9 xem tr\u01B0\u1EDBc" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(false), children: [_jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Quay l\u1EA1i Edit Mode"] })] }) }) }), _jsx(ArrangeLettersIntoWordsClient, { questionData: questionData })] }));
|
|
109
|
-
}
|
|
110
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsx(Card, { children: _jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx(CardTitle, { children: "Arrange Letters Into Words" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "T\u1EA1o c\u00E2u h\u1ECFi s\u1EAFp x\u1EBFp ch\u1EEF c\u00E1i th\u00E0nh t\u1EEB" })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setIsClientMode(true), disabled: subQuestions.length < 1, children: [_jsx(Eye, { className: "mr-2 h-4 w-4" }), "Client Mode"] })] }) }) }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(CardTitle, { children: ["C\u00E2u h\u1ECFi con (", subQuestions.length, "/5)"] }), _jsxs(Button, { onClick: addSubQuestion, disabled: subQuestions.length >= 5, variant: "outline", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Th\u00EAm c\u00E2u h\u1ECFi"] })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [subQuestions.map((subQuestion, sqIndex) => (_jsxs(Card, { className: "border-2", children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(CardTitle, { className: "text-lg", children: ["C\u00E2u ", sqIndex + 1] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => removeSubQuestion(subQuestion.id), disabled: subQuestions.length <= 1, children: _jsx(Trash2, { className: "h-4 w-4 text-red-500" }) })] }) }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: `correctWord-${subQuestion.id}`, children: "T\u1EEB \u0111\u00FAng *" }), _jsx(Input, { id: `correctWord-${subQuestion.id}`, value: subQuestion.correctWord, onChange: (e) => updateSubQuestion(subQuestion.id, 'correctWord', e.target.value.toUpperCase()), placeholder: "Nh\u1EADp t\u1EEB \u0111\u00FAng (vd: COMPUTER)", className: "mt-1", disabled: isClientMode }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "T\u1EEB n\u00E0y s\u1EBD \u0111\u01B0\u1EE3c x\u00E1o tr\u1ED9n th\u00E0nh c\u00E1c k\u00FD t\u1EF1 ng\u1EABu nhi\u00EAn khi hi\u1EC3n th\u1ECB" })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: `image-${subQuestion.id}`, children: "H\u00ECnh \u1EA3nh g\u1EE3i \u00FD *" }), _jsx(FileUpload, { id: `image-${subQuestion.id}`, label: "", accept: "image/*", value: subQuestion.imageUrl, onChange: (key) => updateSubQuestion(subQuestion.id, 'imageUrl', key), onPresignedUrlChange: (presignedUrl) => {
|
|
111
|
-
updateImagePreviewUrl(subQuestion.id, presignedUrl);
|
|
112
|
-
}, disabled: isClientMode, maxSize: 5, placeholder: "Upload \u1EA3nh", required: true, autoUpload: true, prefix: "questions" }), subQuestion.imageUrl && (_jsx("div", { className: "relative mt-2 h-32 w-full max-w-md overflow-hidden rounded border", children: _jsx("img", { src: imagePreviewUrls[subQuestion.id] || subQuestion.imageUrl, alt: `Preview for question ${sqIndex + 1}`, className: "h-full w-full object-contain", onError: () => {
|
|
113
|
-
console.error('Failed to load image:', subQuestion.imageUrl);
|
|
114
|
-
} }) }))] })] })] }, subQuestion.id))), subQuestions.length === 0 && (_jsx("div", { className: "py-8 text-center text-gray-500", children: _jsx("p", { children: "Ch\u01B0a c\u00F3 c\u00E2u h\u1ECFi con n\u00E0o. Nh\u1EA5n \"Th\u00EAm c\u00E2u h\u1ECFi\" \u0111\u1EC3 b\u1EAFt \u0111\u1EA7u." }) }))] })] })] }));
|
|
115
|
-
}
|
|
116
|
-
export function ArrangeLettersIntoWordsCreator(props) {
|
|
117
|
-
return _jsx(ArrangeLettersIntoWordsCreatorContent, { ...props });
|
|
118
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as i,useRef as t,useEffect as n}from"react";import{Button as c}from"../../../../components/ui/button";import{Label as s}from"../../../../components/ui/label";import{Input as l}from"../../../../components/ui/input";import{Card as a,CardContent as o,CardHeader as d,CardTitle as m}from"../../../../components/ui/card";import{Pencil as h,Eye as u,Plus as g,Trash2 as p}from"lucide-react";import{toast as f}from"sonner";import{FileUpload as v}from"../../../../components/ui/file-upload";import{ArrangeLettersIntoWordsClient as N}from"./ArrangeLettersIntoWordsClient";function x({initialData:x,onSave:b,onCancel:y,onChange:C}){const[w,U]=i(x?.subQuestions||[]),T=t(x),W=t(!1),j=t(C),Q=t("");n(()=>{j.current=C},[C]),n(()=>{JSON.stringify(T.current)!==JSON.stringify(x)&&(W.current=!0,T.current=x,x?void 0!==x.subQuestions&&U(x.subQuestions):U([]),setTimeout(()=>{W.current=!1},100))},[x]),n(()=>{if(W.current){const e=JSON.stringify({subQuestions:w});return void(Q.current=e)}const e={subQuestions:w},r=JSON.stringify(e);Q.current!==r&&(Q.current=r,j.current?.(e))},[w]);const[k,S]=i(!1),[$,q]=i({}),O=(e,r,i)=>{U(w.map(t=>t.id===e?{...t,[r]:i}:t))};if(k){const i={subQuestions:w.map(e=>({...e,imageUrl:$[e.id]||e.imageUrl}))};return r("div",{className:"space-y-6",children:[e(a,{children:e(d,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(m,{children:"Arrange Letters Into Words (Preview)"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Chế độ xem trước"})]}),r(c,{variant:"outline",size:"sm",onClick:()=>S(!1),children:[e(h,{className:"mr-2 h-4 w-4"}),"Quay lại Edit Mode"]})]})})}),e(N,{questionData:i})]})}return r("div",{className:"space-y-6",children:[e(a,{children:e(d,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(m,{children:"Arrange Letters Into Words"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Tạo câu hỏi sắp xếp chữ cái thành từ"})]}),r(c,{variant:"outline",size:"sm",onClick:()=>S(!0),disabled:w.length<1,children:[e(u,{className:"mr-2 h-4 w-4"}),"Client Mode"]})]})})}),r(a,{children:[e(d,{children:r("div",{className:"flex items-center justify-between",children:[r(m,{children:["Câu hỏi con (",w.length,"/5)"]}),r(c,{onClick:()=>{if(w.length>=5)return void f.error("Tối đa 5 câu hỏi con!");const e={id:`subq-${Date.now()}`,correctWord:"",imageUrl:""};U([...w,e])},disabled:w.length>=5,variant:"outline",children:[e(g,{className:"mr-2 h-4 w-4"}),"Thêm câu hỏi"]})]})}),r(o,{className:"space-y-4",children:[w.map((i,t)=>r(a,{className:"border-2",children:[e(d,{children:r("div",{className:"flex items-center justify-between",children:[r(m,{className:"text-lg",children:["Câu ",t+1]}),e(c,{variant:"ghost",size:"sm",onClick:()=>{return e=i.id,void(w.length<=1?f.error("Tối thiểu 1 câu hỏi con!"):U(w.filter(r=>r.id!==e)));var e},disabled:w.length<=1,children:e(p,{className:"h-4 w-4 text-red-500"})})]})}),r(o,{className:"space-y-4",children:[r("div",{children:[e(s,{htmlFor:`correctWord-${i.id}`,children:"Từ đúng *"}),e(l,{id:`correctWord-${i.id}`,value:i.correctWord,onChange:e=>O(i.id,"correctWord",e.target.value.toUpperCase()),placeholder:"Nhập từ đúng (vd: COMPUTER)",className:"mt-1",disabled:k}),e("p",{className:"mt-1 text-xs text-gray-500",children:"Từ này sẽ được xáo trộn thành các ký tự ngẫu nhiên khi hiển thị"})]}),r("div",{children:[e(s,{htmlFor:`image-${i.id}`,children:"Hình ảnh gợi ý *"}),e(v,{id:`image-${i.id}`,label:"",accept:"image/*",value:i.imageUrl,onChange:e=>O(i.id,"imageUrl",e),onPresignedUrlChange:e=>{((e,r)=>{q(i=>({...i,[e]:r}))})(i.id,e)},disabled:k,maxSize:5,placeholder:"Upload ảnh",required:!0,autoUpload:!0,prefix:"questions"}),i.imageUrl&&e("div",{className:"relative mt-2 h-32 w-full max-w-md overflow-hidden rounded border",children:e("img",{src:$[i.id]||i.imageUrl,alt:`Preview for question ${t+1}`,className:"h-full w-full object-contain",onError:()=>{console.error("Failed to load image:",i.imageUrl)}})})]})]})]},i.id)),0===w.length&&e("div",{className:"py-8 text-center text-gray-500",children:e("p",{children:'Chưa có câu hỏi con nào. Nhấn "Thêm câu hỏi" để bắt đầu.'})})]})]})]})}export function ArrangeLettersIntoWordsCreator(r){return e(x,{...r})}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './ArrangeLettersIntoWordsClient';
|
|
1
|
+
export*from"./ArrangeLettersIntoWordsCreator";export*from"./ArrangeLettersIntoWordsClient";
|
|
@@ -1,4 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const arrangeLettersIntoWordsRegistration = {
|
|
3
|
-
component: ArrangeLettersIntoWordsCreator,
|
|
4
|
-
};
|
|
1
|
+
import{ArrangeLettersIntoWordsCreator as r}from"./ArrangeLettersIntoWordsCreator";export const arrangeLettersIntoWordsRegistration={component:r};
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
export const transformArrangeLettersIntoWords =
|
|
2
|
-
const answerData = question.answer;
|
|
3
|
-
if (!answerData?.subQuestions) {
|
|
4
|
-
return { apiContent: {}, apiCorrectAnswer: {} };
|
|
5
|
-
}
|
|
6
|
-
const subQuestions = (answerData.subQuestions || []).map((sq) => ({
|
|
7
|
-
id: sq.id,
|
|
8
|
-
imageUrl: sq.imageUrl || '',
|
|
9
|
-
}));
|
|
10
|
-
const answers = (answerData.subQuestions || []).reduce((acc, sq) => {
|
|
11
|
-
if (sq.id && sq.correctWord) {
|
|
12
|
-
acc[sq.id] = sq.correctWord;
|
|
13
|
-
}
|
|
14
|
-
return acc;
|
|
15
|
-
}, {});
|
|
16
|
-
return {
|
|
17
|
-
apiContent: {
|
|
18
|
-
subQuestions,
|
|
19
|
-
},
|
|
20
|
-
apiCorrectAnswer: {
|
|
21
|
-
answers,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
};
|
|
1
|
+
export const transformArrangeLettersIntoWords=r=>{const e=r.answer;if(!e?.subQuestions)return{apiContent:{},apiCorrectAnswer:{}};return{apiContent:{subQuestions:(e.subQuestions||[]).map(r=>({id:r.id,imageUrl:r.imageUrl||""}))},apiCorrectAnswer:{answers:(e.subQuestions||[]).reduce((r,e)=>(e.id&&e.correctWord&&(r[e.id]=e.correctWord),r),{})}}};
|
package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js
CHANGED
|
@@ -1,64 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { cn } from '../../../../shared/lib/utils';
|
|
5
|
-
import { Check, X, ListChecks, Lightbulb } from 'lucide-react';
|
|
6
|
-
export function ChooseCorrectAdjectiveClient({ questionData, onSubmit, isReviewMode = false, userAnswer, }) {
|
|
7
|
-
const [selectedAnswer, setSelectedAnswer] = useState(userAnswer);
|
|
8
|
-
const handleAnswerChange = (index) => {
|
|
9
|
-
if (isReviewMode)
|
|
10
|
-
return;
|
|
11
|
-
setSelectedAnswer(index);
|
|
12
|
-
onSubmit?.(index);
|
|
13
|
-
};
|
|
14
|
-
const isCorrect = (index) => {
|
|
15
|
-
return index === questionData.correctAnswer;
|
|
16
|
-
};
|
|
17
|
-
const isSelected = (index) => {
|
|
18
|
-
return selectedAnswer === index;
|
|
19
|
-
};
|
|
20
|
-
const userAnswerCorrect = selectedAnswer !== undefined && isCorrect(selectedAnswer);
|
|
21
|
-
const hasAnswered = selectedAnswer !== undefined;
|
|
22
|
-
// Get the correct answer text
|
|
23
|
-
const correctAnswerText = questionData.options[questionData.correctAnswer];
|
|
24
|
-
return (_jsx("div", { className: "space-y-5", children: _jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: cn('flex items-center justify-between border-b px-5 py-3', isReviewMode && userAnswerCorrect && 'border-green-200 bg-gradient-to-r from-green-50 to-emerald-50', isReviewMode && hasAnswered && !userAnswerCorrect && 'border-red-200 bg-gradient-to-r from-red-50 to-rose-50', (!isReviewMode || !hasAnswered) && 'border-gray-100 bg-gradient-to-r from-gray-50 to-white'), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('flex h-8 w-8 items-center justify-center rounded-lg text-white shadow-sm', isReviewMode && userAnswerCorrect && 'bg-gradient-to-br from-green-500 to-emerald-600', isReviewMode && hasAnswered && !userAnswerCorrect && 'bg-gradient-to-br from-red-500 to-rose-600', (!isReviewMode || !hasAnswered) && 'bg-gradient-to-br from-teal-500 to-cyan-600'), children: _jsx(ListChecks, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm font-medium text-gray-700", children: "Ch\u1ECDn t\u00EDnh t\u1EEB \u0111\u00FAng" })] }), isReviewMode && hasAnswered && (_jsxs("div", { className: cn('flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold', userAnswerCorrect ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'), children: [userAnswerCorrect ? _jsx(Check, { className: "h-3.5 w-3.5" }) : _jsx(X, { className: "h-3.5 w-3.5" }), userAnswerCorrect ? 'Đúng' : 'Sai'] }))] }), _jsxs("div", { className: "p-5 space-y-5", children: [_jsxs("div", { className: "rounded-xl bg-gradient-to-br from-slate-50 to-gray-50 border border-gray-100 p-5", children: [_jsx("div", { className: "text-lg leading-relaxed flex flex-wrap items-center gap-1", children: questionData.sentence.split('{0}').map((part, index, arr) => (_jsxs("span", { children: [_jsx("span", { className: "text-gray-800", children: part }), index < arr.length - 1 && (_jsx("span", { className: "inline-flex items-center mx-1", children: _jsx("span", { className: cn('inline-block min-w-[100px] px-3 py-1 text-center font-bold rounded-lg border-2 border-dashed', hasAnswered
|
|
25
|
-
? isReviewMode
|
|
26
|
-
? userAnswerCorrect
|
|
27
|
-
? 'border-green-400 bg-green-100 text-green-800'
|
|
28
|
-
: 'border-red-400 bg-red-100 text-red-800'
|
|
29
|
-
: 'border-indigo-400 bg-indigo-100 text-indigo-800'
|
|
30
|
-
: 'border-gray-300 bg-gray-100 text-gray-400'), children: hasAnswered ? questionData.options[selectedAnswer] : '_______' }) }))] }, index))) }), _jsxs("div", { className: "mt-3 flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-gray-500", children: "L\u1EF1a ch\u1ECDn:" }), _jsxs("span", { className: "text-sm font-medium text-gray-600", children: ["(", questionData.options.join(' / '), ")"] })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium text-gray-600 mb-3", children: "Ch\u1ECDn \u0111\u00E1p \u00E1n:" }), _jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: questionData.options.map((option, index) => {
|
|
31
|
-
const selected = isSelected(index);
|
|
32
|
-
const correct = isCorrect(index);
|
|
33
|
-
const letter = String.fromCharCode(65 + index);
|
|
34
|
-
return (_jsxs("button", { type: "button", onClick: () => handleAnswerChange(index), disabled: isReviewMode, className: cn('group flex items-center gap-2 rounded-xl border-2 p-3 text-left transition-all', isReviewMode
|
|
35
|
-
? correct
|
|
36
|
-
? 'border-green-400 bg-green-50'
|
|
37
|
-
: selected
|
|
38
|
-
? 'border-red-400 bg-red-50'
|
|
39
|
-
: 'border-gray-200 bg-gray-50'
|
|
40
|
-
: selected
|
|
41
|
-
? 'border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100'
|
|
42
|
-
: 'border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm'), children: [_jsx("div", { className: cn('flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all', isReviewMode
|
|
43
|
-
? correct
|
|
44
|
-
? 'bg-green-500 text-white'
|
|
45
|
-
: selected
|
|
46
|
-
? 'bg-red-500 text-white'
|
|
47
|
-
: 'bg-gray-200 text-gray-600'
|
|
48
|
-
: selected
|
|
49
|
-
? 'bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm'
|
|
50
|
-
: 'bg-gray-100 text-gray-600 group-hover:bg-gray-200'), children: letter }), _jsx("span", { className: cn('flex-1 text-sm font-semibold', isReviewMode && correct
|
|
51
|
-
? 'text-green-800'
|
|
52
|
-
: isReviewMode && selected && !correct
|
|
53
|
-
? 'text-red-800'
|
|
54
|
-
: 'text-gray-700'), children: option }), isReviewMode && (correct || selected) && (_jsx("div", { className: cn('flex h-5 w-5 items-center justify-center rounded-full', correct ? 'bg-green-500' : 'bg-red-500'), children: correct
|
|
55
|
-
? _jsx(Check, { className: "h-3 w-3 text-white" })
|
|
56
|
-
: _jsx(X, { className: "h-3 w-3 text-white" }) }))] }, index));
|
|
57
|
-
}) })] }), isReviewMode && (_jsxs("div", { className: "space-y-4 pt-2", children: [_jsxs("div", { className: "rounded-xl border border-green-200 bg-gradient-to-r from-green-50 to-emerald-50 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-green-200", children: _jsx(Check, { className: "h-3.5 w-3.5 text-green-700" }) }), _jsx("span", { className: "text-sm font-medium text-green-800", children: "C\u00E2u ho\u00E0n ch\u1EC9nh:" })] }), _jsx("p", { className: "text-base font-medium text-green-900 pl-8", children: questionData.sentence.replace('{0}', correctAnswerText) })] }), _jsx("div", { className: cn('rounded-xl p-4', userAnswerCorrect
|
|
58
|
-
? 'bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200'
|
|
59
|
-
: 'bg-gradient-to-r from-red-50 to-rose-50 border border-red-200'), 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', userAnswerCorrect
|
|
60
|
-
? 'bg-gradient-to-br from-green-500 to-emerald-600'
|
|
61
|
-
: 'bg-gradient-to-br from-red-500 to-rose-600'), children: userAnswerCorrect ? _jsx(Check, { className: "h-5 w-5" }) : _jsx(X, { className: "h-5 w-5" }) }), _jsxs("div", { children: [_jsx("p", { className: cn('text-sm font-semibold', userAnswerCorrect ? 'text-green-800' : 'text-red-800'), children: userAnswerCorrect ? 'Chính xác!' : 'Chưa đúng' }), _jsx("p", { className: cn('text-xs', userAnswerCorrect ? 'text-green-600' : 'text-red-600'), children: userAnswerCorrect
|
|
62
|
-
? 'Bạn đã chọn đúng tính từ.'
|
|
63
|
-
: `Đáp án đúng là "${correctAnswerText}".` })] })] }) }), questionData.explanation && (_jsx("div", { className: "rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm", children: _jsx(Lightbulb, { className: "h-4 w-4" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-semibold text-blue-800", children: "Gi\u1EA3i th\u00EDch:" }), _jsx("p", { className: "text-sm text-blue-700 mt-1", children: questionData.explanation })] })] }) }))] })), !isReviewMode && !hasAnswered && (_jsx("div", { className: "rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex h-8 w-8 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("span", { className: "text-sm font-bold", children: "!" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-amber-800", children: "Ch\u1ECDn t\u00EDnh t\u1EEB ph\u00F9 h\u1EE3p" }), _jsx("p", { className: "text-xs text-amber-600", children: "Nh\u1EA5n v\u00E0o m\u1ED9t trong c\u00E1c l\u1EF1a ch\u1ECDn b\u00EAn tr\u00EAn." })] })] }) }))] })] }) }));
|
|
64
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t}from"react";import{cn as n}from"../../../../shared/lib/utils";import{Check as d,X as a,ListChecks as s,Lightbulb as i}from"lucide-react";export function ChooseCorrectAdjectiveClient({questionData:o,onSubmit:l,isReviewMode:c=!1,userAnswer:m}){const[g,h]=t(m),b=e=>e===o.correctAnswer,x=void 0!==g&&b(g),p=void 0!==g,f=o.options[o.correctAnswer];return e("div",{className:"space-y-5",children:r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:n("flex items-center justify-between border-b px-5 py-3",c&&x&&"border-green-200 bg-gradient-to-r from-green-50 to-emerald-50",c&&p&&!x&&"border-red-200 bg-gradient-to-r from-red-50 to-rose-50",(!c||!p)&&"border-gray-100 bg-gradient-to-r from-gray-50 to-white"),children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-8 w-8 items-center justify-center rounded-lg text-white shadow-sm",c&&x&&"bg-gradient-to-br from-green-500 to-emerald-600",c&&p&&!x&&"bg-gradient-to-br from-red-500 to-rose-600",(!c||!p)&&"bg-gradient-to-br from-teal-500 to-cyan-600"),children:e(s,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Chọn tính từ đúng"})]}),c&&p&&r("div",{className:n("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",x?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(x?d:a,{className:"h-3.5 w-3.5"}),x?"Đúng":"Sai"]})]}),r("div",{className:"p-5 space-y-5",children:[r("div",{className:"rounded-xl bg-gradient-to-br from-slate-50 to-gray-50 border border-gray-100 p-5",children:[e("div",{className:"text-lg leading-relaxed flex flex-wrap items-center gap-1",children:o.sentence.split("{0}").map((t,d,a)=>r("span",{children:[e("span",{className:"text-gray-800",children:t}),d<a.length-1&&e("span",{className:"inline-flex items-center mx-1",children:e("span",{className:n("inline-block min-w-[100px] px-3 py-1 text-center font-bold rounded-lg border-2 border-dashed",p?c?x?"border-green-400 bg-green-100 text-green-800":"border-red-400 bg-red-100 text-red-800":"border-indigo-400 bg-indigo-100 text-indigo-800":"border-gray-300 bg-gray-100 text-gray-400"),children:p?o.options[g]:"_______"})})]},d))}),r("div",{className:"mt-3 flex items-center gap-2",children:[e("span",{className:"text-sm text-gray-500",children:"Lựa chọn:"}),r("span",{className:"text-sm font-medium text-gray-600",children:["(",o.options.join(" / "),")"]})]})]}),r("div",{className:"space-y-2",children:[e("p",{className:"text-sm font-medium text-gray-600 mb-3",children:"Chọn đáp án:"}),e("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:o.options.map((t,s)=>{const i=(e=>g===e)(s),o=b(s),m=String.fromCharCode(65+s);return r("button",{type:"button",onClick:()=>(e=>{c||(h(e),l?.(e))})(s),disabled:c,className:n("group flex items-center gap-2 rounded-xl border-2 p-3 text-left transition-all",c?o?"border-green-400 bg-green-50":i?"border-red-400 bg-red-50":"border-gray-200 bg-gray-50":i?"border-indigo-500 bg-indigo-50 shadow-sm ring-2 ring-indigo-100":"border-gray-200 bg-white hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm"),children:[e("div",{className:n("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-sm font-bold transition-all",c?o?"bg-green-500 text-white":i?"bg-red-500 text-white":"bg-gray-200 text-gray-600":i?"bg-gradient-to-br from-indigo-500 to-purple-600 text-white shadow-sm":"bg-gray-100 text-gray-600 group-hover:bg-gray-200"),children:m}),e("span",{className:n("flex-1 text-sm font-semibold",c&&o?"text-green-800":c&&i&&!o?"text-red-800":"text-gray-700"),children:t}),c&&(o||i)&&e("div",{className:n("flex h-5 w-5 items-center justify-center rounded-full",o?"bg-green-500":"bg-red-500"),children:e(o?d:a,{className:"h-3 w-3 text-white"})})]},s)})})]}),c&&r("div",{className:"space-y-4 pt-2",children:[r("div",{className:"rounded-xl border border-green-200 bg-gradient-to-r from-green-50 to-emerald-50 p-4",children:[r("div",{className:"flex items-center gap-2 mb-2",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-lg bg-green-200",children:e(d,{className:"h-3.5 w-3.5 text-green-700"})}),e("span",{className:"text-sm font-medium text-green-800",children:"Câu hoàn chỉnh:"})]}),e("p",{className:"text-base font-medium text-green-900 pl-8",children:o.sentence.replace("{0}",f)})]}),e("div",{className:n("rounded-xl p-4",x?"bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200":"bg-gradient-to-r from-red-50 to-rose-50 border border-red-200"),children:r("div",{className:"flex items-center gap-3",children:[e("div",{className:n("flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-sm",x?"bg-gradient-to-br from-green-500 to-emerald-600":"bg-gradient-to-br from-red-500 to-rose-600"),children:e(x?d:a,{className:"h-5 w-5"})}),r("div",{children:[e("p",{className:n("text-sm font-semibold",x?"text-green-800":"text-red-800"),children:x?"Chính xác!":"Chưa đúng"}),e("p",{className:n("text-xs",x?"text-green-600":"text-red-600"),children:x?"Bạn đã chọn đúng tính từ.":`Đáp án đúng là "${f}".`})]})]})}),o.explanation&&e("div",{className:"rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-4",children:r("div",{className:"flex items-start gap-3",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm",children:e(i,{className:"h-4 w-4"})}),r("div",{children:[e("p",{className:"text-sm font-semibold text-blue-800",children:"Giải thích:"}),e("p",{className:"text-sm text-blue-700 mt-1",children:o.explanation})]})]})})]}),!c&&!p&&e("div",{className:"rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4",children:r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 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("span",{className:"text-sm font-bold",children:"!"})}),r("div",{children:[e("p",{className:"text-sm font-medium text-amber-800",children:"Chọn tính từ phù hợp"}),e("p",{className:"text-xs text-amber-600",children:"Nhấn vào một trong các lựa chọn bên trên."})]})]})})]})]})})}
|