@tinyweb_dev/oe-exam-sdk 1.0.6 → 1.0.8
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/choose-the-correct-answer-group.type.d.ts +2 -2
- package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.js +5 -1
- 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.d.ts +7 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseAnswerGroupImageUpload.js +5 -2
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +9 -5
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +65 -62
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupItemEditor.d.ts +6 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupItemEditor.js +145 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +6 -15
- package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +5 -4
- 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.d.ts +1 -1
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +79 -3
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +13 -11
- package/dist/components/questions/types/spontaneous-qa-group/index.d.ts +1 -0
- package/dist/components/questions/types/spontaneous-qa-group/index.js +1 -0
- package/dist/components/questions/types/spontaneous-qa-group/map-spontaneous-qa-group-data.d.ts +2 -0
- package/dist/components/questions/types/spontaneous-qa-group/map-spontaneous-qa-group-data.js +74 -0
- 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/questions/viewer/SpontaneousQaGroupViewer.js +4 -79
- 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 +4 -23
- 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/choose-the-correct-answer-group.d.ts +1 -1
- 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
|
@@ -107,7 +107,7 @@ export function DocumentGroupCard({ groupNumber, title, subtitle = '', content,
|
|
|
107
107
|
const showImage = !hasConfig || groupConfig.includes('imageUrl');
|
|
108
108
|
const { previewUrl } = usePresignedFileUrl(imageUrl);
|
|
109
109
|
const displayPreviewUrl = previewUrl || '';
|
|
110
|
-
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-
|
|
110
|
+
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Layers, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-sm font-bold text-gray-900", children: "\u0110o\u1EA1n v\u0103n nh\u00F3m" }), _jsxs("span", { className: "inline-flex items-center rounded-md border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-semibold text-gray-600", children: ["Nh\u00F3m ", groupNumber] })] })] }) }), _jsxs(CardContent, { className: "space-y-2.5 px-3 pb-3", children: [showTitle && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: `${uploadIdPrefix}-title`, className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Type, { className: "h-4 w-4 text-indigo-500" }), "Ti\u00EAu \u0111\u1EC1 nh\u00F3m", ' ', _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(Input, { id: `${uploadIdPrefix}-title`, value: title, onChange: (e) => { if (!isReadOnly)
|
|
111
111
|
onTitleChange(e.target.value); }, readOnly: isReadOnly, placeholder: "Nh\u1EADp ti\u00EAu \u0111\u1EC1 nh\u00F3m c\u00E2u h\u1ECFi\u2026", className: `border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 ${isReadOnly ? 'cursor-not-allowed border-transparent bg-gray-50 text-gray-500 focus:border-transparent focus:ring-0' : ''}` })] })), showSubtitle && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: `${uploadIdPrefix}-subtitle`, className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Pilcrow, { className: "h-4 w-4 text-indigo-500" }), "Ph\u1EE5 \u0111\u1EC1", ' ', _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(Input, { id: `${uploadIdPrefix}-subtitle`, value: subtitle, onChange: (e) => { if (!isReadOnly)
|
|
112
112
|
onSubtitleChange?.(e.target.value); }, readOnly: isReadOnly, placeholder: "Nh\u1EADp ph\u1EE5 \u0111\u1EC1 ho\u1EB7c m\u00F4 t\u1EA3 ng\u1EAFn\u2026", className: `border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 ${isReadOnly ? 'cursor-not-allowed border-transparent bg-gray-50 text-gray-500 focus:border-transparent focus:ring-0' : ''}` })] })), showContent && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(FileText, { className: "h-4 w-4 text-indigo-500" }), "N\u1ED9i dung \u0111o\u1EA1n v\u0103n", ' ', _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(DocumentEditor, { value: content, onChange: onContentChange, isReadOnly: isReadOnly, placeholder: "Nh\u1EADp \u0111o\u1EA1n v\u0103n, email, th\u00F4ng b\u00E1o, qu\u1EA3ng c\u00E1o\u2026 d\u00F9ng chung cho nh\u00F3m c\u00E2u h\u1ECFi n\u00E0y", uploadIdPrefix: uploadIdPrefix }), !isReadOnly && (_jsxs("div", { className: "flex items-start gap-2.5 rounded-lg border border-amber-200 bg-amber-50 px-3.5 py-2.5", children: [_jsx(Info, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500" }), _jsxs("div", { className: "text-xs text-amber-800 leading-relaxed", children: [_jsx("span", { className: "font-semibold", children: "G\u1EE3i \u00FD (ch\u1EC9 d\u00E0nh cho d\u1EA1ng \u0111i\u1EC1n t\u1EEB):" }), ' ', "N\u1EBFu \u0111o\u1EA1n v\u0103n c\u00F3 kho\u1EA3ng tr\u1ED1ng c\u1EA7n \u0111i\u1EC1n, h\u00E3y \u0111\u00E1nh d\u1EA5u b\u1EB1ng", ' ', _jsx("code", { className: "rounded bg-amber-100 px-1 py-0.5 font-mono font-semibold text-amber-700", children: '{0}' }), ",", ' ', _jsx("code", { className: "rounded bg-amber-100 px-1 py-0.5 font-mono font-semibold text-amber-700", children: '{1}' }), ",", ' ', _jsx("code", { className: "rounded bg-amber-100 px-1 py-0.5 font-mono font-semibold text-amber-700", children: '{2}' }), "\u2026 \u2014 m\u1ED7i s\u1ED1 t\u01B0\u01A1ng \u1EE9ng th\u1EE9 t\u1EF1 c\u00E2u h\u1ECFi trong nh\u00F3m. V\u1EDBi d\u1EA1ng b\u00E0i \u0111\u1ECDc th\u00F4ng th\u01B0\u1EDDng, b\u1EA1n kh\u00F4ng c\u1EA7n d\u00F9ng k\u00FD hi\u1EC7u n\u00E0y."] })] }))] })), showImage && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-indigo-500" }), "H\u00ECnh \u1EA3nh nh\u00F3m", ' ', _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), !isReadOnly && (_jsx(FileUpload, { id: `${uploadIdPrefix}-image`, label: "", accept: "image/*", value: imageUrl, onChange: (url) => { if (!isReadOnly)
|
|
113
113
|
onImageChange(url); }, onPresignedUrlChange: onImagePresignedUrlChange, maxSize: 5, placeholder: "Upload \u1EA3nh ho\u1EB7c paste URL", autoUpload: true, prefix: "questions" })), displayPreviewUrl && (_jsx(ImagePreview, { src: displayPreviewUrl, alt: "Group image preview", className: "mt-2 h-48 w-full max-w-md rounded-lg border border-gray-200" }))] }))] })] }));
|
|
@@ -38,5 +38,5 @@ export function ImageLabelGroupCard({ groupNumber, imageLabels, onImageLabelsCha
|
|
|
38
38
|
return;
|
|
39
39
|
onImageLabelsChange(displayItems.filter((_, i) => i !== index));
|
|
40
40
|
};
|
|
41
|
-
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-
|
|
41
|
+
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-gray-100", children: _jsx(Layers, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-sm font-bold text-gray-900", children: "Ng\u00E2n h\u00E0ng \u1EA3nh + t\u1EEB" }), _jsxs("span", { className: "inline-flex items-center rounded-md border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-semibold text-gray-600", children: ["Nh\u00F3m ", groupNumber] }), _jsxs("span", { className: "inline-flex items-center rounded-md border border-blue-200 bg-blue-50 px-2 py-0.5 text-xs font-medium text-blue-600", children: [displayItems.length, " m\u1EE5c"] })] })] }) }), _jsxs(CardContent, { className: "space-y-2.5 px-3 pb-3", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: `${uploadIdPrefix}-title`, className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Type, { className: "h-4 w-4 text-indigo-500" }), "Ti\u00EAu \u0111\u1EC1 nh\u00F3m", ' ', _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn)" })] }), _jsx(Input, { id: `${uploadIdPrefix}-title`, value: title, onChange: (e) => onTitleChange?.(e.target.value), placeholder: "VD: Words from the box", readOnly: isReadOnly, className: `border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 ${isReadOnly ? 'cursor-not-allowed border-transparent bg-gray-50 text-gray-500 focus:border-transparent focus:ring-0' : ''}` })] }), _jsx("div", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: displayItems.map((item, index) => (_jsxs("div", { className: "rounded-md border border-gray-200 bg-white p-2.5 transition-all hover:border-gray-300 hover:shadow-sm", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between", children: [_jsxs("span", { className: "text-xs font-semibold text-gray-600", children: ["M\u1EE5c ", index + 1] }), displayItems.length > 1 && !isReadOnly && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => handleDelete(index), className: "h-7 w-7 p-0 text-red-500 hover:bg-red-50 hover:text-red-600", title: "X\u00F3a m\u1EE5c", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }), _jsxs("div", { className: "space-y-2.5", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsxs(Label, { htmlFor: `${uploadIdPrefix}-label-${index}`, className: "flex items-center gap-1.5 text-xs font-medium text-gray-700", children: [_jsx(Type, { className: "h-3.5 w-3.5 text-indigo-500" }), "Nh\u00E3n"] }), _jsx(Input, { id: `${uploadIdPrefix}-label-${index}`, value: item.label, onChange: (e) => handleFieldChange(index, 'label', e.target.value), placeholder: "VD: swimming", readOnly: isReadOnly, className: `border-gray-200 bg-white text-sm focus:border-indigo-300 focus:ring-indigo-200 ${isReadOnly ? 'cursor-not-allowed bg-gray-50 text-gray-500' : ''}` })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs(Label, { className: "flex items-center gap-1.5 text-xs font-medium text-gray-700", children: [_jsx(ImageIcon, { className: "h-3.5 w-3.5 text-indigo-500" }), "H\u00ECnh \u1EA3nh"] }), !isReadOnly && (_jsx(FileUpload, { id: `${uploadIdPrefix}-image-${index}`, label: "", accept: "image/*", value: item.imageUrl, onChange: (url) => handleFieldChange(index, 'imageUrl', url), maxSize: 5, placeholder: "Upload \u1EA3nh", autoUpload: true, prefix: "questions" })), item.imageUrl && (_jsx(ItemImagePreview, { src: item.imageUrl, alt: item.label || `Item ${index + 1}` }))] })] })] }, index))) }), !isReadOnly && (_jsxs(Button, { type: "button", variant: "outline", className: "w-full border-dashed border-indigo-300 bg-indigo-50/50 text-indigo-700 hover:border-indigo-400 hover:bg-indigo-50 hover:text-indigo-800", onClick: handleAdd, children: [_jsx(PlusCircle, { className: "mr-2 h-4 w-4" }), "Th\u00EAm m\u1EE5c \u1EA3nh + t\u1EEB"] })), _jsxs("div", { className: "rounded-xl border border-indigo-100 bg-indigo-50/40 p-4", children: [_jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-indigo-600", children: "Xem tr\u01B0\u1EDBc h\u00E0ng t\u1EEB" }), _jsx(ImageLabelWordBank, { items: displayItems })] })] })] }));
|
|
42
42
|
}
|
|
@@ -16,10 +16,10 @@ function OptionRow({ option, index, canRemove, onUpdate, onRemove, groupConfig,
|
|
|
16
16
|
const showAnswer = !groupConfig || groupConfig.includes('answer');
|
|
17
17
|
const showContent = groupConfig?.includes('content') ?? false;
|
|
18
18
|
const showImageUrl = !groupConfig || groupConfig.includes('imageUrl');
|
|
19
|
-
return (_jsxs("div", { className: "flex items-start gap-
|
|
19
|
+
return (_jsxs("div", { className: "flex items-start gap-2 rounded-md border border-gray-200 bg-white px-3 py-2.5", children: [_jsx("div", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 text-xs font-bold text-gray-800", children: index + 1 }), _jsxs("div", { className: "flex-1 space-y-3", children: [_jsxs("div", { className: "flex items-end gap-3", children: [showAnswer && (_jsx("div", { className: "flex-1", children: _jsx(Input, { value: option.answer, onChange: (e) => onUpdate(index, 'answer', e.target.value), placeholder: `Nhãn (ví dụ: ${String.fromCharCode(65 + index)} hoặc "a pineapple")`, className: "border-purple-200 bg-white focus:border-purple-400 focus:ring-purple-200" }) })), showContent && (_jsx("div", { className: "flex-1", children: _jsx(Input, { value: option.content || '', onChange: (e) => onUpdate(index, 'content', e.target.value), placeholder: "N\u1ED9i dung (m\u00F4 t\u1EA3 th\u00EAm cho \u0111\u00E1p \u00E1n)", className: "border-purple-200 bg-white focus:border-purple-400 focus:ring-purple-200" }) })), showImageUrl && (_jsx("div", { className: "flex-1", children: _jsx(FileUpload, { id: `option-image-${index}`, label: "", accept: "image/*", value: option.imageUrl || '', onChange: (url) => onUpdate(index, 'imageUrl', url), onPresignedUrlChange: setLocalPreviewUrl, maxSize: 5, placeholder: "Upload \u1EA3nh cho \u0111\u00E1p \u00E1n", autoUpload: true, prefix: "questions" }) }))] }), showImageUrl && displayUrl && (_jsx("div", { className: "relative h-32 w-32 overflow-hidden rounded-lg border border-purple-200 bg-white shadow-sm", children: _jsx("img", { src: displayUrl, alt: option.answer || `Option ${index + 1}`, className: "h-full w-full object-contain" }) }))] }), canRemove && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onRemove(index), className: "flex-shrink-0 text-red-500 hover:bg-red-50 hover:text-red-700", children: _jsx(X, { className: "h-4 w-4" }) }))] }));
|
|
20
20
|
}
|
|
21
21
|
export function MatchAnswerGroupCard({ currentGroupNumber, groupTitle, groupImageUrl, groupImagePreviewUrl, options, groupConfig, showGroupTitle, showGroupImageUrl, onGroupTitleChange, onGroupImageChange, onGroupImagePreviewUrlChange, onUpdateOption, onRemoveOption, onAddOption, }) {
|
|
22
22
|
const { previewUrl: groupImagePresignedUrl } = usePresignedFileUrl(groupImageUrl || '');
|
|
23
23
|
const displayGroupImageUrl = groupImagePreviewUrl || groupImagePresignedUrl || '';
|
|
24
|
-
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-
|
|
24
|
+
return (_jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-gray-100", children: _jsx(Layers, { className: "h-3.5 w-3.5 text-gray-600" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CardTitle, { className: "text-sm font-bold text-gray-900", children: "\u0110\u00E1p \u00E1n gh\u00E9p n\u1ED1i" }), _jsxs("span", { className: "inline-flex items-center rounded-md border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-semibold text-gray-600", children: ["Nh\u00F3m ", currentGroupNumber] })] })] }) }), _jsxs(CardContent, { className: "space-y-2.5 px-3 pb-3", children: [showGroupTitle && (_jsxs("div", { className: "space-y-2 rounded-xl border border-purple-100 bg-gradient-to-r from-purple-50/30 to-violet-50/30 p-4", children: [_jsxs(Label, { htmlFor: "group-title", className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(Type, { className: "h-4 w-4 text-purple-500" }), "Ti\u00EAu \u0111\u1EC1 nh\u00F3m", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(d\u00F9ng chung cho c\u1EA3 nh\u00F3m)" })] }), _jsx(Input, { id: "group-title", value: groupTitle, onChange: (e) => onGroupTitleChange(e.target.value), placeholder: "Nh\u1EADp ti\u00EAu \u0111\u1EC1 nh\u00F3m...", className: "border-purple-200 bg-white focus:border-purple-400 focus:ring-purple-200" })] })), showGroupImageUrl && (_jsxs("div", { className: "space-y-2 rounded-xl border border-purple-100 bg-gradient-to-r from-purple-50/30 to-violet-50/30 p-4", children: [_jsxs(Label, { className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(ImageIcon, { className: "h-4 w-4 text-purple-500" }), "H\u00ECnh \u1EA3nh nh\u00F3m ", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(T\u00F9y ch\u1ECDn - d\u00F9ng chung cho c\u1EA3 nh\u00F3m)" })] }), _jsx(FileUpload, { id: "group-image", label: "", accept: "image/*", value: groupImageUrl || '', onChange: onGroupImageChange, onPresignedUrlChange: onGroupImagePreviewUrlChange, maxSize: 5, placeholder: "Upload \u1EA3nh nh\u00F3m ho\u1EB7c paste URL", autoUpload: true, prefix: "questions" }), displayGroupImageUrl && (_jsx(ImagePreview, { src: displayGroupImageUrl, alt: "Group image preview", className: "mt-2 h-48 w-full max-w-md rounded-lg border border-gray-200" }))] })), _jsx("div", { className: "space-y-4", children: options.map((option, index) => (_jsx(OptionRow, { option: option, index: index, canRemove: options.length > 2, onUpdate: onUpdateOption, onRemove: onRemoveOption, groupConfig: groupConfig }, index))) }), _jsxs(Button, { variant: "outline", size: "sm", onClick: onAddOption, className: "gap-2 border-purple-300 text-purple-600 hover:bg-purple-50 hover:text-purple-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Th\u00EAm \u0111\u00E1p \u00E1n (", options.length + 1, ")"] })] })] }));
|
|
25
25
|
}
|
|
@@ -3,11 +3,8 @@ import type { QuestionEditorRendererProps } from './types';
|
|
|
3
3
|
/** Marketing question types supported by the question-bank editor. */
|
|
4
4
|
export declare enum QuestionBankEditorType {
|
|
5
5
|
CHOOSE_THE_CORRECT_ANSWER = "CHOOSE_THE_CORRECT_ANSWER",
|
|
6
|
-
LOOK_PICTURE_CHOOSE_CORRECT_ANSWER = "LOOK_PICTURE_CHOOSE_CORRECT_ANSWER",
|
|
7
|
-
LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER = "LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER",
|
|
8
6
|
FILL_MISSING_WORDS_IN_GRID = "FILL_MISSING_WORDS_IN_GRID",
|
|
9
7
|
LABEL_THE_PICTURE = "LABEL_THE_PICTURE",
|
|
10
|
-
LOOK_PICTURE_FILL_WORD_HINT = "LOOK_PICTURE_FILL_WORD_HINT",
|
|
11
8
|
READ_AND_COLOR_OBJECTS = "READ_AND_COLOR_OBJECTS",
|
|
12
9
|
IMAGE_OBJECT_MATCHING = "IMAGE_OBJECT_MATCHING",
|
|
13
10
|
READ_PASSAGE_AND_ANSWER_QUESTIONS = "READ_PASSAGE_AND_ANSWER_QUESTIONS",
|
|
@@ -2,18 +2,15 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { t } from '../../../shared/lib/i18n';
|
|
5
|
-
import { renderChooseCorrectAdjectiveEditor, renderChooseTheCorrectAnswerEditor, renderFillInBlankEditor, renderFillMissingWordsInGridEditor, renderImageObjectMatchingEditor, renderLabelThePictureEditor,
|
|
5
|
+
import { renderChooseCorrectAdjectiveEditor, renderChooseTheCorrectAnswerEditor, renderFillInBlankEditor, renderFillMissingWordsInGridEditor, renderImageObjectMatchingEditor, renderLabelThePictureEditor, renderReadAndColorObjectsEditor, renderReadPassageAndAnswerQuestionsEditor, renderWriteAShortLetterEditor, renderWriteCorrectVerbFormEditor, UnsupportedEditorFallback, } from './editor-adapters';
|
|
6
6
|
import { CrosswordPuzzleCreator } from '../types/crossword-puzzle/CrosswordPuzzleCreator';
|
|
7
7
|
import { FindWordsInMatrixCreator } from '../types/find-words-in-matrix/FindWordsInMatrixCreator';
|
|
8
8
|
/** Marketing question types supported by the question-bank editor. */
|
|
9
9
|
export var QuestionBankEditorType;
|
|
10
10
|
(function (QuestionBankEditorType) {
|
|
11
11
|
QuestionBankEditorType["CHOOSE_THE_CORRECT_ANSWER"] = "CHOOSE_THE_CORRECT_ANSWER";
|
|
12
|
-
QuestionBankEditorType["LOOK_PICTURE_CHOOSE_CORRECT_ANSWER"] = "LOOK_PICTURE_CHOOSE_CORRECT_ANSWER";
|
|
13
|
-
QuestionBankEditorType["LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER"] = "LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER";
|
|
14
12
|
QuestionBankEditorType["FILL_MISSING_WORDS_IN_GRID"] = "FILL_MISSING_WORDS_IN_GRID";
|
|
15
13
|
QuestionBankEditorType["LABEL_THE_PICTURE"] = "LABEL_THE_PICTURE";
|
|
16
|
-
QuestionBankEditorType["LOOK_PICTURE_FILL_WORD_HINT"] = "LOOK_PICTURE_FILL_WORD_HINT";
|
|
17
14
|
QuestionBankEditorType["READ_AND_COLOR_OBJECTS"] = "READ_AND_COLOR_OBJECTS";
|
|
18
15
|
QuestionBankEditorType["IMAGE_OBJECT_MATCHING"] = "IMAGE_OBJECT_MATCHING";
|
|
19
16
|
QuestionBankEditorType["READ_PASSAGE_AND_ANSWER_QUESTIONS"] = "READ_PASSAGE_AND_ANSWER_QUESTIONS";
|
|
@@ -49,16 +46,10 @@ export function QuestionEditorRenderer({ questionType, content, correctAnswer, e
|
|
|
49
46
|
switch (questionType) {
|
|
50
47
|
case QuestionBankEditorType.CHOOSE_THE_CORRECT_ANSWER:
|
|
51
48
|
return renderChooseTheCorrectAnswerEditor(adapterProps);
|
|
52
|
-
case QuestionBankEditorType.LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:
|
|
53
|
-
return renderLookPictureChooseCorrectAnswerEditor(adapterProps);
|
|
54
|
-
case QuestionBankEditorType.LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:
|
|
55
|
-
return renderLookPictureFillBlankChooseAnswerEditor(adapterProps);
|
|
56
49
|
case QuestionBankEditorType.FILL_MISSING_WORDS_IN_GRID:
|
|
57
50
|
return renderFillMissingWordsInGridEditor(adapterProps);
|
|
58
51
|
case QuestionBankEditorType.LABEL_THE_PICTURE:
|
|
59
52
|
return renderLabelThePictureEditor(adapterProps);
|
|
60
|
-
case QuestionBankEditorType.LOOK_PICTURE_FILL_WORD_HINT:
|
|
61
|
-
return renderLookPictureFillWordHintEditor(adapterProps);
|
|
62
53
|
case QuestionBankEditorType.READ_AND_COLOR_OBJECTS:
|
|
63
54
|
return renderReadAndColorObjectsEditor(adapterProps);
|
|
64
55
|
case QuestionBankEditorType.IMAGE_OBJECT_MATCHING:
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { QuestionEditorAdapterProps } from './types';
|
|
2
2
|
export declare function renderChooseTheCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
3
|
-
export declare function renderLookPictureChooseCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
4
|
-
export declare function renderLookPictureFillBlankChooseAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
5
3
|
export declare function renderChooseCorrectAdjectiveEditor({ content, correctAnswer, explanation, points, onChange, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { ChooseTheCorrectAnswerCreator } from '../../types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator';
|
|
4
4
|
import { normalizeChooseAnswerCorrectAnswer, normalizeChooseAnswerOptions, pickRawChooseAnswer, } from '../../types/choose-the-correct-answer/normalize';
|
|
5
|
-
import { LookPictureChooseCorrectAnswer } from '../../types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator';
|
|
6
|
-
import { LookPictureFillBlankChooseAnswer } from '../../types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator';
|
|
7
5
|
import { ChooseCorrectAdjectiveCreator } from '../../types/choose-correct-adjective/ChooseCorrectAdjectiveCreator';
|
|
8
6
|
export function renderChooseTheCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }) {
|
|
9
7
|
const rawOptions = content.options;
|
|
@@ -40,45 +38,6 @@ export function renderChooseTheCorrectAnswerEditor({ content, correctAnswer, exp
|
|
|
40
38
|
});
|
|
41
39
|
} }));
|
|
42
40
|
}
|
|
43
|
-
export function renderLookPictureChooseCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }) {
|
|
44
|
-
const initialData = {
|
|
45
|
-
imageUrl: content.imageUrl || '',
|
|
46
|
-
options: content.options || ['', ''],
|
|
47
|
-
correctAnswer: correctAnswer?.answer ?? -1,
|
|
48
|
-
explanation: explanation || '',
|
|
49
|
-
points: points || 1,
|
|
50
|
-
};
|
|
51
|
-
return (_jsx(LookPictureChooseCorrectAnswer, { initialData: initialData, validationRef: validationRef, onChange: (data) => {
|
|
52
|
-
onChange?.({
|
|
53
|
-
content: { imageUrl: data?.imageUrl, options: data?.options },
|
|
54
|
-
answer: { answer: data?.correctAnswer },
|
|
55
|
-
explanation: data?.explanation,
|
|
56
|
-
points: data?.points,
|
|
57
|
-
});
|
|
58
|
-
} }));
|
|
59
|
-
}
|
|
60
|
-
export function renderLookPictureFillBlankChooseAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }) {
|
|
61
|
-
const initialData = {
|
|
62
|
-
imageUrl: content.imageUrl || '',
|
|
63
|
-
question: content.question || '',
|
|
64
|
-
options: content.options || ['', '', '', ''],
|
|
65
|
-
correctAnswer: correctAnswer?.answer ?? -1,
|
|
66
|
-
explanation: explanation || '',
|
|
67
|
-
points: points || 1,
|
|
68
|
-
};
|
|
69
|
-
return (_jsx(LookPictureFillBlankChooseAnswer, { initialData: initialData, validationRef: validationRef, onChange: (data) => {
|
|
70
|
-
onChange?.({
|
|
71
|
-
content: {
|
|
72
|
-
imageUrl: data?.imageUrl,
|
|
73
|
-
question: data?.question,
|
|
74
|
-
options: data?.options,
|
|
75
|
-
},
|
|
76
|
-
answer: { answer: data?.correctAnswer },
|
|
77
|
-
explanation: data?.explanation,
|
|
78
|
-
points: data?.points,
|
|
79
|
-
});
|
|
80
|
-
} }));
|
|
81
|
-
}
|
|
82
41
|
export function renderChooseCorrectAdjectiveEditor({ content, correctAnswer, explanation, points, onChange, }) {
|
|
83
42
|
const initialData = {
|
|
84
43
|
sentence: content.sentence || '',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { renderChooseTheCorrectAnswerEditor,
|
|
2
|
-
export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor,
|
|
1
|
+
export { renderChooseTheCorrectAnswerEditor, renderChooseCorrectAdjectiveEditor, } from './choice-adapters';
|
|
2
|
+
export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor, renderReadAndColorObjectsEditor, renderImageObjectMatchingEditor, } from './media-adapters';
|
|
3
3
|
export { renderReadPassageAndAnswerQuestionsEditor, renderWriteAShortLetterEditor, renderWriteCorrectVerbFormEditor, renderFillInBlankEditor, } from './writing-adapters';
|
|
4
4
|
export { UnsupportedEditorFallback } from './unsupported-fallback';
|
|
5
5
|
export type { QuestionEditorAdapterProps, QuestionEditorChangeData } from './types';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { renderChooseTheCorrectAnswerEditor,
|
|
2
|
-
export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor,
|
|
1
|
+
export { renderChooseTheCorrectAnswerEditor, renderChooseCorrectAdjectiveEditor, } from './choice-adapters';
|
|
2
|
+
export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor, renderReadAndColorObjectsEditor, renderImageObjectMatchingEditor, } from './media-adapters';
|
|
3
3
|
export { renderReadPassageAndAnswerQuestionsEditor, renderWriteAShortLetterEditor, renderWriteCorrectVerbFormEditor, renderFillInBlankEditor, } from './writing-adapters';
|
|
4
4
|
export { UnsupportedEditorFallback } from './unsupported-fallback';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { QuestionEditorAdapterProps } from './types';
|
|
2
2
|
export declare function renderFillMissingWordsInGridEditor({ content, correctAnswer, onChange, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
3
3
|
export declare function renderLabelThePictureEditor({ content, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
4
|
-
export declare function renderLookPictureFillWordHintEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
5
4
|
export declare function renderReadAndColorObjectsEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
6
5
|
export declare function renderImageObjectMatchingEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { FillMissingWordsInGridCreator } from '../../types/fill-missing-words-in-grid/FillMissingWordsInGridCreator';
|
|
4
4
|
import { LabelThePictureCreator } from '../../types/label-the-picture/LabelThePictureCreator';
|
|
5
|
-
import { LookPictureFillWordHintCreator } from '../../types/look-picture-fill-word-hint/LookPictureFillWordHintCreator';
|
|
6
5
|
import { ReadAndColorObjectsCreator } from '../../types/read-and-color-objects/ReadAndColorObjectsCreator';
|
|
7
6
|
import { ImageObjectMatchingCreator } from '../../types/image-object-matching/ImageObjectMatchingCreator';
|
|
8
7
|
export function renderFillMissingWordsInGridEditor({ content, correctAnswer, onChange, }) {
|
|
@@ -63,33 +62,6 @@ export function renderLabelThePictureEditor({ content, explanation, points, onCh
|
|
|
63
62
|
});
|
|
64
63
|
} }));
|
|
65
64
|
}
|
|
66
|
-
export function renderLookPictureFillWordHintEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }) {
|
|
67
|
-
const initialData = {
|
|
68
|
-
subQuestions: [
|
|
69
|
-
{
|
|
70
|
-
id: 'edit-1',
|
|
71
|
-
imageUrl: content.imageUrl || '',
|
|
72
|
-
word: content.word || '',
|
|
73
|
-
correctAnswer: correctAnswer?.correctAnswer || '',
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
hintLetters: [],
|
|
77
|
-
explanation: explanation || '',
|
|
78
|
-
points: points || 1,
|
|
79
|
-
};
|
|
80
|
-
return (_jsx(LookPictureFillWordHintCreator, { initialData: initialData, validationRef: validationRef, onChange: (data) => {
|
|
81
|
-
const subQ = data?.subQuestions?.[0] || {};
|
|
82
|
-
onChange?.({
|
|
83
|
-
content: {
|
|
84
|
-
imageUrl: subQ.imageUrl,
|
|
85
|
-
word: subQ.word,
|
|
86
|
-
},
|
|
87
|
-
answer: { correctAnswer: subQ.correctAnswer },
|
|
88
|
-
explanation: data?.explanation,
|
|
89
|
-
points: data?.points,
|
|
90
|
-
});
|
|
91
|
-
} }));
|
|
92
|
-
}
|
|
93
65
|
export function renderReadAndColorObjectsEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }) {
|
|
94
66
|
const initialData = {
|
|
95
67
|
backgroundImageUrl: content.backgroundImageUrl || '',
|
|
@@ -35,10 +35,6 @@ const QUESTION_TYPE_LABELS = {
|
|
|
35
35
|
MATCH_BY_WRITING_ANSWER: 'Nối bằng cách viết đáp án',
|
|
36
36
|
SPEAKING_DESCRIBE_IMAGE: 'Nói: mô tả tranh',
|
|
37
37
|
SPEAKING_CONVERSATION: 'Nói: hội thoại',
|
|
38
|
-
GN_SPEAKING_INTERVIEW: 'Nói: phỏng vấn',
|
|
39
|
-
LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER: 'Nhìn tranh điền chỗ trống',
|
|
40
|
-
LOOK_PICTURE_CHOOSE_CORRECT_ANSWER: 'Nhìn tranh chọn đáp án',
|
|
41
|
-
LOOK_PICTURE_FILL_WORD_HINT: 'Nhìn tranh điền từ gợi ý',
|
|
42
38
|
LABEL_THE_PICTURE: 'Gắn nhãn hình ảnh',
|
|
43
39
|
MATCH_WORD_TO_PICTURE: 'Nối từ với tranh',
|
|
44
40
|
MATCH_WORD_TO_PICTURE_GROUP: 'Nối từ với tranh (nhóm)',
|
|
@@ -72,9 +68,6 @@ var QuestionTypeVisualKind;
|
|
|
72
68
|
QuestionTypeVisualKind["TEXT"] = "text";
|
|
73
69
|
})(QuestionTypeVisualKind || (QuestionTypeVisualKind = {}));
|
|
74
70
|
const TYPE_VISUAL_KIND = {
|
|
75
|
-
LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER: QuestionTypeVisualKind.IMAGE,
|
|
76
|
-
LOOK_PICTURE_CHOOSE_CORRECT_ANSWER: QuestionTypeVisualKind.IMAGE,
|
|
77
|
-
LOOK_PICTURE_FILL_WORD_HINT: QuestionTypeVisualKind.IMAGE,
|
|
78
71
|
LABEL_THE_PICTURE: QuestionTypeVisualKind.IMAGE,
|
|
79
72
|
MATCH_WORD_TO_PICTURE: QuestionTypeVisualKind.IMAGE,
|
|
80
73
|
MATCH_WORD_TO_PICTURE_GROUP: QuestionTypeVisualKind.IMAGE,
|
|
@@ -33,7 +33,7 @@ export function AnswerTheQuestionClient({ questionData, onSubmit, isReviewMode =
|
|
|
33
33
|
const [answer, setAnswer] = useState(userAnswer || '');
|
|
34
34
|
const imageUrls = toAnswerTheQuestionImageUrls(questionData.imageUrl);
|
|
35
35
|
if (!questionData.question && imageUrls.length === 0) {
|
|
36
|
-
return (_jsx(Card, { children: _jsx(CardContent, { className: "p-
|
|
36
|
+
return (_jsx(Card, { children: _jsx(CardContent, { className: "p-3", children: _jsx("p", { className: "text-gray-500", children: "Kh\u00F4ng c\u00F3 d\u1EEF li\u1EC7u c\u00E2u h\u1ECFi" }) }) }));
|
|
37
37
|
}
|
|
38
38
|
const isExample = questionData.isExample || false;
|
|
39
39
|
const correctAnswer = questionData.correctAnswer || '';
|
|
@@ -43,19 +43,19 @@ export function AnswerTheQuestionClient({ questionData, onSubmit, isReviewMode =
|
|
|
43
43
|
const isCorrect = isReviewMode && userAnswer !== undefined
|
|
44
44
|
? userAnswer.trim().toLowerCase() === correctAnswer.trim().toLowerCase()
|
|
45
45
|
: undefined;
|
|
46
|
-
return (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
return (_jsx(Card, { className: "overflow-hidden border-0 bg-white shadow-sm", children: _jsxs(CardContent, { className: "p-3 space-y-3", children: [(questionData.title || questionData.groupContent) && (_jsxs("div", { className: "rounded-xl border border-indigo-200 bg-gradient-to-r from-indigo-50 to-blue-50 p-4 space-y-2", children: [questionData.title && (_jsx("h3", { className: "text-base font-bold text-indigo-900", children: questionData.title })), questionData.groupContent && (_jsx("p", { className: "text-sm text-indigo-700 leading-relaxed whitespace-pre-wrap", children: questionData.groupContent }))] })), imageUrls.length > 0 && (_jsx("div", { className: "flex flex-wrap justify-center gap-3", children: imageUrls.map((url, imageIndex) => (_jsx("div", { className: "relative max-w-lg overflow-hidden rounded-xl border border-gray-200 bg-gray-50 shadow-sm", children: _jsx(MediaPreview, { src: url, alt: `Question image ${imageIndex + 1}` }) }, `atq-image-${imageIndex}`))) })), _jsxs("div", { className: "rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-5", children: [isExample && (_jsxs("div", { className: "mb-2 inline-flex items-center gap-1.5 rounded-full bg-amber-100 border border-amber-300 px-3 py-1", children: [_jsx(BookOpen, { className: "h-3.5 w-3.5 text-amber-600" }), _jsx("span", { className: "text-xs font-semibold text-amber-700 uppercase tracking-wide", children: "Example" })] })), questionData.question ? (_jsx(Label, { className: "text-base font-semibold text-gray-800 mb-3 block", children: questionData.question })) : null, questionData.suggestedAnswers && questionData.suggestedAnswers.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 mt-2 mb-1", children: questionData.suggestedAnswers.map((suggestion, index) => (_jsx("button", { type: "button", disabled: isReviewMode || isExample, onClick: () => {
|
|
47
|
+
if (!isReviewMode && !isExample) {
|
|
48
|
+
setAnswer(suggestion);
|
|
49
|
+
onSubmit?.(suggestion);
|
|
50
|
+
}
|
|
51
|
+
}, className: `inline-flex items-center rounded-full border px-3 py-1 text-sm font-medium transition-colors ${answer === suggestion
|
|
52
|
+
? 'border-teal-400 bg-teal-50 text-teal-700 ring-1 ring-teal-200'
|
|
53
|
+
: 'border-gray-200 bg-white text-gray-600 hover:border-teal-300 hover:bg-teal-50/50 hover:text-teal-600'} ${isReviewMode || isExample ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'}`, children: suggestion }, index))) })), _jsxs("div", { className: "flex items-center gap-3 mt-3", children: [questionData.prefixText && (_jsx("span", { className: "text-base font-medium text-gray-700", children: questionData.prefixText })), _jsx(Input, { value: displayedAnswer, onChange: (e) => {
|
|
54
|
+
setAnswer(e.target.value);
|
|
55
|
+
onSubmit?.(e.target.value);
|
|
56
|
+
}, placeholder: "Vi\u1EBFt \u0111\u00E1p \u00E1n...", disabled: isReviewMode || isExample, className: `max-w-xs border-2 text-lg font-medium ${isReviewMode
|
|
57
|
+
? isCorrect
|
|
58
|
+
? 'border-green-400 bg-green-50 text-green-700'
|
|
59
|
+
: 'border-red-400 bg-red-50 text-red-700'
|
|
60
|
+
: 'border-teal-300 focus:border-teal-500 focus:ring-teal-200'}` }), questionData.suffixText && (_jsx("span", { className: "text-base font-medium text-gray-700", children: questionData.suffixText })), isReviewMode && isCorrect !== undefined && (_jsx("span", { className: "flex items-center gap-1", children: isCorrect ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "h-5 w-5 text-red-500" })) }))] }), isReviewMode && isCorrect === false && (_jsxs("div", { className: "mt-3 flex items-center gap-2 rounded-lg bg-green-50 border border-green-200 px-4 py-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsxs("span", { className: "text-sm text-green-700", children: ["\u0110\u00E1p \u00E1n \u0111\u00FAng: ", _jsx("strong", { children: correctAnswer })] })] })), autoFillCorrectAnswers && (_jsxs("div", { className: "mt-3 flex items-center gap-2 rounded-lg bg-teal-50 border border-teal-200 px-4 py-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-teal-600" }), _jsxs("span", { className: "text-sm text-teal-700", children: ["\u0110\u00E1p \u00E1n: ", _jsx("strong", { children: correctAnswer })] })] }))] }), explanation && isReviewMode && (_jsxs("div", { className: "rounded-xl border border-blue-200 bg-blue-50 p-4", children: [_jsx("p", { className: "text-sm font-semibold text-blue-800 mb-1", children: "Gi\u1EA3i th\u00EDch:" }), _jsx("p", { className: "text-sm text-blue-700", children: explanation })] }))] }) }));
|
|
61
61
|
}
|
|
@@ -4,11 +4,8 @@ import { useState, useRef, useEffect } from 'react';
|
|
|
4
4
|
import { Button } from '../../../../components/ui/button';
|
|
5
5
|
import { Label } from '../../../../components/ui/label';
|
|
6
6
|
import { Input } from '../../../../components/ui/input';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { Card, CardContent, CardHeader, CardTitle } from '../../../../components/ui/card';
|
|
10
|
-
import { Pencil, Eye, HelpCircle, BookOpen, Plus, X, ListChecks, MessageSquare } from 'lucide-react';
|
|
11
|
-
import { Checkbox } from '../../../../components/ui/checkbox';
|
|
7
|
+
import { HelpCircle, Plus, X, ListChecks, MessageSquare } from 'lucide-react';
|
|
8
|
+
import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
|
|
12
9
|
import { AnswerTheQuestionClient } from './AnswerTheQuestionClient';
|
|
13
10
|
import { useDebouncedCallback } from '../../../../shared/lib/hooks';
|
|
14
11
|
import { BasicQuestionGroupCard } from '../../groups/BasicQuestionGroupCard';
|
|
@@ -318,33 +315,42 @@ function AnswerTheQuestionContent({ initialData, onSave, onSaveToQuestionBank, o
|
|
|
318
315
|
title: groupTitle,
|
|
319
316
|
subtitle: groupSubtitle,
|
|
320
317
|
};
|
|
321
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(
|
|
318
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(AnswerTheQuestionClient, { questionData: questionData, isReviewMode: true, autoFillCorrectAnswers: true, explanation: explanation })] }));
|
|
322
319
|
}
|
|
323
320
|
// Creator UI
|
|
324
|
-
return (_jsxs("div", { className: "space-y-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
321
|
+
return (_jsxs("div", { className: "space-y-3", children: [isGrouped && (_jsx(BasicQuestionGroupCard, { groupNumber: currentGroupNumber, title: groupTitle, subtitle: groupSubtitle, content: groupContent, imageUrl: imageUrl, onTitleChange: setGroupTitle, onSubtitleChange: setGroupSubtitle, onContentChange: setGroupContent, onImageChange: setImageUrl, groupConfig: groupConfig, uploadIdPrefix: `answer-the-question-${partId ?? 'group'}` })), _jsxs(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(HelpCircle, { className: "h-3.5 w-3.5" }), title: "\u0110\u1ECDc c\u00E2u h\u1ECFi v\u00E0 vi\u1EBFt \u0111\u00E1p \u00E1n", points: {
|
|
322
|
+
value: currentQuestion.points || 1,
|
|
323
|
+
onValueChange: (value) => updateCurrentQuestion('points', value),
|
|
324
|
+
}, example: {
|
|
325
|
+
checked: currentQuestion.isExample || false,
|
|
326
|
+
onChange: (checked) => updateCurrentQuestion('isExample', checked),
|
|
327
|
+
}, headerExtra: headerExtra, preview: {
|
|
328
|
+
onClick: () => setIsClientMode(true),
|
|
329
|
+
disabled: !currentQuestion.question,
|
|
330
|
+
} }), children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "question", className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-teal-500" }), "C\u00E2u h\u1ECFi ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "question", value: currentQuestion.question, onChange: (e) => updateCurrentQuestion('question', e.target.value), placeholder: "Nh\u1EADp c\u00E2u h\u1ECFi... (vd: How many dolls has Lucy got?)", className: `border-gray-200 bg-white transition-all focus:border-teal-300 focus:ring-teal-200 ${validationErrors.question ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.question && (_jsx("p", { className: "text-sm text-red-600", children: validationErrors.question }))] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "correctAnswer", className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(HelpCircle, { className: "h-4 w-4 text-green-500" }), "\u0110\u00E1p \u00E1n \u0111\u00FAng ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "correctAnswer", value: currentQuestion.correctAnswer, onChange: (e) => updateCurrentQuestion('correctAnswer', e.target.value), placeholder: "Nh\u1EADp \u0111\u00E1p \u00E1n... (vd: 5 ho\u1EB7c Buster)", className: `border-gray-200 bg-white transition-all focus:border-green-300 focus:ring-green-200 ${validationErrors.correctAnswer ? 'border-red-400 focus:border-red-500 focus:ring-red-200' : ''}` }), validationErrors.correctAnswer && (_jsx("p", { className: "text-sm text-red-600", children: validationErrors.correctAnswer }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "prefixText", className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-gray-400" }), "Text tr\u01B0\u1EDBc \u00F4 tr\u1EA3 l\u1EDDi ", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(t\u00F9y ch\u1ECDn)" })] }), _jsx(Input, { id: "prefixText", value: currentQuestion.prefixText || '', onChange: (e) => updateCurrentQuestion('prefixText', e.target.value), placeholder: "vd: There are", className: "border-gray-200 bg-white transition-all focus:border-gray-300 focus:ring-gray-200" })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { htmlFor: "suffixText", className: "flex items-center gap-2 text-sm font-semibold text-gray-800", children: [_jsx(MessageSquare, { className: "h-4 w-4 text-gray-400" }), "Text sau \u00F4 tr\u1EA3 l\u1EDDi ", _jsx("span", { className: "text-xs font-normal text-gray-500", children: "(t\u00F9y ch\u1ECDn)" })] }), _jsx(Input, { id: "suffixText", value: currentQuestion.suffixText || '', onChange: (e) => updateCurrentQuestion('suffixText', e.target.value), placeholder: "vd: school", className: "border-gray-200 bg-white transition-all focus:border-gray-300 focus:ring-gray-200" })] })] }), hasSuggestedAnswers !== false && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Label, { className: "flex items-center gap-2 text-base font-semibold text-gray-800", children: [_jsx(ListChecks, { className: "h-4 w-4 text-purple-500" }), "\u0110\u00E1p \u00E1n g\u1EE3i \u00FD ", _jsx("span", { className: "text-sm font-normal text-gray-500", children: "(t\u00F9y ch\u1ECDn)" })] }), _jsxs("div", { className: "rounded-xl border border-purple-200 bg-gradient-to-r from-purple-50 to-violet-50 p-4 space-y-3", children: [currentQuestion.suggestedAnswers && currentQuestion.suggestedAnswers.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2", children: currentQuestion.suggestedAnswers.map((suggestion, index) => (_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-white border border-purple-200 px-3 py-1 text-sm font-medium text-purple-700 shadow-sm", children: [suggestion, _jsx("button", { type: "button", onClick: () => {
|
|
331
|
+
const updated = [...(currentQuestion.suggestedAnswers || [])];
|
|
332
|
+
updated.splice(index, 1);
|
|
333
|
+
updateCurrentQuestion('suggestedAnswers', updated);
|
|
334
|
+
}, className: "ml-0.5 rounded-full p-0.5 text-purple-400 hover:bg-purple-100 hover:text-purple-600 transition-colors", children: _jsx(X, { className: "h-3 w-3" }) })] }, index))) })), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { id: "newSuggestedAnswer", placeholder: "Nh\u1EADp \u0111\u00E1p \u00E1n g\u1EE3i \u00FD...", className: "flex-1 border-purple-200 bg-white focus:border-purple-400 focus:ring-purple-200", onKeyDown: (e) => {
|
|
335
|
+
if (e.key === 'Enter') {
|
|
336
|
+
e.preventDefault();
|
|
337
|
+
const input = e.currentTarget;
|
|
338
|
+
const value = input.value.trim();
|
|
339
|
+
if (value) {
|
|
340
|
+
const current = currentQuestion.suggestedAnswers || [];
|
|
341
|
+
updateCurrentQuestion('suggestedAnswers', [...current, value]);
|
|
342
|
+
input.value = '';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "gap-1 border-purple-300 text-purple-600 hover:bg-purple-100 hover:text-purple-700", onClick: () => {
|
|
346
|
+
const input = document.getElementById('newSuggestedAnswer');
|
|
347
|
+
const value = input?.value.trim();
|
|
348
|
+
if (value) {
|
|
349
|
+
const current = currentQuestion.suggestedAnswers || [];
|
|
350
|
+
updateCurrentQuestion('suggestedAnswers', [...current, value]);
|
|
351
|
+
input.value = '';
|
|
352
|
+
}
|
|
353
|
+
}, children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm"] })] }), _jsx("p", { className: "text-xs text-purple-500", children: "Nh\u1EADp \u0111\u00E1p \u00E1n g\u1EE3i \u00FD r\u1ED3i nh\u1EA5n Enter ho\u1EB7c n\u00FAt Th\u00EAm" })] })] })), externalErrors && externalErrors.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 rounded-md border border-red-200 bg-red-50 p-2 text-xs text-red-700", children: [_jsx("span", { className: "font-semibold text-red-800", children: "L\u1ED7i:" }), _jsx("span", { children: externalErrors.join(' · ') })] }))] }), _jsx(CompactExplanationToggle, { value: explanation, onValueChange: setExplanation })] }));
|
|
348
354
|
}
|
|
349
355
|
export function AnswerTheQuestionCreator(props) {
|
|
350
356
|
return _jsx(AnswerTheQuestionContent, { ...props });
|
package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.js
CHANGED
|
@@ -52,6 +52,6 @@ export function AnswerTheQuestionGroupClient({ questionData, isReviewMode = fals
|
|
|
52
52
|
const expectedAnswers = Array.isArray(item.expectedAnswers)
|
|
53
53
|
? item.expectedAnswers.filter((answer) => answer.trim() !== '')
|
|
54
54
|
: [];
|
|
55
|
-
return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-
|
|
55
|
+
return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 text-white", children: _jsx(CircleHelp, { className: "h-3.5 w-3.5" }) }), _jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["C\u00E2u ", item.questionNumber || itemIndex + 1] }), item.isExample && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-700", children: [_jsx(Star, { className: "h-3 w-3" }), "Example"] })), _jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-violet-100 px-2 py-0.5 text-xs font-semibold text-violet-700", children: [_jsx(Sparkles, { className: "h-3 w-3" }), "AI"] })] }), _jsxs("span", { className: "text-xs text-gray-500", children: [item.points || 0, " \u0111i\u1EC3m"] })] }), _jsxs("div", { className: "space-y-3 p-3", children: [toAnswerTheQuestionGroupImageUrls(item.imageUrl).length > 0 && (_jsx("div", { className: "flex flex-wrap justify-center gap-3", children: toAnswerTheQuestionGroupImageUrls(item.imageUrl).map((url, imageIndex) => (_jsx(MediaPreview, { src: url, alt: `Hình ảnh câu ${item.questionNumber || itemIndex + 1} (${imageIndex + 1})` }, `${item.questionNumber}-${imageIndex}`))) })), _jsx("p", { className: "text-sm font-semibold leading-relaxed text-gray-800", children: item.question || 'Câu hỏi chưa được nhập' }), _jsx("div", { className: "rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-sm text-gray-700", children: userValue || (isReviewMode ? '(Chưa trả lời)' : 'Học sinh sẽ nhập câu trả lời tại đây') }), isReviewMode && expectedAnswers.length > 0 && (_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-xs font-medium text-gray-500", children: "\u0110\u00E1p \u00E1n m\u1EABu (AI)" }), _jsx("ul", { className: "list-disc space-y-1 pl-5 text-sm text-gray-700", children: expectedAnswers.map((answer) => (_jsx("li", { children: answer }, answer))) })] }))] })] }, `${item.questionNumber}-${itemIndex}`));
|
|
56
56
|
}), isReviewMode && questionData.explanation && (_jsxs("div", { className: "flex items-start gap-2 rounded-xl border border-amber-100 bg-amber-50 px-4 py-3 text-sm text-amber-800", children: [_jsx(Lightbulb, { className: "mt-0.5 h-4 w-4 flex-shrink-0" }), questionData.explanation] }))] }));
|
|
57
57
|
}
|
package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupCreator.js
CHANGED
|
@@ -10,7 +10,8 @@ import { Card, CardContent, CardHeader, CardTitle } from '../../../../components
|
|
|
10
10
|
import { Switch } from '../../../../components/ui/switch';
|
|
11
11
|
import { RichTextEditor } from '../../../../components/shared/RichTextEditor';
|
|
12
12
|
import { useDebouncedCallback } from '../../../../shared/lib/hooks';
|
|
13
|
-
import {
|
|
13
|
+
import { MessageSquare, Plus, Star, Trash2 } from 'lucide-react';
|
|
14
|
+
import { CompactCreatorHeader, CompactExplanationToggle, CompactFieldCard, CompactPreviewBanner, } from '../../_shared/components/compact';
|
|
14
15
|
import { AnswerTheQuestionGroupClient } from './AnswerTheQuestionGroupClient';
|
|
15
16
|
import { toAnswerTheQuestionGroupImageUrls } from '../../_shared/types/answer-the-question-group.type';
|
|
16
17
|
const DEFAULT_INSTRUCTION = 'Read the text again and answer the questions.';
|
|
@@ -180,10 +181,10 @@ export function AnswerTheQuestionGroupCreator({ initialData, onChange, externalE
|
|
|
180
181
|
};
|
|
181
182
|
const displayErrors = externalErrors && externalErrors.length > 0 ? externalErrors : errors;
|
|
182
183
|
if (isClientMode) {
|
|
183
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(
|
|
184
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(CompactPreviewBanner, { onBack: () => setIsClientMode(false) }), _jsx(AnswerTheQuestionGroupClient, { questionData: buildPayload(), isReviewMode: true })] }));
|
|
184
185
|
}
|
|
185
|
-
return (_jsxs("div", { className: "space-y-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
186
|
+
return (_jsxs("div", { className: "space-y-3", children: [displayErrors.length > 0 && (_jsx("div", { className: "rounded-md border border-red-200 bg-red-50 p-2 text-xs text-red-700", children: displayErrors.map((error) => (_jsx("p", { children: error }, error))) })), _jsxs(CompactFieldCard, { header: _jsx(CompactCreatorHeader, { icon: _jsx(MessageSquare, { className: "h-3.5 w-3.5" }), title: "\u0110\u1ECDc v\u00E0 tr\u1EA3 l\u1EDDi c\u00E2u h\u1ECFi (AI)", preview: { onClick: () => setIsClientMode(true) } }), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "group-instruction", className: "text-sm font-semibold text-gray-800", children: "H\u01B0\u1EDBng d\u1EABn" }), _jsx(Input, { id: "group-instruction", value: instruction, onChange: (event) => setInstruction(event.target.value), placeholder: DEFAULT_INSTRUCTION, className: "h-10 border-gray-200 bg-white" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-sm font-semibold text-gray-800", children: "N\u1ED9i dung b\u00E0i \u0111\u1ECDc (Passage)" }), _jsx(RichTextEditor, { value: passage, onChange: setPassage, minHeightClassName: "min-h-[160px]" })] }), _jsxs("div", { className: "rounded-md border border-gray-200 bg-gray-50 px-3 py-2.5", children: [_jsx(PointsInput, { value: sumPoints(items), allowZero: true, readOnly: true }), _jsx("p", { className: "mt-1.5 text-xs text-gray-500", children: "T\u1ED5ng \u0111i\u1EC3m \u0111\u01B0\u1EE3c c\u1ED9ng t\u1EEB c\u00E1c c\u00E2u kh\u00F4ng ph\u1EA3i example." })] })] }), _jsxs(Card, { className: "overflow-hidden border-0 bg-white shadow-sm", children: [_jsx(CardHeader, { className: "px-3 py-2", children: _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs(CardTitle, { className: "text-sm font-semibold text-gray-800", children: ["Danh s\u00E1ch c\u00E2u h\u1ECFi (", items.length, ")"] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addItem, className: "h-8 gap-1.5 px-2.5 text-xs", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm c\u00E2u h\u1ECFi"] })] }) }), _jsxs(CardContent, { className: "space-y-2.5 px-3 pb-3", children: [items.map((item, itemIndex) => (_jsxs("div", { className: "space-y-2.5 rounded-md border border-gray-200 bg-white px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["C\u00E2u ", itemIndex + 1] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: item.isExample === true, onCheckedChange: (checked) => updateItem(itemIndex, {
|
|
187
|
+
isExample: checked,
|
|
188
|
+
points: checked ? 0 : (item.points || 1),
|
|
189
|
+
}) }), _jsxs(Label, { className: "flex cursor-pointer items-center gap-1 text-xs", children: [_jsx(Star, { className: "h-3 w-3 text-amber-500" }), "C\u00E2u v\u00ED d\u1EE5"] })] }), !item.isExample && (_jsx(PointsInput, { value: item.points, allowZero: true, onChange: (e) => updateItem(itemIndex, { points: Number(e.target.value) || 0 }) })), _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeItem(itemIndex), disabled: items.length <= 1, className: "h-7 w-7 text-red-500 hover:bg-red-50 hover:text-red-600", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { children: "C\u00E2u h\u1ECFi" }), _jsx(Textarea, { value: item.question, onChange: (event) => updateItem(itemIndex, { question: event.target.value }), rows: 2, placeholder: "What is autism?", className: "min-h-[56px] border-gray-200 bg-white" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { children: "\u0110\u00E1p \u00E1n m\u1EABu cho AI" }), item.expectedAnswers.map((answer, answerIndex) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: answer, onChange: (event) => updateExpectedAnswer(itemIndex, answerIndex, event.target.value), placeholder: `Đáp án mẫu ${answerIndex + 1}`, className: "h-10 border-gray-200 bg-white" }), item.expectedAnswers.length > 1 && (_jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeExpectedAnswer(itemIndex, answerIndex), className: "h-7 w-7 text-red-500 hover:bg-red-50 hover:text-red-600", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }))] }, `expected-${itemIndex}-${answerIndex}`))), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => addExpectedAnswer(itemIndex), className: "h-8 gap-1.5 px-2.5 text-xs", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), "Th\u00EAm \u0111\u00E1p \u00E1n m\u1EABu"] })] })] }, `item-${itemIndex}`))), _jsx(CompactExplanationToggle, { value: explanation, onValueChange: setExplanation, defaultVisible: Boolean(initialData?.explanation) })] })] })] }));
|
|
189
190
|
}
|