@tinyweb_dev/oe-exam-sdk 1.0.6 → 1.0.7
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/components/exams/ExamCreator.js +1 -16
- package/dist/components/exams/take/ExamTakingPageContainer.js +0 -12
- package/dist/components/exams/take/components/QuestionRenderer.js +2 -15
- package/dist/components/exams/take/components/question-renderers/index.d.ts +0 -3
- package/dist/components/exams/take/components/question-renderers/index.js +0 -3
- package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.js +0 -4
- package/dist/components/exams/take/types/speaking.types.d.ts +0 -31
- package/dist/components/exams/take/types.d.ts +0 -65
- package/dist/components/exams/take/utils/answer-transformers.js +6 -60
- package/dist/components/exams/take/utils/question-transformers.d.ts +2 -15
- package/dist/components/exams/take/utils/question-transformers.js +0 -143
- package/dist/components/questions/_shared/components/compact/CompactCreatorHeader.d.ts +23 -0
- package/dist/components/questions/_shared/components/compact/CompactCreatorHeader.js +9 -0
- package/dist/components/questions/_shared/components/compact/CompactExampleToggle.d.ts +6 -0
- package/dist/components/questions/_shared/components/compact/CompactExampleToggle.js +8 -0
- package/dist/components/questions/_shared/components/compact/CompactExplanationToggle.d.ts +7 -0
- package/dist/components/questions/_shared/components/compact/CompactExplanationToggle.js +14 -0
- package/dist/components/questions/_shared/components/compact/CompactFieldCard.d.ts +9 -0
- package/dist/components/questions/_shared/components/compact/CompactFieldCard.js +7 -0
- package/dist/components/questions/_shared/components/compact/CompactPreviewBanner.d.ts +7 -0
- package/dist/components/questions/_shared/components/compact/CompactPreviewBanner.js +7 -0
- package/dist/components/questions/_shared/components/compact/CompactPreviewButton.d.ts +6 -0
- package/dist/components/questions/_shared/components/compact/CompactPreviewButton.js +7 -0
- package/dist/components/questions/_shared/components/compact/index.d.ts +6 -0
- package/dist/components/questions/_shared/components/compact/index.js +6 -0
- package/dist/components/questions/_shared/config/question-types.config.js +0 -24
- package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +0 -9
- package/dist/components/questions/_shared/types/index.d.ts +0 -1
- package/dist/components/questions/_shared/types/index.js +0 -1
- package/dist/components/questions/_shared/types/look-and-choose-answer.type.d.ts +0 -13
- package/dist/components/questions/_shared/utils/answer-builder.js +0 -11
- package/dist/components/questions/components/ColorRegionCreator.js +66 -63
- package/dist/components/questions/components/QuestionSearchDropdown.js +0 -8
- package/dist/components/questions/components/QuestionTypeSelector.js +0 -2
- package/dist/components/questions/components/index.d.ts +1 -0
- package/dist/components/questions/components/index.js +1 -0
- package/dist/components/questions/creator/question-type-registry.js +0 -8
- package/dist/components/questions/groups/ArticlesGroupCard.js +2 -2
- package/dist/components/questions/groups/BasicQuestionGroupCard.js +1 -1
- package/dist/components/questions/groups/DocumentGroupCard.js +1 -1
- package/dist/components/questions/groups/ImageLabelGroupCard.js +1 -1
- package/dist/components/questions/groups/MatchAnswerGroupCard.js +2 -2
- package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -3
- package/dist/components/questions/question-bank/QuestionEditorRenderer.js +1 -10
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -2
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -41
- package/dist/components/questions/question-bank/editor-adapters/index.d.ts +2 -2
- package/dist/components/questions/question-bank/editor-adapters/index.js +2 -2
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -1
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -28
- package/dist/components/questions/question-bank/question-bank-picker.utils.js +0 -7
- package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +16 -16
- package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +36 -30
- package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.js +1 -1
- package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupCreator.js +7 -6
- package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +2 -2
- package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +11 -7
- package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +1 -1
- package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +11 -5
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +5 -5
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +34 -28
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseAnswerGroupImageUpload.js +2 -2
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +1 -1
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +44 -28
- package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupClient.js +7 -7
- package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupCreator.js +8 -5
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +2 -2
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +20 -16
- package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleClient.js +1 -1
- package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleCreator.js +66 -29
- package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +5 -5
- package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +45 -37
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.js +24 -20
- package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +2 -2
- package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +68 -65
- package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixClient.js +1 -1
- package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixCreator.js +45 -5
- package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +2 -2
- package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +18 -14
- package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +2 -2
- package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +30 -30
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +2 -2
- package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +24 -31
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +2 -2
- package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +29 -32
- package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +27 -29
- package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +11 -15
- package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +22 -24
- package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +17 -24
- package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +31 -31
- package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +11 -15
- package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +1 -1
- package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +14 -15
- package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +2 -2
- package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +27 -25
- package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesClient.js +12 -12
- package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesCreator.js +8 -5
- package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureClient.js +8 -8
- package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureCreator.js +25 -20
- package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupClient.js +1 -1
- package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupCreator.js +13 -10
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupCreator.js +8 -5
- package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +7 -11
- package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +1 -1
- package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +15 -12
- package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesClient.js +1 -1
- package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesCreator.js +5 -5
- package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +35 -39
- package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +2 -2
- package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardClient.js +1 -1
- package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +7 -8
- package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +1 -1
- package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +30 -23
- package/dist/components/questions/types/spontaneous-qa/SpontaneousQAClient.js +1 -1
- package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +26 -19
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +1 -1
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +13 -11
- package/dist/components/questions/types/true-false/TrueFalseClient.js +2 -2
- package/dist/components/questions/types/true-false/TrueFalseCreator.js +35 -29
- package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupClient.js +1 -1
- package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupCreator.js +11 -7
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -1
- package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +11 -7
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +2 -2
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +21 -56
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +30 -24
- package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +3 -3
- package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +12 -14
- package/dist/components/questions/types/word-ordering/WordOrderingClient.js +1 -1
- package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +27 -18
- package/dist/components/questions/types/word-ordering-group/WordOrderingGroupClient.js +7 -7
- package/dist/components/questions/types/word-ordering-group/WordOrderingGroupCreator.js +16 -13
- package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +2 -2
- package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +34 -28
- package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +2 -2
- package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +22 -22
- package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +21 -18
- package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +1 -1
- package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +7 -4
- package/dist/components/questions/viewer/QuestionViewer.js +0 -98
- package/dist/components/results/renderers/review-question-body-movers.js +2 -26
- package/dist/components/results/review-data.js +0 -4
- package/dist/components/ui/points-input.d.ts +1 -0
- package/dist/components/ui/points-input.js +12 -2
- package/dist/shared/constants/question-skills.js +0 -11
- package/dist/shared/lib/i18n/messages/en/admin.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/en/admin.js +0 -3
- package/dist/shared/lib/i18n/messages/en.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/vi/admin.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/vi/admin.js +0 -3
- package/dist/shared/lib/i18n/messages/vi.d.ts +0 -3
- package/dist/shared/lib/utils/question-reverse-transform.js +0 -19
- package/dist/shared/lib/utils/question-transform-types.d.ts +1 -23
- package/dist/shared/lib/utils/question-transform-validation.js +0 -40
- package/dist/shared/lib/utils/question-transform.js +0 -9
- package/dist/shared/types/common.types.d.ts +1 -1
- package/dist/shared/types/entities/question.types.d.ts +1 -11
- package/dist/shared/types/questions/index.d.ts +0 -3
- package/dist/shared/types/questions/index.js +0 -6
- package/package.json +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.d.ts +0 -2
- package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +0 -131
- package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.d.ts +0 -2
- package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +0 -76
- package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.d.ts +0 -2
- package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +0 -68
- package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.d.ts +0 -16
- package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +0 -212
- package/dist/components/questions/_shared/types/gn-speaking-interview.type.d.ts +0 -32
- package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +0 -1
- package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.d.ts +0 -47
- package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +0 -1
- package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.d.ts +0 -2
- package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +0 -262
- package/dist/components/questions/types/gn-speaking-interview/register.d.ts +0 -2
- package/dist/components/questions/types/gn-speaking-interview/register.js +0 -121
- package/dist/components/questions/types/gn-speaking-interview/transform.d.ts +0 -2
- package/dist/components/questions/types/gn-speaking-interview/transform.js +0 -48
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.d.ts +0 -20
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +0 -72
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.d.ts +0 -15
- package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +0 -230
- package/dist/components/questions/types/look-picture-choose-correct-answer/index.d.ts +0 -1
- package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +0 -1
- package/dist/components/questions/types/look-picture-choose-correct-answer/register.d.ts +0 -2
- package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +0 -66
- package/dist/components/questions/types/look-picture-choose-correct-answer/transform.d.ts +0 -2
- package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +0 -42
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.d.ts +0 -6
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +0 -96
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.d.ts +0 -15
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +0 -238
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +0 -2
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +0 -76
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +0 -19
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.d.ts +0 -7
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +0 -134
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.d.ts +0 -3
- package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +0 -617
- package/dist/components/questions/types/look-picture-fill-word-hint/index.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-word-hint/index.js +0 -2
- package/dist/components/questions/types/look-picture-fill-word-hint/register.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-word-hint/register.js +0 -82
- package/dist/components/questions/types/look-picture-fill-word-hint/transform.d.ts +0 -2
- package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +0 -29
- package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.d.ts +0 -9
- package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +0 -12
- package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.d.ts +0 -17
- package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +0 -47
- package/dist/shared/types/questions/look-picture-choose-correct-answer.d.ts +0 -38
- package/dist/shared/types/questions/look-picture-choose-correct-answer.js +0 -5
- package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.d.ts +0 -63
- package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +0 -9
- package/dist/shared/types/questions/look-picture-fill-word-hint.d.ts +0 -57
- package/dist/shared/types/questions/look-picture-fill-word-hint.js +0 -7
|
@@ -1711,9 +1711,6 @@ const admin = {
|
|
|
1711
1711
|
'admin.exams.partEditor.skillReading': 'Đọc',
|
|
1712
1712
|
'admin.exams.partEditor.skillWriting': 'Viết',
|
|
1713
1713
|
'admin.exams.partEditor.qtFillMissingWordsInGrid': 'Điền chữ cái còn thiếu',
|
|
1714
|
-
'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': 'Nhìn tranh, điền vào chỗ trống',
|
|
1715
|
-
'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': 'Nhìn tranh, chọn đáp án đúng',
|
|
1716
|
-
'admin.exams.partEditor.qtLookPictureFillWordHint': 'Nhìn tranh, điền từ (có gợi ý)',
|
|
1717
1714
|
'admin.exams.partEditor.qtLabelThePicture': 'Gắn nhãn cho tranh',
|
|
1718
1715
|
'admin.exams.partEditor.qtReadAndColorObjects': 'Đọc và tô màu',
|
|
1719
1716
|
'admin.exams.partEditor.qtMultipleChoice': 'Trắc nghiệm',
|
|
@@ -1718,9 +1718,6 @@ declare const vi: {
|
|
|
1718
1718
|
readonly 'admin.exams.partEditor.skillReading': "Đọc";
|
|
1719
1719
|
readonly 'admin.exams.partEditor.skillWriting': "Viết";
|
|
1720
1720
|
readonly 'admin.exams.partEditor.qtFillMissingWordsInGrid': "Điền chữ cái còn thiếu";
|
|
1721
|
-
readonly 'admin.exams.partEditor.qtLookPictureFillBlankChooseAnswer': "Nhìn tranh, điền vào chỗ trống";
|
|
1722
|
-
readonly 'admin.exams.partEditor.qtLookPictureChooseCorrectAnswer': "Nhìn tranh, chọn đáp án đúng";
|
|
1723
|
-
readonly 'admin.exams.partEditor.qtLookPictureFillWordHint': "Nhìn tranh, điền từ (có gợi ý)";
|
|
1724
1721
|
readonly 'admin.exams.partEditor.qtLabelThePicture': "Gắn nhãn cho tranh";
|
|
1725
1722
|
readonly 'admin.exams.partEditor.qtReadAndColorObjects': "Đọc và tô màu";
|
|
1726
1723
|
readonly 'admin.exams.partEditor.qtMultipleChoice': "Trắc nghiệm";
|
|
@@ -50,21 +50,6 @@ const reverseChooseTheCorrectAnswer = (apiQuestion) => {
|
|
|
50
50
|
},
|
|
51
51
|
};
|
|
52
52
|
};
|
|
53
|
-
const reversePictureChoice = (apiQuestion) => {
|
|
54
|
-
const content = asRecord(apiQuestion.content);
|
|
55
|
-
const answer = readAnswer(apiQuestion);
|
|
56
|
-
return {
|
|
57
|
-
content: '',
|
|
58
|
-
answer: {
|
|
59
|
-
imageUrl: asString(content.imageUrl),
|
|
60
|
-
question: asString(content.question),
|
|
61
|
-
options: asArray(content.options).map((option) => typeof option === 'string' ? option : asString(asRecord(option).text)),
|
|
62
|
-
correctAnswer: answer.answer ?? answer.correctAnswer ?? -1,
|
|
63
|
-
explanation: asString(apiQuestion.explanation),
|
|
64
|
-
points: readPoints(apiQuestion),
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
53
|
const reverseFillInBlank = (apiQuestion) => {
|
|
69
54
|
const content = asRecord(apiQuestion.content);
|
|
70
55
|
const answer = readAnswer(apiQuestion);
|
|
@@ -796,15 +781,12 @@ const handlers = {
|
|
|
796
781
|
CROSS_OUT_WORD_GROUP: reverseCrossOutWordGroup,
|
|
797
782
|
WORD_ORDER_AND_MATCH_GROUP: reverseWordOrderAndMatchGroup,
|
|
798
783
|
WORD_ORDER_AND_MATCH: reverseWordOrderAndMatchGroup,
|
|
799
|
-
LOOK_PICTURE_CHOOSE_CORRECT_ANSWER: reversePictureChoice,
|
|
800
|
-
LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER: reversePictureChoice,
|
|
801
784
|
FILL_IN_BLANK: reverseFillInBlank,
|
|
802
785
|
READ_PASSAGE_AND_ANSWER_QUESTIONS: reverseReadPassage,
|
|
803
786
|
LABEL_THE_PICTURE: reverseLabelPicture,
|
|
804
787
|
READ_AND_COLOR_OBJECTS: reverseGroupPayload,
|
|
805
788
|
IMAGE_OBJECT_MATCHING: reverseGroupPayload,
|
|
806
789
|
FILL_MISSING_WORDS_IN_GRID: reverseGrid,
|
|
807
|
-
LOOK_PICTURE_FILL_WORD_HINT: reverseGroupPayload,
|
|
808
790
|
ANSWER_THE_QUESTION: reverseGroupPayload,
|
|
809
791
|
TRUE_FALSE: reverseSimpleAnswer,
|
|
810
792
|
WORD_ORDERING: reverseSimpleAnswer,
|
|
@@ -832,7 +814,6 @@ const handlers = {
|
|
|
832
814
|
SPONTANEOUS_QA_GROUP: reverseSpontaneousQaGroup,
|
|
833
815
|
SPEAKING_CONVERSATION: reverseGroupPayload,
|
|
834
816
|
SPEAKING_CUE_CARD: reverseSimpleAnswer,
|
|
835
|
-
GN_SPEAKING_INTERVIEW: reverseGroupPayload,
|
|
836
817
|
CROSSWORD_PUZZLE: reverseCrosswordPuzzle,
|
|
837
818
|
FIND_WORDS_IN_MATRIX: reverseFindWordsInMatrix,
|
|
838
819
|
SORT_WORDS_INTO_CATEGORIES: reverseSortWordsIntoCategories,
|
|
@@ -244,28 +244,6 @@ export interface FillMissingWordsInGridAnswerData {
|
|
|
244
244
|
}>;
|
|
245
245
|
caseSensitive?: boolean;
|
|
246
246
|
}
|
|
247
|
-
export interface LookAndChooseAnswerData {
|
|
248
|
-
subQuestions: Array<{
|
|
249
|
-
id: string;
|
|
250
|
-
imageUrl: string;
|
|
251
|
-
question: string;
|
|
252
|
-
options: Array<{
|
|
253
|
-
id: string;
|
|
254
|
-
text: string;
|
|
255
|
-
isCorrect: boolean;
|
|
256
|
-
}>;
|
|
257
|
-
}>;
|
|
258
|
-
}
|
|
259
|
-
export interface LookPictureFillWordHintAnswerData {
|
|
260
|
-
subQuestions: Array<{
|
|
261
|
-
id: string;
|
|
262
|
-
imageUrl: string;
|
|
263
|
-
word: string;
|
|
264
|
-
correctAnswer: string;
|
|
265
|
-
}>;
|
|
266
|
-
hintLetters?: string[];
|
|
267
|
-
caseSensitive?: boolean;
|
|
268
|
-
}
|
|
269
247
|
export interface LabelThePictureAnswerData {
|
|
270
248
|
imageUrl: string;
|
|
271
249
|
wordBank: string[];
|
|
@@ -374,7 +352,7 @@ export interface ListenAndDragObjectsIntoSceneAnswerData {
|
|
|
374
352
|
}>;
|
|
375
353
|
groupNumber?: number;
|
|
376
354
|
}
|
|
377
|
-
export type QuestionAnswerData = ListenImageMatchingAnswerData | ListenOrReadChooseAnswerData | ReadChooseAppropriateWordAnswerData | ListenAndChooseAnswerData | ListenAndFillWordAnswerData | TickTrueFalseOrYesNoAnswerData | LookPictureAndTickTrueFalseAnswerData | FillInTheBlankVariantsAnswerData | ListenAndColorObjectsAnswerData | ArrangeLettersIntoWordsAnswerData | WriteShortParagraphAnswerData | ListenAndWriteAnswerData | ViewImageAndFillInTheBlankAnswerData | ReadAndChooseBestAnswerData | LookPictureFillWordAnswerData | FillMissingWordsInGridAnswerData |
|
|
355
|
+
export type QuestionAnswerData = ListenImageMatchingAnswerData | ListenOrReadChooseAnswerData | ReadChooseAppropriateWordAnswerData | ListenAndChooseAnswerData | ListenAndFillWordAnswerData | TickTrueFalseOrYesNoAnswerData | LookPictureAndTickTrueFalseAnswerData | FillInTheBlankVariantsAnswerData | ListenAndColorObjectsAnswerData | ArrangeLettersIntoWordsAnswerData | WriteShortParagraphAnswerData | ListenAndWriteAnswerData | ViewImageAndFillInTheBlankAnswerData | ReadAndChooseBestAnswerData | LookPictureFillWordAnswerData | FillMissingWordsInGridAnswerData | LabelThePictureAnswerData | ReadAndColorObjectsAnswerData | ReadPassageAndAnswerQuestionsAnswerData | AnswerTheQuestionAnswerData | ListenAndChooseFromAnswerGroupAnswerData | ListenAndChooseObjectsInSceneAnswerData | ListenAndDragObjectsIntoSceneAnswerData;
|
|
378
356
|
export interface LookPictureFillWordAnswerData {
|
|
379
357
|
instruction: string;
|
|
380
358
|
wordLimit: number;
|
|
@@ -14,15 +14,6 @@ export function validateQuestionForTransform(question) {
|
|
|
14
14
|
case 'FILL_MISSING_WORDS_IN_GRID':
|
|
15
15
|
validateGrid(content, answer, errors);
|
|
16
16
|
break;
|
|
17
|
-
case 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER':
|
|
18
|
-
validatePictureFillBlank(answer, errors);
|
|
19
|
-
break;
|
|
20
|
-
case 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER':
|
|
21
|
-
validatePictureChoose(answer, errors);
|
|
22
|
-
break;
|
|
23
|
-
case 'LOOK_PICTURE_FILL_WORD_HINT':
|
|
24
|
-
validateWordHint(answer, errors);
|
|
25
|
-
break;
|
|
26
17
|
case 'LABEL_THE_PICTURE':
|
|
27
18
|
validateLabelPicture(answer, errors);
|
|
28
19
|
break;
|
|
@@ -81,37 +72,6 @@ function validateGrid(content, answer, errors) {
|
|
|
81
72
|
if (!isNonEmptyRecord(answer?.answers))
|
|
82
73
|
errors.push('At least one missing letter is required');
|
|
83
74
|
}
|
|
84
|
-
function validatePictureFillBlank(answer, errors) {
|
|
85
|
-
if (!hasText(answer?.imageUrl))
|
|
86
|
-
errors.push('Vui lòng upload hình ảnh');
|
|
87
|
-
if (!hasText(answer?.question))
|
|
88
|
-
errors.push('Vui lòng nhập nội dung câu hỏi');
|
|
89
|
-
validateOptions(answer?.options, errors);
|
|
90
|
-
if (answer?.correctAnswer === undefined || answer.correctAnswer === -1)
|
|
91
|
-
errors.push('Vui lòng chọn đáp án đúng');
|
|
92
|
-
}
|
|
93
|
-
function validatePictureChoose(answer, errors) {
|
|
94
|
-
if (!hasText(answer?.imageUrl))
|
|
95
|
-
errors.push('Vui lòng upload hình ảnh');
|
|
96
|
-
validateOptions(answer?.options, errors);
|
|
97
|
-
if (typeof answer?.correctAnswer !== 'number' || answer.correctAnswer < 0)
|
|
98
|
-
errors.push('Vui lòng chọn đáp án đúng');
|
|
99
|
-
}
|
|
100
|
-
function validateWordHint(answer, errors) {
|
|
101
|
-
if (!hasItems(answer?.subQuestions)) {
|
|
102
|
-
errors.push('Vui lòng nhập dữ liệu câu hỏi');
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
answer.subQuestions.forEach((rawSubQuestion) => {
|
|
106
|
-
const subQuestion = asRecord(rawSubQuestion);
|
|
107
|
-
if (!hasText(subQuestion?.imageUrl))
|
|
108
|
-
errors.push('Vui lòng upload hình ảnh');
|
|
109
|
-
if (!hasText(subQuestion?.word))
|
|
110
|
-
errors.push('Vui lòng nhập từ có chỗ trống');
|
|
111
|
-
if (!hasText(subQuestion?.correctAnswer))
|
|
112
|
-
errors.push('Vui lòng nhập đáp án đúng');
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
75
|
function validateLabelPicture(answer, errors) {
|
|
116
76
|
if (!hasText(answer?.imageUrl))
|
|
117
77
|
errors.push('Vui lòng upload hình ảnh');
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { validateQuestionForTransform } from './question-transform-validation';
|
|
2
2
|
// ─── Import transforms từ từng question type ────────────────────────────────
|
|
3
|
-
import { transformLookPictureChooseCorrectAnswer } from '../../../components/questions/types/look-picture-choose-correct-answer/transform';
|
|
4
|
-
import { transformLookPictureFillBlankChooseAnswer } from '../../../components/questions/types/look-picture-fill-blank-choose-answer/transform';
|
|
5
|
-
import { transformLookPictureFillWordHint } from '../../../components/questions/types/look-picture-fill-word-hint/transform';
|
|
6
3
|
import { transformReadAndColorObjects } from '../../../components/questions/types/read-and-color-objects/transform';
|
|
7
4
|
import { transformReadPassageAndAnswerQuestions } from '../../../components/questions/types/read-passage-and-answer-questions/transform';
|
|
8
5
|
import { transformArrangeLettersIntoWords } from '../../../components/questions/types/arrange-letters-into-words/transform';
|
|
@@ -43,7 +40,6 @@ import { transformSpontaneousQA } from '../../../components/questions/types/spon
|
|
|
43
40
|
import { transformSpontaneousQaGroup } from '../../../components/questions/types/spontaneous-qa-group/transform';
|
|
44
41
|
import { transformSpeakingConversation } from '../../../components/questions/types/speaking-conversation/transform';
|
|
45
42
|
import { transformSpeakingCueCard } from '../../../components/questions/types/speaking-cue-card/transform';
|
|
46
|
-
import { transformGNSpeakingInterview } from '../../../components/questions/types/gn-speaking-interview/transform';
|
|
47
43
|
import { transformWordFillStructuredForm } from '../../../components/questions/types/word-fill-structured-form/transform';
|
|
48
44
|
import { transformCrosswordPuzzle } from '../../../components/questions/types/crossword-puzzle/transform';
|
|
49
45
|
import { transformFindWordsInMatrix } from '../../../components/questions/types/find-words-in-matrix/transform';
|
|
@@ -54,10 +50,6 @@ import { transformMatchWordToPictureGroup } from '../../../components/questions/
|
|
|
54
50
|
import { transformWordOrderingGroup } from '../../../components/questions/types/word-ordering-group/transform';
|
|
55
51
|
// ─── Handler map ────────────────────────────────────────────────────────────
|
|
56
52
|
const questionTransformHandlers = {
|
|
57
|
-
// Look picture
|
|
58
|
-
LOOK_PICTURE_CHOOSE_CORRECT_ANSWER: transformLookPictureChooseCorrectAnswer,
|
|
59
|
-
LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER: transformLookPictureFillBlankChooseAnswer,
|
|
60
|
-
LOOK_PICTURE_FILL_WORD_HINT: transformLookPictureFillWordHint,
|
|
61
53
|
// Reading
|
|
62
54
|
READ_AND_COLOR_OBJECTS: transformReadAndColorObjects,
|
|
63
55
|
IMAGE_OBJECT_MATCHING: transformReadAndColorObjects,
|
|
@@ -101,7 +93,6 @@ const questionTransformHandlers = {
|
|
|
101
93
|
SPONTANEOUS_QA_GROUP: transformSpontaneousQaGroup,
|
|
102
94
|
SPEAKING_CONVERSATION: transformSpeakingConversation,
|
|
103
95
|
SPEAKING_CUE_CARD: transformSpeakingCueCard,
|
|
104
|
-
GN_SPEAKING_INTERVIEW: transformGNSpeakingInterview,
|
|
105
96
|
WORD_FILL_STRUCTURED_FORM: transformWordFillStructuredForm,
|
|
106
97
|
CROSSWORD_PUZZLE: transformCrosswordPuzzle,
|
|
107
98
|
FIND_WORDS_IN_MATRIX: transformFindWordsInMatrix,
|
|
@@ -29,7 +29,7 @@ export declare enum StudentSelectionType {
|
|
|
29
29
|
}
|
|
30
30
|
export type ResultStatus = 'PENDING' | 'PARTIAL_GRADED' | 'GRADED';
|
|
31
31
|
export type StudentStatus = 'NOT_STARTED' | 'IN_PROGRESS' | 'SUBMITTED';
|
|
32
|
-
export type QuestionType = 'FILL_IN_BLANK' | 'TRUE_FALSE' | 'MATCHING' | 'ORDERING' | 'LISTENING' | 'COLORING' | 'ESSAY' | 'LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE' | 'LISTEN_AND_TICK_ANSWER' | 'LISTEN_AND_FILL_NAME_NUMBER' | 'LISTENING_FILL_BLANK' | 'LISTENING_COLOR' | 'TICK_TRUE_OR_FALSE' | 'TICK_YES_OR_NO' | 'READING_TICK_CROSS' | 'ARRANGE_LETTERS_INTO_WORDS' | 'READ_PASSAGE_AND_COMPLETE_STORY' | 'CLOZE_TEST_WITH_TICK_BOX' | 'READ_AND_CHOOSE_APPROPRIATE_WORD' | 'WRITE_SHORT_PARAGRAPH' | 'LABEL_THE_PICTURE' | 'READING_LETTER_ARRANGE' | 'READING_PASSAGE_FILL' | 'FILL_BLANK' | 'FILL_MISSING_WORDS_IN_GRID' | '
|
|
32
|
+
export type QuestionType = 'FILL_IN_BLANK' | 'TRUE_FALSE' | 'MATCHING' | 'ORDERING' | 'LISTENING' | 'COLORING' | 'ESSAY' | 'LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE' | 'LISTEN_AND_TICK_ANSWER' | 'LISTEN_AND_FILL_NAME_NUMBER' | 'LISTENING_FILL_BLANK' | 'LISTENING_COLOR' | 'TICK_TRUE_OR_FALSE' | 'TICK_YES_OR_NO' | 'READING_TICK_CROSS' | 'ARRANGE_LETTERS_INTO_WORDS' | 'READ_PASSAGE_AND_COMPLETE_STORY' | 'CLOZE_TEST_WITH_TICK_BOX' | 'READ_AND_CHOOSE_APPROPRIATE_WORD' | 'WRITE_SHORT_PARAGRAPH' | 'LABEL_THE_PICTURE' | 'READING_LETTER_ARRANGE' | 'READING_PASSAGE_FILL' | 'FILL_BLANK' | 'FILL_MISSING_WORDS_IN_GRID' | 'LABEL_THE_PICTURE' | 'READ_AND_COLOR_OBJECTS' | 'IMAGE_OBJECT_MATCHING' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'TRUE_FALSE_GROUP' | 'TRUE_FALSE_CORRECT_GROUP' | 'FILL_IN_BLANK_GROUP' | 'MATCHING_WITH_LINES_GROUP' | 'CROSS_OUT_WORD_GROUP' | 'SPONTANEOUS_QA_GROUP' | 'WORD_ORDER_AND_MATCH_GROUP' | 'WRITE_A_SHORT_LETTER' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_CORRECT_ADJECTIVE' | 'ANSWER_THE_QUESTION' | 'ANSWER_THE_QUESTION_GROUP' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'MATCH_WORD_TO_PICTURE' | 'WRITE_SENTENCES' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'SPEAKING_CUE_CARD' | 'WORD_FILL_STRUCTURED_FORM' | 'CROSSWORD_PUZZLE' | 'FIND_WORDS_IN_MATRIX' | 'SORT_WORDS_INTO_CATEGORIES' | 'CHOOSE_THEN_ANSWER_GROUP' | 'MATCH_COLUMNS_TO_MAKE_SENTENCES' | 'MATCH_WORD_TO_PICTURE_GROUP' | 'WORD_ORDERING_GROUP';
|
|
33
33
|
export type Level = 'Pre-A1' | 'A1' | 'A2' | 'B1' | 'B2' | 'C1' | 'C2';
|
|
34
34
|
export type Difficulty = 'EASY' | 'MEDIUM' | 'HARD';
|
|
35
35
|
export type Skill = 'LISTENING' | 'READING' | 'WRITING' | 'SPEAKING';
|
|
@@ -217,16 +217,6 @@ export interface LookAndChooseAnswer {
|
|
|
217
217
|
}>;
|
|
218
218
|
}>;
|
|
219
219
|
}
|
|
220
|
-
export interface LookPictureFillWordHintAnswer {
|
|
221
|
-
subQuestions: Array<{
|
|
222
|
-
id: string;
|
|
223
|
-
imageUrl: string;
|
|
224
|
-
word: string;
|
|
225
|
-
correctAnswer: string;
|
|
226
|
-
hintLetters?: string[];
|
|
227
|
-
}>;
|
|
228
|
-
caseSensitive?: boolean;
|
|
229
|
-
}
|
|
230
220
|
export interface ReadPassageAndAnswerQuestionsAnswer {
|
|
231
221
|
passage: string;
|
|
232
222
|
passageTitle?: string;
|
|
@@ -267,7 +257,7 @@ export interface ListenAndChooseObjectsInSceneAnswer {
|
|
|
267
257
|
}>;
|
|
268
258
|
correctObjectId: string;
|
|
269
259
|
}
|
|
270
|
-
export type QuestionAnswer = MultipleChoiceAnswer | FillInBlankAnswer | TrueFalseAnswer | MatchingAnswer | OrderingAnswer | ListeningAnswer | ColoringAnswer | EssayAnswer | ListeningImageMatchingAnswer | ListeningFillBlankAnswer | ListeningMultipleChoiceAnswer | ListeningColorAnswer | ReadingTickCrossAnswer | ReadingLetterArrangeAnswer | ReadingPassageFillAnswer | ListenAndTickAnswer | ListenAndFillWordAnswer | ViewImageAndFillInTheBlankAnswer | FillMissingWordsInGridAnswer | LookAndChooseAnswer |
|
|
260
|
+
export type QuestionAnswer = MultipleChoiceAnswer | FillInBlankAnswer | TrueFalseAnswer | MatchingAnswer | OrderingAnswer | ListeningAnswer | ColoringAnswer | EssayAnswer | ListeningImageMatchingAnswer | ListeningFillBlankAnswer | ListeningMultipleChoiceAnswer | ListeningColorAnswer | ReadingTickCrossAnswer | ReadingLetterArrangeAnswer | ReadingPassageFillAnswer | ListenAndTickAnswer | ListenAndFillWordAnswer | ViewImageAndFillInTheBlankAnswer | FillMissingWordsInGridAnswer | LookAndChooseAnswer | ReadPassageAndAnswerQuestionsAnswer | WriteCorrectVerbFormAnswer | ListenAndChooseObjectsInSceneAnswer;
|
|
271
261
|
export interface Question extends BaseEntity {
|
|
272
262
|
type: QuestionType;
|
|
273
263
|
content: string;
|
|
@@ -21,10 +21,7 @@ export * from './choose-the-correct-answer-group';
|
|
|
21
21
|
export * from './cross-out-word-group';
|
|
22
22
|
export * from './write-correct-verb-form';
|
|
23
23
|
export * from './choose-correct-adjective';
|
|
24
|
-
export * from './look-picture-fill-blank-choose-answer';
|
|
25
24
|
export * from './fill-missing-words-in-grid';
|
|
26
|
-
export * from './look-picture-fill-word-hint';
|
|
27
|
-
export * from './look-picture-choose-correct-answer';
|
|
28
25
|
export * from './listen-and-speak-answer';
|
|
29
26
|
export * from './read-displayed-content';
|
|
30
27
|
export * from './speaking-describe-image';
|
|
@@ -27,14 +27,8 @@ export * from './cross-out-word-group';
|
|
|
27
27
|
export * from './write-correct-verb-form';
|
|
28
28
|
// CHOOSE_CORRECT_ADJECTIVE
|
|
29
29
|
export * from './choose-correct-adjective';
|
|
30
|
-
// LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER
|
|
31
|
-
export * from './look-picture-fill-blank-choose-answer';
|
|
32
30
|
// FILL_MISSING_WORDS_IN_GRID
|
|
33
31
|
export * from './fill-missing-words-in-grid';
|
|
34
|
-
// LOOK_PICTURE_FILL_WORD_HINT
|
|
35
|
-
export * from './look-picture-fill-word-hint';
|
|
36
|
-
// LOOK_PICTURE_CHOOSE_CORRECT_ANSWER
|
|
37
|
-
export * from './look-picture-choose-correct-answer';
|
|
38
32
|
// Add more question types here as they are created:
|
|
39
33
|
// etc.
|
|
40
34
|
export * from './listen-and-speak-answer';
|
package/package.json
CHANGED
package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import type { MoversFillWordHintRendererProps } from '../../types';
|
|
2
|
-
export declare function MoversFillWordHintRenderer({ partNumber, partName, questionCount, instruction, hintLetters, subQuestions, answers, onAnswerChange, isReviewMode, }: MoversFillWordHintRendererProps): import("react").JSX.Element;
|
package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { ZoomIn, Check } from 'lucide-react';
|
|
5
|
-
import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
|
|
6
|
-
import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
|
|
7
|
-
import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
|
|
8
|
-
// Image with zoom functionality
|
|
9
|
-
function QuestionImage({ imageUrl, alt }) {
|
|
10
|
-
const [isZoomed, setIsZoomed] = useState(false);
|
|
11
|
-
// Don't render if no imageUrl
|
|
12
|
-
if (!imageUrl) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative flex items-center justify-center", children: [_jsx(ResolvedImage, { src: imageUrl, alt: alt, className: "h-24 w-24 cursor-pointer rounded-lg object-cover shadow-md", onClick: () => setIsZoomed(true) }), _jsx("button", { type: "button", onClick: () => setIsZoomed(true), className: "absolute -right-1 -top-1 rounded-full bg-white/80 p-1 shadow-md hover:bg-white", "aria-label": "Zoom image", children: _jsx(ZoomIn, { className: "h-3 w-3 text-gray-600" }) })] }), isZoomed && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70", onClick: () => setIsZoomed(false), children: _jsx(ResolvedImage, { src: imageUrl, alt: `${alt} (zoomed)`, className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
|
|
16
|
-
}
|
|
17
|
-
// Hint Letters Component
|
|
18
|
-
function HintLetters({ letters }) {
|
|
19
|
-
return (_jsxs("div", { className: "rounded-lg border-2 border-amber-200 bg-amber-50 p-4", children: [_jsx("p", { className: "mb-3 text-sm font-semibold text-amber-800", children: "Available Letters:" }), _jsx("div", { className: "flex flex-wrap gap-2", children: letters.map((letter, index) => (_jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-lg bg-white text-lg font-bold text-amber-700 shadow-sm", children: letter }, index))) })] }));
|
|
20
|
-
}
|
|
21
|
-
// Word with blank display
|
|
22
|
-
function WordWithBlank({ word, answer, isReviewMode, correctAnswer, }) {
|
|
23
|
-
// Find the position of the underscore
|
|
24
|
-
const blankIndex = word.indexOf('_');
|
|
25
|
-
const before = word.slice(0, blankIndex);
|
|
26
|
-
const after = word.slice(blankIndex + 1);
|
|
27
|
-
const isCorrect = isReviewMode && answer.toLowerCase() === correctAnswer?.toLowerCase();
|
|
28
|
-
const isWrong = isReviewMode && answer && answer.toLowerCase() !== correctAnswer?.toLowerCase();
|
|
29
|
-
const didNotAnswer = isReviewMode && !answer;
|
|
30
|
-
const getBlankStyle = () => {
|
|
31
|
-
if (!isReviewMode)
|
|
32
|
-
return 'border-blue-400 bg-blue-50 text-blue-600';
|
|
33
|
-
if (isCorrect)
|
|
34
|
-
return 'border-green-500 bg-green-100 text-green-600';
|
|
35
|
-
if (isWrong)
|
|
36
|
-
return 'border-red-500 bg-red-100 text-red-600';
|
|
37
|
-
if (didNotAnswer)
|
|
38
|
-
return 'border-blue-500 bg-blue-50 text-blue-600';
|
|
39
|
-
return 'border-gray-300 bg-gray-50 text-gray-400';
|
|
40
|
-
};
|
|
41
|
-
// Show correct answer when user didn't answer or was wrong
|
|
42
|
-
const displayValue = didNotAnswer ? correctAnswer : (answer || '_');
|
|
43
|
-
return (_jsxs("div", { className: "flex items-center justify-center text-2xl font-bold tracking-wider text-gray-700", children: [_jsx("span", { children: before }), _jsx("span", { className: `mx-0.5 inline-flex h-8 w-8 items-center justify-center rounded border-2 ${getBlankStyle()}`, children: displayValue }), _jsx("span", { children: after })] }));
|
|
44
|
-
}
|
|
45
|
-
// Single Sub-Question Component
|
|
46
|
-
function SubQuestionItem({ subQuestion, answer, onChange, isReviewMode, hintLetters, id, }) {
|
|
47
|
-
const isCorrect = isReviewMode &&
|
|
48
|
-
answer.toLowerCase() === subQuestion.correctAnswer?.toLowerCase();
|
|
49
|
-
const isWrong = isReviewMode &&
|
|
50
|
-
answer &&
|
|
51
|
-
answer.toLowerCase() !== subQuestion.correctAnswer?.toLowerCase();
|
|
52
|
-
const didNotAnswer = isReviewMode && !answer;
|
|
53
|
-
return (_jsxs("div", { id: id, className: "rounded-lg border border-gray-200 bg-white p-4 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white", children: subQuestion.questionNumber }), _jsx(QuestionImage, { imageUrl: subQuestion.imageUrl, alt: `Question ${subQuestion.questionNumber}` })] }), _jsx("div", { className: "mb-3", children: _jsx(WordWithBlank, { word: subQuestion.word, answer: answer, isReviewMode: isReviewMode, correctAnswer: subQuestion.correctAnswer }) }), _jsx("div", { className: "flex flex-wrap justify-center gap-2", children: hintLetters.map((letter, index) => {
|
|
54
|
-
const isSelected = answer.toLowerCase() === letter.toLowerCase();
|
|
55
|
-
const isCorrectLetter = subQuestion.correctAnswer?.toLowerCase() === letter.toLowerCase();
|
|
56
|
-
const userDidNotAnswer = !answer;
|
|
57
|
-
const userWasWrong = answer && answer.toLowerCase() !== subQuestion.correctAnswer?.toLowerCase();
|
|
58
|
-
let buttonStyle = 'border-gray-300 bg-white hover:border-blue-300';
|
|
59
|
-
let textStyle = 'text-gray-700';
|
|
60
|
-
if (isReviewMode) {
|
|
61
|
-
if (isCorrectLetter) {
|
|
62
|
-
// Blue if user didn't answer or was wrong, green if correct
|
|
63
|
-
buttonStyle = (userDidNotAnswer || userWasWrong)
|
|
64
|
-
? 'border-blue-500 bg-blue-50'
|
|
65
|
-
: 'border-green-500 bg-green-100';
|
|
66
|
-
textStyle = 'text-gray-800 font-bold';
|
|
67
|
-
}
|
|
68
|
-
else if (isSelected && !isCorrectLetter) {
|
|
69
|
-
buttonStyle = 'border-red-500 bg-red-100';
|
|
70
|
-
textStyle = 'text-gray-800 font-bold';
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
textStyle = 'text-gray-600';
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
else if (isSelected) {
|
|
77
|
-
buttonStyle = 'border-blue-500 bg-blue-100';
|
|
78
|
-
}
|
|
79
|
-
return (_jsx("button", { type: "button", onClick: () => !isReviewMode && onChange(letter), disabled: isReviewMode, className: `flex h-10 w-10 items-center justify-center rounded-lg border-2 text-lg transition-colors ${buttonStyle} ${textStyle} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: letter }, index));
|
|
80
|
-
}) }), isReviewMode && (_jsxs("div", { className: "mt-2 flex items-center justify-center gap-2", children: [isCorrect && (_jsxs("span", { className: "flex items-center gap-1 text-sm font-medium text-green-600", children: [_jsx(Check, { className: "h-4 w-4" }), " Correct"] })), isWrong && (_jsxs("span", { className: "text-sm font-medium text-blue-600", children: ["Correct answer: ", subQuestion.correctAnswer] })), didNotAnswer && (_jsxs("span", { className: "flex items-center gap-1 text-sm font-medium text-blue-600", children: ["Correct answer: ", subQuestion.correctAnswer] }))] }))] }));
|
|
81
|
-
}
|
|
82
|
-
// New format sub-question item (single image shared, inline display)
|
|
83
|
-
function NewFormatSubQuestionItem({ subQuestion, answer, onChange, isReviewMode, hintLetters, id, }) {
|
|
84
|
-
const isCorrect = isReviewMode &&
|
|
85
|
-
answer.toLowerCase() === subQuestion.correctAnswer?.toLowerCase();
|
|
86
|
-
const isWrong = isReviewMode &&
|
|
87
|
-
answer &&
|
|
88
|
-
answer.toLowerCase() !== subQuestion.correctAnswer?.toLowerCase();
|
|
89
|
-
const didNotAnswer = isReviewMode && !answer;
|
|
90
|
-
return (_jsxs("div", { id: id, className: "flex flex-col items-center gap-2 rounded-lg border border-gray-200 bg-white p-4", children: [_jsx(WordWithBlank, { word: subQuestion.word, answer: answer, isReviewMode: isReviewMode, correctAnswer: subQuestion.correctAnswer }), _jsx("div", { className: "flex flex-wrap justify-center gap-1", children: hintLetters.map((letter, index) => {
|
|
91
|
-
const isSelected = answer.toLowerCase() === letter.toLowerCase();
|
|
92
|
-
const isCorrectLetter = subQuestion.correctAnswer?.toLowerCase() === letter.toLowerCase();
|
|
93
|
-
const userDidNotAnswer = !answer;
|
|
94
|
-
const userWasWrong = answer &&
|
|
95
|
-
answer.toLowerCase() !== subQuestion.correctAnswer?.toLowerCase();
|
|
96
|
-
let buttonStyle = 'border-gray-300 bg-white hover:border-blue-300';
|
|
97
|
-
let textStyle = 'text-gray-700';
|
|
98
|
-
if (isReviewMode) {
|
|
99
|
-
if (isCorrectLetter) {
|
|
100
|
-
buttonStyle =
|
|
101
|
-
userDidNotAnswer || userWasWrong
|
|
102
|
-
? 'border-blue-500 bg-blue-50'
|
|
103
|
-
: 'border-green-500 bg-green-100';
|
|
104
|
-
textStyle = 'text-gray-800 font-bold';
|
|
105
|
-
}
|
|
106
|
-
else if (isSelected && !isCorrectLetter) {
|
|
107
|
-
buttonStyle = 'border-red-500 bg-red-100';
|
|
108
|
-
textStyle = 'text-gray-800 font-bold';
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
textStyle = 'text-gray-600';
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else if (isSelected) {
|
|
115
|
-
buttonStyle = 'border-blue-500 bg-blue-100';
|
|
116
|
-
}
|
|
117
|
-
return (_jsx("button", { type: "button", onClick: () => !isReviewMode && onChange(letter), disabled: isReviewMode, className: `flex h-8 w-8 items-center justify-center rounded-lg border-2 text-base transition-colors ${buttonStyle} ${textStyle} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: letter }, index));
|
|
118
|
-
}) }), isReviewMode && (_jsxs("div", { className: "flex items-center justify-center gap-2", children: [isCorrect && (_jsxs("span", { className: "flex items-center gap-1 text-xs font-medium text-green-600", children: [_jsx(Check, { className: "h-3 w-3" }), " Correct"] })), (isWrong || didNotAnswer) && (_jsxs("span", { className: "text-xs font-medium text-blue-600", children: ["Correct answer: ", subQuestion.correctAnswer] }))] }))] }));
|
|
119
|
-
}
|
|
120
|
-
export function MoversFillWordHintRenderer({ partNumber, partName, questionCount, instruction, hintLetters, subQuestions, answers, onAnswerChange, isReviewMode = false, }) {
|
|
121
|
-
// Detect if this is new format (single shared image, multiple blanks with blankIndex)
|
|
122
|
-
const isNewFormat = subQuestions.length > 0 &&
|
|
123
|
-
subQuestions[0].blankIndex !== undefined &&
|
|
124
|
-
subQuestions.every((sq) => sq.imageUrl === subQuestions[0].imageUrl);
|
|
125
|
-
if (isNewFormat) {
|
|
126
|
-
// NEW FORMAT: Single card with shared image and multiple blank inputs
|
|
127
|
-
return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode }), _jsx(HintLetters, { letters: hintLetters })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-6 shadow-sm", children: [_jsx("div", { className: "mb-6 flex justify-center", children: _jsx(QuestionImage, { imageUrl: subQuestions[0].imageUrl, alt: "Question image" }) }), _jsx("div", { className: "flex flex-wrap justify-center gap-4", children: subQuestions.map((subQuestion) => (_jsx(NewFormatSubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, answer: answers[subQuestion.id] || '', onChange: (value) => onAnswerChange(subQuestion.id, value), isReviewMode: isReviewMode, hintLetters: hintLetters }, subQuestion.id))) })] })] }));
|
|
128
|
-
}
|
|
129
|
-
// OLD FORMAT: Grid of individual cards (each with its own image)
|
|
130
|
-
return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode }), _jsx(HintLetters, { letters: hintLetters })] }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: subQuestions.map((subQuestion) => (_jsx(SubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, answer: answers[subQuestion.id] || '', onChange: (value) => onAnswerChange(subQuestion.id, value), isReviewMode: isReviewMode, hintLetters: hintLetters }, subQuestion.id))) })] }));
|
|
131
|
-
}
|
package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import type { MoversPictureChooseRendererProps } from '../../types';
|
|
2
|
-
export declare function MoversPictureChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode, }: MoversPictureChooseRendererProps): import("react").JSX.Element;
|
package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { ZoomIn, Check, X } from 'lucide-react';
|
|
5
|
-
import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
|
|
6
|
-
import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
|
|
7
|
-
import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
|
|
8
|
-
// Image with zoom functionality
|
|
9
|
-
function QuestionImage({ imageUrl, alt }) {
|
|
10
|
-
const [isZoomed, setIsZoomed] = useState(false);
|
|
11
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative flex items-center justify-center", children: [_jsx(ResolvedImage, { src: imageUrl, alt: alt, className: "max-h-[180px] cursor-pointer rounded-lg object-contain shadow-md", onClick: () => setIsZoomed(true) }), _jsx("button", { type: "button", onClick: () => setIsZoomed(true), className: "absolute right-2 top-2 rounded-full bg-white/80 p-1.5 shadow-md hover:bg-white", "aria-label": "Zoom image", children: _jsx(ZoomIn, { className: "h-4 w-4 text-gray-600" }) })] }), isZoomed && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70", onClick: () => setIsZoomed(false), children: _jsx(ResolvedImage, { src: imageUrl, alt: `${alt} (zoomed)`, className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
|
|
12
|
-
}
|
|
13
|
-
// Single Sub-Question Component
|
|
14
|
-
function SubQuestionItem({ subQuestion, selectedOptionId, onSelect, isReviewMode, id, }) {
|
|
15
|
-
// Review mode states
|
|
16
|
-
const isUserCorrect = isReviewMode && selectedOptionId === subQuestion.correctOptionId;
|
|
17
|
-
const getOptionStyle = (optionId) => {
|
|
18
|
-
if (!isReviewMode) {
|
|
19
|
-
return selectedOptionId === optionId
|
|
20
|
-
? 'border-blue-500 bg-[#f4f9ff]'
|
|
21
|
-
: 'border-blue-200 bg-white hover:border-blue-300 hover:bg-blue-50/30';
|
|
22
|
-
}
|
|
23
|
-
// Review mode
|
|
24
|
-
const isSelected = selectedOptionId === optionId;
|
|
25
|
-
const isCorrect = subQuestion.correctOptionId === optionId;
|
|
26
|
-
if (isCorrect) {
|
|
27
|
-
// ✅ Green if user answered correctly
|
|
28
|
-
// ⚪ Blue if user didn't answer or was wrong (show correct answer)
|
|
29
|
-
return isUserCorrect
|
|
30
|
-
? 'border-green-500 bg-green-50'
|
|
31
|
-
: 'border-blue-500 bg-blue-50';
|
|
32
|
-
}
|
|
33
|
-
if (isSelected && !isCorrect) {
|
|
34
|
-
// ❌ Red for wrong answer
|
|
35
|
-
return 'border-red-500 bg-red-50';
|
|
36
|
-
}
|
|
37
|
-
return 'border-blue-200 bg-white';
|
|
38
|
-
};
|
|
39
|
-
const getRadioStyle = (optionId) => {
|
|
40
|
-
if (!isReviewMode) {
|
|
41
|
-
return selectedOptionId === optionId
|
|
42
|
-
? 'border-blue-500 bg-blue-500'
|
|
43
|
-
: 'border-gray-300 bg-white';
|
|
44
|
-
}
|
|
45
|
-
// Review mode
|
|
46
|
-
const isSelected = selectedOptionId === optionId;
|
|
47
|
-
const isCorrect = subQuestion.correctOptionId === optionId;
|
|
48
|
-
if (isCorrect) {
|
|
49
|
-
return isUserCorrect
|
|
50
|
-
? 'border-green-500 bg-green-500'
|
|
51
|
-
: 'border-blue-500 bg-blue-500';
|
|
52
|
-
}
|
|
53
|
-
if (isSelected && !isCorrect) {
|
|
54
|
-
return 'border-red-500 bg-red-500';
|
|
55
|
-
}
|
|
56
|
-
return 'border-gray-300 bg-white';
|
|
57
|
-
};
|
|
58
|
-
// Get icon for review mode
|
|
59
|
-
const getReviewIcon = (optionId) => {
|
|
60
|
-
if (!isReviewMode)
|
|
61
|
-
return null;
|
|
62
|
-
const isSelected = selectedOptionId === optionId;
|
|
63
|
-
const isCorrect = subQuestion.correctOptionId === optionId;
|
|
64
|
-
if (isCorrect) {
|
|
65
|
-
return _jsx(Check, { className: "h-4 w-4 text-white" });
|
|
66
|
-
}
|
|
67
|
-
if (isSelected && !isCorrect) {
|
|
68
|
-
return _jsx(X, { className: "h-4 w-4 text-white" });
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
};
|
|
72
|
-
return (_jsxs("div", { id: id, className: "rounded-lg border border-gray-200 bg-white p-4 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white", children: subQuestion.questionNumber }), _jsx(QuestionImage, { imageUrl: subQuestion.imageUrl, alt: `Question ${subQuestion.questionNumber}` })] }), subQuestion.questionText && (_jsx("p", { className: "mb-3 text-[17px] font-bold text-[#001590]", children: subQuestion.questionText })), _jsx("div", { className: "flex flex-col gap-2", children: subQuestion.options.map((option) => (_jsxs("button", { type: "button", onClick: () => !isReviewMode && onSelect(option.id), disabled: isReviewMode, className: `flex items-center gap-3 rounded-lg border-2 px-3 py-2 text-left transition-colors ${getOptionStyle(option.id)} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: [_jsxs("span", { className: "text-sm font-medium text-gray-600", children: [option.label, "."] }), _jsx("span", { className: "flex-1 text-sm text-gray-700", children: option.text }), _jsx("div", { className: `flex h-5 w-5 items-center justify-center rounded-full border-2 ${getRadioStyle(option.id)}`, children: isReviewMode ? (getReviewIcon(option.id)) : (selectedOptionId === option.id && (_jsx("div", { className: "h-2 w-2 rounded-full bg-white" }))) })] }, option.id))) })] }));
|
|
73
|
-
}
|
|
74
|
-
export function MoversPictureChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode = false, }) {
|
|
75
|
-
return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode })] }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: subQuestions.map((subQuestion) => (_jsx(SubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, selectedOptionId: answers[subQuestion.id], onSelect: (optionId) => onAnswerChange(subQuestion.id, optionId), isReviewMode: isReviewMode }, subQuestion.id))) })] }));
|
|
76
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import type { MoversPictureFillBlankChooseRendererProps } from '../../types';
|
|
2
|
-
export declare function MoversPictureFillBlankChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode, }: MoversPictureFillBlankChooseRendererProps): import("react").JSX.Element;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { ZoomIn } from 'lucide-react';
|
|
5
|
-
import { ResolvedImage } from '../../../../../components/common/ResolvedImage';
|
|
6
|
-
import CambridgeYlePartBanner from '../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner';
|
|
7
|
-
import CambridgeYleInstructionBanner from '../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner';
|
|
8
|
-
// Image with zoom functionality
|
|
9
|
-
function QuestionImage({ imageUrl, alt }) {
|
|
10
|
-
const [isZoomed, setIsZoomed] = useState(false);
|
|
11
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative flex items-center justify-center", children: [_jsx(ResolvedImage, { src: imageUrl, alt: alt, className: "max-h-[150px] cursor-pointer rounded-lg object-contain shadow-md", onClick: () => setIsZoomed(true) }), _jsx("button", { type: "button", onClick: () => setIsZoomed(true), className: "absolute right-1 top-1 rounded-full bg-white/80 p-1 shadow-md hover:bg-white", "aria-label": "Zoom image", children: _jsx(ZoomIn, { className: "h-3 w-3 text-gray-600" }) })] }), isZoomed && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70", onClick: () => setIsZoomed(false), children: _jsx(ResolvedImage, { src: imageUrl, alt: `${alt} (zoomed)`, className: "max-h-[90vh] max-w-[90vw] rounded-lg object-contain", showLoadingState: false }) }))] }));
|
|
12
|
-
}
|
|
13
|
-
// Render question text with blank highlight
|
|
14
|
-
function QuestionWithBlank({ question, selectedAnswer, isReviewMode, isCorrect, }) {
|
|
15
|
-
// Split by {0} placeholder
|
|
16
|
-
const parts = question.split('{0}');
|
|
17
|
-
const getBlankStyle = () => {
|
|
18
|
-
if (!isReviewMode || !selectedAnswer) {
|
|
19
|
-
return 'border-blue-400 text-blue-600';
|
|
20
|
-
}
|
|
21
|
-
return isCorrect
|
|
22
|
-
? 'border-green-500 text-green-600'
|
|
23
|
-
: 'border-red-500 text-red-600';
|
|
24
|
-
};
|
|
25
|
-
return (_jsxs("p", { className: "text-sm font-medium text-gray-700", children: [parts[0], _jsx("span", { className: `mx-1 inline-block min-w-[60px] border-b-2 border-dashed px-2 text-center font-semibold ${getBlankStyle()}`, children: selectedAnswer || '______' }), parts[1]] }));
|
|
26
|
-
}
|
|
27
|
-
// Single Sub-Question Component
|
|
28
|
-
function SubQuestionItem({ subQuestion, selectedOptionId, onSelect, isReviewMode, id, }) {
|
|
29
|
-
const selectedOption = subQuestion.options.find((o) => o.id === selectedOptionId);
|
|
30
|
-
// Review mode states
|
|
31
|
-
const isUserCorrect = isReviewMode && selectedOptionId === subQuestion.correctOptionId;
|
|
32
|
-
const getOptionStyle = (optionId) => {
|
|
33
|
-
if (!isReviewMode) {
|
|
34
|
-
return selectedOptionId === optionId
|
|
35
|
-
? 'border-blue-500 bg-blue-50'
|
|
36
|
-
: 'border-gray-300 bg-white hover:border-blue-300';
|
|
37
|
-
}
|
|
38
|
-
// Review mode
|
|
39
|
-
const isSelected = selectedOptionId === optionId;
|
|
40
|
-
const isCorrect = subQuestion.correctOptionId === optionId;
|
|
41
|
-
if (isCorrect) {
|
|
42
|
-
// ✅ Green if user answered correctly
|
|
43
|
-
// ⚪ Blue if user didn't answer or was wrong (show correct answer)
|
|
44
|
-
return isUserCorrect
|
|
45
|
-
? 'border-green-500 bg-green-50'
|
|
46
|
-
: 'border-blue-500 bg-blue-50';
|
|
47
|
-
}
|
|
48
|
-
if (isSelected && !isCorrect) {
|
|
49
|
-
// ❌ Red for wrong answer
|
|
50
|
-
return 'border-red-500 bg-red-50';
|
|
51
|
-
}
|
|
52
|
-
return 'border-gray-300 bg-white';
|
|
53
|
-
};
|
|
54
|
-
const getTextStyle = (optionId) => {
|
|
55
|
-
if (!isReviewMode)
|
|
56
|
-
return 'text-gray-700';
|
|
57
|
-
const isSelected = selectedOptionId === optionId;
|
|
58
|
-
const isCorrect = subQuestion.correctOptionId === optionId;
|
|
59
|
-
if (isCorrect || isSelected) {
|
|
60
|
-
return 'text-gray-800 font-bold';
|
|
61
|
-
}
|
|
62
|
-
return 'text-gray-600';
|
|
63
|
-
};
|
|
64
|
-
return (_jsxs("div", { id: id, className: "rounded-lg border border-gray-200 bg-white p-4 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white", children: subQuestion.questionNumber }), _jsx(QuestionImage, { imageUrl: subQuestion.imageUrl, alt: `Question ${subQuestion.questionNumber}` })] }), _jsx("div", { className: "mb-3", children: _jsx(QuestionWithBlank, { question: subQuestion.question, selectedAnswer: selectedOption?.text, isReviewMode: isReviewMode, isCorrect: selectedOptionId === subQuestion.correctOptionId }) }), _jsx("div", { className: "flex flex-wrap gap-2", children: subQuestion.options.map((option) => (_jsxs("button", { type: "button", onClick: () => !isReviewMode && onSelect(option.id), disabled: isReviewMode, className: `rounded-lg border-2 px-3 py-1.5 text-sm transition-colors ${getOptionStyle(option.id)} ${getTextStyle(option.id)} ${isReviewMode ? 'cursor-default' : 'cursor-pointer'}`, children: [option.label, ". ", option.text] }, option.id))) })] }));
|
|
65
|
-
}
|
|
66
|
-
export function MoversPictureFillBlankChooseRenderer({ partNumber, partName, questionCount, instruction, subQuestions, answers, onAnswerChange, isReviewMode = false, }) {
|
|
67
|
-
return (_jsxs("div", { className: "flex h-full flex-col gap-4 overflow-y-auto p-6", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(CambridgeYlePartBanner, { partNumber: partNumber, questionCount: questionCount, partName: partName, isReviewMode: isReviewMode }), _jsx(CambridgeYleInstructionBanner, { instruction: instruction, isReviewMode: isReviewMode })] }), _jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: subQuestions.map((subQuestion) => (_jsx(SubQuestionItem, { id: `question-${subQuestion.id}`, subQuestion: subQuestion, selectedOptionId: answers[subQuestion.id], onSelect: (optionId) => onAnswerChange(subQuestion.id, optionId), isReviewMode: isReviewMode }, subQuestion.id))) })] }));
|
|
68
|
-
}
|
package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { QuestionPart } from '../../../utils/question-transformers';
|
|
2
|
-
interface SpeakingGNInterviewRendererProps {
|
|
3
|
-
part: QuestionPart;
|
|
4
|
-
answers: Record<string, unknown>;
|
|
5
|
-
onAnswerChange: (questionId: string, value: unknown) => void;
|
|
6
|
-
isReviewMode?: boolean;
|
|
7
|
-
onExit: () => void;
|
|
8
|
-
onPartComplete?: () => void;
|
|
9
|
-
onPartBack?: () => void;
|
|
10
|
-
speakingTheme?: string;
|
|
11
|
-
teacherVideoUrl?: string;
|
|
12
|
-
onTeacherIntroPlayed?: () => void;
|
|
13
|
-
skipTeacherVideo?: boolean;
|
|
14
|
-
}
|
|
15
|
-
export declare function SpeakingGNInterviewRenderer(props: SpeakingGNInterviewRendererProps): import("react").JSX.Element;
|
|
16
|
-
export {};
|