@tinyweb_dev/oe-exam-sdk 0.1.26 → 0.1.28
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/README.md +79 -5
- package/dist/components/exams/ExamPreviewDialog.d.ts +7 -6
- package/dist/components/exams/ExamPreviewDialog.js +1 -1
- package/dist/components/exams/index.d.ts +0 -1
- package/dist/components/exams/take/components/QuestionRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -1
- package/dist/components/exams/take/exam-taking.utils.d.ts +0 -13
- package/dist/components/exams/take/exam-taking.utils.js +1 -1
- package/dist/components/exams/take/utils/answer-transformers.js +1 -1
- package/dist/components/exams/take/utils/question-transformers.d.ts +7 -17
- package/dist/components/exams/take/utils/question-transformers.js +1 -1
- package/dist/components/questions/_shared/config/question-types.config.js +1 -1
- package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.d.ts +36 -0
- package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +40 -0
- package/dist/components/questions/_shared/types/index.d.ts +1 -0
- package/dist/components/questions/_shared/types/index.js +1 -1
- package/dist/components/questions/_shared/types/true-false-group.type.d.ts +31 -0
- package/dist/components/questions/_shared/types/true-false-group.type.js +1 -0
- package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +11 -17
- package/dist/components/questions/creator/question-type-registry.js +1 -1
- package/dist/components/questions/index.d.ts +0 -1
- package/dist/components/questions/index.js +1 -1
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/index.d.ts +3 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/index.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.d.ts +4 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/register.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/register.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/transform.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/index.d.ts +5 -0
- package/dist/components/questions/types/cross-out-word-group/index.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.d.ts +6 -0
- package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/register.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/register.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/transform.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/transform.js +1 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +1 -0
- package/dist/components/questions/types/true-false-group/index.d.ts +5 -0
- package/dist/components/questions/types/true-false-group/index.js +1 -0
- package/dist/components/questions/types/true-false-group/map-true-false-group-data.d.ts +4 -0
- package/dist/components/questions/types/true-false-group/map-true-false-group-data.js +1 -0
- package/dist/components/questions/types/true-false-group/register.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/register.js +1 -0
- package/dist/components/questions/types/true-false-group/transform.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/transform.js +1 -0
- package/dist/components/questions/types/word-fill-structured-form/index.d.ts +1 -0
- package/dist/components/questions/types/word-fill-structured-form/index.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.d.ts +7 -0
- package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.js +1 -0
- package/dist/components/questions/types/word-fill-structured-form/register.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -1
- package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.d.ts +8 -0
- package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.js +1 -0
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.d.ts +7 -0
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +1 -0
- package/dist/components/questions/viewer/QuestionViewer.js +1 -1
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +4 -0
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +1 -0
- package/dist/components/questions/viewer/TrueFalseGroupViewer.d.ts +8 -0
- package/dist/components/questions/viewer/TrueFalseGroupViewer.js +1 -0
- package/dist/components/questions/viewer/WordFillStructuredFormViewer.d.ts +9 -0
- package/dist/components/questions/viewer/WordFillStructuredFormViewer.js +1 -0
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +4 -0
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +1 -0
- package/dist/components/questions/viewer/index.d.ts +6 -0
- package/dist/components/questions/viewer/index.js +1 -1
- package/dist/components/results/renderers/review-question-body-dedicated.js +1 -1
- package/dist/components/results/review-data.js +1 -1
- package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -1
- package/dist/mcp/config.d.ts +12 -0
- package/dist/mcp/config.js +1 -0
- package/dist/mcp/http-client.d.ts +6 -0
- package/dist/mcp/http-client.js +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/tools/_helpers.d.ts +4 -0
- package/dist/mcp/tools/_helpers.js +1 -0
- package/dist/mcp/tools/exams.d.ts +2 -0
- package/dist/mcp/tools/exams.js +1 -0
- package/dist/mcp/tools/index.d.ts +2 -0
- package/dist/mcp/tools/index.js +1 -0
- package/dist/mcp/tools/results.d.ts +2 -0
- package/dist/mcp/tools/results.js +1 -0
- package/dist/shared/constants/question-skills.js +1 -1
- package/dist/shared/lib/i18n/messages/en/admin.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/en/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/en.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/vi/admin.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/vi/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/vi.d.ts +4 -11
- package/dist/shared/lib/utils/question-reverse-transform.js +1 -1
- package/dist/shared/lib/utils/question-transform.js +1 -1
- package/dist/shared/types/common.types.d.ts +1 -1
- package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +41 -0
- package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -0
- package/dist/shared/types/questions/cross-out-word-group.d.ts +41 -0
- package/dist/shared/types/questions/cross-out-word-group.js +1 -0
- package/dist/shared/types/questions/index.d.ts +2 -0
- package/dist/shared/types/questions/index.js +1 -1
- package/package.json +166 -169
- package/dist/components/exams/ExamPreviewPartContent.d.ts +0 -18
- package/dist/components/exams/ExamPreviewPartContent.js +0 -1
- package/dist/components/exams/ExamPreviewSidebar.d.ts +0 -17
- package/dist/components/exams/ExamPreviewSidebar.js +0 -1
- package/dist/components/exams/exam-preview.types.d.ts +0 -34
- package/dist/components/exams/exam-preview.types.js +0 -1
- package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +0 -30
- package/dist/components/questions/_shared/utils/parseFillBlankStem.js +0 -1
- package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +0 -2
- package/dist/components/questions/question-bank/EditQuestionBankDialog.js +0 -1
- package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -23
- package/dist/components/questions/question-bank/QuestionEditorRenderer.js +0 -1
- package/dist/components/questions/question-bank/difficulty.d.ts +0 -15
- package/dist/components/questions/question-bank/difficulty.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/index.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/index.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -6
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/types.d.ts +0 -1
- package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +0 -8
- package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +0 -1
- package/dist/components/questions/question-bank/index.d.ts +0 -4
- package/dist/components/questions/question-bank/index.js +0 -1
- package/dist/components/questions/question-bank/types.d.ts +0 -59
- /package/dist/components/questions/{question-bank/editor-adapters/types.js → _shared/types/choose-the-correct-answer-group.type.js} +0 -0
- /package/dist/components/questions/{question-bank/types.js → _shared/types/cross-out-word-group.type.js} +0 -0
package/package.json
CHANGED
|
@@ -1,169 +1,166 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tinyweb_dev/oe-exam-sdk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Reusable OceanEdu question components.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"bin": {
|
|
10
|
-
"oe-exam-mcp": "./dist/mcp/index.js"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"dist",
|
|
14
|
-
"README.md"
|
|
15
|
-
],
|
|
16
|
-
"sideEffects": [
|
|
17
|
-
"**/*.css"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"clean": "rm -rf dist",
|
|
21
|
-
"build:compile": "tsc -p tsconfig.build.json",
|
|
22
|
-
"build:alias": "tsc-alias -p tsconfig.build.json",
|
|
23
|
-
"build:
|
|
24
|
-
"build:
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"release
|
|
31
|
-
"release:
|
|
32
|
-
"release:
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"@types/
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"@
|
|
115
|
-
"@
|
|
116
|
-
"@
|
|
117
|
-
"@
|
|
118
|
-
"@
|
|
119
|
-
"@
|
|
120
|
-
"@
|
|
121
|
-
"@radix-ui/react-
|
|
122
|
-
"@radix-ui/react-
|
|
123
|
-
"@radix-ui/react-
|
|
124
|
-
"@radix-ui/react-
|
|
125
|
-
"@radix-ui/react-
|
|
126
|
-
"@radix-ui/react-
|
|
127
|
-
"@radix-ui/react-
|
|
128
|
-
"@radix-ui/react-
|
|
129
|
-
"@radix-ui/react-
|
|
130
|
-
"@radix-ui/react-
|
|
131
|
-
"@radix-ui/react-
|
|
132
|
-
"@radix-ui/react-
|
|
133
|
-
"@radix-ui/react-
|
|
134
|
-
"@radix-ui/react-
|
|
135
|
-
"@radix-ui/react-
|
|
136
|
-
"@
|
|
137
|
-
"@
|
|
138
|
-
"@
|
|
139
|
-
"@
|
|
140
|
-
"@tiptap/extension-table": "^3.22.3",
|
|
141
|
-
"@tiptap/extension-
|
|
142
|
-
"@tiptap/extension-
|
|
143
|
-
"@tiptap/
|
|
144
|
-
"@tiptap/
|
|
145
|
-
"@tiptap/
|
|
146
|
-
"@
|
|
147
|
-
"@
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"zustand": "^5.0.8"
|
|
168
|
-
}
|
|
169
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@tinyweb_dev/oe-exam-sdk",
|
|
3
|
+
"version": "0.1.28",
|
|
4
|
+
"description": "Reusable OceanEdu question components.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"oe-exam-mcp": "./dist/mcp/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"sideEffects": [
|
|
17
|
+
"**/*.css"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"build:compile": "tsc -p tsconfig.build.json",
|
|
22
|
+
"build:alias": "tsc-alias -p tsconfig.build.json",
|
|
23
|
+
"build:check-aliases": "node ./scripts/check-aliases.mjs",
|
|
24
|
+
"build:ts": "npm run build:compile && npm run build:assets && npm run build:alias && npm run build:check-aliases",
|
|
25
|
+
"build:assets": "for d in cambridge-yle english-certification summer-sky; do [ -d src/components/themes/$d/assets ] && cp -R src/components/themes/$d/assets dist/components/themes/$d/ || true; done; [ -d src/components/shared/audio/assets ] && cp -R src/components/shared/audio/assets dist/components/shared/audio/ || true; [ -d src/components/results/report/assets ] && mkdir -p dist/components/results/report && cp -R src/components/results/report/assets dist/components/results/report/ || true; (cd src && find . -name '*.module.css' -exec cp --parents {} ../dist/ \\;); cp src/global.d.ts dist/global.d.ts",
|
|
26
|
+
"minify:js": "find dist -name '*.js' -type f -exec sh -c 'for f do terser \"$f\" --compress directives=false --mangle --module --comments false --output \"$f\"; done' sh {} +",
|
|
27
|
+
"build": "npm run clean && npm run build:ts && npm run minify:js",
|
|
28
|
+
"dev": "node ./scripts/dev-watch.mjs",
|
|
29
|
+
"pack:local": "npm pack",
|
|
30
|
+
"release": "npm run release:patch",
|
|
31
|
+
"release:patch": "npm version patch --no-git-tag-version && npm run release:push",
|
|
32
|
+
"release:minor": "npm version minor --no-git-tag-version && npm run release:push",
|
|
33
|
+
"release:major": "npm version major --no-git-tag-version && npm run release:push",
|
|
34
|
+
"release:push": "npm run build && npm pack --dry-run && VERSION=$(node -p \"require('./package.json').version\") && git add package.json package-lock.json && git commit -m \"chore(sdk): release v$VERSION\" && git tag \"sdk-v$VERSION\" && git push origin HEAD && git push origin \"sdk-v$VERSION\"",
|
|
35
|
+
"prepack": "npm run build"
|
|
36
|
+
},
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./api": {
|
|
43
|
+
"types": "./dist/api/index.d.ts",
|
|
44
|
+
"import": "./dist/api/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./components": {
|
|
47
|
+
"types": "./dist/components/index.d.ts",
|
|
48
|
+
"import": "./dist/components/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./mcp": {
|
|
51
|
+
"types": "./dist/mcp/index.d.ts",
|
|
52
|
+
"import": "./dist/mcp/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./components/exams": {
|
|
55
|
+
"types": "./dist/components/exams/index.d.ts",
|
|
56
|
+
"import": "./dist/components/exams/index.js"
|
|
57
|
+
},
|
|
58
|
+
"./components/exams/take": {
|
|
59
|
+
"types": "./dist/components/exams/take/index.d.ts",
|
|
60
|
+
"import": "./dist/components/exams/take/index.js"
|
|
61
|
+
},
|
|
62
|
+
"./components/exams/entry": {
|
|
63
|
+
"types": "./dist/components/exams/entry/index.d.ts",
|
|
64
|
+
"import": "./dist/components/exams/entry/index.js"
|
|
65
|
+
},
|
|
66
|
+
"./components/exams/rooms": {
|
|
67
|
+
"types": "./dist/components/exams/rooms/index.d.ts",
|
|
68
|
+
"import": "./dist/components/exams/rooms/index.js"
|
|
69
|
+
},
|
|
70
|
+
"./components/questions": {
|
|
71
|
+
"types": "./dist/components/questions/index.d.ts",
|
|
72
|
+
"import": "./dist/components/questions/index.js"
|
|
73
|
+
},
|
|
74
|
+
"./components/themes": {
|
|
75
|
+
"types": "./dist/components/themes/index.d.ts",
|
|
76
|
+
"import": "./dist/components/themes/index.js"
|
|
77
|
+
},
|
|
78
|
+
"./components/results": {
|
|
79
|
+
"types": "./dist/components/results/index.d.ts",
|
|
80
|
+
"import": "./dist/components/results/index.js"
|
|
81
|
+
},
|
|
82
|
+
"./components/questions/*": {
|
|
83
|
+
"types": "./dist/components/questions/*.d.ts",
|
|
84
|
+
"import": "./dist/components/questions/*.js"
|
|
85
|
+
},
|
|
86
|
+
"./shared": {
|
|
87
|
+
"types": "./dist/shared/index.d.ts",
|
|
88
|
+
"import": "./dist/shared/index.js"
|
|
89
|
+
},
|
|
90
|
+
"./*": {
|
|
91
|
+
"types": "./dist/components/questions/*.d.ts",
|
|
92
|
+
"import": "./dist/components/questions/*.js"
|
|
93
|
+
},
|
|
94
|
+
"./package.json": "./package.json"
|
|
95
|
+
},
|
|
96
|
+
"publishConfig": {
|
|
97
|
+
"access": "public"
|
|
98
|
+
},
|
|
99
|
+
"peerDependencies": {
|
|
100
|
+
"next": ">=15",
|
|
101
|
+
"react": ">=19",
|
|
102
|
+
"react-dom": ">=19"
|
|
103
|
+
},
|
|
104
|
+
"devDependencies": {
|
|
105
|
+
"@types/node": "^25.9.3",
|
|
106
|
+
"terser": "^5.48.0",
|
|
107
|
+
"tsc-alias": "^1.8.17",
|
|
108
|
+
"typescript": "~5.9.2"
|
|
109
|
+
},
|
|
110
|
+
"dependencies": {
|
|
111
|
+
"@dnd-kit/core": "^6.3.1",
|
|
112
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
113
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
114
|
+
"@fortawesome/free-solid-svg-icons": "^7.3.1",
|
|
115
|
+
"@fortawesome/react-fontawesome": "^3.3.1",
|
|
116
|
+
"@hookform/resolvers": "^5.2.2",
|
|
117
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
118
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
119
|
+
"@radix-ui/react-avatar": "^1.1.10",
|
|
120
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
121
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
122
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
123
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
124
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
125
|
+
"@radix-ui/react-label": "^2.1.7",
|
|
126
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
127
|
+
"@radix-ui/react-progress": "^1.1.7",
|
|
128
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
129
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
130
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
131
|
+
"@radix-ui/react-separator": "^1.1.7",
|
|
132
|
+
"@radix-ui/react-slot": "^1.2.3",
|
|
133
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
134
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
135
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
136
|
+
"@tanstack/react-query": "^5.90.2",
|
|
137
|
+
"@tiptap/extension-table": "^3.22.3",
|
|
138
|
+
"@tiptap/extension-table-cell": "^3.22.3",
|
|
139
|
+
"@tiptap/extension-table-header": "^3.22.3",
|
|
140
|
+
"@tiptap/extension-table-row": "^3.22.3",
|
|
141
|
+
"@tiptap/extension-text-align": "^3.22.3",
|
|
142
|
+
"@tiptap/extension-underline": "^3.22.3",
|
|
143
|
+
"@tiptap/pm": "^3.22.3",
|
|
144
|
+
"@tiptap/react": "^3.22.3",
|
|
145
|
+
"@tiptap/starter-kit": "^3.22.3",
|
|
146
|
+
"@types/qrcode": "^1.5.6",
|
|
147
|
+
"@xyflow/react": "^12.8.6",
|
|
148
|
+
"axios": "^1.12.2",
|
|
149
|
+
"class-variance-authority": "^0.7.1",
|
|
150
|
+
"clsx": "^2.1.1",
|
|
151
|
+
"cmdk": "^1.1.1",
|
|
152
|
+
"date-fns": "^4.1.0",
|
|
153
|
+
"embla-carousel-react": "^8.6.0",
|
|
154
|
+
"howler": "^2.2.4",
|
|
155
|
+
"lucide-react": "^0.544.0",
|
|
156
|
+
"qrcode": "^1.5.4",
|
|
157
|
+
"radix-ui": "^1.4.3",
|
|
158
|
+
"react-day-picker": "^9.14.0",
|
|
159
|
+
"react-hook-form": "^7.65.0",
|
|
160
|
+
"sonner": "^2.0.7",
|
|
161
|
+
"tailwind-merge": "^3.3.1",
|
|
162
|
+
"vaul": "^1.1.2",
|
|
163
|
+
"zod": "^4.1.11",
|
|
164
|
+
"zustand": "^5.0.8"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { RefObject } from 'react';
|
|
2
|
-
import { type PreviewQuestion, type QuestionsByPart } from './exam-preview.types';
|
|
3
|
-
export interface ExamPreviewPartContentProps {
|
|
4
|
-
loading: boolean;
|
|
5
|
-
error: string | null;
|
|
6
|
-
questions: PreviewQuestion[];
|
|
7
|
-
currentPart: QuestionsByPart | null;
|
|
8
|
-
currentPartQuestions: PreviewQuestion[];
|
|
9
|
-
currentPartIndex: number;
|
|
10
|
-
totalParts: number;
|
|
11
|
-
partDisplayName: string;
|
|
12
|
-
partTotalPoints: number;
|
|
13
|
-
contentRef: RefObject<HTMLDivElement | null>;
|
|
14
|
-
onRetry: () => void;
|
|
15
|
-
onPreviousPart: () => void;
|
|
16
|
-
onNextPart: () => void;
|
|
17
|
-
}
|
|
18
|
-
export declare function ExamPreviewPartContent({ loading, error, questions, currentPart, currentPartQuestions, currentPartIndex, totalParts, partDisplayName, partTotalPoints, contentRef, onRetry, onPreviousPart, onNextPart, }: ExamPreviewPartContentProps): import("react").JSX.Element;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{ArrowLeft as r,ArrowRight as n,Loader2 as t}from"lucide-react";import{Badge as a}from"../../components/ui/badge";import{Button as s}from"../../components/ui/button";import{QuestionViewer as l}from"../questions/viewer/QuestionViewer";import{useT as d}from"../../shared/lib/i18n";import{difficultyBadgeClass as m,getQuestionDifficulty as c,getQuestionNumber as o,getQuestionPoints as p}from"./exam-preview.types";export function ExamPreviewPartContent({loading:x,error:u,questions:h,currentPart:v,currentPartQuestions:b,currentPartIndex:f,totalParts:N,partDisplayName:g,partTotalPoints:w,contentRef:y,onRetry:P,onPreviousPart:j,onNextPart:q}){const S=d();return e("div",{className:"flex-1 overflow-y-auto",children:i("div",{className:"flex h-full flex-col",children:[i("div",{className:"flex items-center justify-between border-b pb-4",children:[i("div",{children:[e("h3",{className:"text-lg font-semibold",children:x?e("span",{className:"text-gray-400",children:S("admin.exams.preview.loading")}):N>0?S("admin.exams.preview.partIndex",{index:String(f+1),total:String(N)}):S("admin.exams.preview.noQuestions")}),v&&i("div",{className:"mt-1 inline-flex items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-1.5",children:[e("span",{className:"text-sm font-semibold text-blue-700",children:g}),e("span",{className:"text-xs text-blue-600",children:S("admin.exams.preview.questions",{count:String(b.length)})})]})]}),v&&e("div",{className:"flex items-center gap-2",children:e(a,{variant:"outline",children:S("admin.exams.preview.points",{count:String(w)})})})]}),e("div",{ref:y,className:"flex-1 overflow-y-auto py-4",children:x?i("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:[e(t,{className:"h-8 w-8 animate-spin text-blue-500"}),e("p",{className:"text-gray-600",children:S("admin.exams.preview.loadingQuestions")})]}):u?e("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:i("div",{className:"rounded-lg border border-red-200 bg-red-50 p-6 text-center",children:[e("p",{className:"font-medium text-red-800",children:u}),e(s,{variant:"outline",onClick:P,className:"mt-4",children:S("admin.exams.preview.retry")})]})}):0===h.length?e("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:e("div",{className:"rounded-lg border border-yellow-200 bg-yellow-50 p-6 text-center",children:e("p",{className:"font-medium text-yellow-800",children:S("admin.exams.preview.examNoQuestions")})})}):b.length>0?e("div",{className:"space-y-6",children:b.map(r=>{const n=o(r),t=c(r);return i("div",{id:`preview-q-${r.id}`,className:"rounded-xl border border-gray-200 bg-white p-4 shadow-sm",children:[i("div",{className:"mb-3 flex items-center justify-between gap-2 border-b border-gray-100 pb-3",children:[e("span",{className:"inline-flex h-7 min-w-7 items-center justify-center rounded-md bg-blue-100 px-2 text-xs font-bold text-blue-700",children:S("admin.exams.preview.questionLabel",{number:String(n)})}),i("div",{className:"flex items-center gap-2",children:[e(a,{variant:"outline",children:S("admin.exams.preview.points",{count:String(p(r))})}),e(a,{className:m(t),children:t})]})]}),e(l,{question:r,isReviewMode:!0})]},r.id)})}):null}),!x&&N>0&&i("div",{className:"mt-auto flex items-center justify-between border-t border-gray-200 bg-gray-50 px-4 py-3",children:[i(s,{variant:"outline",onClick:j,disabled:0===f,className:"flex h-9 items-center gap-2 px-3 text-sm",children:[e(r,{className:"h-4 w-4"}),e("span",{className:"hidden sm:inline",children:S("admin.exams.preview.prevPart")}),e("span",{className:"sm:hidden",children:S("admin.exams.preview.prev")})]}),i("div",{className:"text-sm text-gray-600",children:[f+1," / ",N]}),i(s,{variant:"outline",onClick:q,disabled:f===N-1,className:"flex h-9 items-center gap-2 px-3 text-sm",children:[e("span",{className:"hidden sm:inline",children:S("admin.exams.preview.nextPart")}),e("span",{className:"sm:hidden",children:S("admin.exams.preview.next")}),e(n,{className:"h-4 w-4"})]})]})]})})}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type PreviewQuestion, type QuestionsByPart } from './exam-preview.types';
|
|
2
|
-
export interface ExamPreviewSidebarProps {
|
|
3
|
-
examName: string;
|
|
4
|
-
duration: number;
|
|
5
|
-
totalPoints: number;
|
|
6
|
-
questions: PreviewQuestion[];
|
|
7
|
-
questionsByPart: QuestionsByPart[];
|
|
8
|
-
currentPart: QuestionsByPart | null;
|
|
9
|
-
currentPartIndex: number;
|
|
10
|
-
totalParts: number;
|
|
11
|
-
progress: number;
|
|
12
|
-
loading: boolean;
|
|
13
|
-
showPartsDetail: boolean;
|
|
14
|
-
onTogglePartsDetail: () => void;
|
|
15
|
-
onGoToPart: (index: number) => void;
|
|
16
|
-
}
|
|
17
|
-
export declare function ExamPreviewSidebar({ examName, duration, totalPoints, questions, questionsByPart, currentPart, currentPartIndex, totalParts, progress, loading, showPartsDetail, onTogglePartsDetail, onGoToPart, }: ExamPreviewSidebarProps): import("react").JSX.Element;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Badge as t}from"../../components/ui/badge";import{Button as s}from"../../components/ui/button";import{Card as i,CardContent as r,CardHeader as n,CardTitle as m}from"../../components/ui/card";import{Progress as l}from"../../components/ui/progress";import{Loader2 as d}from"lucide-react";import{useT as c}from"../../shared/lib/i18n";import{getQuestionNumber as o}from"./exam-preview.types";export function ExamPreviewSidebar({examName:p,duration:x,totalPoints:h,questions:u,questionsByPart:g,currentPart:v,currentPartIndex:N,totalParts:f,progress:b,loading:y,showPartsDetail:w,onTogglePartsDetail:j,onGoToPart:q}){const P=c();return e("div",{className:"w-full overflow-y-auto border-b border-gray-200 sm:w-80 sm:border-b-0 sm:border-r",children:a("div",{className:"space-y-4 p-4",children:[a(i,{children:[e(n,{className:"pb-3",children:e(m,{className:"text-base",children:P("admin.exams.preview.examInfo")})}),a(r,{className:"space-y-3",children:[a("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:P("admin.exams.preview.duration")}),e("span",{className:"text-sm font-medium",children:P("admin.exams.view.minutes",{count:String(x)})})]}),a("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:P("admin.exams.preview.questionCount")}),e("span",{className:"text-sm font-medium",children:y?"...":P("admin.exams.preview.questions",{count:String(u.length)})})]}),a("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:P("admin.exams.preview.totalPoints")}),e("span",{className:"text-sm font-medium",children:P("admin.exams.preview.points",{count:String(h)})})]})]})]}),!y&&f>0&&e(i,{children:e(r,{className:"p-4",children:a("div",{className:"space-y-2",children:[a("div",{className:"flex justify-between text-sm",children:[e("span",{children:P("admin.exams.preview.progress")}),a("span",{className:"font-medium",children:[N+1,"/",f]})]}),e(l,{value:b,className:"h-2"})]})})}),y?e("div",{className:"flex items-center justify-center py-4",children:a("div",{className:"flex items-center gap-2 text-gray-500",children:[e(d,{className:"h-4 w-4 animate-spin"}),e("span",{className:"text-sm",children:P("admin.exams.preview.loading")})]})}):f>0&&a("div",{className:"space-y-3",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:P("admin.exams.preview.questionNavigation")}),e("div",{className:"flex flex-wrap gap-2",children:g.map((e,t)=>a(s,{variant:t===N?"default":"outline",size:"sm",onClick:()=>q(t),className:"h-8 px-3 text-xs font-medium",children:["P",e.partNo]},e.partId||`part-${e.partNo}`))}),v&&e("div",{className:"rounded bg-gray-50 p-2 text-xs",children:e("span",{className:"font-medium",children:P("admin.exams.preview.partQuestions",{part:String(v.partNo),count:String(v.questions.length)})})}),v&&e("div",{className:"rounded-lg bg-gray-50 p-3",children:e("div",{className:"grid max-h-64 grid-cols-6 gap-2 overflow-y-auto pr-2",children:v.questions.map(a=>e(s,{variant:"ghost",size:"sm",onClick:()=>{const e=document.getElementById(`preview-q-${a.id}`);e?.scrollIntoView({behavior:"smooth",block:"start"})},className:"h-8 w-full border border-gray-300 bg-white p-0 text-xs font-medium transition-all duration-200 hover:bg-gray-100",children:o(a)},a.id))})})]}),!y&&u.length>0&&a("div",{children:[a("div",{className:"mb-2 flex items-center justify-between",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:p}),e(s,{variant:"ghost",size:"sm",onClick:j,className:"h-6 px-2 text-xs text-gray-600 hover:text-gray-900",children:P(w?"admin.exams.preview.collapse":"admin.exams.preview.detail")})]}),e("div",{className:"rounded-lg bg-gray-50 p-3",children:a("div",{className:"flex items-center justify-between",children:[a("div",{children:[a("span",{className:"text-sm font-medium text-gray-900",children:["Total:"," ",P("admin.exams.preview.questions",{count:String(u.length)})]}),e("div",{className:"mt-1 flex gap-3",children:a("span",{className:"text-xs text-gray-600",children:[g.length," part(s)"]})})]}),e("div",{className:"text-xs text-gray-500",children:P("admin.exams.view.minutes",{count:String(x)})})]})}),w&&e("div",{className:"mt-3 space-y-2",children:g.map((s,i)=>{const r=i===N;return e("div",{className:"cursor-pointer rounded-lg border-2 p-3 transition-all duration-200 "+(r?"border-blue-400 bg-blue-50 shadow-md":"border-gray-200 bg-white hover:border-gray-300"),onClick:()=>q(i),children:a("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm font-medium "+(r?"text-blue-900":"text-gray-900"),children:s.partName}),e(t,{variant:"secondary",className:"text-xs "+(r?"bg-blue-200 text-blue-800":"bg-gray-100 text-gray-700"),children:P("admin.exams.preview.questions",{count:String(s.questions.length)})})]})},s.partId||`part-detail-${s.partNo}`)})})]})]})})}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ExamPart, ExamQuestion } from '../../shared/types/entities/exam.types';
|
|
2
|
-
export type PreviewQuestion = Partial<ExamQuestion> & {
|
|
3
|
-
id?: string;
|
|
4
|
-
partId?: string;
|
|
5
|
-
questionNumber?: number;
|
|
6
|
-
points?: number | string;
|
|
7
|
-
difficulty?: string;
|
|
8
|
-
};
|
|
9
|
-
export interface QuestionsByPart {
|
|
10
|
-
partId: string;
|
|
11
|
-
partNo: number;
|
|
12
|
-
partName: string;
|
|
13
|
-
questions: PreviewQuestion[];
|
|
14
|
-
}
|
|
15
|
-
export interface OrderedPart {
|
|
16
|
-
id: string;
|
|
17
|
-
name?: string;
|
|
18
|
-
}
|
|
19
|
-
/** SDK fetch helpers return either `{ data: T }` or the bare value. */
|
|
20
|
-
export declare function unwrapApiData<T>(res: {
|
|
21
|
-
data: T;
|
|
22
|
-
} | T): T;
|
|
23
|
-
export declare function sumQuestionPoints(questions: PreviewQuestion[]): number;
|
|
24
|
-
export declare function getQuestionPoints(question: PreviewQuestion): number;
|
|
25
|
-
export declare function getQuestionNumber(question: PreviewQuestion): number;
|
|
26
|
-
export declare function getQuestionDifficulty(question: PreviewQuestion): string;
|
|
27
|
-
export declare function difficultyBadgeClass(difficulty?: string): string;
|
|
28
|
-
/**
|
|
29
|
-
* Build ordered parts from template first, then any extra part ids on questions.
|
|
30
|
-
*/
|
|
31
|
-
export declare function buildOrderedParts(templateParts: Array<ExamPart & {
|
|
32
|
-
title?: string;
|
|
33
|
-
}> | undefined, questions: PreviewQuestion[]): OrderedPart[];
|
|
34
|
-
export declare function groupQuestionsByPart(questions: PreviewQuestion[], orderedParts: OrderedPart[]): QuestionsByPart[];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function unwrapApiData(t){return t&&"object"==typeof t&&"data"in t?t.data:t}export function sumQuestionPoints(t){return t.reduce((t,e)=>t+(Number(e.points)||0),0)}export function getQuestionPoints(t){return Number(t.points)||1}export function getQuestionNumber(t){return t.questionNumber??0}export function getQuestionDifficulty(t){return t.difficulty??"N/A"}export function difficultyBadgeClass(t){switch(t?.toUpperCase()){case"EASY":return"bg-green-100 text-green-800";case"MEDIUM":return"bg-orange-100 text-orange-800";case"HARD":return"bg-red-100 text-red-800";default:return"bg-gray-100 text-gray-800"}}export function buildOrderedParts(t,e){const r=(t??[]).map(t=>({id:t.id,name:t.name||t.title})),n=new Set(r.map(t=>t.id));for(const t of e){const e=t.partId??"";e&&!n.has(e)&&(n.add(e),r.push({id:e}))}return r}export function groupQuestionsByPart(t,e){const r=new Map;for(const n of t){const t=n.partId??"";if(!r.has(t)){const n=e.findIndex(e=>e.id===t),o=n>=0?n+1:1;r.set(t,{partId:t,partNo:o,partName:e[n]?.name||`Part ${o}`,questions:[]})}r.get(t).questions.push(n)}return Array.from(r.values()).sort((t,e)=>t.partNo-e.partNo)}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse FILL_IN_BLANK stem text into display tokens.
|
|
3
|
-
*
|
|
4
|
-
* Contract (workbook / Pearson map):
|
|
5
|
-
* - Bold: lightweight markdown `**text**` (toggle, non-nested)
|
|
6
|
-
* - Blanks: `{0}`, `{1}`, … left-to-right
|
|
7
|
-
* - Multi-line: `\n`
|
|
8
|
-
*
|
|
9
|
-
* Blank may sit *inside* a bold span (e.g. `**1. {0}:**`). Older viewers
|
|
10
|
-
* split blanks first then bold, which left orphan `**` in the UI.
|
|
11
|
-
*/
|
|
12
|
-
export type FillBlankStemTextToken = {
|
|
13
|
-
kind: 'text';
|
|
14
|
-
text: string;
|
|
15
|
-
bold: boolean;
|
|
16
|
-
};
|
|
17
|
-
export type FillBlankStemBlankToken = {
|
|
18
|
-
kind: 'blank';
|
|
19
|
-
index: number;
|
|
20
|
-
/** True when blank is inside an open `**…**` span (label bold only; input stays normal weight). */
|
|
21
|
-
bold: boolean;
|
|
22
|
-
};
|
|
23
|
-
export type FillBlankStemToken = FillBlankStemTextToken | FillBlankStemBlankToken;
|
|
24
|
-
/**
|
|
25
|
-
* Tokenize one line. Unclosed bold at EOL → remaining text is plain and
|
|
26
|
-
* dangling `**` markers are dropped so they never show in the UI.
|
|
27
|
-
*/
|
|
28
|
-
export declare function parseFillBlankStemLine(line: string): FillBlankStemToken[];
|
|
29
|
-
/** Split stem on newlines and parse each line. */
|
|
30
|
-
export declare function parseFillBlankStem(stem: string): FillBlankStemToken[][];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function parseFillBlankStemLine(t){const e=[];let n=!1,l="",i=0;const o=()=>{l&&(e.push({kind:"text",text:l,bold:n}),l="")};for(;i<t.length;)if("*"!==t[i]||"*"!==t[i+1]){if("{"===t[i]){const l=/^\{(\d+)\}/.exec(t.slice(i));if(l){o(),e.push({kind:"blank",index:Number(l[1]),bold:n}),i+=l[0].length;continue}}l+=t[i],i+=1}else o(),n=!n,i+=2;return n&&l?(e.push({kind:"text",text:l,bold:!1}),l=""):o(),0===e.length?[{kind:"text",text:t,bold:!1}]:e}export function parseFillBlankStem(t){if(!t)return[[{kind:"text",text:"",bold:!1}]];return(t.includes("\n")?t.split("\n"):[t]).map(t=>parseFillBlankStemLine(t))}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t,Fragment as i}from"react/jsx-runtime";import{useEffect as a,useRef as n,useState as s}from"react";import{FileQuestion as l,Loader2 as o,Lock as d,Pencil as r,Save as c}from"lucide-react";import{Button as m}from"../../../components/ui/button";import{Dialog as h,DialogContent as p,DialogFooter as u,DialogHeader as x,DialogTitle as N}from"../../../components/ui/dialog";import{Input as g}from"../../../components/ui/input";import{Label as f}from"../../../components/ui/label";import{Select as b,SelectContent as v,SelectItem as y,SelectTrigger as w,SelectValue as I}from"../../../components/ui/select";import{getQuestionTypeLabel as k,SKILL_METADATA as q}from"../../../shared/constants/question-skills";import{t as E}from"../../../shared/lib/i18n";import{cn as G}from"../../../shared/lib/utils";import{SkillEnum as B}from"../../../shared/types/common.types";import{DIFFICULTY_LEVELS as j,DifficultyLevel as A,parseDifficultyLevel as S}from"./difficulty";import{QuestionEditorRenderer as T}from"./QuestionEditorRenderer";const R=[{value:B.READING,label:q[B.READING].name,emoji:q[B.READING].emoji},{value:B.WRITING,label:q[B.WRITING].name,emoji:q[B.WRITING].emoji},{value:B.LISTENING,label:q[B.LISTENING].name,emoji:q[B.LISTENING].emoji},{value:B.SPEAKING,label:q[B.SPEAKING].name,emoji:q[B.SPEAKING].emoji}];export function EditQuestionBankDialog({open:q,onOpenChange:C,question:P,onSave:D,saving:K}){const L=n(null),[W,F]=s(""),[O,Q]=s(""),[V,Y]=s(A.EASY),[z,H]=s(B.READING),[J,M]=s({}),[U,X]=s({});a(()=>{var e;P&&(F(P.code||""),Q(P.title||""),Y(S(String(P.difficulty||""))),H((e=P.skill?String(P.skill):null)===B.WRITING?B.WRITING:e===B.LISTENING?B.LISTENING:e===B.SPEAKING?B.SPEAKING:B.READING),M({content:P.content,answer:P.correctAnswer,explanation:P.explanation||"",points:Number(P.points)}),X({}))},[P]);const Z=R.find(e=>e.value===z);return e(h,{open:q,onOpenChange:C,children:t(p,{className:"max-w-4xl max-h-[90vh] flex flex-col p-0",children:[e(x,{className:"px-6 py-4 border-b bg-slate-50",children:t(N,{className:"flex items-center gap-3 text-lg",children:[e("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-amber-100",children:e(r,{className:"h-5 w-5 text-amber-600"})}),t("div",{children:[e("span",{className:"font-semibold",children:E("admin.questionBank.dialog.edit.title")}),P&&t("span",{className:"ml-2 text-sm font-normal text-slate-500",children:["• ",P.code]})]})]})}),e("div",{className:"flex-1 overflow-y-auto px-6 py-5",children:P&&t("div",{className:"space-y-6",children:[t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"1"}),E("admin.questionBank.dialog.edit.section1")]}),t("div",{className:"grid grid-cols-2 gap-4",children:[t("div",{className:"space-y-1.5",children:[t(f,{htmlFor:"edit-code",className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.code")," ",e("span",{className:"text-rose-500",children:"*"})]}),e(g,{id:"edit-code",value:W,onChange:e=>{F(e.target.value),U.code&&X(e=>({...e,code:void 0}))},placeholder:E("admin.questionBank.dialog.edit.codePlaceholder"),className:G("h-10",U.code&&"border-rose-500 focus-visible:ring-rose-500")}),U.code&&e("p",{className:"text-xs text-rose-500",children:U.code})]}),t("div",{className:"space-y-1.5",children:[t(f,{htmlFor:"edit-title",className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.titleLabel")," ",e("span",{className:"text-rose-500",children:"*"})]}),e(g,{id:"edit-title",value:O,onChange:e=>{Q(e.target.value),U.title&&X(e=>({...e,title:void 0}))},placeholder:E("admin.questionBank.dialog.edit.titlePlaceholder"),className:G("h-10",U.title&&"border-rose-500 focus-visible:ring-rose-500")}),U.title&&e("p",{className:"text-xs text-rose-500",children:U.title})]})]}),t("div",{className:"grid grid-cols-2 gap-4",children:[t("div",{className:"space-y-1.5",children:[t(f,{className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.difficulty")," ",e("span",{className:"text-rose-500",children:"*"})]}),t(b,{value:V,onValueChange:e=>Y(S(e)),children:[e(w,{className:"h-10 bg-white w-full",children:e(I,{})}),e(v,{children:j.map(i=>e(y,{value:i.value,children:t("div",{className:"flex items-center gap-2",children:[i.icon,e("span",{children:E(i.labelKey)})]})},i.value))})]})]}),t("div",{className:"space-y-1.5",children:[t(f,{className:"text-sm text-slate-600 flex items-center gap-1",children:[E("admin.questionBank.dialog.edit.skill"),e(d,{className:"h-3 w-3 text-slate-400"})]}),t("div",{className:"flex items-center gap-2 px-4 py-2 bg-slate-100 rounded-lg border border-slate-200 h-10",children:[e("span",{children:Z?.emoji}),e("span",{className:"text-sm text-slate-600 font-medium",children:Z?.label||z}),e("span",{className:"text-xs text-slate-400 ml-auto",children:E("admin.questionBank.dialog.edit.unchangeable")})]})]})]})]}),t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"2"}),E("admin.questionBank.dialog.edit.section2"),e(d,{className:"h-3.5 w-3.5 text-slate-400"})]}),e("div",{className:"w-1/2",children:t("div",{className:"flex items-center gap-2 px-4 py-2.5 bg-slate-100 rounded-lg border border-slate-200 h-10",children:[e(l,{className:"h-4 w-4 text-slate-500"}),e("span",{className:"text-sm text-slate-600 font-medium",children:k(P.questionType)}),e("span",{className:"text-xs text-slate-400 ml-auto",children:E("admin.questionBank.dialog.edit.unchangeable")})]})})]}),t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"3"}),E("admin.questionBank.dialog.edit.section3")]}),e("div",{className:"border rounded-lg p-4 bg-white",children:e(T,{questionType:P.questionType,content:P.content,correctAnswer:P.correctAnswer,explanation:P.explanation,points:Number(P.points),onChange:e=>{M({content:e.content,answer:e.answer,explanation:e.explanation,points:e.points})},validationRef:L})})]})]})}),e(u,{className:"px-6 py-4 border-t bg-slate-50",children:t("div",{className:"flex items-center justify-between w-full",children:[t("p",{className:"text-xs text-slate-500",children:[e("span",{className:"text-rose-500",children:"*"})," ",E("admin.questionBank.dialog.edit.required")]}),t("div",{className:"flex gap-2",children:[e(m,{type:"button",variant:"outline",onClick:()=>C(!1),disabled:K,children:E("admin.questionBank.dialog.edit.cancel")}),e(m,{type:"button",onClick:async()=>{const e={};if(W.trim()||(e.code=E("admin.questionBank.dialog.edit.codeError")),O.trim()||(e.title=E("admin.questionBank.dialog.edit.titleError")),Object.keys(e).length>0)return void X(e);if(L.current){if(!await L.current.triggerValidation())return}const t={code:W.trim(),title:O.trim(),difficulty:V,skill:z,content:J.content,correctAnswer:J.answer??void 0,explanation:J.explanation,points:J.points};D(t)},disabled:K,className:"bg-indigo-600 hover:bg-indigo-700",children:t(i,K?{children:[e(o,{className:"mr-2 h-4 w-4 animate-spin"}),E("admin.questionBank.dialog.edit.saving")]}:{children:[e(c,{className:"mr-2 h-4 w-4"}),E("admin.questionBank.dialog.edit.save")]})})]})]})})]})})}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from 'react';
|
|
2
|
-
import type { QuestionEditorRendererProps } from './types';
|
|
3
|
-
/** Marketing question types supported by the question-bank editor. */
|
|
4
|
-
export declare enum QuestionBankEditorType {
|
|
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
|
-
FILL_MISSING_WORDS_IN_GRID = "FILL_MISSING_WORDS_IN_GRID",
|
|
9
|
-
LABEL_THE_PICTURE = "LABEL_THE_PICTURE",
|
|
10
|
-
LOOK_PICTURE_FILL_WORD_HINT = "LOOK_PICTURE_FILL_WORD_HINT",
|
|
11
|
-
READ_AND_COLOR_OBJECTS = "READ_AND_COLOR_OBJECTS",
|
|
12
|
-
IMAGE_OBJECT_MATCHING = "IMAGE_OBJECT_MATCHING",
|
|
13
|
-
READ_PASSAGE_AND_ANSWER_QUESTIONS = "READ_PASSAGE_AND_ANSWER_QUESTIONS",
|
|
14
|
-
WRITE_A_SHORT_LETTER = "WRITE_A_SHORT_LETTER",
|
|
15
|
-
WRITE_CORRECT_VERB_FORM = "WRITE_CORRECT_VERB_FORM",
|
|
16
|
-
FILL_IN_BLANK = "FILL_IN_BLANK",
|
|
17
|
-
CHOOSE_CORRECT_ADJECTIVE = "CHOOSE_CORRECT_ADJECTIVE"
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Renders the appropriate Creator for a question-bank item.
|
|
21
|
-
* Maps API content/correctAnswer into Creator initialData and back via onChange.
|
|
22
|
-
*/
|
|
23
|
-
export declare function QuestionEditorRenderer({ questionType, content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorRendererProps): ReactNode;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{jsx as _}from"react/jsx-runtime";import{useEffect as E,useRef as e,useState as t}from"react";import{t as n}from"../../../shared/lib/i18n";import{renderChooseCorrectAdjectiveEditor as R,renderChooseTheCorrectAnswerEditor as O,renderFillInBlankEditor as T,renderFillMissingWordsInGridEditor as r,renderImageObjectMatchingEditor as o,renderLabelThePictureEditor as i,renderLookPictureChooseCorrectAnswerEditor as C,renderLookPictureFillBlankChooseAnswerEditor as I,renderLookPictureFillWordHintEditor as a,renderReadAndColorObjectsEditor as A,renderReadPassageAndAnswerQuestionsEditor as L,renderWriteAShortLetterEditor as S,renderWriteCorrectVerbFormEditor as s,UnsupportedEditorFallback as N}from"./editor-adapters";export var QuestionBankEditorType;!function(_){_.CHOOSE_THE_CORRECT_ANSWER="CHOOSE_THE_CORRECT_ANSWER",_.LOOK_PICTURE_CHOOSE_CORRECT_ANSWER="LOOK_PICTURE_CHOOSE_CORRECT_ANSWER",_.LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER="LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER",_.FILL_MISSING_WORDS_IN_GRID="FILL_MISSING_WORDS_IN_GRID",_.LABEL_THE_PICTURE="LABEL_THE_PICTURE",_.LOOK_PICTURE_FILL_WORD_HINT="LOOK_PICTURE_FILL_WORD_HINT",_.READ_AND_COLOR_OBJECTS="READ_AND_COLOR_OBJECTS",_.IMAGE_OBJECT_MATCHING="IMAGE_OBJECT_MATCHING",_.READ_PASSAGE_AND_ANSWER_QUESTIONS="READ_PASSAGE_AND_ANSWER_QUESTIONS",_.WRITE_A_SHORT_LETTER="WRITE_A_SHORT_LETTER",_.WRITE_CORRECT_VERB_FORM="WRITE_CORRECT_VERB_FORM",_.FILL_IN_BLANK="FILL_IN_BLANK",_.CHOOSE_CORRECT_ADJECTIVE="CHOOSE_CORRECT_ADJECTIVE"}(QuestionBankEditorType||(QuestionBankEditorType={}));export function QuestionEditorRenderer({questionType:u,content:B,correctAnswer:c,explanation:p,points:d,onChange:H,validationRef:D}){const W=e(null),[y,Q]=t(!1);E(()=>{Q(!0)},[]);const k=D||W;if(!y)return _("div",{className:"text-center py-8 text-gray-500",children:n("admin.questionBank.dialog.edit.loading")});const F={content:B,correctAnswer:c,explanation:p,points:d,onChange:H,validationRef:k};switch(u){case QuestionBankEditorType.CHOOSE_THE_CORRECT_ANSWER:return O(F);case QuestionBankEditorType.LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:return C(F);case QuestionBankEditorType.LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:return I(F);case QuestionBankEditorType.FILL_MISSING_WORDS_IN_GRID:return r(F);case QuestionBankEditorType.LABEL_THE_PICTURE:return i(F);case QuestionBankEditorType.LOOK_PICTURE_FILL_WORD_HINT:return a(F);case QuestionBankEditorType.READ_AND_COLOR_OBJECTS:return A(F);case QuestionBankEditorType.IMAGE_OBJECT_MATCHING:return o(F);case QuestionBankEditorType.READ_PASSAGE_AND_ANSWER_QUESTIONS:return L(F);case QuestionBankEditorType.WRITE_A_SHORT_LETTER:return S(F);case QuestionBankEditorType.WRITE_CORRECT_VERB_FORM:return s(F);case QuestionBankEditorType.FILL_IN_BLANK:return T(F);case QuestionBankEditorType.CHOOSE_CORRECT_ADJECTIVE:return R(F);default:return _(N,{questionType:u,content:B,correctAnswer:c,explanation:p})}}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import type { MessageKey } from '../../../shared/lib/i18n';
|
|
3
|
-
/** Question-bank difficulty values (API wire format). */
|
|
4
|
-
export declare enum DifficultyLevel {
|
|
5
|
-
EASY = "easy",
|
|
6
|
-
MEDIUM = "medium",
|
|
7
|
-
HARD = "hard"
|
|
8
|
-
}
|
|
9
|
-
export interface DifficultyLevelOption {
|
|
10
|
-
value: DifficultyLevel;
|
|
11
|
-
labelKey: MessageKey;
|
|
12
|
-
icon: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
export declare const DIFFICULTY_LEVELS: DifficultyLevelOption[];
|
|
15
|
-
export declare function parseDifficultyLevel(value: string | null | undefined): DifficultyLevel;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Sparkles as e,Target as i,Zap as l}from"lucide-react";import{createElement as f}from"react";export var DifficultyLevel;!function(e){e.EASY="easy",e.MEDIUM="medium",e.HARD="hard"}(DifficultyLevel||(DifficultyLevel={}));export const DIFFICULTY_LEVELS=[{value:DifficultyLevel.EASY,labelKey:"admin.questionBank.difficulty.easy",icon:f(l,{className:"h-3.5 w-3.5"})},{value:DifficultyLevel.MEDIUM,labelKey:"admin.questionBank.difficulty.medium",icon:f(i,{className:"h-3.5 w-3.5"})},{value:DifficultyLevel.HARD,labelKey:"admin.questionBank.difficulty.hard",icon:f(e,{className:"h-3.5 w-3.5"})}];export function parseDifficultyLevel(e){return e===DifficultyLevel.MEDIUM?DifficultyLevel.MEDIUM:e===DifficultyLevel.HARD?DifficultyLevel.HARD:DifficultyLevel.EASY}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { QuestionEditorAdapterProps } from './types';
|
|
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
|
-
export declare function renderChooseCorrectAdjectiveEditor({ content, correctAnswer, explanation, points, onChange, }: QuestionEditorAdapterProps): import("react").JSX.Element;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{jsx as e}from"react/jsx-runtime";import{ChooseTheCorrectAnswerCreator as n}from"../../types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator";import{normalizeChooseAnswerCorrectAnswer as o,normalizeChooseAnswerOptions as t,pickRawChooseAnswer as r}from"../../types/choose-the-correct-answer/normalize";import{LookPictureChooseCorrectAnswer as i}from"../../types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator";import{LookPictureFillBlankChooseAnswer as s}from"../../types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator";import{ChooseCorrectAdjectiveCreator as a}from"../../types/choose-correct-adjective/ChooseCorrectAdjectiveCreator";export function renderChooseTheCorrectAnswerEditor({content:i,correctAnswer:s,explanation:a,points:c,onChange:p,validationRef:l}){const w=i.options,m={question:i.question||"",options:t(w,4),correctAnswer:o(r(s),w),multipleAnswers:Boolean(i.multipleAnswers??s?.multipleAnswers),imageUrl:i.imageUrl||"",audioUrl:i.audioUrl||"",askerName:i.askerName||"",answererName:i.answererName||"",explanation:a||"",points:c||1};return e(n,{initialData:m,validationRef:l,onChange:e=>{p?.({content:{question:e?.question,options:e?.options,imageUrl:e?.imageUrl,audioUrl:e?.audioUrl,askerName:e?.askerName,answererName:e?.answererName,...e?.multipleAnswers?{multipleAnswers:!0}:{}},answer:{answer:e?.correctAnswer,...e?.multipleAnswers?{multipleAnswers:!0}:{}},explanation:e?.explanation,points:e?.points})}})}export function renderLookPictureChooseCorrectAnswerEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:s,validationRef:a}){const c={imageUrl:n.imageUrl||"",options:n.options||["",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(i,{initialData:c,validationRef:a,onChange:e=>{s?.({content:{imageUrl:e?.imageUrl,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}export function renderLookPictureFillBlankChooseAnswerEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:i,validationRef:a}){const c={imageUrl:n.imageUrl||"",question:n.question||"",options:n.options||["","","",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(s,{initialData:c,validationRef:a,onChange:e=>{i?.({content:{imageUrl:e?.imageUrl,question:e?.question,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}export function renderChooseCorrectAdjectiveEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:i}){const s={sentence:n.sentence||"",options:n.options||["","",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(a,{initialData:s,onChange:e=>{i?.({content:{sentence:e?.sentence,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { renderChooseTheCorrectAnswerEditor, renderLookPictureChooseCorrectAnswerEditor, renderLookPictureFillBlankChooseAnswerEditor, renderChooseCorrectAdjectiveEditor, } from './choice-adapters';
|
|
2
|
-
export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor, renderLookPictureFillWordHintEditor, renderReadAndColorObjectsEditor, renderImageObjectMatchingEditor, } from './media-adapters';
|
|
3
|
-
export { renderReadPassageAndAnswerQuestionsEditor, renderWriteAShortLetterEditor, renderWriteCorrectVerbFormEditor, renderFillInBlankEditor, } from './writing-adapters';
|
|
4
|
-
export { UnsupportedEditorFallback } from './unsupported-fallback';
|
|
5
|
-
export type { QuestionEditorAdapterProps, QuestionEditorChangeData } from './types';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export{renderChooseTheCorrectAnswerEditor,renderLookPictureChooseCorrectAnswerEditor,renderLookPictureFillBlankChooseAnswerEditor,renderChooseCorrectAdjectiveEditor}from"./choice-adapters";export{renderFillMissingWordsInGridEditor,renderLabelThePictureEditor,renderLookPictureFillWordHintEditor,renderReadAndColorObjectsEditor,renderImageObjectMatchingEditor}from"./media-adapters";export{renderReadPassageAndAnswerQuestionsEditor,renderWriteAShortLetterEditor,renderWriteCorrectVerbFormEditor,renderFillInBlankEditor}from"./writing-adapters";export{UnsupportedEditorFallback}from"./unsupported-fallback";
|