@tinyweb_dev/oe-exam-sdk 0.2.3 → 0.2.4
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/questions/types/write-a-short-letter/WriteAShortLetterClient.js +16 -2
- package/dist/components/questions/viewer/AnswerTheQuestionGroupViewer.d.ts +8 -0
- package/dist/components/questions/viewer/AnswerTheQuestionGroupViewer.js +11 -0
- package/dist/components/questions/viewer/QuestionViewer.js +40 -6
- package/dist/components/questions/viewer/index.d.ts +1 -0
- package/dist/components/questions/viewer/index.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/shared/lib/utils/question-reverse-transform.js +55 -2
- package/package.json +1 -1
|
@@ -17,8 +17,22 @@ function GuideImageDisplay({ imageKey }) {
|
|
|
17
17
|
} }) }));
|
|
18
18
|
}
|
|
19
19
|
export function WriteAShortLetterClient({ questionData, onSubmit, isReviewMode = false, userAnswer, explanation, }) {
|
|
20
|
-
const {
|
|
21
|
-
const instruction = instructions?.mainInstruction ||
|
|
20
|
+
const { minWords = 20, maxWords } = questionData;
|
|
21
|
+
const instruction = questionData.instructions?.mainInstruction ||
|
|
22
|
+
(typeof questionData.instructions === 'string' ? questionData.instructions : '') ||
|
|
23
|
+
questionData.instruction ||
|
|
24
|
+
questionData.prompt ||
|
|
25
|
+
'';
|
|
26
|
+
const informations = Array.isArray(questionData.informations)
|
|
27
|
+
? questionData.informations
|
|
28
|
+
: Array.isArray(questionData.requirements)
|
|
29
|
+
? questionData.requirements
|
|
30
|
+
: [];
|
|
31
|
+
const guideImages = Array.isArray(questionData.guideImages)
|
|
32
|
+
? questionData.guideImages
|
|
33
|
+
: Array.isArray(questionData.images)
|
|
34
|
+
? questionData.images
|
|
35
|
+
: [];
|
|
22
36
|
// Initialize answer state - ensure it's always a string
|
|
23
37
|
const [answer, setAnswer] = useState(typeof userAnswer === 'string' ? userAnswer : '');
|
|
24
38
|
// Sync userAnswer when it changes (e.g., when loading from server in review mode)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Question } from '../../../shared/types/entities/question.types';
|
|
2
|
+
type AnswerTheQuestionGroupViewerProps = {
|
|
3
|
+
question: Question;
|
|
4
|
+
isReviewMode?: boolean;
|
|
5
|
+
userAnswer?: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function AnswerTheQuestionGroupViewer({ question, isReviewMode, userAnswer, }: AnswerTheQuestionGroupViewerProps): import("react").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { AnswerTheQuestionGroupClient } from '../types/answer-the-question-group/AnswerTheQuestionGroupClient';
|
|
4
|
+
import { mapQuestionToAnswerTheQuestionGroupData } from '../types/answer-the-question-group/map-answer-the-question-group-data';
|
|
5
|
+
export function AnswerTheQuestionGroupViewer({ question, isReviewMode = false, userAnswer, }) {
|
|
6
|
+
const questionData = mapQuestionToAnswerTheQuestionGroupData(question);
|
|
7
|
+
const reviewAnswers = isReviewMode && !userAnswer
|
|
8
|
+
? questionData.items.map((item) => item.expectedAnswers[0] || '')
|
|
9
|
+
: userAnswer;
|
|
10
|
+
return (_jsx(AnswerTheQuestionGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers }));
|
|
11
|
+
}
|
|
@@ -20,6 +20,7 @@ import { LookPictureFillBlankChooseAnswerClient } from '../types/look-picture-fi
|
|
|
20
20
|
import { FillMissingWordsInGridClient } from '../types/fill-missing-words-in-grid/FillMissingWordsInGridClient';
|
|
21
21
|
import { WordFillStructuredFormClient } from '../types/word-fill-structured-form/WordFillStructuredFormClient';
|
|
22
22
|
import { CrosswordPuzzleClient } from '../types/crossword-puzzle/CrosswordPuzzleClient';
|
|
23
|
+
import { FindWordsInMatrixClient } from '../types/find-words-in-matrix/FindWordsInMatrixClient';
|
|
23
24
|
import { parseFillBlankStemLine } from '../_shared/utils/parseFillBlankStem';
|
|
24
25
|
import { WordFillStructuredFormViewer } from './WordFillStructuredFormViewer';
|
|
25
26
|
import { ChooseTheCorrectAnswerGroupViewer } from './ChooseTheCorrectAnswerGroupViewer';
|
|
@@ -27,6 +28,7 @@ import { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
|
27
28
|
import { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
28
29
|
import { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
29
30
|
import { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
31
|
+
import { AnswerTheQuestionGroupViewer } from './AnswerTheQuestionGroupViewer';
|
|
30
32
|
export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false, userAnswer, }) {
|
|
31
33
|
const [selectedAnswer, setSelectedAnswer] = useState(userAnswer || null);
|
|
32
34
|
const [playCount, setPlayCount] = useState(0);
|
|
@@ -314,13 +316,41 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
314
316
|
}, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
315
317
|
};
|
|
316
318
|
const renderWriteAShortLetter = () => {
|
|
317
|
-
const
|
|
319
|
+
const content = (question.content || {});
|
|
320
|
+
const answer = (question.answer || {});
|
|
321
|
+
const mainInstruction = content?.instructions?.mainInstruction ||
|
|
322
|
+
content?.instruction ||
|
|
323
|
+
content?.prompt ||
|
|
324
|
+
answer?.instructions?.mainInstruction ||
|
|
325
|
+
answer?.instruction ||
|
|
326
|
+
(typeof content?.instructions === 'string' ? content.instructions : '') ||
|
|
327
|
+
(typeof content === 'string' ? content : '') ||
|
|
328
|
+
'';
|
|
329
|
+
const informations = (Array.isArray(content?.informations)
|
|
330
|
+
? content.informations
|
|
331
|
+
: Array.isArray(content?.requirements)
|
|
332
|
+
? content.requirements
|
|
333
|
+
: Array.isArray(answer?.informations)
|
|
334
|
+
? answer.informations
|
|
335
|
+
: []).map((info) => typeof info === 'string' ? info : (info.text || info.content || ''));
|
|
336
|
+
const guideImages = Array.isArray(content?.guideImages)
|
|
337
|
+
? content.guideImages
|
|
338
|
+
: Array.isArray(answer?.guideImages)
|
|
339
|
+
? answer.guideImages
|
|
340
|
+
: [];
|
|
341
|
+
const contexts = content?.contexts || answer?.contexts || [];
|
|
342
|
+
const minWords = content?.minWords ?? answer?.minWords ?? 20;
|
|
343
|
+
const maxWords = content?.maxWords ?? answer?.maxWords ?? null;
|
|
318
344
|
const questionData = {
|
|
319
|
-
contexts
|
|
320
|
-
informations
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
345
|
+
contexts,
|
|
346
|
+
informations,
|
|
347
|
+
guideImages,
|
|
348
|
+
minWords,
|
|
349
|
+
maxWords,
|
|
350
|
+
instructions: {
|
|
351
|
+
mainInstruction,
|
|
352
|
+
},
|
|
353
|
+
instruction: mainInstruction,
|
|
324
354
|
};
|
|
325
355
|
return (_jsx(WriteAShortLetterClient, { questionData: questionData, onSubmit: (answerText) => {
|
|
326
356
|
setSelectedAnswer(answerText);
|
|
@@ -600,6 +630,8 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
600
630
|
return (_jsx(TrueFalseGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
601
631
|
case 'CROSS_OUT_WORD_GROUP':
|
|
602
632
|
return (_jsx(CrossOutWordGroupViewer, { question: question, isReviewMode: isReviewMode }));
|
|
633
|
+
case 'ANSWER_THE_QUESTION_GROUP':
|
|
634
|
+
return (_jsx(AnswerTheQuestionGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
603
635
|
case 'SPONTANEOUS_QA_GROUP':
|
|
604
636
|
return (_jsx(SpontaneousQaGroupViewer, { question: question, isReviewMode: isReviewMode }));
|
|
605
637
|
case 'WORD_ORDER_AND_MATCH_GROUP':
|
|
@@ -646,6 +678,8 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
646
678
|
return (_jsx(WordFillStructuredFormViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
647
679
|
case 'CROSSWORD_PUZZLE':
|
|
648
680
|
return (_jsx(CrosswordPuzzleClient, { content: question.content, correctAnswer: question.answer, isReviewMode: isReviewMode, userAnswers: userAnswer }));
|
|
681
|
+
case 'FIND_WORDS_IN_MATRIX':
|
|
682
|
+
return (_jsx(FindWordsInMatrixClient, { content: question.content, correctAnswer: question.answer, showSolution: isReviewMode }));
|
|
649
683
|
default:
|
|
650
684
|
return _jsxs("div", { children: ["Lo\u1EA1i c\u00E2u h\u1ECFi kh\u00F4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3: ", question.type] });
|
|
651
685
|
}
|
|
@@ -6,3 +6,4 @@ export { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
|
6
6
|
export { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
7
7
|
export { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
8
8
|
export { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
9
|
+
export { AnswerTheQuestionGroupViewer } from './AnswerTheQuestionGroupViewer';
|
|
@@ -6,3 +6,4 @@ export { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
|
6
6
|
export { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
7
7
|
export { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
8
8
|
export { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
9
|
+
export { AnswerTheQuestionGroupViewer } from './AnswerTheQuestionGroupViewer';
|
package/dist/index.d.ts
CHANGED
|
@@ -26,4 +26,4 @@ export { validateQuestion } from './components/questions/_shared/utils/question-
|
|
|
26
26
|
export { buildAnswerPayload } from './components/questions/_shared/utils/answer-builder';
|
|
27
27
|
export type { QuestionFormState } from './components/questions/_shared/hooks/useQuestionFormState';
|
|
28
28
|
export * from './components/questions/_shared/types';
|
|
29
|
-
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, } from './components/questions/viewer';
|
|
29
|
+
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, } from './components/questions/viewer';
|
package/dist/index.js
CHANGED
|
@@ -21,4 +21,4 @@ export { QUESTION_TYPE_CONFIG, QUESTION_TYPES_WITH_DEDICATED_COMPONENTS } from '
|
|
|
21
21
|
export { validateQuestion } from './components/questions/_shared/utils/question-validation';
|
|
22
22
|
export { buildAnswerPayload } from './components/questions/_shared/utils/answer-builder';
|
|
23
23
|
export * from './components/questions/_shared/types';
|
|
24
|
-
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, } from './components/questions/viewer';
|
|
24
|
+
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, } from './components/questions/viewer';
|
|
@@ -424,8 +424,8 @@ const handlers = {
|
|
|
424
424
|
WORD_ORDERING: reverseSimpleAnswer,
|
|
425
425
|
WORD_FILL_PARAGRAPH: reverseSimpleAnswer,
|
|
426
426
|
MATCH_BY_WRITING_ANSWER: reverseGroupPayload,
|
|
427
|
-
|
|
428
|
-
WRITE_A_SHORT_LETTER:
|
|
427
|
+
WRITE_SHORT_PARAGRAPH: reverseWriteShortParagraph,
|
|
428
|
+
WRITE_A_SHORT_LETTER: reverseWriteAShortLetter,
|
|
429
429
|
WRITE_CORRECT_VERB_FORM: reverseSimpleAnswer,
|
|
430
430
|
CHOOSE_CORRECT_ADJECTIVE: reverseSimpleAnswer,
|
|
431
431
|
WORD_FILL_STRUCTURED_FORM: reverseGroupPayload,
|
|
@@ -449,6 +449,59 @@ const handlers = {
|
|
|
449
449
|
CROSSWORD_PUZZLE: reverseCrosswordPuzzle,
|
|
450
450
|
FIND_WORDS_IN_MATRIX: reverseFindWordsInMatrix,
|
|
451
451
|
};
|
|
452
|
+
function reverseWriteAShortLetter(apiQuestion) {
|
|
453
|
+
const content = asRecord(apiQuestion.content);
|
|
454
|
+
const answer = readAnswer(apiQuestion);
|
|
455
|
+
const informations = asArray(content.informations ?? answer.informations).map((item) => asString(item)).filter(Boolean);
|
|
456
|
+
const guideImages = asArray(content.guideImages ?? answer.guideImages).map((item) => asString(item)).filter(Boolean);
|
|
457
|
+
const contexts = asArray(content.contexts ?? answer.contexts);
|
|
458
|
+
const instructions = isRecord(content.instructions)
|
|
459
|
+
? content.instructions
|
|
460
|
+
: isRecord(answer.instructions)
|
|
461
|
+
? answer.instructions
|
|
462
|
+
: { mainInstruction: asString(content.instruction ?? content.prompt ?? answer.instruction ?? answer.prompt) };
|
|
463
|
+
const minWords = asNumber(content.minWords ?? answer.minWords, 20);
|
|
464
|
+
const maxWords = content.maxWords !== undefined && content.maxWords !== null
|
|
465
|
+
? asNumber(content.maxWords, 0) || null
|
|
466
|
+
: answer.maxWords !== undefined && answer.maxWords !== null
|
|
467
|
+
? asNumber(answer.maxWords, 0) || null
|
|
468
|
+
: null;
|
|
469
|
+
const resolved = {
|
|
470
|
+
instructions,
|
|
471
|
+
instruction: asString(instructions.mainInstruction || instructions.instruction),
|
|
472
|
+
informations,
|
|
473
|
+
guideImages,
|
|
474
|
+
contexts,
|
|
475
|
+
minWords,
|
|
476
|
+
maxWords,
|
|
477
|
+
};
|
|
478
|
+
return {
|
|
479
|
+
content: resolved,
|
|
480
|
+
answer: resolved,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function reverseWriteShortParagraph(apiQuestion) {
|
|
484
|
+
const content = asRecord(apiQuestion.content);
|
|
485
|
+
const answer = readAnswer(apiQuestion);
|
|
486
|
+
const contexts = asArray(content.contexts ?? answer.contexts);
|
|
487
|
+
const instruction = asString(content.instruction ?? content.instructions?.mainInstruction ?? answer.instruction);
|
|
488
|
+
const minWords = asNumber(content.minWords ?? answer.minWords, 20);
|
|
489
|
+
const maxWords = content.maxWords !== undefined && content.maxWords !== null
|
|
490
|
+
? asNumber(content.maxWords, 0) || null
|
|
491
|
+
: answer.maxWords !== undefined && answer.maxWords !== null
|
|
492
|
+
? asNumber(answer.maxWords, 0) || null
|
|
493
|
+
: null;
|
|
494
|
+
const resolved = {
|
|
495
|
+
instruction,
|
|
496
|
+
contexts,
|
|
497
|
+
minWords,
|
|
498
|
+
maxWords,
|
|
499
|
+
};
|
|
500
|
+
return {
|
|
501
|
+
content: resolved,
|
|
502
|
+
answer: resolved,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
452
505
|
function reverseCrosswordPuzzle(apiQuestion) {
|
|
453
506
|
const apiContent = (apiQuestion.content || {});
|
|
454
507
|
const apiAnswer = (apiQuestion.correctAnswer || apiQuestion.correct_answer || apiQuestion.answer || {});
|