@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,11 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
import { CambridgeYleTimer } from './CambridgeYleTimer';
|
|
4
|
-
import { Loader2 } from 'lucide-react';
|
|
5
|
-
import arrowLeftImg from '../summer-sky/assets/images/arrow-left.png';
|
|
6
|
-
import titleLogoImg from '../summer-sky/assets/images/title-logo.png';
|
|
7
|
-
import submitImg from '../summer-sky/assets/images/submit.png';
|
|
8
|
-
import hasAnsweredImg from '../summer-sky/assets/images/has_answered.png';
|
|
9
|
-
export function CambridgeYleHeader({ totalQuestions, answeredCount, remainingSeconds, isSubmitting, isCameraActive, onSubmit, onClose, }) {
|
|
10
|
-
return (_jsxs("header", { className: "w-full bg-transparent px-4 pt-4 pb-0 sm:px-8 relative flex flex-wrap sm:flex-nowrap items-start sm:items-center justify-between z-50", children: [_jsx("div", { onClick: onClose, className: "cursor-pointer hover:scale-105 active:scale-95 transition-transform shrink-0", title: "Tho\u00E1t b\u00E0i thi", children: _jsx(Image, { src: arrowLeftImg, alt: "Quay l\u1EA1i", className: "w-[50px] sm:w-[80px]" }) }), _jsx("div", { className: "absolute left-1/2 -translate-x-1/2 -top-2 sm:top-0 pointer-events-none hidden sm:block", children: _jsx(Image, { src: titleLogoImg, alt: "Title Logo", className: "w-[200px] sm:w-[320px] h-auto" }) }), _jsx("div", { className: "sm:hidden flex-1 flex justify-center pointer-events-none", children: _jsx(Image, { src: titleLogoImg, alt: "Title Logo", className: "w-[150px] h-auto -mt-2" }) }), _jsxs("div", { className: "absolute right-4 sm:right-8 top-8 flex flex-row items-center gap-3 sm:gap-4 z-[100]", children: [isCameraActive && (_jsx("div", { className: "flex items-center justify-center rounded-full bg-white/20 p-2 backdrop-blur-sm shrink-0", title: "Camera \u0111ang ghi h\u00ECnh", children: _jsx("div", { className: "h-3 w-3 animate-pulse rounded-full bg-red-500" }) })), _jsx(CambridgeYleTimer, { remainingSeconds: remainingSeconds, totalQuestions: totalQuestions, answeredCount: answeredCount }), _jsxs("div", { className: "flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] bg-[#FF9900] shadow-[0_4px_20px_rgba(0,0,0,0.25)] border-none shrink-0", title: "S\u1ED1 c\u00E2u h\u1ECFi \u0111\u00E3 ho\u00E0n th\u00E0nh", children: [_jsx(Image, { src: hasAnsweredImg, alt: "Progress", width: 75, height: 75, className: "w-[50px] sm:w-[65px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10" }), _jsxs("span", { className: "flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]", style: { fontFamily: '"SVN-Volte Rounded", "Quicksand", sans-serif', textShadow: '0 2px 4px rgba(0,0,0,0.2)' }, children: [answeredCount, "/", totalQuestions] })] }), _jsxs("button", { onClick: onSubmit, disabled: isSubmitting, className: `group cursor-pointer flex items-center h-[40px] sm:h-[50px] w-[130px] sm:w-[170px] rounded-[33.5px] shadow-[0_4px_20px_rgba(0,0,0,0.25)] transition-all duration-300 hover:scale-105 active:scale-95 disabled:pointer-events-none disabled:opacity-60 border-none shrink-0 ${isSubmitting ? 'bg-slate-400' : 'bg-[#16CA3B] hover:bg-[#15b736]'}`, children: [_jsx(Image, { src: submitImg, alt: "Submit", width: 75, height: 75, className: "w-[50px] sm:w-[65px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none transition-transform duration-300 group-hover:scale-110 z-10" }), isSubmitting ? (_jsx("div", { className: "flex-1 flex justify-center pr-[10px] sm:pr-[16px]", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-white" }) })) : (_jsx("span", { className: "flex-1 text-center font-bold text-[18px] sm:text-[20px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]", style: { fontFamily: '"SVN-Volte Rounded", "Quicksand", sans-serif', textShadow: '0 2px 4px rgba(0,0,0,0.2)' }, children: "N\u1ED9p b\u00E0i" }))] })] })] }));
|
|
11
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as s}from"react/jsx-runtime";import t from"next/image";import{CambridgeYleTimer as r}from"./CambridgeYleTimer";import{Loader2 as a}from"lucide-react";import i from"../summer-sky/assets/images/arrow-left.png";import n from"../summer-sky/assets/images/title-logo.png";import o from"../summer-sky/assets/images/submit.png";import m from"../summer-sky/assets/images/has_answered.png";export function CambridgeYleHeader({totalQuestions:l,answeredCount:p,remainingSeconds:x,isSubmitting:d,isCameraActive:c,onSubmit:h,onClose:u}){return s("header",{className:"w-full bg-transparent px-4 pt-4 pb-0 sm:px-8 relative flex flex-wrap sm:flex-nowrap items-start sm:items-center justify-between z-50",children:[e("div",{onClick:u,className:"cursor-pointer hover:scale-105 active:scale-95 transition-transform shrink-0",title:"Thoát bài thi",children:e(t,{src:i,alt:"Quay lại",className:"w-[50px] sm:w-[80px]"})}),e("div",{className:"absolute left-1/2 -translate-x-1/2 -top-2 sm:top-0 pointer-events-none hidden sm:block",children:e(t,{src:n,alt:"Title Logo",className:"w-[200px] sm:w-[320px] h-auto"})}),e("div",{className:"sm:hidden flex-1 flex justify-center pointer-events-none",children:e(t,{src:n,alt:"Title Logo",className:"w-[150px] h-auto -mt-2"})}),s("div",{className:"absolute right-4 sm:right-8 top-8 flex flex-row items-center gap-3 sm:gap-4 z-[100]",children:[c&&e("div",{className:"flex items-center justify-center rounded-full bg-white/20 p-2 backdrop-blur-sm shrink-0",title:"Camera đang ghi hình",children:e("div",{className:"h-3 w-3 animate-pulse rounded-full bg-red-500"})}),e(r,{remainingSeconds:x,totalQuestions:l,answeredCount:p}),s("div",{className:"flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] bg-[#FF9900] shadow-[0_4px_20px_rgba(0,0,0,0.25)] border-none shrink-0",title:"Số câu hỏi đã hoàn thành",children:[e(t,{src:m,alt:"Progress",width:75,height:75,className:"w-[50px] sm:w-[65px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),s("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:[p,"/",l]})]}),s("button",{onClick:h,disabled:d,className:"group cursor-pointer flex items-center h-[40px] sm:h-[50px] w-[130px] sm:w-[170px] rounded-[33.5px] shadow-[0_4px_20px_rgba(0,0,0,0.25)] transition-all duration-300 hover:scale-105 active:scale-95 disabled:pointer-events-none disabled:opacity-60 border-none shrink-0 "+(d?"bg-slate-400":"bg-[#16CA3B] hover:bg-[#15b736]"),children:[e(t,{src:o,alt:"Submit",width:75,height:75,className:"w-[50px] sm:w-[65px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none transition-transform duration-300 group-hover:scale-110 z-10"}),d?e("div",{className:"flex-1 flex justify-center pr-[10px] sm:pr-[16px]",children:e(a,{className:"h-6 w-6 animate-spin text-white"})}):e("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[20px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:"Nộp bài"})]})]})]})}
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Info, Megaphone } from 'lucide-react';
|
|
4
|
-
export default function CambridgeYleInstructionBanner({ instruction, instructions, hasExample = false, children, isReviewMode = false, }) {
|
|
5
|
-
if (isReviewMode)
|
|
6
|
-
return null;
|
|
7
|
-
const hasInstructionsList = instructions && instructions.length > 0;
|
|
8
|
-
return (_jsxs("div", { className: "shrink-0 space-y-3 px-2 sm:px-6 mb-2 sm:mb-4", children: [instruction && (_jsxs("div", { className: "flex w-full items-center gap-4 sm:gap-5 rounded-[24px] bg-[#F8FBFF] border-2 border-dashed border-blue-300 px-5 py-4 transition-all hover:bg-blue-50/50", children: [_jsx("div", { className: "flex items-center justify-center w-12 h-12 sm:w-14 sm:h-14 rounded-[16px] bg-[#0070FF] shadow-[4px_4px_0px_rgba(191,219,254,1)] shrink-0 -rotate-6 transition-transform hover:rotate-0", children: _jsx(Megaphone, { className: "h-6 w-6 sm:h-7 sm:w-7 text-white", strokeWidth: 2.5 }) }), _jsx("div", { className: "flex-1 flex flex-col justify-center", children: _jsxs("p", { className: "text-[15px] sm:text-[18px] font-black uppercase tracking-wide text-[#002868] leading-snug", style: { fontFamily: '"SVN-Volte Rounded", "Quicksand", sans-serif' }, children: [instruction, hasExample && _jsx("span", { className: "inline-block text-[#0070FF] ml-2 text-[14px] sm:text-[16px] font-bold tracking-normal bg-blue-100 px-3 py-0.5 rounded-full align-middle -mt-1", children: "THERE IS ONE EXAMPLE" })] }) })] })), children, hasInstructionsList && (_jsx("div", { className: "rounded-lg border border-blue-200 bg-white p-4 shadow-sm", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("h4", { className: "flex items-center gap-2 font-semibold text-blue-900", children: [_jsx(Info, { className: "h-4 w-4" }), "Instructions"] }), _jsx("ol", { className: "list-inside list-decimal space-y-1.5 text-sm text-gray-700", children: instructions.map((item, index) => (_jsx("li", { className: "leading-relaxed", children: item }, index))) })] }) }))] }));
|
|
9
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{Info as t,Megaphone as l}from"lucide-react";export default function a({instruction:a,instructions:i,hasExample:r=!1,children:n,isReviewMode:d=!1}){if(d)return null;const c=i&&i.length>0;return s("div",{className:"shrink-0 space-y-3 px-2 sm:px-6 mb-2 sm:mb-4",children:[a&&s("div",{className:"flex w-full items-center gap-4 sm:gap-5 rounded-[24px] bg-[#F8FBFF] border-2 border-dashed border-blue-300 px-5 py-4 transition-all hover:bg-blue-50/50",children:[e("div",{className:"flex items-center justify-center w-12 h-12 sm:w-14 sm:h-14 rounded-[16px] bg-[#0070FF] shadow-[4px_4px_0px_rgba(191,219,254,1)] shrink-0 -rotate-6 transition-transform hover:rotate-0",children:e(l,{className:"h-6 w-6 sm:h-7 sm:w-7 text-white",strokeWidth:2.5})}),e("div",{className:"flex-1 flex flex-col justify-center",children:s("p",{className:"text-[15px] sm:text-[18px] font-black uppercase tracking-wide text-[#002868] leading-snug",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif'},children:[a,r&&e("span",{className:"inline-block text-[#0070FF] ml-2 text-[14px] sm:text-[16px] font-bold tracking-normal bg-blue-100 px-3 py-0.5 rounded-full align-middle -mt-1",children:"THERE IS ONE EXAMPLE"})]})})]}),n,c&&e("div",{className:"rounded-lg border border-blue-200 bg-white p-4 shadow-sm",children:s("div",{className:"space-y-3",children:[s("h4",{className:"flex items-center gap-2 font-semibold text-blue-900",children:[e(t,{className:"h-4 w-4"}),"Instructions"]}),e("ol",{className:"list-inside list-decimal space-y-1.5 text-sm text-gray-700",children:i.map((s,t)=>e("li",{className:"leading-relaxed",children:s},t))})]})})]})}
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
import prevBtnImg from '../summer-sky/assets/images/prev-question-btn.png';
|
|
4
|
-
import nextBtnImg from '../summer-sky/assets/images/next-question-btn.png';
|
|
5
|
-
export function CambridgeYleNavButton({ direction, onClick, disabled = false, }) {
|
|
6
|
-
const imgSrc = direction === 'prev' ? prevBtnImg : nextBtnImg;
|
|
7
|
-
const altText = direction === 'prev' ? 'Câu trước' : 'Câu tiếp theo';
|
|
8
|
-
return (_jsx("button", { onClick: onClick, disabled: disabled, className: `flex items-center justify-center transition-transform outline-none bg-transparent border-none
|
|
9
|
-
${disabled
|
|
10
|
-
? 'cursor-not-allowed opacity-45 grayscale pointer-events-none'
|
|
11
|
-
: 'cursor-pointer hover:scale-[1.05] active:scale-[0.95]'}
|
|
12
|
-
`, "aria-label": altText, title: disabled ? 'Không thể chuyển câu' : undefined, children: _jsx(Image, { src: imgSrc, alt: altText, className: "w-16 h-auto sm:w-20" }) }));
|
|
13
|
-
}
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import t from"next/image";import n from"../summer-sky/assets/images/prev-question-btn.png";import r from"../summer-sky/assets/images/next-question-btn.png";export function CambridgeYleNavButton({direction:s,onClick:o,disabled:i=!1}){const a="prev"===s?"Câu trước":"Câu tiếp theo";return e("button",{onClick:o,disabled:i,className:`flex items-center justify-center transition-transform outline-none bg-transparent border-none\n ${i?"cursor-not-allowed opacity-45 grayscale pointer-events-none":"cursor-pointer hover:scale-[1.05] active:scale-[0.95]"}\n `,"aria-label":a,title:i?"Không thể chuyển câu":void 0,children:e(t,{src:"prev"===s?n:r,alt:a,className:"w-16 h-auto sm:w-20"})})}
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
import backgroundTitleImg from '../summer-sky/assets/images/background_title.png';
|
|
4
|
-
export default function CambridgeYlePartBanner({ partName, isReviewMode = false, }) {
|
|
5
|
-
if (!partName || isReviewMode)
|
|
6
|
-
return null;
|
|
7
|
-
return (_jsxs("div", { className: "relative mx-auto flex shrink-0 items-center justify-center w-[260px] sm:w-[320px] h-[55px] sm:h-[70px] drop-shadow-[0_4px_6px_rgba(0,0,0,0.3)] mb-1 sm:mb-2 mt-0", children: [_jsx(Image, { src: backgroundTitleImg, alt: "Part Badge", fill: true, className: "object-fill pointer-events-none" }), _jsx("span", { className: "relative z-10 text-yellow-300 font-black uppercase text-[24px] sm:text-[30px] tracking-[0.08em] -translate-y-0.5 sm:-translate-y-1", style: { textShadow: '0px 2px 4px rgba(0,0,0,0.8)', fontFamily: '"SVN-Volte Rounded", "Quicksand", sans-serif' }, children: partName })] }));
|
|
8
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import s from"next/image";import a from"../summer-sky/assets/images/background_title.png";export default function r({partName:r,isReviewMode:m=!1}){return!r||m?null:t("div",{className:"relative mx-auto flex shrink-0 items-center justify-center w-[260px] sm:w-[320px] h-[55px] sm:h-[70px] drop-shadow-[0_4px_6px_rgba(0,0,0,0.3)] mb-1 sm:mb-2 mt-0",children:[e(s,{src:a,alt:"Part Badge",fill:!0,className:"object-fill pointer-events-none"}),e("span",{className:"relative z-10 text-yellow-300 font-black uppercase text-[24px] sm:text-[30px] tracking-[0.08em] -translate-y-0.5 sm:-translate-y-1",style:{textShadow:"0px 2px 4px rgba(0,0,0,0.8)",fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif'},children:r})]})}
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Trophy } from 'lucide-react';
|
|
3
|
-
export function CambridgeYleProgressBar({ progress, className = '', }) {
|
|
4
|
-
const clampedProgress = Math.min(100, Math.max(0, progress));
|
|
5
|
-
return (_jsxs("div", { className: `flex items-center gap-2 sm:gap-3 ${className}`, children: [_jsx("div", { className: "relative h-2 w-full max-w-md overflow-hidden rounded-full bg-gray-200 sm:h-3", children: _jsx("div", { className: "h-full rounded-full bg-gradient-to-r from-orange-400 via-red-400 to-red-500 transition-all duration-300 ease-out", style: { width: `${clampedProgress}%` } }) }), _jsx("div", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center sm:h-8 sm:w-8", children: _jsx(Trophy, { className: "h-5 w-5 text-yellow-500 sm:h-6 sm:w-6" }) })] }));
|
|
6
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Trophy as s}from"lucide-react";export function CambridgeYleProgressBar({progress:a,className:l=""}){const t=Math.min(100,Math.max(0,a));return r("div",{className:`flex items-center gap-2 sm:gap-3 ${l}`,children:[e("div",{className:"relative h-2 w-full max-w-md overflow-hidden rounded-full bg-gray-200 sm:h-3",children:e("div",{className:"h-full rounded-full bg-gradient-to-r from-orange-400 via-red-400 to-red-500 transition-all duration-300 ease-out",style:{width:`${t}%`}})}),e("div",{className:"flex h-6 w-6 flex-shrink-0 items-center justify-center sm:h-8 sm:w-8",children:e(s,{className:"h-5 w-5 text-yellow-500 sm:h-6 sm:w-6"})})]})}
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cn } from '../../../shared/lib/utils';
|
|
3
|
-
export default function CambridgeYleQuestionCard({ children, className, }) {
|
|
4
|
-
return _jsx("div", { className: cn('relative w-full h-full flex flex-col', className), children: children });
|
|
5
|
-
}
|
|
1
|
+
import{jsx as l}from"react/jsx-runtime";import{cn as e}from"../../../shared/lib/utils";export default function r({children:r,className:i}){return l("div",{className:e("relative w-full h-full flex flex-col",i),children:r})}
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cn } from '../../../shared/lib/utils';
|
|
3
|
-
/**
|
|
4
|
-
* Full-width question card container for coloring/painting questions.
|
|
5
|
-
* Uses background without dashed separator (unlike CambridgeYleQuestionCard).
|
|
6
|
-
*/
|
|
7
|
-
export default function CambridgeYleQuestionCardFullWidth({ children, className, }) {
|
|
8
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn('relative mx-auto flex min-h-[70vh] w-full flex-1 flex-col rounded-2xl bg-white p-4 shadow-lg lg:hidden', className), children: _jsx("div", { className: "flex-1 overflow-auto", children: children }) }), _jsx("div", { className: cn('relative mx-auto hidden w-full max-w-[1400px] flex-1 min-h-0 flex-col rounded-[24px] border-[12px] border-[#3182CE] bg-white shadow-xl lg:flex', className), children: _jsx("div", { className: "flex-1 overflow-auto p-6 md:p-8", children: children }) })] }));
|
|
9
|
-
}
|
|
1
|
+
import{jsx as e,Fragment as l,jsxs as r}from"react/jsx-runtime";import{cn as a}from"../../../shared/lib/utils";export default function d({children:d,className:i}){return r(l,{children:[e("div",{className:a("relative mx-auto flex min-h-[70vh] w-full flex-1 flex-col rounded-2xl bg-white p-4 shadow-lg lg:hidden",i),children:e("div",{className:"flex-1 overflow-auto",children:d})}),e("div",{className:a("relative mx-auto hidden w-full max-w-[1400px] flex-1 min-h-0 flex-col rounded-[24px] border-[12px] border-[#3182CE] bg-white shadow-xl lg:flex",i),children:e("div",{className:"flex-1 overflow-auto p-6 md:p-8",children:d})})]})}
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cn } from '../../../shared/lib/utils';
|
|
3
|
-
import Image from 'next/image';
|
|
4
|
-
import phaoImg from './assets/images/phao.png';
|
|
5
|
-
import sanhoImg from './assets/images/sanho.png';
|
|
6
|
-
import saoImg from './assets/images/sao.png';
|
|
7
|
-
import voocImg from './assets/images/vooc.png';
|
|
8
|
-
const PART_ICONS = [phaoImg, sanhoImg, saoImg, voocImg];
|
|
9
|
-
export function CambridgeYleSidebar({ parts, questions, currentQuestionGlobalIndex, onPartClick, onQuestionClick, isNavDisabled, className, }) {
|
|
10
|
-
const currentQuestion = questions[currentQuestionGlobalIndex];
|
|
11
|
-
const currentPartIndex = currentQuestion ? currentQuestion.partIndex : 0;
|
|
12
|
-
return (_jsxs("div", { className: cn("flex flex-col w-full h-full pb-4", className), children: [_jsxs("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-4 lg:p-6 pb-2", children: [_jsxs("div", { className: "flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px]", children: [_jsx("div", { className: "flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white", children: _jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), _jsx("polyline", { points: "2 17 12 22 22 17" }), _jsx("polyline", { points: "2 12 12 17 22 12" })] }) }), _jsx("span", { className: "font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent", children: "Parts" })] }), _jsx("div", { className: "flex flex-col gap-2.5", children: parts.map((part, idx) => {
|
|
13
|
-
const isCurrent = idx === currentPartIndex;
|
|
14
|
-
const iconSrc = PART_ICONS[idx % PART_ICONS.length];
|
|
15
|
-
const prevCategory = idx > 0 ? parts[idx - 1].category : null;
|
|
16
|
-
const showCategoryTitle = part.category && part.category !== prevCategory;
|
|
17
|
-
return (_jsxs("div", { className: "flex flex-col", children: [showCategoryTitle && (_jsxs("div", { className: "flex items-center gap-2 mt-5 mb-3 px-1", children: [_jsx("div", { className: "h-[4px] w-4 rounded-full bg-blue-500" }), _jsx("span", { className: "text-[14px] font-black uppercase tracking-[0.15em] text-blue-800", children: part.category?.replace(/_/g, ' ') }), _jsx("div", { className: "h-[2px] flex-1 rounded-full bg-blue-100" })] })), _jsxs("button", { type: "button", onClick: () => onPartClick(idx), disabled: isNavDisabled, className: cn("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm", isCurrent
|
|
18
|
-
? "bg-blue-600 text-white border-blue-600"
|
|
19
|
-
: "bg-white text-slate-800 border-transparent", !isCurrent && !isNavDisabled ? "hover:border-blue-200" : "", isNavDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex items-center justify-center w-8 h-8 shrink-0", children: _jsx(Image, { src: iconSrc, alt: `part icon ${idx}`, className: "w-[30px] h-auto object-contain" }) }), _jsx("span", { className: "font-black text-[15px]", children: part.name || `Part ${part.partNo}` })] }), _jsxs("span", { className: cn("text-[13px] font-bold tracking-wide", isCurrent ? "text-blue-100" : "text-blue-900/60"), children: [part.answeredCount, "/", part.totalQuestions] })] })] }, idx));
|
|
20
|
-
}) })] }), _jsx("div", { className: "px-6", children: _jsx("hr", { className: "border-t-2 border-dashed border-blue-100" }) }), _jsxs("div", { className: "flex-1 p-4 lg:p-6 pt-4 flex flex-col min-h-0", children: [_jsxs("div", { className: "flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px] shrink-0", children: [_jsx("div", { className: "flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white", children: _jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1" }), _jsx("path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }), _jsx("path", { d: "M12 11h4" }), _jsx("path", { d: "M12 16h4" }), _jsx("path", { d: "M8 11h.01" }), _jsx("path", { d: "M8 16h.01" })] }) }), _jsx("span", { className: "font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent", children: "Question List" })] }), _jsx("div", { className: "flex-1 overflow-y-auto custom-scrollbar pr-1", children: _jsx("div", { className: "grid grid-cols-5 gap-2", children: questions.map((q) => {
|
|
21
|
-
const isCurrent = q.globalIndex === currentQuestionGlobalIndex;
|
|
22
|
-
const isAnswered = q.isAnswered;
|
|
23
|
-
let btnStyle = "bg-white text-slate-800 shadow-sm border-transparent";
|
|
24
|
-
if (isCurrent) {
|
|
25
|
-
btnStyle = "bg-blue-600 text-white border-blue-600 shadow-md";
|
|
26
|
-
}
|
|
27
|
-
else if (isAnswered) {
|
|
28
|
-
btnStyle = "bg-[#4ade80] text-white border-transparent shadow-sm";
|
|
29
|
-
}
|
|
30
|
-
if (!isCurrent && !isNavDisabled) {
|
|
31
|
-
btnStyle += " hover:shadow-md hover:text-blue-600";
|
|
32
|
-
}
|
|
33
|
-
if (isNavDisabled) {
|
|
34
|
-
btnStyle += " opacity-50 cursor-not-allowed";
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
btnStyle += " cursor-pointer";
|
|
38
|
-
}
|
|
39
|
-
return (_jsx("button", { type: "button", onClick: () => onQuestionClick(q.globalIndex), disabled: isNavDisabled, className: cn("h-[44px] w-full rounded-[10px] flex items-center justify-center font-bold text-[15px] transition-all border", btnStyle), children: q.questionNumber }, q.globalIndex));
|
|
40
|
-
}) }) }), _jsx("div", { className: "shrink-0 mt-4 pt-4 border-t border-blue-200/50", children: _jsxs("div", { className: "flex items-center justify-between text-[11px] xl:text-[11.5px] font-bold text-gray-700", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "w-3.5 h-3.5 rounded-full bg-blue-600 shadow-sm" }), _jsx("span", { children: "Current" })] }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "w-3.5 h-3.5 rounded-full bg-green-500 shadow-sm" }), _jsx("span", { children: "Answered" })] }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "w-3.5 h-3.5 rounded-full bg-[#f4f9ff] border border-blue-200 shadow-sm" }), _jsx("span", { children: "Not answered" })] })] }) })] })] }));
|
|
41
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{cn as r}from"../../../shared/lib/utils";import s from"next/image";import l from"./assets/images/phao.png";import a from"./assets/images/sanho.png";import n from"./assets/images/sao.png";import i from"./assets/images/vooc.png";const o=[l,a,n,i];export function CambridgeYleSidebar({parts:l,questions:a,currentQuestionGlobalIndex:n,onPartClick:i,onQuestionClick:d,isNavDisabled:c,className:p}){const m=a[n],h=m?m.partIndex:0;return t("div",{className:r("flex flex-col w-full h-full pb-4",p),children:[t("div",{className:"flex-1 overflow-y-auto custom-scrollbar p-4 lg:p-6 pb-2",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px]",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("polygon",{points:"12 2 2 7 12 12 22 7 12 2"}),e("polyline",{points:"2 17 12 22 22 17"}),e("polyline",{points:"2 12 12 17 22 12"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Parts"})]}),e("div",{className:"flex flex-col gap-2.5",children:l.map((a,n)=>{const d=n===h,p=o[n%o.length],m=n>0?l[n-1].category:null,b=a.category&&a.category!==m;return t("div",{className:"flex flex-col",children:[b&&t("div",{className:"flex items-center gap-2 mt-5 mb-3 px-1",children:[e("div",{className:"h-[4px] w-4 rounded-full bg-blue-500"}),e("span",{className:"text-[14px] font-black uppercase tracking-[0.15em] text-blue-800",children:a.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>i(n),disabled:c,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",d?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",d||c?"":"hover:border-blue-200",c?"opacity-50 cursor-not-allowed":"cursor-pointer"),children:[t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex items-center justify-center w-8 h-8 shrink-0",children:e(s,{src:p,alt:`part icon ${n}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:a.name||`Part ${a.partNo}`})]}),t("span",{className:r("text-[13px] font-bold tracking-wide",d?"text-blue-100":"text-blue-900/60"),children:[a.answeredCount,"/",a.totalQuestions]})]})]},n)})})]}),e("div",{className:"px-6",children:e("hr",{className:"border-t-2 border-dashed border-blue-100"})}),t("div",{className:"flex-1 p-4 lg:p-6 pt-4 flex flex-col min-h-0",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px] shrink-0",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}),e("path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}),e("path",{d:"M12 11h4"}),e("path",{d:"M12 16h4"}),e("path",{d:"M8 11h.01"}),e("path",{d:"M8 16h.01"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Question List"})]}),e("div",{className:"flex-1 overflow-y-auto custom-scrollbar pr-1",children:e("div",{className:"grid grid-cols-5 gap-2",children:a.map(t=>{const s=t.globalIndex===n,l=t.isAnswered;let a="bg-white text-slate-800 shadow-sm border-transparent";return s?a="bg-blue-600 text-white border-blue-600 shadow-md":l&&(a="bg-[#4ade80] text-white border-transparent shadow-sm"),s||c||(a+=" hover:shadow-md hover:text-blue-600"),a+=c?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{type:"button",onClick:()=>d(t.globalIndex),disabled:c,className:r("h-[44px] w-full rounded-[10px] flex items-center justify-center font-bold text-[15px] transition-all border",a),children:t.questionNumber},t.globalIndex)})})}),e("div",{className:"shrink-0 mt-4 pt-4 border-t border-blue-200/50",children:t("div",{className:"flex items-center justify-between text-[11px] xl:text-[11.5px] font-bold text-gray-700",children:[t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-blue-600 shadow-sm"}),e("span",{children:"Current"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-green-500 shadow-sm"}),e("span",{children:"Answered"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-[#f4f9ff] border border-blue-200 shadow-sm"}),e("span",{children:"Not answered"})]})]})})]})]})}
|
|
@@ -1,25 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
import summerSkyClockImg from '@/components/themes/summer-sky/assets/images/clock.png';
|
|
4
|
-
export function CambridgeYleTimer({ remainingSeconds, totalQuestions, answeredCount, }) {
|
|
5
|
-
const minutes = Math.floor(remainingSeconds / 60);
|
|
6
|
-
const seconds = remainingSeconds % 60;
|
|
7
|
-
const formattedTime = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
8
|
-
// Use the same styles as the Speaking exam timer but relative positioning
|
|
9
|
-
// Warning colors can be added if needed based on remainingSeconds,
|
|
10
|
-
// but for now we'll match the default blue theme.
|
|
11
|
-
let bgColorClass = 'bg-[#001590]';
|
|
12
|
-
let shadowClass = 'shadow-[0_4px_20px_rgba(0,0,0,0.25)]';
|
|
13
|
-
// Optional warning states (similar to ExamTimer.module.css)
|
|
14
|
-
if (remainingSeconds <= 120) {
|
|
15
|
-
bgColorClass = 'bg-[rgba(220,38,38,0.85)]'; // Critical
|
|
16
|
-
shadowClass = 'shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse';
|
|
17
|
-
}
|
|
18
|
-
else if (remainingSeconds <= 300) {
|
|
19
|
-
bgColorClass = 'bg-[rgba(180,120,0,0.85)]'; // Warning
|
|
20
|
-
}
|
|
21
|
-
return (_jsxs("div", { className: `flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none ${bgColorClass} ${shadowClass}`, children: [_jsx(Image, { src: summerSkyClockImg, alt: "clock", width: 75, height: 75, className: "w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10" }), _jsx("span", { className: "flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]", style: {
|
|
22
|
-
fontFamily: "'SVN-Volte Rounded', 'Quicksand', sans-serif",
|
|
23
|
-
textShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
|
|
24
|
-
}, children: formattedTime })] }));
|
|
25
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import s from"next/image";import r from"../../../components/themes/summer-sky/assets/images/clock.png";export function CambridgeYleTimer({remainingSeconds:a,totalQuestions:n,answeredCount:p}){const o=a%60,x=`${Math.floor(a/60).toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}`;let m="bg-[#001590]",i="shadow-[0_4px_20px_rgba(0,0,0,0.25)]";return a<=120?(m="bg-[rgba(220,38,38,0.85)]",i="shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse"):a<=300&&(m="bg-[rgba(180,120,0,0.85)]"),t("div",{className:`flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none ${m} ${i}`,children:[e(s,{src:r,alt:"clock",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),e("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:"'SVN-Volte Rounded', 'Quicksand', sans-serif",textShadow:"0 2px 4px rgba(0, 0, 0, 0.2)"},children:x})]})}
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// Previously known as the "Movers" theme
|
|
3
|
-
export { CambridgeYleExamLayout } from './CambridgeYleExamLayout';
|
|
4
|
-
export { CambridgeYleHeader } from './CambridgeYleHeader';
|
|
5
|
-
export { CambridgeYleNavButton } from './CambridgeYleNavButton';
|
|
6
|
-
export { CambridgeYleProgressBar } from './CambridgeYleProgressBar';
|
|
7
|
-
export { CambridgeYleTimer } from './CambridgeYleTimer';
|
|
8
|
-
export { default as CambridgeYleQuestionCard } from './CambridgeYleQuestionCard';
|
|
9
|
-
export { default as CambridgeYleQuestionCardFullWidth } from './CambridgeYleQuestionCardFullWidth';
|
|
10
|
-
export { default as CambridgeYlePartBanner } from './CambridgeYlePartBanner';
|
|
11
|
-
export { default as CambridgeYleInstructionBanner } from './CambridgeYleInstructionBanner';
|
|
12
|
-
export { default as CambridgeYleAudioPlayer } from './CambridgeYleAudioPlayer';
|
|
13
|
-
export { default as CambridgeYleExampleText } from './CambridgeYleExampleText';
|
|
1
|
+
export{CambridgeYleExamLayout}from"./CambridgeYleExamLayout";export{CambridgeYleHeader}from"./CambridgeYleHeader";export{CambridgeYleNavButton}from"./CambridgeYleNavButton";export{CambridgeYleProgressBar}from"./CambridgeYleProgressBar";export{CambridgeYleTimer}from"./CambridgeYleTimer";export{default as CambridgeYleQuestionCard}from"./CambridgeYleQuestionCard";export{default as CambridgeYleQuestionCardFullWidth}from"./CambridgeYleQuestionCardFullWidth";export{default as CambridgeYlePartBanner}from"./CambridgeYlePartBanner";export{default as CambridgeYleInstructionBanner}from"./CambridgeYleInstructionBanner";export{default as CambridgeYleAudioPlayer}from"./CambridgeYleAudioPlayer";export{default as CambridgeYleExampleText}from"./CambridgeYleExampleText";
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
|
-
import { ResolvedImage } from '../../../components/common/ResolvedImage';
|
|
5
|
-
import { cn } from '../../../shared/lib/utils';
|
|
6
|
-
import { transformAnswerTheQuestion } from '../../../components/exams/take/exam-taking.utils';
|
|
7
|
-
/**
|
|
8
|
-
* Branded English Certification renderer for `ANSWER_THE_QUESTION`.
|
|
9
|
-
*
|
|
10
|
-
* Lists each question with an inline text input (plus optional prefix/suffix and
|
|
11
|
-
* suggested answers). Reuses {@link transformAnswerTheQuestion} so the stored
|
|
12
|
-
* answer shape (`{ [questionId]: { answer: string } }`) stays compatible with
|
|
13
|
-
* the grading store.
|
|
14
|
-
*/
|
|
15
|
-
export function EcAnswerTheQuestion({ part, answers, onAnswerChange, isReviewMode = false, }) {
|
|
16
|
-
const { questions, instruction, imageUrl, title, groupContent } = useMemo(() => transformAnswerTheQuestion(part.questions), [part.questions]);
|
|
17
|
-
const handleChange = (questionId, value) => {
|
|
18
|
-
onAnswerChange(questionId, { answer: value });
|
|
19
|
-
};
|
|
20
|
-
return (_jsxs("div", { className: "flex flex-col gap-4", children: [instruction && (_jsx("div", { className: "rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]", children: instruction })), imageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: imageUrl, alt: title || 'Group image', className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), _jsx("div", { className: "flex flex-col gap-3", children: questions.map((q) => {
|
|
21
|
-
const stored = answers[q.id]?.answer ?? q.exampleAnswer ?? '';
|
|
22
|
-
return (_jsx("div", { id: `question-${q.id}`, className: cn('rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]', q.isExample && 'opacity-90'), children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: q.questionNumber }), _jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [q.imageUrl && (_jsx(ResolvedImage, { src: q.imageUrl, alt: `Question ${q.questionNumber}`, className: "max-h-28 w-auto rounded object-contain" })), _jsx("p", { className: "text-sm text-[#0f1730]", children: q.question }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [q.prefixText && (_jsx("span", { className: "text-sm text-[#64748b]", children: q.prefixText })), q.isExample ? (_jsx("span", { className: "rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]", children: q.exampleAnswer })) : (_jsx("input", { type: "text", value: stored, disabled: isReviewMode, placeholder: "Nh\u1EADp c\u00E2u tr\u1EA3 l\u1EDDi\u2026", onChange: (e) => handleChange(q.id, e.target.value), className: cn('min-w-[200px] flex-1 rounded-lg border-2 border-[#9cc4f5] bg-white px-3 py-2 text-sm font-medium text-[#0f1730] outline-none transition-all focus:border-[#1167e8]', isReviewMode && 'cursor-not-allowed opacity-70') })), q.suffixText && (_jsx("span", { className: "text-sm text-[#64748b]", children: q.suffixText }))] }), q.suggestedAnswers && q.suggestedAnswers.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5", children: q.suggestedAnswers.map((sa, idx) => (_jsx("span", { className: "rounded-full border border-[#e2ecf8] bg-[#f4f9ff] px-2.5 py-0.5 text-xs text-[#0b57d0]", children: sa }, `${q.id}-sa-${idx}`))) }))] })] }) }, q.id));
|
|
23
|
-
}) })] }));
|
|
24
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useMemo as t}from"react";import{ResolvedImage as r}from"../../../components/common/ResolvedImage";import{cn as a}from"../../../shared/lib/utils";import{transformAnswerTheQuestion as n}from"../../../components/exams/take/exam-taking.utils";export function EcAnswerTheQuestion({part:i,answers:l,onAnswerChange:d,isReviewMode:o=!1}){const{questions:c,instruction:m,imageUrl:x,title:p,groupContent:f}=t(()=>n(i.questions),[i.questions]);return s("div",{className:"flex flex-col gap-4",children:[m&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:m}),x&&e("div",{className:"flex items-center justify-center",children:e(r,{src:x,alt:p||"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-3",children:c.map(t=>{const n=l[t.id]?.answer??t.exampleAnswer??"";return e("div",{id:`question-${t.id}`,className:a("rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",t.isExample&&"opacity-90"),children:s("div",{className:"flex items-start gap-3",children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:t.questionNumber}),s("div",{className:"min-w-0 flex-1 space-y-2",children:[t.imageUrl&&e(r,{src:t.imageUrl,alt:`Question ${t.questionNumber}`,className:"max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:t.question}),s("div",{className:"flex flex-wrap items-center gap-2",children:[t.prefixText&&e("span",{className:"text-sm text-[#64748b]",children:t.prefixText}),t.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:t.exampleAnswer}):e("input",{type:"text",value:n,disabled:o,placeholder:"Nhập câu trả lời…",onChange:e=>{return s=t.id,r=e.target.value,void d(s,{answer:r});var s,r},className:a("min-w-[200px] flex-1 rounded-lg border-2 border-[#9cc4f5] bg-white px-3 py-2 text-sm font-medium text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",o&&"cursor-not-allowed opacity-70")}),t.suffixText&&e("span",{className:"text-sm text-[#64748b]",children:t.suffixText})]}),t.suggestedAnswers&&t.suggestedAnswers.length>0&&e("div",{className:"flex flex-wrap gap-1.5",children:t.suggestedAnswers.map((s,r)=>e("span",{className:"rounded-full border border-[#e2ecf8] bg-[#f4f9ff] px-2.5 py-0.5 text-xs text-[#0b57d0]",children:s},`${t.id}-sa-${r}`))})]})]})},t.id)})})]})}
|
|
@@ -1,88 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
|
-
import { ResolvedImage } from '../../../components/common/ResolvedImage';
|
|
5
|
-
import { cn } from '../../../shared/lib/utils';
|
|
6
|
-
import { transformMatchByWritingAnswer } from '../../../components/exams/take/exam-taking.utils';
|
|
7
|
-
/** Letters A, B, C, … used to label the answer options. */
|
|
8
|
-
const OPTION_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
9
|
-
const BADGE_TONE_CLASS = {
|
|
10
|
-
empty: 'bg-[#eef3fb] text-[#94a3b8] border border-[#dbe5f2]',
|
|
11
|
-
filled: 'bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-white border border-transparent',
|
|
12
|
-
correct: 'bg-[#16a34a] text-white border border-transparent',
|
|
13
|
-
wrong: 'bg-[#ef4444] text-white border border-transparent',
|
|
14
|
-
};
|
|
15
|
-
/** Big rounded badge that mirrors the currently selected letter. */
|
|
16
|
-
function LetterBadge({ letter, tone }) {
|
|
17
|
-
return (_jsx("span", { className: cn('flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-base font-bold transition-colors', BADGE_TONE_CLASS[tone]), children: letter || '—' }));
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Branded English Certification renderer for `MATCH_BY_WRITING_ANSWER`.
|
|
21
|
-
*
|
|
22
|
-
* Shows a lettered answer bank (A–H) at the top, then each question with a
|
|
23
|
-
* dropdown to pick its matching letter plus a big letter badge mirroring the
|
|
24
|
-
* current selection. Selected letters are dimmed in the bank (take mode) so the
|
|
25
|
-
* student can track which options are still free. Reuses
|
|
26
|
-
* {@link transformMatchByWritingAnswer} so the stored answer shape
|
|
27
|
-
* (`{ [questionId]: { answer: string } }`) stays compatible with the grading
|
|
28
|
-
* store.
|
|
29
|
-
*/
|
|
30
|
-
export function EcMatchByWritingAnswer({ part, answers, onAnswerChange, isReviewMode = false, }) {
|
|
31
|
-
const { questions, options, instruction, groupImageUrl } = useMemo(() => transformMatchByWritingAnswer(part.questions), [part.questions]);
|
|
32
|
-
/** Map each option's stored answer value → its display letter (A, B, C…). */
|
|
33
|
-
const answerToLetter = useMemo(() => {
|
|
34
|
-
const map = new Map();
|
|
35
|
-
options.forEach((opt, idx) => {
|
|
36
|
-
map.set(opt.answer, OPTION_LETTERS[idx] ?? String(idx + 1));
|
|
37
|
-
});
|
|
38
|
-
return map;
|
|
39
|
-
}, [options]);
|
|
40
|
-
/** Resolve the stored value for a question (selection or example fallback). */
|
|
41
|
-
const getStored = (q) => answers[q.id]?.answer ?? q.exampleAnswer ?? '';
|
|
42
|
-
/** Letters currently assigned across all questions — drives bank dimming. */
|
|
43
|
-
const usedLetters = useMemo(() => {
|
|
44
|
-
const set = new Set();
|
|
45
|
-
questions.forEach((q) => {
|
|
46
|
-
const value = getStored(q);
|
|
47
|
-
const letter = answerToLetter.get(value);
|
|
48
|
-
if (letter)
|
|
49
|
-
set.add(letter);
|
|
50
|
-
});
|
|
51
|
-
return set;
|
|
52
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
|
-
}, [questions, answers, answerToLetter]);
|
|
54
|
-
const handleSelect = (questionId, value) => {
|
|
55
|
-
onAnswerChange(questionId, { answer: value });
|
|
56
|
-
};
|
|
57
|
-
return (_jsxs("div", { className: "flex flex-col gap-4", children: [instruction && (_jsx("div", { className: "rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]", children: instruction })), groupImageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: groupImageUrl, alt: "Group image", className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), options.length > 0 && (_jsxs("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-[#64748b]", children: "ANSWER OPTIONS" }), _jsx("div", { className: "mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2", children: options.map((opt, idx) => {
|
|
58
|
-
const letter = OPTION_LETTERS[idx] ?? String(idx + 1);
|
|
59
|
-
// Dim used options only in take mode so review stays comparable.
|
|
60
|
-
const isUsed = !isReviewMode && usedLetters.has(letter);
|
|
61
|
-
return (_jsxs("div", { className: cn('flex items-start gap-2.5 rounded-xl border border-[#e2ecf8] bg-[#f4f9ff] px-3 py-2 transition-opacity', isUsed && 'opacity-50'), children: [_jsxs("span", { className: "relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: [letter, isUsed && (_jsx("span", { className: "absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-[#16a34a] text-[8px] text-white", children: "\u2713" }))] }), _jsxs("div", { className: "min-w-0 text-sm text-[#0f1730]", children: [opt.imageUrl && (_jsx(ResolvedImage, { src: opt.imageUrl, alt: opt.answer, className: "mb-1 max-h-24 w-auto rounded object-contain" })), _jsx("span", { className: "font-medium", children: opt.content || opt.answer })] })] }, `${opt.answer}-${idx}`));
|
|
62
|
-
}) })] })), _jsx("div", { className: "flex flex-col gap-3", children: questions.map((q) => {
|
|
63
|
-
const stored = getStored(q);
|
|
64
|
-
const selectedLetter = answerToLetter.get(stored) ?? '';
|
|
65
|
-
// Review correctness is only known for example rows (the
|
|
66
|
-
// transformer exposes `exampleAnswer`); other rows stay neutral.
|
|
67
|
-
const reviewCorrect = isReviewMode && q.isExample
|
|
68
|
-
? stored === (q.exampleAnswer ?? '')
|
|
69
|
-
: undefined;
|
|
70
|
-
const rowTint = reviewCorrect === true
|
|
71
|
-
? 'border-[#bbf7d0] bg-[#f0fdf4]'
|
|
72
|
-
: reviewCorrect === false
|
|
73
|
-
? 'border-[#fecaca] bg-[#fef2f2]'
|
|
74
|
-
: 'border-[#d9e4f2] bg-white/90';
|
|
75
|
-
const badgeTone = reviewCorrect === true
|
|
76
|
-
? 'correct'
|
|
77
|
-
: reviewCorrect === false
|
|
78
|
-
? 'wrong'
|
|
79
|
-
: selectedLetter
|
|
80
|
-
? 'filled'
|
|
81
|
-
: 'empty';
|
|
82
|
-
return (_jsxs("div", { id: `question-${q.id}`, className: cn('flex items-center gap-3 rounded-xl border p-3 shadow-sm transition-colors', rowTint, q.isExample && 'opacity-90'), children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: q.questionNumber }), _jsxs("div", { className: "min-w-0 flex-1", children: [q.imageUrl && (_jsx(ResolvedImage, { src: q.imageUrl, alt: `Question ${q.questionNumber}`, className: "mb-2 max-h-28 w-auto rounded object-contain" })), _jsx("p", { className: "text-sm text-[#0f1730]", children: q.question })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(LetterBadge, { letter: selectedLetter, tone: badgeTone }), q.isExample ? (_jsx("span", { className: "rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]", children: q.exampleAnswer })) : (_jsxs("select", { value: stored, disabled: isReviewMode, onChange: (e) => handleSelect(q.id, e.target.value), className: cn('h-9 min-w-[150px] rounded-lg border-2 border-[#9cc4f5] bg-white px-3 text-sm font-semibold text-[#0f1730] outline-none transition-all focus:border-[#1167e8]', isReviewMode && 'cursor-not-allowed opacity-70'), children: [_jsx("option", { value: "", children: "\u2014" }), options.map((opt, idx) => {
|
|
83
|
-
const letter = OPTION_LETTERS[idx] ?? String(idx + 1);
|
|
84
|
-
const label = opt.content || opt.answer;
|
|
85
|
-
return (_jsx("option", { value: opt.answer, children: label ? `${letter} — ${label}` : letter }, `${q.id}-${idx}`));
|
|
86
|
-
})] }))] })] }, q.id));
|
|
87
|
-
}) })] }));
|
|
88
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as n}from"../../../components/common/ResolvedImage";import{cn as s}from"../../../shared/lib/utils";import{transformMatchByWritingAnswer as a}from"../../../components/exams/take/exam-taking.utils";const o="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),i={empty:"bg-[#eef3fb] text-[#94a3b8] border border-[#dbe5f2]",filled:"bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-white border border-transparent",correct:"bg-[#16a34a] text-white border border-transparent",wrong:"bg-[#ef4444] text-white border border-transparent"};function d({letter:t,tone:r}){return e("span",{className:s("flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-base font-bold transition-colors",i[r]),children:t||"—"})}export function EcMatchByWritingAnswer({part:i,answers:l,onAnswerChange:c,isReviewMode:m=!1}){const{questions:f,options:b,instruction:p,groupImageUrl:x}=r(()=>a(i.questions),[i.questions]),u=r(()=>{const e=new Map;return b.forEach((t,r)=>{e.set(t.answer,o[r]??String(r+1))}),e},[b]),g=e=>l[e.id]?.answer??e.exampleAnswer??"",h=r(()=>{const e=new Set;return f.forEach(t=>{const r=g(t),n=u.get(r);n&&e.add(n)}),e},[f,l,u]);return t("div",{className:"flex flex-col gap-4",children:[p&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:p}),x&&e("div",{className:"flex items-center justify-center",children:e(n,{src:x,alt:"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),b.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"ANSWER OPTIONS"}),e("div",{className:"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2",children:b.map((r,a)=>{const i=o[a]??String(a+1),d=!m&&h.has(i);return t("div",{className:s("flex items-start gap-2.5 rounded-xl border border-[#e2ecf8] bg-[#f4f9ff] px-3 py-2 transition-opacity",d&&"opacity-50"),children:[t("span",{className:"relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:[i,d&&e("span",{className:"absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-[#16a34a] text-[8px] text-white",children:"✓"})]}),t("div",{className:"min-w-0 text-sm text-[#0f1730]",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:r.answer,className:"mb-1 max-h-24 w-auto rounded object-contain"}),e("span",{className:"font-medium",children:r.content||r.answer})]})]},`${r.answer}-${a}`)})})]}),e("div",{className:"flex flex-col gap-3",children:f.map(r=>{const a=g(r),i=u.get(a)??"",l=m&&r.isExample?a===(r.exampleAnswer??""):void 0,f=!0===l?"border-[#bbf7d0] bg-[#f0fdf4]":!1===l?"border-[#fecaca] bg-[#fef2f2]":"border-[#d9e4f2] bg-white/90",p=!0===l?"correct":!1===l?"wrong":i?"filled":"empty";return t("div",{id:`question-${r.id}`,className:s("flex items-center gap-3 rounded-xl border p-3 shadow-sm transition-colors",f,r.isExample&&"opacity-90"),children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:r.questionNumber}),t("div",{className:"min-w-0 flex-1",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:`Question ${r.questionNumber}`,className:"mb-2 max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:r.question})]}),t("div",{className:"flex shrink-0 items-center gap-2",children:[e(d,{letter:i,tone:p}),r.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:r.exampleAnswer}):t("select",{value:a,disabled:m,onChange:e=>{return t=r.id,n=e.target.value,void c(t,{answer:n});var t,n},className:s("h-9 min-w-[150px] rounded-lg border-2 border-[#9cc4f5] bg-white px-3 text-sm font-semibold text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",m&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"—"}),b.map((t,n)=>{const s=o[n]??String(n+1),a=t.content||t.answer;return e("option",{value:t.answer,children:a?`${s} — ${a}`:s},`${r.id}-${n}`)})]})]})]},r.id)})})]})}
|
|
@@ -1,55 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
|
-
import { ResolvedImage } from '../../../components/common/ResolvedImage';
|
|
5
|
-
import { cn } from '../../../shared/lib/utils';
|
|
6
|
-
import { transformWordFillParagraph } from '../../../components/exams/take/exam-taking.utils';
|
|
7
|
-
/**
|
|
8
|
-
* Branded English Certification renderer for `WORD_FILL_PARAGRAPH`.
|
|
9
|
-
*
|
|
10
|
-
* Shows an optional word bank, then the paragraph with inline blanks. Supports
|
|
11
|
-
* `WITH_WORD_BANK` (dropdown selecting a bank word) and `DEFAULT` (free text
|
|
12
|
-
* input). Reuses {@link transformWordFillParagraph} so the stored answer shape
|
|
13
|
-
* (`{ [questionId]: string[] }` indexed by blank) stays compatible with the
|
|
14
|
-
* grading store.
|
|
15
|
-
*/
|
|
16
|
-
export function EcWordFillParagraph({ part, answers, onAnswerChange, isReviewMode = false, }) {
|
|
17
|
-
const data = useMemo(() => transformWordFillParagraph(part.questions), [part.questions]);
|
|
18
|
-
const { questionId, paragraph, title, imageUrl, wordBank, viewMode, instruction } = data;
|
|
19
|
-
const currentAnswers = answers[questionId] || [];
|
|
20
|
-
const segments = useMemo(() => paragraph.split(/(\{\d+\})/), [paragraph]);
|
|
21
|
-
const useWordBank = viewMode === 'WITH_WORD_BANK';
|
|
22
|
-
const usedWords = new Set(currentAnswers.filter(Boolean));
|
|
23
|
-
const setBlank = (blankIndex, value) => {
|
|
24
|
-
if (isReviewMode)
|
|
25
|
-
return;
|
|
26
|
-
const next = [...currentAnswers];
|
|
27
|
-
next[blankIndex] = value;
|
|
28
|
-
onAnswerChange(questionId, next);
|
|
29
|
-
};
|
|
30
|
-
return (_jsxs("div", { className: "flex flex-col gap-4", children: [instruction && (_jsx("div", { className: "rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]", children: instruction })), imageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: imageUrl, alt: title || 'Illustration', className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), useWordBank && wordBank.length > 0 && (_jsxs("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-[#64748b]", children: "Word bank" }), _jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: wordBank.map((item, idx) => {
|
|
31
|
-
const isUsed = usedWords.has(item.word);
|
|
32
|
-
return (_jsx("span", { className: cn('rounded-full border px-3 py-1 text-sm font-semibold transition-all', item.isExample
|
|
33
|
-
? 'border-[#b9edc8] bg-[#ddf8e7] text-[#15803d]'
|
|
34
|
-
: isUsed
|
|
35
|
-
? 'border-[#d9e4f2] bg-[#f4f9ff] text-[#94a3b8] line-through'
|
|
36
|
-
: 'border-[#9cc4f5] bg-white text-[#0b57d0]'), children: item.word }, `${item.word}-${idx}`));
|
|
37
|
-
}) })] })), _jsx("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-5 text-base leading-loose text-[#0f1730] shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: segments.map((segment, idx) => {
|
|
38
|
-
const blankMatch = segment.match(/^\{(\d+)\}$/);
|
|
39
|
-
if (!blankMatch) {
|
|
40
|
-
return _jsx("span", { children: segment }, idx);
|
|
41
|
-
}
|
|
42
|
-
const blankIndex = parseInt(blankMatch[1], 10);
|
|
43
|
-
const studentAnswer = currentAnswers[blankIndex] || '';
|
|
44
|
-
if (useWordBank) {
|
|
45
|
-
return (_jsxs("span", { className: "mx-1 inline-flex items-baseline gap-1 align-baseline", children: [_jsxs("span", { className: "text-[11px] font-bold text-[#1f7cff]", children: ["(", blankIndex + 1, ")"] }), _jsxs("select", { value: studentAnswer, disabled: isReviewMode, onChange: (e) => setBlank(blankIndex, e.target.value), className: cn('rounded-lg border-2 px-2 py-1 text-sm font-semibold outline-none transition-all', studentAnswer
|
|
46
|
-
? 'border-[#1167e8] text-[#0b57d0]'
|
|
47
|
-
: 'border-[#9cc4f5] text-[#64748b]', isReviewMode && 'cursor-not-allowed opacity-70'), children: [_jsx("option", { value: "", children: "\u2014\u2014\u2014" }), wordBank
|
|
48
|
-
.filter((w) => !w.isExample)
|
|
49
|
-
.map((w, wi) => (_jsx("option", { value: w.word, children: w.word }, `${blankIndex}-${wi}`)))] })] }, idx));
|
|
50
|
-
}
|
|
51
|
-
return (_jsxs("span", { className: "mx-1 inline-flex items-baseline gap-1 align-baseline", children: [_jsxs("span", { className: "text-[11px] font-bold text-[#1f7cff]", children: ["(", blankIndex + 1, ")"] }), _jsx("input", { type: "text", value: studentAnswer, disabled: isReviewMode, placeholder: "\u00B7\u00B7\u00B7", onChange: (e) => setBlank(blankIndex, e.target.value), style: { width: `${Math.max(4, studentAnswer.length + 1)}ch` }, className: cn('inline-block min-w-[4ch] max-w-[16ch] border-b-2 bg-transparent px-1 text-center text-sm font-semibold outline-none transition-colors', studentAnswer
|
|
52
|
-
? 'border-[#1167e8] text-[#0b57d0]'
|
|
53
|
-
: 'border-[#9cc4f5] text-[#64748b]', isReviewMode && 'cursor-not-allowed opacity-70') })] }, idx));
|
|
54
|
-
}) })] }));
|
|
55
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as n}from"../../../shared/lib/utils";import{transformWordFillParagraph as o}from"../../../components/exams/take/exam-taking.utils";export function EcWordFillParagraph({part:l,answers:s,onAnswerChange:i,isReviewMode:d=!1}){const c=r(()=>o(l.questions),[l.questions]),{questionId:m,paragraph:p,title:x,imageUrl:b,wordBank:f,viewMode:h,instruction:u}=c,g=s[m]||[],w=r(()=>p.split(/(\{\d+\})/),[p]),N="WITH_WORD_BANK"===h,v=new Set(g.filter(Boolean)),y=(e,t)=>{if(d)return;const r=[...g];r[e]=t,i(m,r)};return t("div",{className:"flex flex-col gap-4",children:[u&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:u}),b&&e("div",{className:"flex items-center justify-center",children:e(a,{src:b,alt:x||"Illustration",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),N&&f.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Word bank"}),e("div",{className:"mt-2 flex flex-wrap gap-2",children:f.map((t,r)=>{const a=v.has(t.word);return e("span",{className:n("rounded-full border px-3 py-1 text-sm font-semibold transition-all",t.isExample?"border-[#b9edc8] bg-[#ddf8e7] text-[#15803d]":a?"border-[#d9e4f2] bg-[#f4f9ff] text-[#94a3b8] line-through":"border-[#9cc4f5] bg-white text-[#0b57d0]"),children:t.word},`${t.word}-${r}`)})})]}),e("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-5 text-base leading-loose text-[#0f1730] shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:w.map((r,a)=>{const o=r.match(/^\{(\d+)\}$/);if(!o)return e("span",{children:r},a);const l=parseInt(o[1],10),s=g[l]||"";return t("span",N?{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",l+1,")"]}),t("select",{value:s,disabled:d,onChange:e=>y(l,e.target.value),className:n("rounded-lg border-2 px-2 py-1 text-sm font-semibold outline-none transition-all",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",d&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"———"}),f.filter(e=>!e.isExample).map((t,r)=>e("option",{value:t.word,children:t.word},`${l}-${r}`))]})]}:{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",l+1,")"]}),e("input",{type:"text",value:s,disabled:d,placeholder:"···",onChange:e=>y(l,e.target.value),style:{width:`${Math.max(4,s.length+1)}ch`},className:n("inline-block min-w-[4ch] max-w-[16ch] border-b-2 bg-transparent px-1 text-center text-sm font-semibold outline-none transition-colors",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",d&&"cursor-not-allowed opacity-70")})]},a)})})]})}
|