@tinyweb_dev/oe-exam-sdk 0.1.24 → 0.1.27

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.
Files changed (133) hide show
  1. package/README.md +5 -4
  2. package/dist/components/exams/ExamPreviewDialog.d.ts +7 -6
  3. package/dist/components/exams/ExamPreviewDialog.js +1 -1
  4. package/dist/components/exams/index.d.ts +0 -1
  5. package/dist/components/exams/take/components/QuestionRenderer.js +1 -1
  6. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +1 -1
  7. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -1
  8. package/dist/components/exams/take/exam-taking.utils.d.ts +0 -13
  9. package/dist/components/exams/take/exam-taking.utils.js +1 -1
  10. package/dist/components/exams/take/utils/answer-transformers.js +1 -1
  11. package/dist/components/exams/take/utils/question-transformers.d.ts +7 -17
  12. package/dist/components/exams/take/utils/question-transformers.js +1 -1
  13. package/dist/components/questions/_shared/config/question-types.config.js +1 -1
  14. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.d.ts +36 -0
  15. package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +40 -0
  16. package/dist/components/questions/_shared/types/index.d.ts +1 -0
  17. package/dist/components/questions/_shared/types/index.js +1 -1
  18. package/dist/components/questions/_shared/types/true-false-group.type.d.ts +31 -0
  19. package/dist/components/questions/_shared/types/true-false-group.type.js +1 -0
  20. package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +29 -26
  21. package/dist/components/questions/creator/question-type-registry.js +1 -1
  22. package/dist/components/questions/index.d.ts +0 -1
  23. package/dist/components/questions/index.js +1 -1
  24. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +1 -1
  25. package/dist/components/questions/types/choose-the-correct-answer/transform.js +1 -1
  26. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.d.ts +2 -0
  27. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +1 -0
  28. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.d.ts +2 -0
  29. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +1 -0
  30. package/dist/components/questions/types/choose-the-correct-answer-group/index.d.ts +2 -0
  31. package/dist/components/questions/types/choose-the-correct-answer-group/index.js +1 -0
  32. package/dist/components/questions/types/choose-the-correct-answer-group/register.d.ts +2 -0
  33. package/dist/components/questions/types/choose-the-correct-answer-group/register.js +1 -0
  34. package/dist/components/questions/types/choose-the-correct-answer-group/transform.d.ts +2 -0
  35. package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +1 -0
  36. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.d.ts +2 -0
  37. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +1 -0
  38. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.d.ts +2 -0
  39. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +1 -0
  40. package/dist/components/questions/types/cross-out-word-group/index.d.ts +4 -0
  41. package/dist/components/questions/types/cross-out-word-group/index.js +1 -0
  42. package/dist/components/questions/types/cross-out-word-group/register.d.ts +2 -0
  43. package/dist/components/questions/types/cross-out-word-group/register.js +1 -0
  44. package/dist/components/questions/types/cross-out-word-group/transform.d.ts +2 -0
  45. package/dist/components/questions/types/cross-out-word-group/transform.js +1 -0
  46. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.d.ts +2 -0
  47. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -0
  48. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.d.ts +2 -0
  49. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +1 -0
  50. package/dist/components/questions/types/true-false-group/index.d.ts +4 -0
  51. package/dist/components/questions/types/true-false-group/index.js +1 -0
  52. package/dist/components/questions/types/true-false-group/register.d.ts +2 -0
  53. package/dist/components/questions/types/true-false-group/register.js +1 -0
  54. package/dist/components/questions/types/true-false-group/transform.d.ts +2 -0
  55. package/dist/components/questions/types/true-false-group/transform.js +1 -0
  56. package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.d.ts +14 -0
  57. package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.js +1 -0
  58. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.d.ts +1 -1
  59. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
  60. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.d.ts +1 -1
  61. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +1 -1
  62. package/dist/components/questions/types/word-fill-structured-form/register.js +1 -1
  63. package/dist/components/questions/types/word-fill-structured-form/transform.d.ts +5 -2
  64. package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -1
  65. package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.d.ts +24 -0
  66. package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.js +1 -0
  67. package/dist/components/questions/viewer/QuestionViewer.js +1 -1
  68. package/dist/components/results/renderers/review-question-body-dedicated.js +1 -1
  69. package/dist/components/results/review-data.js +1 -1
  70. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
  71. package/dist/index.d.ts +1 -2
  72. package/dist/index.js +1 -1
  73. package/dist/mcp/config.d.ts +12 -0
  74. package/dist/mcp/config.js +1 -0
  75. package/dist/mcp/http-client.d.ts +6 -0
  76. package/dist/mcp/http-client.js +1 -0
  77. package/dist/mcp/index.d.ts +6 -0
  78. package/dist/mcp/index.js +2 -0
  79. package/dist/mcp/tools/_helpers.d.ts +4 -0
  80. package/dist/mcp/tools/_helpers.js +1 -0
  81. package/dist/mcp/tools/exams.d.ts +2 -0
  82. package/dist/mcp/tools/exams.js +1 -0
  83. package/dist/mcp/tools/index.d.ts +2 -0
  84. package/dist/mcp/tools/index.js +1 -0
  85. package/dist/mcp/tools/results.d.ts +2 -0
  86. package/dist/mcp/tools/results.js +1 -0
  87. package/dist/shared/constants/question-skills.js +1 -1
  88. package/dist/shared/lib/i18n/messages/en/admin.d.ts +4 -11
  89. package/dist/shared/lib/i18n/messages/en/admin.js +1 -1
  90. package/dist/shared/lib/i18n/messages/en.d.ts +4 -11
  91. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +4 -11
  92. package/dist/shared/lib/i18n/messages/vi/admin.js +1 -1
  93. package/dist/shared/lib/i18n/messages/vi.d.ts +4 -11
  94. package/dist/shared/lib/utils/question-reverse-transform.js +1 -1
  95. package/dist/shared/lib/utils/question-transform.js +1 -1
  96. package/dist/shared/types/common.types.d.ts +1 -1
  97. package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +41 -0
  98. package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -0
  99. package/dist/shared/types/questions/cross-out-word-group.d.ts +41 -0
  100. package/dist/shared/types/questions/cross-out-word-group.js +1 -0
  101. package/dist/shared/types/questions/index.d.ts +2 -0
  102. package/dist/shared/types/questions/index.js +1 -1
  103. package/package.json +165 -163
  104. package/dist/components/exams/ExamPreviewPartContent.d.ts +0 -18
  105. package/dist/components/exams/ExamPreviewPartContent.js +0 -1
  106. package/dist/components/exams/ExamPreviewSidebar.d.ts +0 -17
  107. package/dist/components/exams/ExamPreviewSidebar.js +0 -1
  108. package/dist/components/exams/exam-preview.types.d.ts +0 -34
  109. package/dist/components/exams/exam-preview.types.js +0 -1
  110. package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +0 -30
  111. package/dist/components/questions/_shared/utils/parseFillBlankStem.js +0 -1
  112. package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +0 -2
  113. package/dist/components/questions/question-bank/EditQuestionBankDialog.js +0 -1
  114. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -23
  115. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +0 -1
  116. package/dist/components/questions/question-bank/difficulty.d.ts +0 -15
  117. package/dist/components/questions/question-bank/difficulty.js +0 -1
  118. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -5
  119. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -1
  120. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +0 -5
  121. package/dist/components/questions/question-bank/editor-adapters/index.js +0 -1
  122. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -6
  123. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -1
  124. package/dist/components/questions/question-bank/editor-adapters/types.d.ts +0 -1
  125. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +0 -8
  126. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +0 -1
  127. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +0 -5
  128. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +0 -1
  129. package/dist/components/questions/question-bank/index.d.ts +0 -4
  130. package/dist/components/questions/question-bank/index.js +0 -1
  131. package/dist/components/questions/question-bank/types.d.ts +0 -59
  132. /package/dist/components/questions/{question-bank/editor-adapters/types.js → _shared/types/choose-the-correct-answer-group.type.js} +0 -0
  133. /package/dist/components/questions/{question-bank/types.js → _shared/types/cross-out-word-group.type.js} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @tinyweb_dev/oe-exam-sdk
2
2
 
3
- SDK tái sử dụng cho hệ thống OE Exam: màn tạo đề, quản lý câu hỏi, làm bài, xem kết quả theme giao diện.
3
+ SDK tái sử dụng cho hệ thống OE Exam: màn tạo đề, quản lý câu hỏi, làm bài, xem kết quả, theme giao diện và MCP tools.
4
4
 
5
5
  ## Cài đặt
6
6
 
@@ -91,6 +91,7 @@ export function ResultReviewPage({ attemptId, token, router }) {
91
91
  @tinyweb_dev/oe-exam-sdk # export tổng hợp thường dùng
92
92
  @tinyweb_dev/oe-exam-sdk/api # API adapters, constants, types
93
93
  @tinyweb_dev/oe-exam-sdk/shared # shared constants/types/helpers
94
+ @tinyweb_dev/oe-exam-sdk/mcp # MCP server entry và tools
94
95
  @tinyweb_dev/oe-exam-sdk/components # shared UI components
95
96
  @tinyweb_dev/oe-exam-sdk/components/exams # màn tạo đề / câu hỏi / làm bài / vào phòng
96
97
  @tinyweb_dev/oe-exam-sdk/components/exams/entry # màn vào phòng (entry) + state machine
@@ -237,16 +238,16 @@ Các report shell, renderer, transform helper, polling/status helper và result-
237
238
 
238
239
  ## MCP server
239
240
 
240
- MCP đã tách sang package riêng:
241
+ SDK expose bin:
241
242
 
242
243
  ```bash
243
- npm install @tinyweb_dev/oe-exam-mcp-server
244
+ oe-exam-mcp
244
245
  ```
245
246
 
246
247
  Chạy bằng PAT/API token. Nếu token có dạng `oeexam_...`, MCP tự gửi qua `X-API-Key`; token khác sẽ gửi qua `Authorization: Bearer`.
247
248
 
248
249
  ```bash
249
- OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx @tinyweb_dev/oe-exam-mcp-server
250
+ OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx oe-exam-mcp
250
251
  ```
251
252
 
252
253
  Tools hiện có:
@@ -10,10 +10,11 @@ export interface ExamPreviewDialogProps {
10
10
  title?: string;
11
11
  }
12
12
  /**
13
- * Read-only popup that previews an exam by id.
14
- *
15
- * UI mirrors the host app: one Part per screen (all questions of that part),
16
- * Next/Prev navigates between parts. No attempt is created data comes from
17
- * {@link ExamQuestionsSdkApi}. Questions render via QuestionViewer in review mode.
13
+ * Read-only popup that previews an exam (đề) by id: the layout mirrors the
14
+ * exam taking experience (left sidebar with exam info + progress + question
15
+ * navigation, right pane showing one question at a time) but creates NO attempt
16
+ * exam + questions are fetched through {@link ExamQuestionsSdkApi}, so it
17
+ * matches exactly how the đề looks. Each question renders via {@link QuestionViewer}
18
+ * in review mode (correct answers highlighted).
18
19
  */
19
- export declare function ExamPreviewDialog({ open, onOpenChange, examId, api, title, }: ExamPreviewDialogProps): import("react").JSX.Element;
20
+ export declare function ExamPreviewDialog({ open, onOpenChange, examId, api, title }: ExamPreviewDialogProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useEffect as r,useMemo as a,useRef as n,useState as o}from"react";import{Eye as i}from"lucide-react";import{Button as l}from"../../components/ui/button";import{Dialog as s,DialogContent as m,DialogHeader as c,DialogTitle as u}from"../../components/ui/dialog";import{useT as p}from"../../shared/lib/i18n";import{ExamPreviewPartContent as d}from"./ExamPreviewPartContent";import{ExamPreviewSidebar as x}from"./ExamPreviewSidebar";import{buildOrderedParts as h,getQuestionNumber as f,getQuestionPoints as g,groupQuestionsByPart as P,sumQuestionPoints as v,unwrapApiData as w}from"./exam-preview.types";export function ExamPreviewDialog({open:N,onOpenChange:y,examId:b,api:E,title:T}){const j=p(),[q,C]=o(null),[D,I]=o([]),[Q,O]=o(0),[R,k]=o(!1),[B,G]=o(!1),[S,z]=o(null),[A,F]=o(0),H=n(null);r(()=>{if(!N||!b)return;let e=!1;return G(!0),z(null),O(0),(async()=>{try{const t=w(await E.getExam(b)),r=E.getQuestions?w(await E.getQuestions(b)):[];if(e)return;const a=[...r].sort((e,t)=>f(e)-f(t));C(t),I(a)}catch{e||z(j("admin.exams.preview.loadError"))}finally{e||G(!1)}})(),()=>{e=!0}},[N,b,A,E,j]),r(()=>{N||(C(null),I([]),O(0),k(!1),z(null))},[N]);const J=a(()=>h(q?.template?.parts??[],D),[q,D]),K=a(()=>P(D,J),[D,J]);r(()=>{0!==K.length?Q>K.length-1&&O(K.length-1):0!==Q&&O(0)},[Q,K.length]);const L=q?.name??T??"",M=q?.template?.totalTime??q?.duration??0,U=v(D),V=K[Q]??null,W=V?.questions??[],X=K.length,Y=X>0?(Q+1)/X*100:0,Z=V?.partName??"",$=W.reduce((e,t)=>e+g(t),0),_=()=>{H.current?.scrollTo({top:0,behavior:"smooth"})};return e(s,{open:N,onOpenChange:y,children:t(m,{className:"max-h-[95vh] max-w-7xl overflow-y-auto",children:[e(c,{children:t(u,{className:"flex items-center gap-2",children:[e(i,{className:"h-5 w-5 text-blue-600"}),j("admin.exams.preview.title",{name:L})]})}),t("div",{className:"flex h-[80vh] flex-col gap-4 sm:flex-row",children:[e(x,{examName:L,duration:M,totalPoints:U,questions:D,questionsByPart:K,currentPart:V,currentPartIndex:Q,totalParts:X,progress:Y,loading:B,showPartsDetail:R,onTogglePartsDetail:()=>k(e=>!e),onGoToPart:e=>{e<0||e>=X||(O(e),_())}}),e(d,{loading:B,error:S,questions:D,currentPart:V,currentPartQuestions:W,currentPartIndex:Q,totalParts:X,partDisplayName:Z,partTotalPoints:$,contentRef:H,onRetry:()=>F(e=>e+1),onPreviousPart:()=>{Q>0&&(O(Q-1),_())},onNextPart:()=>{Q<X-1&&(O(Q+1),_())}})]}),e("div",{className:"border-t pt-4",children:t("div",{className:"flex items-center justify-between",children:[e("div",{className:"text-sm text-gray-600",children:j("admin.exams.preview.footerNote")}),e(l,{variant:"outline",onClick:()=>y(!1),className:"border-gray-300",children:j("admin.exams.preview.close")})]})})]})})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useEffect as a,useMemo as n,useRef as i,useState as s}from"react";import{ArrowLeft as r,ArrowRight as l,Eye as d,Loader2 as m}from"lucide-react";import{Badge as c}from"../../components/ui/badge";import{Button as o}from"../../components/ui/button";import{Card as p,CardContent as x,CardHeader as u,CardTitle as h}from"../../components/ui/card";import{Dialog as g,DialogContent as f,DialogHeader as N,DialogTitle as v}from"../../components/ui/dialog";import{Progress as b}from"../../components/ui/progress";import{useT as y}from"../../shared/lib/i18n";import{QuestionViewer as w}from"../questions/viewer/QuestionViewer";function j(e){return e&&"object"==typeof e&&"data"in e?e.data:e}function I(e){switch(e?.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 ExamPreviewDialog({open:q,onOpenChange:S,examId:C,api:Q,title:k}){const E=y(),[P,z]=s(null),[A,M]=s([]),[$,D]=s(0),[T,O]=s("all"),[R,U]=s(!1),[H,V]=s(!1),[Y,B]=s(null),[F,G]=s(0),J=i(null);a(()=>{if(!q||!C)return;let e=!1;return V(!0),B(null),D(0),O("all"),(async()=>{try{const t=j(await Q.getExam(C)),a=Q.getQuestions?j(await Q.getQuestions(C)):[];if(e)return;const n=[...a].sort((e,t)=>(e.questionNumber??0)-(t.questionNumber??0));z(t),M(n)}catch{e||B(E("admin.exams.preview.loadError"))}finally{e||V(!1)}})(),()=>{e=!0}},[q,C,F,Q,E]),a(()=>{q||(z(null),M([]),D(0),O("all"),U(!1),B(null))},[q]);const K=n(()=>{const e=(P?.template?.parts??[]).map(e=>({id:e.id,name:e.name||e.title})),t=new Set(e.map(e=>e.id));for(const a of A){const n=a.partId??"";n&&!t.has(n)&&(t.add(n),e.push({id:n}))}return e},[P,A]),L=e=>{const t=K.findIndex(t=>t.id===(e??""));return t>=0?t+1:1},W=n(()=>{const e=new Map;for(const t of A){const a=t.partId??"";if(!e.has(a)){const t=K.findIndex(e=>e.id===a),n=t>=0?t+1:1;e.set(a,{partId:a,partNo:n,partName:K[t]?.name||`Part ${n}`,questions:[]})}e.get(a).questions.push(t)}return Array.from(e.values()).sort((e,t)=>e.partNo-t.partNo)},[A,K]),X=P?.name??k??"",Z=P?.template?.totalTime??P?.duration??0,_=function(e){return e.reduce((e,t)=>e+(Number(t.points)||0),0)}(A),ee=A[$],te=A.length>0?($+1)/A.length*100:0,ae=e=>{D(e),J.current?.scrollTo({top:0,behavior:"smooth"})},ne="all"===T?A:A.filter(e=>L(e.partId)===T);return e(g,{open:q,onOpenChange:S,children:t(f,{className:"max-h-[95vh] max-w-7xl overflow-y-auto",children:[e(N,{children:t(v,{className:"flex items-center gap-2",children:[e(d,{className:"h-5 w-5 text-blue-600"}),E("admin.exams.preview.title",{name:X})]})}),t("div",{className:"flex h-[80vh] flex-col gap-4 sm:flex-row",children:[e("div",{className:"w-full overflow-y-auto border-b border-gray-200 sm:w-80 sm:border-b-0 sm:border-r",children:t("div",{className:"space-y-4 p-4",children:[t(p,{children:[e(u,{className:"pb-3",children:e(h,{className:"text-base",children:E("admin.exams.preview.examInfo")})}),t(x,{className:"space-y-3",children:[t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.duration")}),e("span",{className:"text-sm font-medium",children:E("admin.exams.view.minutes",{count:String(Z)})})]}),t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.questionCount")}),e("span",{className:"text-sm font-medium",children:H?"...":E("admin.exams.preview.questions",{count:String(A.length)})})]}),t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.totalPoints")}),e("span",{className:"text-sm font-medium",children:E("admin.exams.preview.points",{count:String(_)})})]})]})]}),!H&&A.length>0&&e(p,{children:e(x,{className:"p-4",children:t("div",{className:"space-y-2",children:[t("div",{className:"flex justify-between text-sm",children:[e("span",{children:E("admin.exams.preview.progress")}),t("span",{className:"font-medium",children:[$+1,"/",A.length]})]}),e(b,{value:te,className:"h-2"})]})})}),H?e("div",{className:"flex items-center justify-center py-4",children:t("div",{className:"flex items-center gap-2 text-gray-500",children:[e(m,{className:"h-4 w-4 animate-spin"}),e("span",{className:"text-sm",children:E("admin.exams.preview.loading")})]})}):A.length>0&&t("div",{className:"space-y-3",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:E("admin.exams.preview.questionNavigation")}),t("div",{className:"flex flex-wrap gap-2",children:[e(o,{variant:"all"===T?"default":"outline",size:"sm",onClick:()=>O("all"),className:"h-8 px-3 text-xs font-medium",children:E("admin.exams.preview.all")}),W.map(e=>t(o,{variant:T===e.partNo?"default":"outline",size:"sm",onClick:()=>{O(e.partNo);const t=e.questions[0];if(t){const e=A.findIndex(e=>e.id===t.id);-1!==e&&ae(e)}},className:"h-8 px-3 text-xs font-medium",children:["P",e.partNo]},e.partId||`part-${e.partNo}`))]}),e("div",{className:"rounded bg-gray-50 p-2 text-xs",children:e("span",{className:"font-medium",children:"all"===T?E("admin.exams.preview.allQuestions",{count:String(A.length)}):E("admin.exams.preview.partQuestions",{part:String(T),count:String(W.find(e=>e.partNo===T)?.questions.length??0)})})}),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:ne.map(t=>{const a=A.findIndex(e=>e.id===t.id);return e(o,{variant:"ghost",size:"sm",onClick:()=>ae(a),className:"h-8 w-full p-0 text-xs font-medium transition-all duration-200 "+(a===$?"border-2 border-blue-500 bg-blue-500 text-white hover:bg-blue-600":"border border-gray-300 bg-white hover:bg-gray-100"),children:t.questionNumber},t.id)})})})]}),!H&&A.length>0&&t("div",{children:[t("div",{className:"mb-2 flex items-center justify-between",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:X}),e(o,{variant:"ghost",size:"sm",onClick:()=>U(e=>!e),className:"h-6 px-2 text-xs text-gray-600 hover:text-gray-900",children:E(R?"admin.exams.preview.collapse":"admin.exams.preview.detail")})]}),e("div",{className:"rounded-lg bg-gray-50 p-3",children:t("div",{className:"flex items-center justify-between",children:[t("div",{children:[t("span",{className:"text-sm font-medium text-gray-900",children:["Total: ",E("admin.exams.preview.questions",{count:String(A.length)})]}),e("div",{className:"mt-1 flex gap-3",children:t("span",{className:"text-xs text-gray-600",children:[W.length," part(s)"]})})]}),e("div",{className:"text-xs text-gray-500",children:E("admin.exams.view.minutes",{count:String(Z)})})]})}),R&&e("div",{className:"mt-3 space-y-2",children:W.map(a=>{const n=L(ee?.partId)===a.partNo;return e("div",{className:"cursor-pointer rounded-lg border-2 p-3 transition-all duration-200 "+(n?"border-blue-400 bg-blue-50 shadow-md":"border-gray-200 bg-white hover:border-gray-300"),onClick:()=>{const e=a.questions[0];if(e){const t=A.findIndex(t=>t.id===e.id);-1!==t&&(ae(t),O(a.partNo))}},children:t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm font-medium "+(n?"text-blue-900":"text-gray-900"),children:a.partName}),e(c,{variant:"secondary",className:"text-xs "+(n?"bg-blue-200 text-blue-800":"bg-gray-100 text-gray-700"),children:E("admin.exams.preview.questions",{count:String(a.questions.length)})})]})},a.partId||`part-${a.partNo}`)})})]})]})}),e("div",{className:"flex-1 overflow-y-auto",children:t("div",{className:"flex h-full flex-col",children:[t("div",{className:"flex items-center justify-between border-b pb-4",children:[t("div",{children:[e("h3",{className:"text-lg font-semibold",children:H?e("span",{className:"text-gray-400",children:E("admin.exams.preview.loading")}):A.length>0?E("admin.exams.preview.questionIndex",{index:String($+1),total:String(A.length)}):E("admin.exams.preview.noQuestions")}),ee&&e("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:(e=>{const t=K.findIndex(t=>t.id===(e??""));return K[t]?.name||`Part ${t>=0?t+1:1}`})(ee.partId)})})]}),ee&&t("div",{className:"flex items-center gap-2",children:[e(c,{variant:"outline",children:E("admin.exams.preview.points",{count:String(Number(ee.points)||1)})}),e(c,{className:I(ee.difficulty),children:ee.difficulty??"N/A"})]})]}),e("div",{ref:J,className:"flex-1 overflow-y-auto py-4",children:H?t("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:[e(m,{className:"h-8 w-8 animate-spin text-blue-500"}),e("p",{className:"text-gray-600",children:E("admin.exams.preview.loadingQuestions")})]}):Y?e("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:t("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:Y}),e(o,{variant:"outline",onClick:()=>G(e=>e+1),className:"mt-4",children:E("admin.exams.preview.retry")})]})}):0===A.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:E("admin.exams.preview.examNoQuestions")})})}):ee?e(w,{question:ee,isReviewMode:!0}):null}),!H&&A.length>0&&t("div",{className:"mt-auto flex items-center justify-between border-t border-gray-200 bg-gray-50 px-4 py-3",children:[t(o,{variant:"outline",onClick:()=>{$>0&&ae($-1)},disabled:0===$,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:E("admin.exams.preview.prevQuestion")}),e("span",{className:"sm:hidden",children:E("admin.exams.preview.prev")})]}),t("div",{className:"text-sm text-gray-600",children:[$+1," / ",A.length]}),t(o,{variant:"outline",onClick:()=>{$<A.length-1&&ae($+1)},disabled:$===A.length-1,className:"flex h-9 items-center gap-2 px-3 text-sm",children:[e("span",{className:"hidden sm:inline",children:E("admin.exams.preview.nextQuestion")}),e("span",{className:"sm:hidden",children:E("admin.exams.preview.next")}),e(l,{className:"h-4 w-4"})]})]})]})})]}),e("div",{className:"border-t pt-4",children:t("div",{className:"flex items-center justify-between",children:[e("div",{className:"text-sm text-gray-600",children:E("admin.exams.preview.footerNote")}),e(o,{variant:"outline",onClick:()=>S(!1),className:"border-gray-300",children:E("admin.exams.preview.close")})]})})]})})}
@@ -32,5 +32,4 @@ export { EXAM_DIFFICULTY, ExamViewDialog } from './ExamViewDialog';
32
32
  export type { ExamDifficulty, ExamViewDialogExam, ExamViewDialogProps } from './ExamViewDialog';
33
33
  export { ExamPreviewDialog } from './ExamPreviewDialog';
34
34
  export type { ExamPreviewDialogProps } from './ExamPreviewDialog';
35
- export type { PreviewQuestion, QuestionsByPart } from './exam-preview.types';
36
35
  export { QuestionStatus, clearQuestionStatuses, getQuestionStatus, initializeQuestionStatusesFromAPI, setQuestionStatus } from './exam-question-status';
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{MoversListenAndWriteRenderer as t,MoversChooseBestAnswerRenderer as s,MoversChooseAdjectiveRenderer as i,MoversWritingRenderer as r,MoversColoringRenderer as o,MoversPictureChooseRenderer as a,MoversPictureFillBlankChooseRenderer as u,MoversReadingPassageRenderer as c,MoversLabelThePictureRenderer as m,MoversFillWordHintRenderer as l,MoversGridFillRenderer as g,MoversTrueFalseRenderer as p,MoversAnswerTheQuestionRenderer as _,MoversWriteSentencesRenderer as N,MoversWordOrderingRenderer as E,MoversWordFillParagraphRenderer as d,MoversMatchByWritingAnswerRenderer as C,MoversWordFillStructuredFormRenderer as A}from"./question-renderers";import{SpeakingQuestionRenderer as I}from"./speaking/renderers";import{transformFillInBlank as w,transformWriteCorrectVerbForm as R,transformChooseCorrectAnswer as T,transformChooseCorrectAdjective as h,transformWriteShortLetter as S,transformColorObjects as O,transformPictureChoose as U,transformPictureFillBlankChoose as q,transformReadingPassage as M,transformLabelPicture as b,transformFillWordHint as L,transformGridFill as x,transformAnswerTheQuestion as v,transformTrueFalse as D,transformWordOrdering as f,transformWordFillParagraph as P,transformMatchByWritingAnswer as W,transformWriteSentences as G,transformWordFillStructuredForm as H}from"../utils/question-transformers";import{normalizeColoringAssignments as B}from"../utils/coloring-assignments";export function QuestionRenderer({part:K,answers:Q,onAnswerChange:F,isReviewMode:k=!1,onExit:j,onPartComplete:y,onPartBack:V,speakingTheme:J,initialQuestionIndex:Y,skipTeacherVideo:X,onTeacherIntroPlayed:z,currentQuestionIndex:Z}){const{partNo:$,questionType:ee,questions:ne}=K,te=ne.filter(e=>!e.is_example).length,se=e=>{if(void 0!==Z&&Z>=0){if(e.length>0&&"isExample"in e[0]){const n=e.filter(e=>e.isExample),t=e.filter(e=>!e.isExample);if(Z<t.length)return 0===Z&&n.length>0?[...n,t[Z]]:[t[Z]]}else if(Z<e.length)return[e[Z]]}return e};switch(ee){case"FILL_IN_BLANK":{const n=w(ne);return e(t,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,title:n.title,imageUrl:n.groupImageUrl||n.imageUrl,audioUrl:n.audioUrl||K.audioUrl,exampleText:n.exampleText,exampleHighlight:n.exampleHighlight,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k,showHints:n.showHints,groupContent:n.groupContent,groupTitle:n.groupTitle})}case"WRITE_CORRECT_VERB_FORM":{const n=R(ne);return e(t,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,title:n.title,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"CHOOSE_THE_CORRECT_ANSWER":{const n=T(ne);return e(s,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,imageUrl:n.groupImageUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,articles:n.articles,audioUrl:n.audioUrl||K.audioUrl,example:n.example,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"CHOOSE_CORRECT_ADJECTIVE":{const n=h(ne);return e(i,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"WRITE_A_SHORT_LETTER":{const n=ne[0],t=S(n),s=Q[n.id]||"";return e(r,{partNumber:$,partName:K.name,instruction:K.instructions,prompt:t.prompt,requirements:t.requirements,minWords:t.minWords,maxWords:t.maxWords,answer:s,onAnswerChange:e=>F(n.id,e),isReviewMode:k,guideImages:t.guideImages})}case"READ_AND_COLOR_OBJECTS":{const n=O(ne),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(Q).filter(([e])=>t.has(e))),i=B(s,n.hintItems);return e(o,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||K.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void F(e,s.color)}F(e,t)},isReviewMode:k})}case"LOOK_PICTURE_CHOOSE_CORRECT_ANSWER":{const n=U(ne);return e(a,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,subQuestions:n.subQuestions,answers:Q,onAnswerChange:F,isReviewMode:k})}case"LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER":{const n=q(ne);return e(u,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,subQuestions:n.subQuestions,answers:Q,onAnswerChange:F,isReviewMode:k})}case"READ_PASSAGE_AND_ANSWER_QUESTIONS":{const n=M(ne);return e(c,{partNumber:$,partName:K.name,questionCount:n.questions.length,instruction:K.instructions||n.instruction,passageTitle:n.passageTitle,passage:n.passage,passageImageUrl:n.passageImageUrl,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"LABEL_THE_PICTURE":{const n=b(ne);return e(m,{partNumber:$,partName:K.name,questionCount:n.labels.length,instruction:K.instructions||n.instruction,imageUrl:n.imageUrl,wordBank:n.wordBank,labels:n.labels,answers:Q,onAnswerChange:F,isReviewMode:k})}case"LOOK_PICTURE_FILL_WORD_HINT":{const n=L(ne);return e(l,{partNumber:$,partName:K.name,questionCount:n.subQuestions.length,instruction:K.instructions||n.instruction,hintLetters:n.hintLetters,subQuestions:n.subQuestions,answers:Q,onAnswerChange:F,isReviewMode:k})}case"FILL_MISSING_WORDS_IN_GRID":{const n=x(ne);return e(g,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,grid:n.grid,rows:n.rows,columns:n.columns,cellAnswers:{},answers:Q,onAnswerChange:F,isReviewMode:k,disabledCells:n.disabledCells})}case"IMAGE_OBJECT_MATCHING":{const n=O(ne),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(Q).filter(([e])=>t.has(e))),i=B(s,n.hintItems);return e(o,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||K.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void F(e,s.color)}F(e,t)},isReviewMode:k})}case"ANSWER_THE_QUESTION":{const n=v(ne);return e(_,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,imageUrl:n.imageUrl,audioUrl:K.audioUrl,title:n.title,groupContent:n.groupContent,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"TRUE_FALSE":{const n=D(ne);return e(p,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,imageUrl:n.imageUrl,groupContent:n.groupContent,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"WORD_ORDERING":{const n=f(ne);return e(E,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"WORD_FILL_PARAGRAPH":{const n=P(ne),t=n.wordBank.filter(e=>e.isExample).length,s=n.paragraph.match(/\{\d+\}/g),i=s?s.length:0,r=Math.max(1,i-t);let o=K.instructions||n.instruction;return o=o.replace(/\{FROM\}/gi,"1").replace(/\{TO\}/gi,String(r)),e(d,{partNumber:$,partName:K.name,questionCount:te,instruction:o,questionId:n.questionId,paragraph:n.paragraph,title:n.title,imageUrl:n.imageUrl,wordBank:n.wordBank,viewMode:n.viewMode,answers:Q,onAnswerChange:F,exampleAnswer:n.exampleAnswer,isReviewMode:k,emailFrom:n.emailFrom,emailTo:n.emailTo})}case"MATCH_BY_WRITING_ANSWER":{const n=W(ne);return e(C,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,audioUrl:K.audioUrl,options:n.options,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k,viewMode:n.viewMode,groupImageUrl:n.groupImageUrl})}case"WORD_FILL_STRUCTURED_FORM":{const n=H(ne);return e(A,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,audioUrl:n.audioUrl||K.audioUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,groupImageUrl:n.groupImageUrl,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"WRITE_SENTENCES":{const n=G(ne);return e(N,{partNumber:$,partName:K.name,questionCount:te,instruction:K.instructions||n.instruction,imageUrl:n.imageUrl,title:n.title,groupContent:n.groupContent,questions:se(n.questions),answers:Q,onAnswerChange:F,isReviewMode:k})}case"LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE":case"LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP":case"LISTEN_AND_DRAG_OBJECTS_INTO_SCENE":case"LISTEN_AND_SPEAK_ANSWER":case"LISTEN_AND_SPEAK_COMPARE_IMAGES":case"LISTEN_AND_SPEAK_WITH_STORY_IMAGES":case"LISTEN_AND_SPEAK_IMAGE_GROUP":case"LISTEN_AND_SPEAK_ODD_ONE_OUT":case"LISTEN_AND_SPEAK_QUESTION_LIST":case"LISTEN_AND_SPEAK_INFO_EXCHANGE":case"SPEAKING_DESCRIBE_IMAGE":case"READ_DISPLAYED_CONTENT":case"SPONTANEOUS_QA":case"SPEAKING_CONVERSATION":case"GN_SPEAKING_INTERVIEW":case"SPEAKING_CUE_CARD":return e(I,{part:K,answers:Q,onAnswerChange:F,isReviewMode:k,onExit:j,onPartComplete:y,onPartBack:V,speakingTheme:J,initialQuestionIndex:Y,skipTeacherVideo:X,onTeacherIntroPlayed:z,currentQuestionIndex:Z});default:return e("div",{className:"flex h-full items-center justify-center",children:n("div",{className:"text-center",children:[e("p",{className:"text-lg font-semibold text-red-500",children:"Unsupported question type"}),e("p",{className:"mt-2 text-gray-500",children:ee})]})})}}
1
+ "use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{MoversListenAndWriteRenderer as t,MoversChooseBestAnswerRenderer as s,MoversChooseAdjectiveRenderer as i,MoversWritingRenderer as r,MoversColoringRenderer as o,MoversPictureChooseRenderer as a,MoversPictureFillBlankChooseRenderer as u,MoversReadingPassageRenderer as c,MoversLabelThePictureRenderer as m,MoversFillWordHintRenderer as l,MoversGridFillRenderer as p,MoversTrueFalseRenderer as g,MoversAnswerTheQuestionRenderer as _,MoversWriteSentencesRenderer as N,MoversWordOrderingRenderer as E,MoversWordFillParagraphRenderer as C,MoversMatchByWritingAnswerRenderer as d,MoversWordFillStructuredFormRenderer as A}from"./question-renderers";import{SpeakingQuestionRenderer as R}from"./speaking/renderers";import{transformFillInBlank as w,transformWriteCorrectVerbForm as I,transformChooseCorrectAnswer as T,transformChooseTheCorrectAnswerGroup as h,transformChooseCorrectAdjective as S,transformWriteShortLetter as O,transformColorObjects as U,transformPictureChoose as q,transformPictureFillBlankChoose as M,transformReadingPassage as b,transformLabelPicture as L,transformFillWordHint as x,transformGridFill as v,transformAnswerTheQuestion as D,transformTrueFalse as f,transformWordOrdering as P,transformWordFillParagraph as W,transformMatchByWritingAnswer as G,transformWriteSentences as H,transformWordFillStructuredForm as B}from"../utils/question-transformers";import{normalizeColoringAssignments as K}from"../utils/coloring-assignments";export function QuestionRenderer({part:Q,answers:F,onAnswerChange:k,isReviewMode:j=!1,onExit:y,onPartComplete:V,onPartBack:J,speakingTheme:Y,initialQuestionIndex:X,skipTeacherVideo:z,onTeacherIntroPlayed:Z,currentQuestionIndex:$}){const{partNo:ee,questionType:ne,questions:te}=Q,se=te.filter(e=>!e.is_example).length,ie=e=>{if(void 0!==$&&$>=0){if(e.length>0&&"isExample"in e[0]){const n=e.filter(e=>e.isExample),t=e.filter(e=>!e.isExample);if($<t.length)return 0===$&&n.length>0?[...n,t[$]]:[t[$]]}else if($<e.length)return[e[$]]}return e};switch(ne){case"FILL_IN_BLANK":{const n=w(te);return e(t,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,title:n.title,imageUrl:n.groupImageUrl||n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,exampleText:n.exampleText,exampleHighlight:n.exampleHighlight,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j,showHints:n.showHints,groupContent:n.groupContent,groupTitle:n.groupTitle})}case"WRITE_CORRECT_VERB_FORM":{const n=I(te);return e(t,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,title:n.title,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_THE_CORRECT_ANSWER":{const n=T(te);return e(s,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.groupImageUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,articles:n.articles,audioUrl:n.audioUrl||Q.audioUrl,example:n.example,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_THE_CORRECT_ANSWER_GROUP":{const n=h(te);return e(s,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,example:n.example,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_CORRECT_ADJECTIVE":{const n=S(te);return e(i,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WRITE_A_SHORT_LETTER":{const n=te[0],t=O(n),s=F[n.id]||"";return e(r,{partNumber:ee,partName:Q.name,instruction:Q.instructions,prompt:t.prompt,requirements:t.requirements,minWords:t.minWords,maxWords:t.maxWords,answer:s,onAnswerChange:e=>k(n.id,e),isReviewMode:j,guideImages:t.guideImages})}case"READ_AND_COLOR_OBJECTS":{const n=U(te),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(F).filter(([e])=>t.has(e))),i=K(s,n.hintItems);return e(o,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void k(e,s.color)}k(e,t)},isReviewMode:j})}case"LOOK_PICTURE_CHOOSE_CORRECT_ANSWER":{const n=q(te);return e(a,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER":{const n=M(te);return e(u,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"READ_PASSAGE_AND_ANSWER_QUESTIONS":{const n=b(te);return e(c,{partNumber:ee,partName:Q.name,questionCount:n.questions.length,instruction:Q.instructions||n.instruction,passageTitle:n.passageTitle,passage:n.passage,passageImageUrl:n.passageImageUrl,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"LABEL_THE_PICTURE":{const n=L(te);return e(m,{partNumber:ee,partName:Q.name,questionCount:n.labels.length,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,wordBank:n.wordBank,labels:n.labels,answers:F,onAnswerChange:k,isReviewMode:j})}case"LOOK_PICTURE_FILL_WORD_HINT":{const n=x(te);return e(l,{partNumber:ee,partName:Q.name,questionCount:n.subQuestions.length,instruction:Q.instructions||n.instruction,hintLetters:n.hintLetters,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"FILL_MISSING_WORDS_IN_GRID":{const n=v(te);return e(p,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,grid:n.grid,rows:n.rows,columns:n.columns,cellAnswers:{},answers:F,onAnswerChange:k,isReviewMode:j,disabledCells:n.disabledCells})}case"IMAGE_OBJECT_MATCHING":{const n=U(te),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(F).filter(([e])=>t.has(e))),i=K(s,n.hintItems);return e(o,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void k(e,s.color)}k(e,t)},isReviewMode:j})}case"ANSWER_THE_QUESTION":{const n=D(te);return e(_,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,audioUrl:Q.audioUrl,title:n.title,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"TRUE_FALSE":{const n=f(te);return e(g,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WORD_ORDERING":{const n=P(te);return e(E,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WORD_FILL_PARAGRAPH":{const n=W(te),t=n.wordBank.filter(e=>e.isExample).length,s=n.paragraph.match(/\{\d+\}/g),i=s?s.length:0,r=Math.max(1,i-t);let o=Q.instructions||n.instruction;return o=o.replace(/\{FROM\}/gi,"1").replace(/\{TO\}/gi,String(r)),e(C,{partNumber:ee,partName:Q.name,questionCount:se,instruction:o,questionId:n.questionId,paragraph:n.paragraph,title:n.title,imageUrl:n.imageUrl,wordBank:n.wordBank,viewMode:n.viewMode,answers:F,onAnswerChange:k,exampleAnswer:n.exampleAnswer,isReviewMode:j,emailFrom:n.emailFrom,emailTo:n.emailTo})}case"MATCH_BY_WRITING_ANSWER":{const n=G(te);return e(d,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,audioUrl:Q.audioUrl,options:n.options,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j,viewMode:n.viewMode,groupImageUrl:n.groupImageUrl})}case"WORD_FILL_STRUCTURED_FORM":{const n=B(te);return e(A,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,audioUrl:n.audioUrl||Q.audioUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,groupImageUrl:n.groupImageUrl,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WRITE_SENTENCES":{const n=H(te);return e(N,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,title:n.title,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE":case"LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP":case"LISTEN_AND_DRAG_OBJECTS_INTO_SCENE":case"LISTEN_AND_SPEAK_ANSWER":case"LISTEN_AND_SPEAK_COMPARE_IMAGES":case"LISTEN_AND_SPEAK_WITH_STORY_IMAGES":case"LISTEN_AND_SPEAK_IMAGE_GROUP":case"LISTEN_AND_SPEAK_ODD_ONE_OUT":case"LISTEN_AND_SPEAK_QUESTION_LIST":case"LISTEN_AND_SPEAK_INFO_EXCHANGE":case"SPEAKING_DESCRIBE_IMAGE":case"READ_DISPLAYED_CONTENT":case"SPONTANEOUS_QA":case"SPEAKING_CONVERSATION":case"GN_SPEAKING_INTERVIEW":case"SPEAKING_CUE_CARD":return e(R,{part:Q,answers:F,onAnswerChange:k,isReviewMode:j,onExit:y,onPartComplete:V,onPartBack:J,speakingTheme:Y,initialQuestionIndex:X,skipTeacherVideo:z,onTeacherIntroPlayed:Z,currentQuestionIndex:$});default:return e("div",{className:"flex h-full items-center justify-center",children:n("div",{className:"text-center",children:[e("p",{className:"text-lg font-semibold text-red-500",children:"Unsupported question type"}),e("p",{className:"mt-2 text-gray-500",children:ne})]})})}}
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import{ResolvedImage as t}from"../../../../../components/common/ResolvedImage";import l from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import a from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import s from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import o from"../../../../../components/themes/cambridge-yle/CambridgeYleExampleText";export function MoversListenAndWriteRenderer({partNumber:i,partName:n,questionCount:d,instruction:m,imageUrl:c,audioUrl:b,title:x,exampleText:p,exampleHighlight:u,questions:h,answers:g,onAnswerChange:f,isReviewMode:w=!1,showHints:N=!1,groupContent:v,groupTitle:y}){const C=!!(b||c||v||p);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative",children:[r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-4",children:[e(l,{partNumber:i,questionCount:d,partName:n,isReviewMode:w}),e(a,{instruction:m,hasExample:!!p,isReviewMode:w})]}),C&&r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100",children:[b&&e(s,{audioSrc:b,compact:!0}),r("div",{className:"max-h-[35vh] overflow-y-auto custom-scrollbar pr-2 flex flex-col gap-3",children:[c&&e("div",{className:"flex items-center justify-center",children:e(t,{src:c,alt:"Shared illustration",className:"max-h-[200px] rounded-lg object-contain shadow-md"})}),v&&r("div",{className:"rounded-lg bg-amber-50 p-3 text-sm leading-relaxed text-gray-700 shadow-inner",children:[y&&e("h3",{className:"mb-2 font-semibold text-gray-800",children:y}),v]})]}),p&&e(o,{text:p,highlightedWord:u||""})]}),r("div",{className:"flex flex-col gap-4 p-3 sm:gap-6 sm:pb-6 sm:px-6",children:[x&&e("h2",{className:"text-center text-3xl font-bold uppercase text-coral-500",children:x}),e("div",{className:"flex flex-col gap-6 sm:gap-8",children:h.map(l=>{const a=l.isExample||!1,o=w||a,i=a&&l.correctAnswer?l.correctAnswer:g[l.id]||"",n=(g[l.id]||"").trim().toLowerCase(),d=(l.correctAnswer||"").trim().toLowerCase(),m=!!n,c=w&&!a&&m&&n===d,b=w&&!a&&m&&n!==d;return r("div",{id:`question-${l.id}`,className:"flex flex-col gap-4 rounded-2xl border p-4 sm:p-6 transition-all duration-200 hover:shadow-md "+(a?"border-amber-300 bg-amber-50/60 shadow-xs":"border-slate-200/80 bg-white shadow-xs hover:border-blue-300"),children:[r("div",{className:"flex items-center justify-between border-b border-slate-100 pb-3",children:[r("div",{className:"flex items-center gap-2",children:[e("span",{className:"inline-flex items-center justify-center rounded-full px-3.5 py-1 text-sm font-bold text-white shadow-xs "+(a?"bg-amber-500":w?c?"bg-emerald-500":b?"bg-rose-500":"bg-[#001590]":"bg-[#001590]"),children:a?"Ví dụ":`${l.questionNumber}.`}),a&&e("span",{className:"rounded-md bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-700",children:"Example"})]}),w&&!a&&e("div",{children:e("span",c?{className:"inline-flex items-center gap-1 rounded-full bg-emerald-50 px-2.5 py-0.5 text-xs font-semibold text-emerald-700 border border-emerald-200",children:"✓ Đúng"}:b?{className:"inline-flex items-center gap-1 rounded-full bg-rose-50 px-2.5 py-0.5 text-xs font-semibold text-rose-700 border border-rose-200",children:"✕ Chưa đúng"}:{className:"inline-flex items-center gap-1 rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium text-slate-600",children:"Chưa trả lời"})})]}),l.audioUrl&&e("div",{className:"w-full my-1",children:e(s,{audioSrc:l.audioUrl,compact:!0,dense:!0})}),l.imageUrl&&e("div",{className:"flex items-center justify-center rounded-xl bg-slate-50/80 p-3 border border-slate-100 max-w-md mx-auto w-full",children:e(t,{src:l.imageUrl,alt:`Question ${l.questionNumber} illustration`,className:"max-h-[200px] sm:max-h-[220px] w-auto rounded-lg object-contain drop-shadow-xs"})}),r("div",{className:"flex flex-wrap items-baseline gap-2 text-base sm:text-lg leading-relaxed text-slate-800 pt-1",children:[l.textBefore&&e("span",{className:"font-medium",children:l.textBefore}),e("span",{className:"inline-block min-w-[140px] sm:min-w-[160px]",children:e("input",{type:"text",value:i,onChange:e=>f(l.id,e.target.value),disabled:o,placeholder:a?"":"...",className:`w-full rounded-lg border-2 px-3 py-1.5 text-center font-semibold outline-none transition-all ${a?"border-amber-300 bg-amber-100/50 text-amber-800 disabled:opacity-100":w?c?"border-emerald-400 bg-emerald-50 text-emerald-800":"border-rose-400 bg-rose-50 text-rose-800":"border-blue-200 bg-blue-50/30 text-blue-900 focus:border-blue-500 focus:bg-white focus:ring-4 focus:ring-blue-100"} ${o?"disabled:cursor-not-allowed disabled:opacity-75":""}`})}),l.textAfter&&e("span",{className:"font-medium",children:l.textAfter}),l.verbHint&&r("span",{className:"italic text-slate-500 font-normal",children:["(",l.verbHint,")"]})]}),N&&l.hints&&l.hints.length>0&&!w&&r("div",{className:"flex flex-wrap items-center gap-2 pt-2 border-t border-slate-100",children:[e("span",{className:"text-xs font-medium text-slate-500",children:"Gợi ý:"}),l.hints.map((r,t)=>e("button",{type:"button",onClick:()=>f(l.id,r),className:"rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-700 shadow-2xs transition-all hover:bg-blue-600 hover:text-white hover:border-blue-600 active:scale-95",children:r},t))]}),w&&!a&&l.correctAnswer&&e("div",{className:"mt-1 rounded-lg bg-emerald-50/80 p-2.5 text-sm border border-emerald-200/80",children:r("span",{className:"font-semibold text-emerald-800",children:["Đáp án đúng: ",e("span",{className:"font-bold underline",children:l.correctAnswer})]})})]},l.id)})})]})]})}
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Fragment as t}from"react";import{ResolvedImage as l}from"../../../../../components/common/ResolvedImage";import a from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import s from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import o from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import n from"../../../../../components/themes/cambridge-yle/CambridgeYleExampleText";function i(l){return l.split("\n").map((l,a)=>r(t,{children:[a>0?e("br",{}):null,l]},a))}export function MoversListenAndWriteRenderer({partNumber:t,partName:d,questionCount:m,instruction:c,imageUrl:b,audioUrl:x,title:p,exampleText:u,exampleHighlight:h,questions:g,answers:f,onAnswerChange:w,isReviewMode:N=!1,showHints:v=!1,groupContent:y,groupTitle:C}){const A=!!(x||b||y||u);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative",children:[r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-4",children:[e(a,{partNumber:t,questionCount:m,partName:d,isReviewMode:N}),e(s,{instruction:c,hasExample:!!u,isReviewMode:N})]}),A&&r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100",children:[x&&e(o,{audioSrc:x,compact:!0}),r("div",{className:"max-h-[35vh] overflow-y-auto custom-scrollbar pr-2 flex flex-col gap-3",children:[b&&e("div",{className:"flex items-center justify-center",children:e(l,{src:b,alt:"Shared illustration",className:"max-h-[200px] rounded-lg object-contain shadow-md"})}),y&&r("div",{className:"rounded-lg bg-amber-50 p-3 text-sm leading-relaxed text-gray-700 shadow-inner",children:[C&&e("h3",{className:"mb-2 font-semibold text-gray-800",children:C}),y]})]}),u&&e(n,{text:u,highlightedWord:h||""})]}),r("div",{className:"flex flex-col gap-4 p-3 sm:gap-6 sm:pb-6 sm:px-6",children:[p&&e("h2",{className:"text-center text-3xl font-bold uppercase text-coral-500",children:p}),e("div",{className:"flex flex-col gap-6 sm:gap-8",children:g.map(t=>{const a=t.isExample||!1,s=N||a,n=a&&t.correctAnswer?t.correctAnswer:f[t.id]||"",d=(f[t.id]||"").trim().toLowerCase(),m=(t.correctAnswer||"").trim().toLowerCase(),c=!!d,b=N&&!a&&c&&d===m,x=N&&!a&&c&&d!==m;return r("div",{id:`question-${t.id}`,className:"flex flex-col gap-4 rounded-2xl border p-4 sm:p-6 transition-all duration-200 hover:shadow-md "+(a?"border-amber-300 bg-amber-50/60 shadow-xs":"border-slate-200/80 bg-white shadow-xs hover:border-blue-300"),children:[r("div",{className:"flex items-center justify-between border-b border-slate-100 pb-3",children:[r("div",{className:"flex items-center gap-2",children:[e("span",{className:"inline-flex items-center justify-center rounded-full px-3.5 py-1 text-sm font-bold text-white shadow-xs "+(a?"bg-amber-500":N?b?"bg-emerald-500":x?"bg-rose-500":"bg-[#001590]":"bg-[#001590]"),children:a?"Ví dụ":`${t.questionNumber}.`}),a&&e("span",{className:"rounded-md bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-700",children:"Example"})]}),N&&!a&&e("div",{children:e("span",b?{className:"inline-flex items-center gap-1 rounded-full bg-emerald-50 px-2.5 py-0.5 text-xs font-semibold text-emerald-700 border border-emerald-200",children:"✓ Đúng"}:x?{className:"inline-flex items-center gap-1 rounded-full bg-rose-50 px-2.5 py-0.5 text-xs font-semibold text-rose-700 border border-rose-200",children:"✕ Chưa đúng"}:{className:"inline-flex items-center gap-1 rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium text-slate-600",children:"Chưa trả lời"})})]}),t.audioUrl&&e("div",{className:"w-full my-1",children:e(o,{audioSrc:t.audioUrl,compact:!0,dense:!0})}),t.imageUrl&&e("div",{className:"flex items-center justify-center rounded-xl bg-slate-50/80 p-3 border border-slate-100 max-w-md mx-auto w-full",children:e(l,{src:t.imageUrl,alt:`Question ${t.questionNumber} illustration`,className:"max-h-[200px] sm:max-h-[220px] w-auto rounded-lg object-contain drop-shadow-xs"})}),r("div",{className:"text-base sm:text-lg leading-relaxed text-slate-800 pt-1",children:[t.textBefore&&e("span",{className:"font-medium",children:i(t.textBefore)}),e("span",{className:"mx-1 inline-block w-[7.5rem] max-w-[40%] min-w-[5.5rem] align-baseline sm:w-[8.5rem]",children:e("input",{type:"text",value:n,onChange:e=>w(t.id,e.target.value),disabled:s,placeholder:a?"":"...",className:`w-full rounded-md border-2 px-2 py-1 text-center text-sm font-semibold outline-none transition-all sm:text-base ${a?"border-amber-300 bg-amber-100/50 text-amber-800 disabled:opacity-100":N?b?"border-emerald-400 bg-emerald-50 text-emerald-800":"border-rose-400 bg-rose-50 text-rose-800":"border-blue-200 bg-blue-50/30 text-blue-900 focus:border-blue-500 focus:bg-white focus:ring-4 focus:ring-blue-100"} ${s?"disabled:cursor-not-allowed disabled:opacity-75":""}`})}),t.textAfter&&e("span",{className:"font-medium",children:i(t.textAfter)}),t.verbHint&&r("span",{className:"ml-1 italic text-slate-500 font-normal",children:["(",t.verbHint,")"]})]}),v&&t.hints&&t.hints.length>0&&!N&&r("div",{className:"flex flex-wrap items-center gap-2 pt-2 border-t border-slate-100",children:[e("span",{className:"text-xs font-medium text-slate-500",children:"Gợi ý:"}),t.hints.map((r,l)=>e("button",{type:"button",onClick:()=>w(t.id,r),className:"rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-700 shadow-2xs transition-all hover:bg-blue-600 hover:text-white hover:border-blue-600 active:scale-95",children:r},l))]}),N&&!a&&t.correctAnswer&&e("div",{className:"mt-1 rounded-lg bg-emerald-50/80 p-2.5 text-sm border border-emerald-200/80",children:r("span",{className:"font-semibold text-emerald-800",children:["Đáp án đúng: ",e("span",{className:"font-bold underline",children:t.correctAnswer})]})})]},t.id)})})]})]})}
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useEffect as n,useMemo as a,useCallback as l,memo as s}from"react";import{ResolvedImage as i}from"../../../../../components/common/ResolvedImage";import o from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import c from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import{cn as u}from"../../../../../shared/lib/utils";function m(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function p(e,t){return e.replace(/\{([\w\d]+)\}/g,(e,r)=>{const n=function(e,t){if(!e?.length)return null;const r=Number(t),n=Number.isFinite(r)&&r>=0&&r<e.length?e[r]:null;return null!=n&&"options"in n&&n.options?.length&&n.options.length>=2?n.options:null}(t,r);if(n){return`\n <span class="structured-blank-wrapper" data-blank-wrapper="${r}">\n <select data-blank-key="${r}" class="structured-blank-input structured-blank-select">${['<option value="">—</option>',...n.map(e=>`<option value="${m(e)}">${m(e)}</option>`)].join("")}</select>\n <span class="structured-blank-hint" data-blank-hint="${r}"></span>\n </span>\n `}return`\n <span class="structured-blank-wrapper" data-blank-wrapper="${r}">\n <input type="text" data-blank-key="${r}" placeholder="" class="structured-blank-input" />\n <span class="structured-blank-hint" data-blank-hint="${r}"></span>\n </span>\n `})}function b(e,t){const r=e.trim();return t?r:r.toLowerCase()}const g={},x=s(function({question:l,initialAnswers:s,onBlankChange:o,isReviewMode:d}){const c=r(null),m=r(o);m.current=o;const g=r(!1),x=r(s),h=a(()=>p(l.content,l.wordBank),[l.content,l.wordBank]);return n(()=>{const e=c.current;if(!e)return;g.current||(e.innerHTML=h,g.current=!0);const t=e.querySelectorAll("input.structured-blank-input, select.structured-blank-input"),r=[];return t.forEach(t=>{const n=t.getAttribute("data-blank-key")||"",a=e.querySelector(`[data-blank-wrapper="${n}"]`),s=e.querySelector(`[data-blank-hint="${n}"]`),i=x.current[n]||"",o=l.answers[n]||"",c=i.trim().length>0,p=c&&b(i,l.caseSensitive)===b(o,l.caseSensitive),g=d&&!p&&o.trim().length>0;t.value=g?`${c?i:"(trống)"} → ${o}`:i,t.disabled=d;const h="SELECT"===t.tagName,f=l.blankStyle||"word",w="letter"===f,y="phrase"===f;w&&!h&&"maxLength"in t&&(t.maxLength=Math.max(1,(o||" ").trim().length||1)),t.className=u("structured-blank-input inline-block bg-slate-50/40 text-sm font-semibold outline-none transition-all align-baseline hover:bg-slate-100/60 focus:bg-teal-50/60 focus:ring-0",h?"min-w-[5.5rem] max-w-[10rem] rounded border px-2 py-1 text-center":w?"h-7 w-7 rounded border-2 px-0 text-center uppercase":y?"min-w-[9rem] max-w-[18rem] w-[14ch] rounded-t border-b-2 px-2 py-0.5 text-center":"min-w-[4.5rem] max-w-[7.5rem] w-[8ch] rounded-t border-b-2 px-1 py-0.5 text-center",d?p?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":c?"border-rose-500 bg-rose-50 text-rose-800 font-bold":"border-amber-500 bg-amber-50 text-amber-800 font-bold":"border-slate-400 text-slate-800 focus:border-teal-600"),h||w||!("size"in t)||(t.size=y?18:10),w&&(t.style.display="inline-block",t.style.width="1.75rem",t.style.height="1.75rem",t.style.minWidth="1.75rem",t.style.maxWidth="1.75rem",t.style.padding="0",t.style.margin="0 2px",t.style.borderWidth="2px",t.style.borderStyle="solid",t.style.borderRadius="4px",t.style.textAlign="center",t.style.fontWeight="700",t.style.textTransform="uppercase",t.style.boxSizing="border-box",t.style.verticalAlign="baseline"),a&&(a.className=u("structured-blank-wrapper inline-flex items-baseline align-baseline mx-1 my-0.5",d&&"mx-1 my-0.5")),s&&(s.textContent="",s.className="structured-blank-hint hidden");const k=e=>{const t=e.target;m.current(n,t.value)},v=h?"change":"input";t.addEventListener(v,k),r.push({el:t,handler:k,eventName:v})}),()=>{r.forEach(({el:e,handler:t,eventName:r})=>{e.removeEventListener(r,t)})}},[h,d]),t("div",{className:"space-y-3",children:[l.title&&e("h3",{className:"text-base font-semibold text-gray-800",children:l.title}),l.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200",children:e(i,{src:l.imageUrl,alt:l.title||"Question image",className:"max-h-48 w-auto object-contain"})})}),e("div",{ref:c,className:u("structured-form-content rounded-lg border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4 text-sm leading-relaxed text-gray-800","[&_.structured-blank-wrapper]:inline-flex [&_.structured-blank-wrapper]:align-baseline [&_.structured-blank-wrapper]:items-baseline [&_.structured-blank-hint]:max-w-[180px]","[&_table.dialogue]:w-full [&_table.dialogue]:border-collapse [&_table.dialogue]:table-fixed","[&_table.dialogue_td.speaker]:w-[1%] [&_table.dialogue_td.speaker]:whitespace-nowrap","[&_table.dialogue_td.speaker]:align-top [&_table.dialogue_td.speaker]:pr-3","[&_table.dialogue_td.speaker]:font-semibold [&_table.dialogue_td.speaker]:text-slate-900","[&_table.dialogue_td]:align-top [&_table.dialogue_td]:py-1.5")}),d&&t("div",{className:"space-y-2 rounded-lg border border-slate-200 bg-slate-50 p-3",children:[t("div",{className:"flex flex-wrap gap-2 text-[11px] font-medium",children:[t("span",{className:"inline-flex items-center gap-1 rounded-full bg-green-100 px-2 py-1 text-green-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-green-500"}),"Đúng"]}),t("span",{className:"inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-1 text-red-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-red-500"}),"Sai"]}),t("span",{className:"inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-1 text-amber-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-amber-500"}),"Chưa trả lời"]})]}),t("div",{children:[e("span",{className:"text-[10px] font-medium uppercase tracking-wider text-slate-500",children:"Đáp án đúng"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(l.answers).map(([e,r])=>t("span",{className:"rounded border border-green-300 bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-800",children:[e,": ",r]},e))})]})]})]})});export function MoversWordFillStructuredFormRenderer({partNumber:n,partName:s,questionCount:u,instruction:m,audioUrl:p,groupTitle:b,groupContent:h,groupImageUrl:f,questions:w,answers:y,onAnswerChange:k,isReviewMode:v=!1}){const N=r(y);N.current=y;const _=r(k);_.current=k;const $=l((e,t,r)=>{const n=N.current[e]||{};_.current(e,{...n,[t]:r})},[]),C=a(()=>{const e={};return w.forEach(t=>{e[t.id]=(e,r)=>$(t.id,e,r)}),e},[w,$]);return t("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar",children:[t("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-2",children:[e(o,{partNumber:n,questionCount:u,partName:s,isReviewMode:v}),e(d,{instruction:m,isReviewMode:v}),b&&e("h2",{className:"text-center text-xl font-bold uppercase text-coral-500",children:b}),p&&e(c,{audioSrc:p,compact:!0}),f&&e("div",{className:"flex items-center justify-center",children:e(i,{src:f,alt:b||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),h&&e("div",{className:"article-content rounded-lg bg-amber-50 p-4 text-sm leading-relaxed text-gray-700 max-h-[500px] overflow-y-auto pr-2 custom-scrollbar",dangerouslySetInnerHTML:{__html:h}})]}),w.length>0&&e("div",{className:"px-3 sm:px-6",children:e("hr",{className:"border-t border-slate-200/60 my-1"})}),e("div",{className:"grid grid-cols-1 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6",children:w.map(r=>t("div",{id:`question-${r.id}`,className:"rounded-xl border border-gray-200 bg-white p-4 shadow-sm transition-all hover:border-indigo-200 hover:shadow-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-violet-600 text-xs font-bold text-white shadow-sm",children:r.questionNumber})}),e(x,{question:r,initialAnswers:y[r.id]||g,onBlankChange:C[r.id],isReviewMode:v})]},r.id))})]})}
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useRef as t,useEffect as n,useMemo as a,useCallback as s,memo as l}from"react";import{ResolvedImage as i}from"../../../../../components/common/ResolvedImage";import o from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import c from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import{cn as m}from"../../../../../shared/lib/utils";function u(e,r){const t=e.trim();return r?t:t.toLowerCase()}const p={},b=l(function({question:s,initialAnswers:l,onBlankChange:o,isReviewMode:d}){const c=t(null),p=t(o);p.current=o;const b=t(!1),g=t(l),x=a(()=>s.content.replace(/\{([\w\d]+)\}/g,(e,r)=>`\n <span class="structured-blank-wrapper" data-blank-wrapper="${r}">\n <input type="text" data-blank-key="${r}" placeholder="" class="structured-blank-input" />\n <span class="structured-blank-hint" data-blank-hint="${r}"></span>\n </span>\n `),[s.content]);return n(()=>{const e=c.current;if(!e)return;b.current||(e.innerHTML=x,b.current=!0);const r=e.querySelectorAll("input.structured-blank-input"),t=[];return r.forEach(r=>{const n=r.getAttribute("data-blank-key")||"",a=e.querySelector(`[data-blank-wrapper="${n}"]`),l=e.querySelector(`[data-blank-hint="${n}"]`),i=g.current[n]||"",o=s.answers[n]||"",c=i.trim().length>0,b=c&&u(i,s.caseSensitive)===u(o,s.caseSensitive),x=d&&!b&&o.trim().length>0;r.value=x?`${c?i:"(trống)"} → ${o}`:i,r.disabled=d,r.className=m("structured-blank-input inline-block min-w-[90px] max-w-[200px] rounded-t border-b-2 bg-slate-50/40 px-2 py-0.5 text-sm font-semibold outline-none transition-all align-baseline hover:bg-slate-100/60 focus:bg-teal-50/60 focus:ring-0",d?b?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":c?"border-rose-500 bg-rose-50 text-rose-800 font-bold":"border-amber-500 bg-amber-50 text-amber-800 font-bold":"border-slate-400 text-slate-800 focus:border-teal-600"),a&&(a.className=m("structured-blank-wrapper inline-flex items-baseline align-baseline mx-1 my-0.5",d&&"mx-1 my-0.5")),l&&(l.textContent="",l.className="structured-blank-hint hidden");const h=e=>{const r=e.target;p.current(n,r.value)};r.addEventListener("input",h),t.push({el:r,handler:h})}),()=>{t.forEach(({el:e,handler:r})=>{e.removeEventListener("input",r)})}},[x,d]),r("div",{className:"space-y-3",children:[s.title&&e("h3",{className:"text-base font-semibold text-gray-800",children:s.title}),s.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200",children:e(i,{src:s.imageUrl,alt:s.title||"Question image",className:"max-h-48 w-auto object-contain"})})}),e("div",{ref:c,className:"structured-form-content rounded-lg border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4 text-sm leading-relaxed text-gray-800 [&_.structured-blank-wrapper]:inline-flex [&_.structured-blank-wrapper]:align-baseline [&_.structured-blank-wrapper]:items-baseline [&_.structured-blank-hint]:max-w-[180px]"}),d&&r("div",{className:"space-y-2 rounded-lg border border-slate-200 bg-slate-50 p-3",children:[r("div",{className:"flex flex-wrap gap-2 text-[11px] font-medium",children:[r("span",{className:"inline-flex items-center gap-1 rounded-full bg-green-100 px-2 py-1 text-green-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-green-500"}),"Đúng"]}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-1 text-red-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-red-500"}),"Sai"]}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-1 text-amber-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-amber-500"}),"Chưa trả lời"]})]}),r("div",{children:[e("span",{className:"text-[10px] font-medium uppercase tracking-wider text-slate-500",children:"Đáp án đúng"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(s.answers).map(([e,t])=>r("span",{className:"rounded border border-green-300 bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-800",children:[e,": ",t]},e))})]})]})]})});export function MoversWordFillStructuredFormRenderer({partNumber:n,partName:l,questionCount:m,instruction:u,audioUrl:g,groupTitle:x,groupContent:h,groupImageUrl:f,questions:w,answers:v,onAnswerChange:N,isReviewMode:y=!1}){const k=t(v);k.current=v;const C=t(N);C.current=N;const q=s((e,r,t)=>{const n=k.current[e]||{};C.current(e,{...n,[r]:t})},[]),j=a(()=>{const e={};return w.forEach(r=>{e[r.id]=(e,t)=>q(r.id,e,t)}),e},[w,q]);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar",children:[r("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-2",children:[e(o,{partNumber:n,questionCount:m,partName:l,isReviewMode:y}),e(d,{instruction:u,isReviewMode:y}),x&&e("h2",{className:"text-center text-xl font-bold uppercase text-coral-500",children:x}),g&&e(c,{audioSrc:g,compact:!0}),f&&e("div",{className:"flex items-center justify-center",children:e(i,{src:f,alt:x||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),h&&e("div",{className:"article-content rounded-lg bg-amber-50 p-4 text-sm leading-relaxed text-gray-700 max-h-[500px] overflow-y-auto pr-2 custom-scrollbar",dangerouslySetInnerHTML:{__html:h}})]}),w.length>0&&e("div",{className:"px-3 sm:px-6",children:e("hr",{className:"border-t border-slate-200/60 my-1"})}),e("div",{className:"grid grid-cols-1 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6",children:w.map(t=>r("div",{id:`question-${t.id}`,className:"rounded-xl border border-gray-200 bg-white p-4 shadow-sm transition-all hover:border-indigo-200 hover:shadow-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-violet-600 text-xs font-bold text-white shadow-sm",children:t.questionNumber})}),e(b,{question:t,initialAnswers:v[t.id]||p,onBlankChange:j[t.id],isReviewMode:y})]},t.id))})]})}
@@ -11,13 +11,6 @@ export interface TemplateSection {
11
11
  viewMode?: string;
12
12
  wordBankConfig?: string[];
13
13
  }
14
- export type WfsfBlankStyle = 'letter' | 'word' | 'phrase';
15
- export type WfsfWordBankEntry = {
16
- options: string[];
17
- } | {
18
- word: string;
19
- isExample?: boolean;
20
- } | null;
21
14
  export interface WordFillStructuredFormQuestion {
22
15
  id: string;
23
16
  content: string;
@@ -27,9 +20,6 @@ export interface WordFillStructuredFormQuestion {
27
20
  caseSensitive?: boolean;
28
21
  imageUrl?: string;
29
22
  questionNumber?: number;
30
- blankStyle?: WfsfBlankStyle;
31
- viewMode?: string;
32
- wordBank?: WfsfWordBankEntry[];
33
23
  }
34
24
  export interface ExamTakingPart {
35
25
  id: string;
@@ -120,8 +110,6 @@ export declare function transformWordFillStructuredForm(questions: ExamTakingQue
120
110
  groupContent: string;
121
111
  groupImageUrl: string;
122
112
  questions: {
123
- wordBank?: WfsfWordBankEntry[];
124
- viewMode?: string;
125
113
  id: string;
126
114
  title: string;
127
115
  content: string;
@@ -129,6 +117,5 @@ export declare function transformWordFillStructuredForm(questions: ExamTakingQue
129
117
  caseSensitive: boolean;
130
118
  imageUrl: string;
131
119
  questionNumber: number;
132
- blankStyle: WfsfBlankStyle;
133
120
  }[];
134
121
  };
@@ -1 +1 @@
1
- export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const r=n.find(n=>String(n.id)===t);return{id:t,name:r?.name??`Part ${e[0]?.part_no??t}`,template:r,partId:t,partNo:e[0]?.part_no,instructions:r?.instructions,audioUrl:r?.audioUrl,questionType:r?.questionType??e[0]?.question_type,isGroup:r?.isGroup,group:r?.group,sections:r?.sections,viewMode:"string"==typeof r?.group?.viewMode?r.group.viewMode:void 0,startIndex:r?.startIndex,endIndex:r?.endIndex,questions:e.sort((t,n)=>t.question_number-n.question_number)}})}export function transformAnswerTheQuestion(t){return{instruction:n(t[0]?.content,"instruction"),imageUrl:n(t[0]?.content,"imageUrl"),title:n(t[0]?.content,"title"),groupContent:n(t[0]?.content,"groupContent"),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),prefixText:n(t.content,"prefixText"),suffixText:n(t.content,"suffixText"),exampleAnswer:n(t.content,"exampleAnswer"),suggestedAnswers:r(t.content,"suggestedAnswers"),isExample:Boolean(t.is_example)}))}}export function transformMatchByWritingAnswer(t){return{instruction:n(t[0]?.content,"instruction"),groupImageUrl:n(t[0]?.content,"groupImageUrl"),options:o(t[0]?.content,"options").map(t=>({answer:String(t.answer??t.value??""),text:String(t.text??t.label??""),content:String(t.content??t.text??t.label??""),imageUrl:"string"==typeof t.imageUrl?t.imageUrl:void 0})),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),exampleAnswer:n(t.content,"exampleAnswer"),isExample:Boolean(t.is_example)}))}}export function transformWordFillParagraph(t){const e=t[0];return{questionId:e?.id??"",paragraph:n(e?.content,"paragraph")||n(e?.content,"text"),title:n(e?.content,"title"),imageUrl:n(e?.content,"imageUrl"),wordBank:o(e?.content,"wordBank").map(t=>({word:String(t.word??t.text??""),isExample:Boolean(t.isExample)})),viewMode:n(e?.content,"viewMode"),instruction:n(e?.content,"instruction")}}export function transformWriteShortLetter(o){if(!o)return{prompt:"",requirements:[],minWords:void 0,maxWords:void 0,guideImages:[]};const i=t(o.content),s=t(i.instructions),a="string"==typeof s.mainInstruction?s.mainInstruction:"",u=Array.isArray(i.informations)?i.informations.filter(t=>"string"==typeof t):[],c=r(o.content,"guideImages"),p=e(o.content,"minWords"),m=e(o.content,"maxWords");if(a||u.length)return{prompt:a,requirements:u,minWords:p,maxWords:m,guideImages:c};return{prompt:(Array.isArray(i.contexts)?i.contexts:[]).map(t).filter(t=>"text"===t.type&&"string"==typeof t.text).map(t=>String(t.text)).join("\n")||n(o.content,"prompt")||n(o.content,"question"),requirements:r(o.content,"requirements"),minWords:p,maxWords:m,guideImages:c}}export function transformWordFillStructuredForm(e){const r=e[0],o=t=>{const n=String(t||"").toLowerCase();return"letter"===n||"box"===n?"letter":"phrase"===n||"sentence"===n?"phrase":"word"};return{instruction:n(r?.content,"instruction"),groupTitle:n(r?.content,"groupTitle"),groupContent:n(r?.content,"groupContent"),groupImageUrl:n(r?.content,"groupImageUrl"),questions:e.map(e=>{const r=e.content,s=e,a=s.correct_answer??s.answer,u=i(a,"answers"),c=Object.keys(u).length>0?u:i(r,"answers"),p=t(r),m=(t=>{if(!Array.isArray(t)||0===t.length)return;const n=t.map(t=>{if(null==t)return null;if("object"!=typeof t||Array.isArray(t))return null;const n=t;if(Array.isArray(n.options)){const t=n.options.map(t=>String(t??"").trim()).filter(t=>t.length>0);return t.length>=2?{options:t}:null}const e=String(n.word??"").trim();return e?n.isExample?{word:e,isExample:!0}:{word:e}:null});return n.some(t=>null!=t)?n:void 0})(p.wordBank),l=Boolean(m?.some(t=>null!=t&&"options"in t&&Array.isArray(t.options))),g=Boolean(m?.some(t=>null!=t&&"word"in t&&t.word)),d=n(r,"viewMode")||(l?"WITH_OPTIONS":g?"WITH_WORD_BANK":void 0);return{id:e.id,title:n(r,"title"),content:n(r,"content")||n(r,"html")||n(r,"text"),answers:c,caseSensitive:Boolean(t(a).caseSensitive??p.caseSensitive),imageUrl:n(r,"imageUrl"),questionNumber:e.question_number,blankStyle:o(n(r,"blankStyle")),...d?{viewMode:d}:{},...m?{wordBank:m}:{}}})}}function t(t){return"object"==typeof t&&null!==t?t:{}}function n(n,e){const r=t(n)[e];return"string"==typeof r?r:""}function e(n,e){const r=t(n)[e];return"number"==typeof r?r:void 0}function r(n,e){const r=t(n)[e];return Array.isArray(r)?r.filter(t=>"string"==typeof t):[]}function o(n,e){const r=t(n)[e];return Array.isArray(r)?r.map(t):[]}function i(n,e){const r=t(n)[e],o=t(r);return Object.fromEntries(Object.entries(o).map(([t,n])=>[t,String(n??"")]))}
1
+ export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const r=n.find(n=>String(n.id)===t);return{id:t,name:r?.name??`Part ${e[0]?.part_no??t}`,template:r,partId:t,partNo:e[0]?.part_no,instructions:r?.instructions,audioUrl:r?.audioUrl,questionType:r?.questionType??e[0]?.question_type,isGroup:r?.isGroup,group:r?.group,sections:r?.sections,viewMode:"string"==typeof r?.group?.viewMode?r.group.viewMode:void 0,startIndex:r?.startIndex,endIndex:r?.endIndex,questions:e.sort((t,n)=>t.question_number-n.question_number)}})}export function transformAnswerTheQuestion(t){return{instruction:n(t[0]?.content,"instruction"),imageUrl:n(t[0]?.content,"imageUrl"),title:n(t[0]?.content,"title"),groupContent:n(t[0]?.content,"groupContent"),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),prefixText:n(t.content,"prefixText"),suffixText:n(t.content,"suffixText"),exampleAnswer:n(t.content,"exampleAnswer"),suggestedAnswers:r(t.content,"suggestedAnswers"),isExample:Boolean(t.is_example)}))}}export function transformMatchByWritingAnswer(t){return{instruction:n(t[0]?.content,"instruction"),groupImageUrl:n(t[0]?.content,"groupImageUrl"),options:o(t[0]?.content,"options").map(t=>({answer:String(t.answer??t.value??""),text:String(t.text??t.label??""),content:String(t.content??t.text??t.label??""),imageUrl:"string"==typeof t.imageUrl?t.imageUrl:void 0})),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),exampleAnswer:n(t.content,"exampleAnswer"),isExample:Boolean(t.is_example)}))}}export function transformWordFillParagraph(t){const e=t[0];return{questionId:e?.id??"",paragraph:n(e?.content,"paragraph")||n(e?.content,"text"),title:n(e?.content,"title"),imageUrl:n(e?.content,"imageUrl"),wordBank:o(e?.content,"wordBank").map(t=>({word:String(t.word??t.text??""),isExample:Boolean(t.isExample)})),viewMode:n(e?.content,"viewMode"),instruction:n(e?.content,"instruction")}}export function transformWriteShortLetter(o){if(!o)return{prompt:"",requirements:[],minWords:void 0,maxWords:void 0,guideImages:[]};const i=t(o.content),s=t(i.instructions),u="string"==typeof s.mainInstruction?s.mainInstruction:"",a=Array.isArray(i.informations)?i.informations.filter(t=>"string"==typeof t):[],c=r(o.content,"guideImages"),p=e(o.content,"minWords"),m=e(o.content,"maxWords");if(u||a.length)return{prompt:u,requirements:a,minWords:p,maxWords:m,guideImages:c};return{prompt:(Array.isArray(i.contexts)?i.contexts:[]).map(t).filter(t=>"text"===t.type&&"string"==typeof t.text).map(t=>String(t.text)).join("\n")||n(o.content,"prompt")||n(o.content,"question"),requirements:r(o.content,"requirements"),minWords:p,maxWords:m,guideImages:c}}export function transformWordFillStructuredForm(e){return{instruction:n(e[0]?.content,"instruction"),groupTitle:n(e[0]?.content,"groupTitle"),groupContent:n(e[0]?.content,"groupContent"),groupImageUrl:n(e[0]?.content,"groupImageUrl"),questions:e.map(e=>({id:e.id,title:n(e.content,"title"),content:n(e.content,"content")||n(e.content,"html")||n(e.content,"text"),answers:i(e.content,"answers"),caseSensitive:Boolean(t(e.content).caseSensitive),imageUrl:n(e.content,"imageUrl"),questionNumber:e.question_number}))}}function t(t){return"object"==typeof t&&null!==t?t:{}}function n(n,e){const r=t(n)[e];return"string"==typeof r?r:""}function e(n,e){const r=t(n)[e];return"number"==typeof r?r:void 0}function r(n,e){const r=t(n)[e];return Array.isArray(r)?r.filter(t=>"string"==typeof t):[]}function o(n,e){const r=t(n)[e];return Array.isArray(r)?r.map(t):[]}function i(n,e){const r=t(n)[e],o=t(r);return Object.fromEntries(Object.entries(o).map(([t,n])=>[t,String(n??"")]))}
@@ -1 +1 @@
1
- function n(n){const t=n.match(/-opt-(\d+)$/);return t?parseInt(t[1],10):0}function t(n){return"string"==typeof n&&n.includes("-opt-")}function e(n){return Array.isArray(n)&&n.every(n=>t(n))}function s(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)&&t(n.optionId)}function o(n){return n.startsWith("sq-")||n.includes("-sq-")||n.includes("-blank-")}function r(n){return/^\d+-\d+$/.test(n)}function i(n){return n.startsWith("label-")}function u(n){return n.startsWith("region-")}function f(n,t){for(const n of t)if("READ_PASSAGE_AND_ANSWER_QUESTIONS"===n.questionType&&n.questions.length>0)return{parentId:n.questions[0].id,questionType:n.questionType};return null}function a(n){for(const t of n)if("FILL_MISSING_WORDS_IN_GRID"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function c(n){for(const t of n)if("LABEL_THE_PICTURE"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function p(n,t){for(const e of t)if(("READ_AND_COLOR_OBJECTS"===e.questionType||"IMAGE_OBJECT_MATCHING"===e.questionType)&&e.questions.length>0){const t=e.questions[0],s=t.content;if((s?.regions||s?.regionNodes||[]).some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function d(n,t){for(const e of t)if("LOOK_PICTURE_FILL_WORD_HINT"===e.questionType)for(const t of e.questions){if(n.startsWith(`${t.id}-blank-`))return{parentId:t.id,questionType:e.questionType};const s=t.content;if(s?.subQuestions?.some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function I(n,t){for(const e of t)for(const t of e.questions)if(t.id===n)return e.questionType;return null}function q(n,t){return"number"==typeof n||"string"==typeof n?{answer:n}:Array.isArray(n)?"WORD_FILL_PARAGRAPH"===t?{answers:n}:{answer:n}:"object"==typeof n&&null!==n?n:{answer:n}}export function transformAnswersForSubmission(l,y){const T=[],_=new Map,h=new Map,w=new Map,A=new Map,g=new Set;for(const n of y)for(const t of n.questions)"SPEAKING"===t.question_skill_type&&g.add(t.id);for(const[S,b]of Object.entries(l)){if(null==b||""===b)continue;if(g.has(S)&&"string"==typeof b)continue;if(r(S)){const n=a(y);n&&(h.has(n.parentId)||h.set(n.parentId,{}),h.get(n.parentId)[S]=String(b));continue}if(i(S)){const n=c(y);n&&(w.has(n.parentId)||w.set(n.parentId,{}),w.get(n.parentId)[S]=String(b));continue}if(u(S)){const n=p(S,y);n&&(A.has(n.parentId)||A.set(n.parentId,{}),A.get(n.parentId)[S]=String(b));continue}if(o(S)){let e=f(0,y);if(e||(e=d(S,y)),e){_.has(e.parentId)||_.set(e.parentId,{});const s=t(b)?n(b):b;_.get(e.parentId)[S]=s}continue}const l=I(S,y);let E;E=t(b)?q(n(b),l):e(b)?q(b.map(t=>n(t)),l):s(b)?q(n(b.optionId),l):q(b,l),T.push({questionId:S,answer:E})}for(const[n,t]of _){if(Object.keys(t).some(n=>n.includes("-blank-"))){const e=Object.entries(t).sort(([n],[t])=>{const e=n.match(/-blank-(\d+)$/),s=t.match(/-blank-(\d+)$/);return(e?parseInt(e[1],10):0)-(s?parseInt(s[1],10):0)}).map(([,n])=>n).join(", ");T.push({questionId:n,answer:{answer:e}})}else T.push({questionId:n,answer:{subAnswers:t}})}for(const[n,t]of h)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of w)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of A)T.push({questionId:n,answer:{answers:t}});return T}export function getValidQuestionIds(n){const t=new Set;for(const e of n)for(const n of e.questions)t.add(n.id);return t}
1
+ function n(n){const t=n.match(/-opt-(\d+)$/);return t?parseInt(t[1],10):0}function t(n){return"string"==typeof n&&n.includes("-opt-")}function e(n){return Array.isArray(n)&&n.every(n=>t(n))}function s(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)&&t(n.optionId)}function o(n){return n.startsWith("sq-")||n.includes("-sq-")||n.includes("-blank-")||n.includes("-item-")}function r(n){return/^\d+-\d+$/.test(n)}function i(n){return n.startsWith("label-")}function u(n){return n.startsWith("region-")}function f(n,t){for(const e of t){if("READ_PASSAGE_AND_ANSWER_QUESTIONS"===e.questionType&&e.questions.length>0)return{parentId:e.questions[0].id,questionType:e.questionType};if("CHOOSE_THE_CORRECT_ANSWER_GROUP"===e.questionType){const t=e.questions.find(t=>n.startsWith(`${t.id}-item-`));if(t)return{parentId:t.id,questionType:e.questionType}}}return null}function a(n){for(const t of n)if("FILL_MISSING_WORDS_IN_GRID"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function c(n){for(const t of n)if("LABEL_THE_PICTURE"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function p(n,t){for(const e of t)if(("READ_AND_COLOR_OBJECTS"===e.questionType||"IMAGE_OBJECT_MATCHING"===e.questionType)&&e.questions.length>0){const t=e.questions[0],s=t.content;if((s?.regions||s?.regionNodes||[]).some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function d(n,t){for(const e of t)if("LOOK_PICTURE_FILL_WORD_HINT"===e.questionType)for(const t of e.questions){if(n.startsWith(`${t.id}-blank-`))return{parentId:t.id,questionType:e.questionType};const s=t.content;if(s?.subQuestions?.some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function q(n,t){for(const e of t)for(const t of e.questions)if(t.id===n)return e.questionType;return null}function I(n,t){return"number"==typeof n||"string"==typeof n?{answer:n}:Array.isArray(n)?"WORD_FILL_PARAGRAPH"===t?{answers:n}:{answer:n}:"object"==typeof n&&null!==n?n:{answer:n}}export function transformAnswersForSubmission(l,y){const T=[],_=new Map,h=new Map,A=new Map,w=new Map,g=new Set;for(const n of y)for(const t of n.questions)"SPEAKING"===t.question_skill_type&&g.add(t.id);for(const[m,O]of Object.entries(l)){if(null==O||""===O)continue;if(g.has(m)&&"string"==typeof O)continue;if(r(m)){const n=a(y);n&&(h.has(n.parentId)||h.set(n.parentId,{}),h.get(n.parentId)[m]=String(O));continue}if(i(m)){const n=c(y);n&&(A.has(n.parentId)||A.set(n.parentId,{}),A.get(n.parentId)[m]=String(O));continue}if(u(m)){const n=p(m,y);n&&(w.has(n.parentId)||w.set(n.parentId,{}),w.get(n.parentId)[m]=String(O));continue}if(o(m)){let e=f(m,y);if(e||(e=d(m,y)),e){_.has(e.parentId)||_.set(e.parentId,{});const s=t(O)?n(O):O;_.get(e.parentId)[m]=s}continue}const l=q(m,y);let S;S=t(O)?I(n(O),l):e(O)?I(O.map(t=>n(t)),l):s(O)?I(n(O.optionId),l):I(O,l),T.push({questionId:m,answer:S})}for(const[n,t]of _){if(Object.keys(t).some(n=>n.includes("-item-"))){const e=y.flatMap(n=>n.questions).find(t=>t.id===n),s=Array.isArray(e?.content?.items)?e.content.items.length:0,o=Array.from({length:s},(e,s)=>{const o=t[`${n}-item-${s}`];return"string"==typeof o?o:""});T.push({questionId:n,answer:{answer:o}});continue}if(Object.keys(t).some(n=>n.includes("-blank-"))){const e=Object.entries(t).sort(([n],[t])=>{const e=n.match(/-blank-(\d+)$/),s=t.match(/-blank-(\d+)$/);return(e?parseInt(e[1],10):0)-(s?parseInt(s[1],10):0)}).map(([,n])=>n).join(", ");T.push({questionId:n,answer:{answer:e}})}else T.push({questionId:n,answer:{subAnswers:t}})}for(const[n,t]of h)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of A)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of w)T.push({questionId:n,answer:{answers:t}});return T}export function getValidQuestionIds(n){const t=new Set;for(const e of n)for(const n of e.questions)t.add(n.id);return t}
@@ -5,7 +5,7 @@
5
5
  * Each transformer handles specific question type data structure.
6
6
  */
7
7
  import type { FillBlankQuestion, ChooseBestAnswerQuestion, PictureChooseSubQuestion, PictureFillBlankSubQuestion, ReadingPassageQuestion, LabelThePictureLabel, FillWordHintSubQuestion, ColoringHintItem, ColoringRegion } from '../types';
8
- export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'TRUE_FALSE' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD';
8
+ export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'TRUE_FALSE' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD';
9
9
  export interface ApiQuestion {
10
10
  id: string;
11
11
  content: any;
@@ -140,9 +140,7 @@ export declare function transformWriteCorrectVerbForm(questions: ApiQuestion[]):
140
140
  title: string;
141
141
  instruction: string;
142
142
  };
143
- export declare function transformChooseCorrectAnswer(questions: ApiQuestion[], optionsConfig?: {
144
- shuffleOptions?: boolean;
145
- }): {
143
+ export declare function transformChooseCorrectAnswer(questions: ApiQuestion[]): {
146
144
  questions: ChooseBestAnswerQuestion[];
147
145
  example?: import('../types').ChooseBestAnswerExample;
148
146
  imageUrl?: string;
@@ -157,6 +155,11 @@ export declare function transformChooseCorrectAnswer(questions: ApiQuestion[], o
157
155
  audioUrl?: string;
158
156
  instruction: string;
159
157
  };
158
+ export declare function transformChooseTheCorrectAnswerGroup(questions: ApiQuestion[]): {
159
+ questions: ChooseBestAnswerQuestion[];
160
+ example?: import('../types').ChooseBestAnswerExample;
161
+ instruction: string;
162
+ };
160
163
  export interface ChooseAdjectiveOption {
161
164
  id: string;
162
165
  label: string;
@@ -315,13 +318,6 @@ export declare function transformWriteSentences(questions: ApiQuestion[]): {
315
318
  title?: string;
316
319
  groupContent?: string;
317
320
  };
318
- export type WfsfBlankStyle = 'letter' | 'word' | 'phrase';
319
- export type WfsfWordBankEntry = {
320
- options: string[];
321
- } | {
322
- word: string;
323
- isExample?: boolean;
324
- } | null;
325
321
  export interface WordFillStructuredFormQuestion {
326
322
  id: string;
327
323
  questionNumber: number;
@@ -330,12 +326,6 @@ export interface WordFillStructuredFormQuestion {
330
326
  content: string;
331
327
  answers: Record<string, string>;
332
328
  caseSensitive: boolean;
333
- /** letter = square boxes; word / phrase = underline width */
334
- blankStyle: WfsfBlankStyle;
335
- /** WITH_OPTIONS when choice-inline options present (plan 0024). */
336
- viewMode?: string;
337
- /** Index i ↔ blank key "i" (or order of {n} appearance). */
338
- wordBank?: WfsfWordBankEntry[];
339
329
  }
340
330
  export declare function transformWordFillStructuredForm(questions: ApiQuestion[]): {
341
331
  questions: WordFillStructuredFormQuestion[];
@@ -1 +1 @@
1
- export function groupQuestionsByPart(t,e){const n=new Map,o=new Map;for(const e of t){const t=o.get(e.part_id)||[];t.push(e),o.set(e.part_id,t)}for(const[t,r]of o.entries()){const o=[...r].sort((t,e)=>t.question_number-e.question_number),i=o[0];if(!i)continue;const s=e?.find(e=>String(e.id)===String(t)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),l=u?parseInt(u[0],10):i.part_no,c=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===c?.type,p=s?.sections??[],d=new Set(p.map(t=>t.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:c,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[e,r]of s.sections.entries()){const i=o.filter(t=>{const e=t.question_number-1;return e>=r.startIndex&&e<=r.endIndex});if(!i.length)continue;const u=`${t}_section_${e}`,c=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:t,partNo:l,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:c,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((t,e)=>{const n=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder,o=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder;return n!==o?n-o:(t.questions[0]?.question_number||0)-(e.questions[0]?.question_number||0)})}export function transformFillInBlank(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload,r=[],i=t=>t.replace(/\*\*/g,"");for(const e of t){const t=e.content,n=e.is_example||!1,o=t.question||t.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const s=o.split("\n").filter(t=>t.trim());for(const o of s){const s=o.match(/\{(\d+)\}/);if(!s)continue;const a=parseInt(s[1],10),u=o.split(/\{\d+\}/),l=i(u[0]?.trim()||""),c=i(u[1]?.trim()||"");r.push({id:`${e.id}-blank-${a}`,questionNumber:e.question_number,textBefore:l,textAfter:c,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[a]:void 0})}}else{const s=o.match(/^(.*?)\{0\}(.*)$/),a=i(s?s[1].trim():o),u=i(s?s[2].trim():"");r.push({id:e.id,questionNumber:e.question_number,textBefore:a,textAfter:u,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"",imageUrl:o?n?.imageUrl:void 0,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(t){const e=t[0],n=e?.content;return{questions:t.map(t=>{const e=t.content,n=e.sentence||"",o=n.match(/^(.*?)\{0\}(.*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:t.id,questionNumber:t.question_number,textBefore:r,textAfter:i,verbHint:e.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}function t(t,e){const n=[...t];let o=function(t){let e=0;for(let n=0;n<t.length;n++)e=(e<<5)-e+t.charCodeAt(n),e|=0;return Math.abs(e)}(e);for(let t=n.length-1;t>0;t--){o=1664525*o+1013904223&2147483647;const e=o%(t+1);[n[t],n[e]]=[n[e],n[t]]}return n}const e=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(n,o){const r=o?.shuffleOptions??!0,i=n[0]?.content,s=n[0]?.questionGroup?.payload,a=n.find(t=>t.is_example),u=n.filter(t=>!t.is_example);let l;if(a){const t=a.content,n=(t.options||[]).map((t,n)=>{const o="object"==typeof t&&null!==t,r=o&&t.id?String(t.id):`${a.id}-opt-${n}`,i=o?t.text??t.content??"":String(t),s=o?t.imageUrl:void 0;return{id:r,label:e[n]||String(n+1),text:i,...s?{imageUrl:s}:{}}}),o=a.correct_answer?.answer??a.correct_answer?.optionId;let r="";if("string"==typeof o&&o){const t=n.find(t=>t.id===o);r=t?t.id:o}else"number"==typeof o&&o>=0&&o<n.length&&(r=n[o]?.id||"");l={questionNumber:a.question_number,questionText:t.question||"",options:n,correctOptionId:r||n[0]?.id||"",optionType:t.optionType||"text",imageUrl:t.imageUrl,audioUrl:t.audioUrl}}const c=u.map(n=>{const o=n.content,i=o.optionType||"text",s=(o.options||[]).map((t,o)=>{const r="object"==typeof t&&null!==t,i=r&&t.id?String(t.id):`${n.id}-opt-${o}`,s=r?t.text??t.content??"":String(t),a=r?t.imageUrl:void 0;return{id:i,label:e[o]||String(o+1),text:s,...a?{imageUrl:a}:{}}}),a=n.correct_answer?.answer??n.correct_answer?.optionId??n.correct_answer?.optionIds,u=t=>{if(null==t)return;const e=String(t),n=s.find(t=>t.id===e);if(n)return n.id;const o=e.match(/-opt-(\d+)$/);if(o){const t=parseInt(o[1],10);if(t>=0&&t<s.length)return s[t]?.id}if("number"==typeof t&&t>=0&&t<s.length)return s[t]?.id;const r=parseInt(e,10);return!isNaN(r)&&r>=0&&r<s.length&&!e.startsWith("opt-")?s[r]?.id:e};let l=[];if(Array.isArray(a))l=a.map(u).filter(t=>Boolean(t));else{const t=u(a);t&&(l=[t])}const c=r?t(s,n.id).map((t,n)=>({...t,label:e[n]||String(n+1)})):s;return{id:n.id,questionNumber:n.question_number,questionText:o.question||"",options:c,correctOptionId:l[0],correctOptionIds:l,imageUrl:o.imageUrl,audioUrl:o.audioUrl,optionType:i,multipleAnswers:Boolean(o.multipleAnswers||Array.isArray(a)),explanation:n.explanation}}),m=c.some(t=>!!t.audioUrl?.trim())||!!l?.audioUrl?.trim();return{questions:c,example:l,imageUrl:i?.imageUrl,groupImageUrl:s?.mainImageUrl||s?.imageUrl,groupTitle:s?.title,groupContent:s?.content,articles:s?.articles,audioUrl:m?void 0:i?.audioUrl,instruction:i?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseCorrectAdjective(t){return{questions:t.map(t=>{const n=t.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:t.id,questionNumber:t.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(t){const e=t.content;if(e.instructions?.mainInstruction||e.informations?.length)return{prompt:e.instructions?.mainInstruction||"",requirements:e.informations,minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages};return{prompt:e.contexts?.filter(t=>"text"===t.type).map(t=>t.text).join("\n")||"",minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages}}export function transformColorObjects(t){const e=t[0],n=e?.content,o=n?.colorNodes?.map(t=>({id:t.id,color:t.color,label:t.label}))||n?.hintItems||[],r=n?.regionNodes?.map(t=>({id:t.id,x:t.x,y:t.y,width:t.width,height:t.height,correctHintId:t.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(t){if(function(t){const e=t[0];if(!e)return!1;const n=e.content;return void 0!==n?.question&&!n?.questions&&void 0!==e.questionGroup?.payload?.passage}(t)){const n=t[0],o=n.questionGroup?.payload||{},r=t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=t[0],o=n?.content,r=o?.questions?.map((t,o)=>({id:t.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:t.question,options:(t.options||[]).map((o,r)=>({id:`${t.id||n.id}-opt-${r}`,label:e[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(t){const e=t[0],n=e?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(t=>({id:t.id,number:t.number,isPreFilled:t.isPreFilled||!1,correctAnswer:t.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function n(t){return t&&"string"==typeof t.word&&!t.subQuestions}export function transformFillWordHint(t){const e=t[0],o=e?.content;if(t.length>1&&t.every(t=>n(t.content))){const n=e.questionGroup?.payload?.hintLetters||[];return{subQuestions:t.map(t=>{const e=t.content,n=e.word.replace(/\{\d+\}/,"_");return{id:t.id,questionNumber:t.question_number,imageUrl:e.imageUrl||"",word:n}}),hintLetters:n,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(n(o)){const t=o,n=e.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(t){const e=[],n=t.split(",").map(t=>t.trim());for(const t of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(t));){const o=parseInt(n[1],10),r=t.replace(n[0],"_");e.push({index:o,displayWord:r})}}return e.sort((t,e)=>t.index-e.index),e}(t.word).map(n=>({id:`${e.id}-blank-${n.index}`,questionNumber:e.question_number,imageUrl:t.imageUrl||"",word:n.displayWord,blankIndex:n.index})),hintLetters:n,instruction:t.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((t,n)=>({id:t.id,questionNumber:e.question_number+n,imageUrl:t.imageUrl||"",word:t.word||""}))||[],hintLetters:r?.hintLetters||e.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(t){const e=t[0],n=e?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:(e.question||"").replace(/\{\d+\}/g,"______"),imageUrl:e.imageUrl,prefixText:e.prefixText,suffixText:e.suffixText,suggestedAnswers:e.suggestedAnswers,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(t){const e=t[0]?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=n&&"boolean"==typeof t.correct_answer?.answer?t.correct_answer.answer:void 0;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:e?.mainImageUrl||e?.imageUrl,groupContent:e?.content||e?.groupContent}}export function transformWordOrdering(t){return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=Array.isArray(t.correct_answer?.answer)?t.correct_answer.answer:Array.isArray(e.answer)?e.answer:void 0;return{id:t.id,questionNumber:t.question_number,words:e.words||[],imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content,r=o?.title||n?.title||t.find(t=>t.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(t=>"string"==typeof t?{word:t}:t),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let l;l="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const c=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:e?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:l,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:c,emailTo:m}}export function transformMatchByWritingAnswer(t){const e=t[0]?.questionGroup?.payload,n=t.some(t=>!!t.content?.askerName),o=t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0,askerName:e.askerName,answererName:e.answererName}}),r=e?.options?.map(t=>({answer:t.answer,imageUrl:t.imageUrl||"",content:t.content||""}))||[],i=n?t[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:e?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload;return{questions:t.map(t=>({id:t.id,questionNumber:t.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}function o(t){const e=String(t||"").toLowerCase();return"letter"===e||"box"===e?"letter":"phrase"===e||"sentence"===e?"phrase":"word"}export function transformWordFillStructuredForm(t){const e=t[0],n=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.correct_answer||{};let r=e?.content||"";const i=e?.blocks;!r&&i?.length&&(r=i.map(t=>(t.heading?`<h3>${t.heading}</h3>`:"")+(t.content||"")).join(""));const s=function(t){if(!Array.isArray(t)||0===t.length)return;const e=t.map(t=>{if(null==t)return null;if("object"!=typeof t||Array.isArray(t))return null;const e=t;if(Array.isArray(e.options)){const t=e.options.map(t=>String(t??"").trim()).filter(t=>t.length>0);return t.length>=2?{options:t}:null}const n=String(e.word??"").trim();return n?e.isExample?{word:n,isExample:!0}:{word:n}:null});return e.some(t=>null!=t)?e:void 0}(e?.wordBank),a=Boolean(s?.some(t=>null!=t&&"options"in t&&Array.isArray(t.options))),u=Boolean(s?.some(t=>null!=t&&"word"in t&&t.word)),l=e?.viewMode||(a?"WITH_OPTIONS":u?"WITH_WORD_BANK":void 0);return{id:t.id,questionNumber:t.question_number,title:e?.title||"",imageUrl:e?.imageUrl,content:r,answers:n?.answers||{},caseSensitive:n?.caseSensitive??e?.caseSensitive??!1,blankStyle:o(e?.blankStyle),...l?{viewMode:l}:{},...s?{wordBank:s}:{}}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:e?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:e?.correctAnswer?.objectId||e?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(t){return{questions:t.map(t=>{const e=t.content,n=t.questionGroup?.payload||{};return{id:t.id,questionNumber:t.question_number,audioUrl:e?.audioUrl||"",arrowNode:e?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:e?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
1
+ export function groupQuestionsByPart(t,e){const n=new Map,o=new Map;for(const e of t){const t=o.get(e.part_id)||[];t.push(e),o.set(e.part_id,t)}for(const[t,r]of o.entries()){const o=[...r].sort((t,e)=>t.question_number-e.question_number),i=o[0];if(!i)continue;const s=e?.find(e=>String(e.id)===String(t)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),c=u?parseInt(u[0],10):i.part_no,l=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===l?.type,p=s?.sections??[],d=new Set(p.map(t=>t.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const e=`${t}_part`;n.set(e,{partId:t,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:l,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const e=`${t}_part`;n.set(e,{partId:t,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[e,r]of s.sections.entries()){const i=o.filter(t=>{const e=t.question_number-1;return e>=r.startIndex&&e<=r.endIndex});if(!i.length)continue;const u=`${t}_section_${e}`,l=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:t,partNo:c,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:l,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((t,e)=>{const n=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder,o=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder;return n!==o?n-o:(t.questions[0]?.question_number||0)-(e.questions[0]?.question_number||0)})}export function transformFillInBlank(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload,r=[];for(const e of t){const t=e.content,n=e.is_example||!1,o=t.question||t.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const i=o.split("\n").filter(t=>t.trim());for(const o of i){const i=o.match(/\{(\d+)\}/);if(!i)continue;const s=parseInt(i[1],10),a=o.split(/\{\d+\}/),u=a[0]?.trim()||"",c=a[1]?.trim()||"";r.push({id:`${e.id}-blank-${s}`,questionNumber:e.question_number,textBefore:u,textAfter:c,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[s]:void 0})}}else{const i=o.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),s=i?i[1].trim():o,a=i?i[2].trim():"";r.push({id:e.id,questionNumber:e.question_number,textBefore:s,textAfter:a,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"",imageUrl:o?n?.imageUrl:void 0,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(t){const e=t[0],n=e?.content;return{questions:t.map(t=>{const e=t.content,n=e.sentence||"",o=n.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:t.id,questionNumber:t.question_number,textBefore:r,textAfter:i,verbHint:e.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}const t=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(e){const n=e[0]?.content,o=e[0]?.questionGroup?.payload,r=e.find(t=>t.is_example),i=e.filter(t=>!t.is_example);let s;if(r){const e=r.content,n=(e.options||[]).map((e,n)=>{const o="object"==typeof e&&null!==e,i=o&&e.id?String(e.id):`${r.id}-opt-${n}`,s=o?e.text??e.content??"":String(e),a=o?e.imageUrl:void 0;return{id:i,label:t[n]||String(n+1),text:s,...a?{imageUrl:a}:{}}}),o=r.correct_answer?.answer??r.correct_answer?.optionId;let i="";if("string"==typeof o&&o){const t=n.find(t=>t.id===o);i=t?t.id:o}else"number"==typeof o&&o>=0&&o<n.length&&(i=n[o]?.id||"");s={questionNumber:r.question_number,questionText:e.question||"",options:n,correctOptionId:i||n[0]?.id||"",optionType:e.optionType||"text",imageUrl:e.imageUrl,audioUrl:e.audioUrl}}const a=i.map(e=>{const n=e.content,o=n.optionType||"text",r=(n.options||[]).map((n,o)=>{const r="object"==typeof n&&null!==n,i=r&&n.id?String(n.id):`${e.id}-opt-${o}`,s=r?n.text??n.content??"":String(n),a=r?n.imageUrl:void 0;return{id:i,label:t[o]||String(o+1),text:s,...a?{imageUrl:a}:{}}}),i=e.correct_answer?.answer??e.correct_answer?.optionId??e.correct_answer?.optionIds,s=t=>{if(null==t)return;const e=String(t),n=r.find(t=>t.id===e);if(n)return n.id;const o=e.match(/-opt-(\d+)$/);if(o){const t=parseInt(o[1],10);if(t>=0&&t<r.length)return r[t]?.id}if("number"==typeof t&&t>=0&&t<r.length)return r[t]?.id;const i=parseInt(e,10);return!isNaN(i)&&i>=0&&i<r.length&&!e.startsWith("opt-")?r[i]?.id:e};let a=[];if(Array.isArray(i))a=i.map(s).filter(t=>Boolean(t));else{const t=s(i);t&&(a=[t])}return{id:e.id,questionNumber:e.question_number,questionText:n.question||"",options:r,correctOptionId:a[0],correctOptionIds:a,imageUrl:n.imageUrl,audioUrl:n.audioUrl,optionType:o,multipleAnswers:Boolean(n.multipleAnswers||Array.isArray(i)),explanation:e.explanation}}),u=a.some(t=>!!t.audioUrl?.trim())||!!s?.audioUrl?.trim();return{questions:a,example:s,imageUrl:n?.imageUrl,groupImageUrl:o?.mainImageUrl||o?.imageUrl,groupTitle:o?.title,groupContent:o?.content,articles:o?.articles,audioUrl:u?void 0:n?.audioUrl,instruction:n?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseTheCorrectAnswerGroup(e){const n=e[0],o=n?.content,r=Array.isArray(o?.items)?o.items:[],i=Array.isArray(n?.correct_answer?.answer)?n.correct_answer.answer:[],s=r.find(t=>t.isExample),a=r.filter(t=>!t.isExample),u=(e,n)=>(e||[]).map((e,o)=>{const r="object"==typeof e&&null!==e;return{id:r&&e.id?String(e.id):`${n}-opt-${o+1}`,label:t[o]||String(o+1),text:String(r?e.text??"":e),...r&&e.imageUrl?{imageUrl:e.imageUrl}:{}}});let c;if(s){const t=r.indexOf(s),e=u(s.content?.options,`${n.id}-ex`),o=s.correctAnswer?.answer||i[t]||e[0]?.id||"";c={questionNumber:s.questionNumber||t+1,questionText:s.content?.question||"",options:e,correctOptionId:o,optionType:s.content?.optionType||"text"}}return{questions:a.map(t=>{const e=r.indexOf(t),o=u(t.content?.options,`${n.id}-item-${e}`),s=t.correctAnswer?.answer||i[e]||"";return{id:`${n.id}-item-${e}`,questionNumber:t.questionNumber||e+1,questionText:t.content?.question||"",options:o,correctOptionId:s,correctOptionIds:s?[s]:[],optionType:t.content?.optionType||"text"}}),example:c,instruction:o?.meta?.instruction||"Choose the correct answer."}}export function transformChooseCorrectAdjective(e){return{questions:e.map(e=>{const n=e.content,o=n.sentence||"",r=o.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:e.id,questionNumber:e.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(t){const e=t.content;if(e.instructions?.mainInstruction||e.informations?.length)return{prompt:e.instructions?.mainInstruction||"",requirements:e.informations,minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages};return{prompt:e.contexts?.filter(t=>"text"===t.type).map(t=>t.text).join("\n")||"",minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages}}export function transformColorObjects(t){const e=t[0],n=e?.content,o=n?.colorNodes?.map(t=>({id:t.id,color:t.color,label:t.label}))||n?.hintItems||[],r=n?.regionNodes?.map(t=>({id:t.id,x:t.x,y:t.y,width:t.width,height:t.height,correctHintId:t.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(e){if(function(t){const e=t[0];if(!e)return!1;const n=e.content;return void 0!==n?.question&&!n?.questions&&void 0!==e.questionGroup?.payload?.passage}(e)){const n=e[0],o=n.questionGroup?.payload||{},r=e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=e[0],o=n?.content,r=o?.questions?.map((e,o)=>({id:e.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:e.question,options:(e.options||[]).map((o,r)=>({id:`${e.id||n.id}-opt-${r}`,label:t[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(t){const e=t[0],n=e?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(t=>({id:t.id,number:t.number,isPreFilled:t.isPreFilled||!1,correctAnswer:t.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function e(t){return t&&"string"==typeof t.word&&!t.subQuestions}export function transformFillWordHint(t){const n=t[0],o=n?.content;if(t.length>1&&t.every(t=>e(t.content))){const e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:t.map(t=>{const e=t.content,n=e.word.replace(/\{\d+\}/,"_");return{id:t.id,questionNumber:t.question_number,imageUrl:e.imageUrl||"",word:n}}),hintLetters:e,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(e(o)){const t=o,e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(t){const e=[],n=t.split(",").map(t=>t.trim());for(const t of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(t));){const o=parseInt(n[1],10),r=t.replace(n[0],"_");e.push({index:o,displayWord:r})}}return e.sort((t,e)=>t.index-e.index),e}(t.word).map(e=>({id:`${n.id}-blank-${e.index}`,questionNumber:n.question_number,imageUrl:t.imageUrl||"",word:e.displayWord,blankIndex:e.index})),hintLetters:e,instruction:t.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((t,e)=>({id:t.id,questionNumber:n.question_number+e,imageUrl:t.imageUrl||"",word:t.word||""}))||[],hintLetters:r?.hintLetters||n.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(t){const e=t[0],n=e?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:(e.question||"").replace(/\{\d+\}/g,"______"),imageUrl:e.imageUrl,prefixText:e.prefixText,suffixText:e.suffixText,suggestedAnswers:e.suggestedAnswers,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(t){const e=t[0]?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=n&&"boolean"==typeof t.correct_answer?.answer?t.correct_answer.answer:void 0;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:e?.mainImageUrl||e?.imageUrl,groupContent:e?.content||e?.groupContent}}export function transformWordOrdering(t){return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=Array.isArray(t.correct_answer?.answer)?t.correct_answer.answer:Array.isArray(e.answer)?e.answer:void 0;return{id:t.id,questionNumber:t.question_number,words:e.words||[],imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content,r=o?.title||n?.title||t.find(t=>t.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(t=>"string"==typeof t?{word:t}:t),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let c;c="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const l=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:e?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:c,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:l,emailTo:m}}export function transformMatchByWritingAnswer(t){const e=t[0]?.questionGroup?.payload,n=t.some(t=>!!t.content?.askerName),o=t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0,askerName:e.askerName,answererName:e.answererName}}),r=e?.options?.map(t=>({answer:t.answer,imageUrl:t.imageUrl||"",content:t.content||""}))||[],i=n?t[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:e?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload;return{questions:t.map(t=>({id:t.id,questionNumber:t.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}export function transformWordFillStructuredForm(t){const e=t[0],n=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.correct_answer||{};let o=e?.content||"";const r=e?.blocks;return!o&&r?.length&&(o=r.map(t=>(t.heading?`<h3>${t.heading}</h3>`:"")+(t.content||"")).join("")),{id:t.id,questionNumber:t.question_number,title:e?.title||"",imageUrl:e?.imageUrl,content:o,answers:n?.answers||{},caseSensitive:n?.caseSensitive??e?.caseSensitive??!1}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:e?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:e?.correctAnswer?.objectId||e?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(t){return{questions:t.map(t=>{const e=t.content,n=t.questionGroup?.payload||{};return{id:t.id,questionNumber:t.question_number,audioUrl:e?.audioUrl||"",arrowNode:e?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:e?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
@@ -1 +1 @@
1
- export const QUESTION_TYPE_CONFIG={FILL_IN_BLANK:{label:"Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!0},TRUE_FALSE:{label:"Đúng/Sai",requiresContent:!0,hasDedicatedComponent:!0},MATCHING:{label:"Nối",requiresContent:!0,hasDedicatedComponent:!1},ORDERING:{label:"Sắp xếp",requiresContent:!0,hasDedicatedComponent:!1},LISTENING:{label:"Nghe",requiresContent:!0,hasDedicatedComponent:!1},COLORING:{label:"Tô màu",requiresContent:!0,hasDedicatedComponent:!1},ESSAY:{label:"Viết luận",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE:{label:"Nghe - Điền chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_TICK_ANSWER:{label:"Nghe - Tick đáp án",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_FILL_NAME_NUMBER:{label:"Nghe - Điền tên/số",requiresContent:!0,hasDedicatedComponent:!1},TICK_TRUE_OR_FALSE:{label:"Đọc - Tick/Cross",requiresContent:!0,hasDedicatedComponent:!1},TICK_YES_OR_NO:{label:"Đọc - Tick/Cross (Yes/No)",requiresContent:!0,hasDedicatedComponent:!1},READING_TICK_CROSS:{label:"Đọc - Tick/Cross (Reading)",requiresContent:!0,hasDedicatedComponent:!1},ARRANGE_LETTERS_INTO_WORDS:{label:"Đọc - Sắp xếp chữ cái",requiresContent:!0,hasDedicatedComponent:!0},READ_PASSAGE_AND_COMPLETE_STORY:{label:"Đọc - Điền vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!1},READ_PASSAGE_AND_ANSWER_QUESTIONS:{label:"Đọc đoạn văn và trả lời câu hỏi",requiresContent:!0,hasDedicatedComponent:!0},CLOZE_TEST_WITH_TICK_BOX:{label:"Cloze test với tick box",requiresContent:!0,hasDedicatedComponent:!1},READ_AND_CHOOSE_APPROPRIATE_WORD:{label:"Đọc - Chọn từ phù hợp",requiresContent:!0,hasDedicatedComponent:!1},WRITE_SHORT_PARAGRAPH:{label:"Viết - Đoạn văn ngắn",requiresContent:!0,hasDedicatedComponent:!0},FILL_MISSING_WORDS_IN_GRID:{label:"Điền từ còn thiếu vào grid",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:{label:"Nhìn tranh, chọn đáp án đúng",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:{label:"Nhìn tranh, điền chỗ trống, chọn đáp án",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_FILL_WORD_HINT:{label:"Nhìn tranh điền từ gợi ý",requiresContent:!0,hasDedicatedComponent:!0},LABEL_THE_PICTURE:{label:"Label the Picture",requiresContent:!0,hasDedicatedComponent:!0},READ_AND_COLOR_OBJECTS:{label:"Read and Color Objects",requiresContent:!0,hasDedicatedComponent:!0},IMAGE_OBJECT_MATCHING:{label:"Image Object Matching",requiresContent:!0,hasDedicatedComponent:!0},LISTENING_FILL_BLANK:{label:"Nghe - Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},LISTENING_COLOR:{label:"Nghe - Tô màu",requiresContent:!0,hasDedicatedComponent:!1},READING_LETTER_ARRANGE:{label:"Đọc - Sắp xếp chữ cái",requiresContent:!0,hasDedicatedComponent:!1},READING_PASSAGE_FILL:{label:"Đọc - Điền vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!1},FILL_BLANK:{label:"Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},CHOOSE_THE_CORRECT_ANSWER:{label:"Choose the correct answer",requiresContent:!1,hasDedicatedComponent:!0},WRITE_A_SHORT_LETTER:{label:"Write a Short Letter",requiresContent:!0,hasDedicatedComponent:!0},WRITE_CORRECT_VERB_FORM:{label:"Viết dạng đúng của động từ",requiresContent:!0,hasDedicatedComponent:!0},CHOOSE_CORRECT_ADJECTIVE:{label:"Chọn dạng đúng của tính từ",requiresContent:!0,hasDedicatedComponent:!0},ANSWER_THE_QUESTION:{label:"Nghe - Đọc câu hỏi và viết đáp án",requiresContent:!0,hasDedicatedComponent:!0},WORD_ORDERING:{label:"Sắp xếp từ",requiresContent:!0,hasDedicatedComponent:!0},WORD_FILL_PARAGRAPH:{label:"Điền từ vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!0},MATCH_BY_WRITING_ANSWER:{label:"Ghép đáp án bằng cách viết",requiresContent:!0,hasDedicatedComponent:!0},WRITE_SENTENCES:{label:"Viết câu",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP:{label:"Nghe và chọn trong nhóm đáp án",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE:{label:"Nghe và chọn đối tượng trong cảnh",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_DRAG_OBJECTS_INTO_SCENE:{label:"Nghe và kéo thả đối tượng vào cảnh",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_ANSWER:{label:"Nghe và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_IMAGE_GROUP:{label:"Nghe, nhìn nhóm ảnh và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_QUESTION_LIST:{label:"Nghe, chọn câu hỏi và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_COMPARE_IMAGES:{label:"Nghe và So sánh điểm khác biệt (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_WITH_STORY_IMAGES:{label:"Nghe, nhìn ảnh truyện và kể lại (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_ODD_ONE_OUT:{label:"Nghe, chọn hình khác loại và giải thích (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_INFO_EXCHANGE:{label:"Trao đổi thông tin (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},READ_DISPLAYED_CONTENT:{label:"Đọc nội dung hiển thị (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_DESCRIBE_IMAGE:{label:"Nhìn tranh mô tả (Speaking Part 2)",requiresContent:!0,hasDedicatedComponent:!0},SPONTANEOUS_QA:{label:"Hỏi đáp tự phát (Speaking Part 3)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_CONVERSATION:{label:"Hội thoại Speaking (KFS Speaking)",requiresContent:!0,hasDedicatedComponent:!0},GN_SPEAKING_INTERVIEW:{label:"GN Speaking - Hỏi đáp (Virtual + Real)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_CUE_CARD:{label:"IELTS Cue Card (Speaking Part 2)",requiresContent:!0,hasDedicatedComponent:!0},WORD_FILL_STRUCTURED_FORM:{label:"Điền từ vào biểu mẫu có cấu trúc",requiresContent:!0,hasDedicatedComponent:!0}};export const QUESTION_TYPES_WITH_DEDICATED_COMPONENTS=["FILL_IN_BLANK","ARRANGE_LETTERS_INTO_WORDS","WRITE_SHORT_PARAGRAPH","FILL_MISSING_WORDS_IN_GRID","LOOK_PICTURE_CHOOSE_CORRECT_ANSWER","LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER","LOOK_PICTURE_FILL_WORD_HINT","LABEL_THE_PICTURE","READ_AND_COLOR_OBJECTS","IMAGE_OBJECT_MATCHING","READ_PASSAGE_AND_ANSWER_QUESTIONS","CHOOSE_THE_CORRECT_ANSWER","WRITE_A_SHORT_LETTER","WRITE_CORRECT_VERB_FORM","CHOOSE_CORRECT_ADJECTIVE","ANSWER_THE_QUESTION","TRUE_FALSE","WORD_ORDERING","WORD_FILL_PARAGRAPH","MATCH_BY_WRITING_ANSWER","WRITE_SENTENCES","LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP","LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE","LISTEN_AND_DRAG_OBJECTS_INTO_SCENE","LISTEN_AND_SPEAK_ANSWER","LISTEN_AND_SPEAK_IMAGE_GROUP","LISTEN_AND_SPEAK_QUESTION_LIST","LISTEN_AND_SPEAK_COMPARE_IMAGES","LISTEN_AND_SPEAK_WITH_STORY_IMAGES","LISTEN_AND_SPEAK_ODD_ONE_OUT","LISTEN_AND_SPEAK_INFO_EXCHANGE","READ_DISPLAYED_CONTENT","SPEAKING_DESCRIBE_IMAGE","SPONTANEOUS_QA","SPEAKING_CONVERSATION","GN_SPEAKING_INTERVIEW","SPEAKING_CUE_CARD","WORD_FILL_STRUCTURED_FORM"];export function getQuestionTypeLabel(e){return QUESTION_TYPE_CONFIG[e]?.label||e}
1
+ export const QUESTION_TYPE_CONFIG={FILL_IN_BLANK:{label:"Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!0},TRUE_FALSE:{label:"Đúng/Sai",requiresContent:!0,hasDedicatedComponent:!0},MATCHING:{label:"Nối",requiresContent:!0,hasDedicatedComponent:!1},ORDERING:{label:"Sắp xếp",requiresContent:!0,hasDedicatedComponent:!1},LISTENING:{label:"Nghe",requiresContent:!0,hasDedicatedComponent:!1},COLORING:{label:"Tô màu",requiresContent:!0,hasDedicatedComponent:!1},ESSAY:{label:"Viết luận",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE:{label:"Nghe - Điền chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_TICK_ANSWER:{label:"Nghe - Tick đáp án",requiresContent:!0,hasDedicatedComponent:!1},LISTEN_AND_FILL_NAME_NUMBER:{label:"Nghe - Điền tên/số",requiresContent:!0,hasDedicatedComponent:!1},TICK_TRUE_OR_FALSE:{label:"Đọc - Tick/Cross",requiresContent:!0,hasDedicatedComponent:!1},TICK_YES_OR_NO:{label:"Đọc - Tick/Cross (Yes/No)",requiresContent:!0,hasDedicatedComponent:!1},READING_TICK_CROSS:{label:"Đọc - Tick/Cross (Reading)",requiresContent:!0,hasDedicatedComponent:!1},ARRANGE_LETTERS_INTO_WORDS:{label:"Đọc - Sắp xếp chữ cái",requiresContent:!0,hasDedicatedComponent:!0},READ_PASSAGE_AND_COMPLETE_STORY:{label:"Đọc - Điền vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!1},READ_PASSAGE_AND_ANSWER_QUESTIONS:{label:"Đọc đoạn văn và trả lời câu hỏi",requiresContent:!0,hasDedicatedComponent:!0},CLOZE_TEST_WITH_TICK_BOX:{label:"Cloze test với tick box",requiresContent:!0,hasDedicatedComponent:!1},READ_AND_CHOOSE_APPROPRIATE_WORD:{label:"Đọc - Chọn từ phù hợp",requiresContent:!0,hasDedicatedComponent:!1},WRITE_SHORT_PARAGRAPH:{label:"Viết - Đoạn văn ngắn",requiresContent:!0,hasDedicatedComponent:!0},FILL_MISSING_WORDS_IN_GRID:{label:"Điền từ còn thiếu vào grid",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:{label:"Nhìn tranh, chọn đáp án đúng",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:{label:"Nhìn tranh, điền chỗ trống, chọn đáp án",requiresContent:!0,hasDedicatedComponent:!0},LOOK_PICTURE_FILL_WORD_HINT:{label:"Nhìn tranh điền từ gợi ý",requiresContent:!0,hasDedicatedComponent:!0},LABEL_THE_PICTURE:{label:"Label the Picture",requiresContent:!0,hasDedicatedComponent:!0},READ_AND_COLOR_OBJECTS:{label:"Read and Color Objects",requiresContent:!0,hasDedicatedComponent:!0},IMAGE_OBJECT_MATCHING:{label:"Image Object Matching",requiresContent:!0,hasDedicatedComponent:!0},LISTENING_FILL_BLANK:{label:"Nghe - Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},LISTENING_COLOR:{label:"Nghe - Tô màu",requiresContent:!0,hasDedicatedComponent:!1},READING_LETTER_ARRANGE:{label:"Đọc - Sắp xếp chữ cái",requiresContent:!0,hasDedicatedComponent:!1},READING_PASSAGE_FILL:{label:"Đọc - Điền vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!1},FILL_BLANK:{label:"Điền vào chỗ trống",requiresContent:!0,hasDedicatedComponent:!1},CHOOSE_THE_CORRECT_ANSWER:{label:"Choose the correct answer",requiresContent:!1,hasDedicatedComponent:!0},CHOOSE_THE_CORRECT_ANSWER_GROUP:{label:"Choose the correct answer (group)",requiresContent:!0,hasDedicatedComponent:!0},TRUE_FALSE_GROUP:{label:"Đúng/Sai (nhóm)",requiresContent:!0,hasDedicatedComponent:!0},CROSS_OUT_WORD_GROUP:{label:"Cross out word (group)",requiresContent:!0,hasDedicatedComponent:!0},WRITE_A_SHORT_LETTER:{label:"Write a Short Letter",requiresContent:!0,hasDedicatedComponent:!0},WRITE_CORRECT_VERB_FORM:{label:"Viết dạng đúng của động từ",requiresContent:!0,hasDedicatedComponent:!0},CHOOSE_CORRECT_ADJECTIVE:{label:"Chọn dạng đúng của tính từ",requiresContent:!0,hasDedicatedComponent:!0},ANSWER_THE_QUESTION:{label:"Nghe - Đọc câu hỏi và viết đáp án",requiresContent:!0,hasDedicatedComponent:!0},WORD_ORDERING:{label:"Sắp xếp từ",requiresContent:!0,hasDedicatedComponent:!0},WORD_FILL_PARAGRAPH:{label:"Điền từ vào đoạn văn",requiresContent:!0,hasDedicatedComponent:!0},MATCH_BY_WRITING_ANSWER:{label:"Ghép đáp án bằng cách viết",requiresContent:!0,hasDedicatedComponent:!0},WRITE_SENTENCES:{label:"Viết câu",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP:{label:"Nghe và chọn trong nhóm đáp án",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE:{label:"Nghe và chọn đối tượng trong cảnh",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_DRAG_OBJECTS_INTO_SCENE:{label:"Nghe và kéo thả đối tượng vào cảnh",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_ANSWER:{label:"Nghe và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_IMAGE_GROUP:{label:"Nghe, nhìn nhóm ảnh và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_QUESTION_LIST:{label:"Nghe, chọn câu hỏi và trả lời (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_COMPARE_IMAGES:{label:"Nghe và So sánh điểm khác biệt (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_WITH_STORY_IMAGES:{label:"Nghe, nhìn ảnh truyện và kể lại (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_ODD_ONE_OUT:{label:"Nghe, chọn hình khác loại và giải thích (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},LISTEN_AND_SPEAK_INFO_EXCHANGE:{label:"Trao đổi thông tin (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},READ_DISPLAYED_CONTENT:{label:"Đọc nội dung hiển thị (Speaking)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_DESCRIBE_IMAGE:{label:"Nhìn tranh mô tả (Speaking Part 2)",requiresContent:!0,hasDedicatedComponent:!0},SPONTANEOUS_QA:{label:"Hỏi đáp tự phát (Speaking Part 3)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_CONVERSATION:{label:"Hội thoại Speaking (KFS Speaking)",requiresContent:!0,hasDedicatedComponent:!0},GN_SPEAKING_INTERVIEW:{label:"GN Speaking - Hỏi đáp (Virtual + Real)",requiresContent:!0,hasDedicatedComponent:!0},SPEAKING_CUE_CARD:{label:"IELTS Cue Card (Speaking Part 2)",requiresContent:!0,hasDedicatedComponent:!0},WORD_FILL_STRUCTURED_FORM:{label:"Điền từ vào biểu mẫu có cấu trúc",requiresContent:!0,hasDedicatedComponent:!0}};export const QUESTION_TYPES_WITH_DEDICATED_COMPONENTS=["FILL_IN_BLANK","ARRANGE_LETTERS_INTO_WORDS","WRITE_SHORT_PARAGRAPH","FILL_MISSING_WORDS_IN_GRID","LOOK_PICTURE_CHOOSE_CORRECT_ANSWER","LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER","LOOK_PICTURE_FILL_WORD_HINT","LABEL_THE_PICTURE","READ_AND_COLOR_OBJECTS","IMAGE_OBJECT_MATCHING","READ_PASSAGE_AND_ANSWER_QUESTIONS","CHOOSE_THE_CORRECT_ANSWER","CHOOSE_THE_CORRECT_ANSWER_GROUP","TRUE_FALSE_GROUP","CROSS_OUT_WORD_GROUP","WRITE_A_SHORT_LETTER","WRITE_CORRECT_VERB_FORM","CHOOSE_CORRECT_ADJECTIVE","ANSWER_THE_QUESTION","TRUE_FALSE","WORD_ORDERING","WORD_FILL_PARAGRAPH","MATCH_BY_WRITING_ANSWER","WRITE_SENTENCES","LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP","LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE","LISTEN_AND_DRAG_OBJECTS_INTO_SCENE","LISTEN_AND_SPEAK_ANSWER","LISTEN_AND_SPEAK_IMAGE_GROUP","LISTEN_AND_SPEAK_QUESTION_LIST","LISTEN_AND_SPEAK_COMPARE_IMAGES","LISTEN_AND_SPEAK_WITH_STORY_IMAGES","LISTEN_AND_SPEAK_ODD_ONE_OUT","LISTEN_AND_SPEAK_INFO_EXCHANGE","READ_DISPLAYED_CONTENT","SPEAKING_DESCRIBE_IMAGE","SPONTANEOUS_QA","SPEAKING_CONVERSATION","GN_SPEAKING_INTERVIEW","SPEAKING_CUE_CARD","WORD_FILL_STRUCTURED_FORM"];export function getQuestionTypeLabel(e){return QUESTION_TYPE_CONFIG[e]?.label||e}
@@ -0,0 +1,36 @@
1
+ export interface ChooseTheCorrectAnswerGroupOptionData {
2
+ id: string;
3
+ text: string;
4
+ }
5
+ export interface ChooseTheCorrectAnswerGroupItemData {
6
+ question: string;
7
+ optionType: 'text' | 'image';
8
+ options: ChooseTheCorrectAnswerGroupOptionData[];
9
+ correctAnswer: string;
10
+ isExample?: boolean;
11
+ points: number;
12
+ questionNumber: number;
13
+ }
14
+ export interface ChooseTheCorrectAnswerGroupData {
15
+ instruction: string;
16
+ items: ChooseTheCorrectAnswerGroupItemData[];
17
+ explanation?: string;
18
+ points?: number;
19
+ }
20
+ export interface ChooseTheCorrectAnswerGroupCreatorProps {
21
+ initialData?: ChooseTheCorrectAnswerGroupData;
22
+ onSave?: (data: ChooseTheCorrectAnswerGroupData) => void;
23
+ onCancel?: () => void;
24
+ onChange?: (data: ChooseTheCorrectAnswerGroupData) => void;
25
+ externalErrors?: string[];
26
+ onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void;
27
+ validationRef?: React.MutableRefObject<{
28
+ triggerValidation: () => Promise<boolean>;
29
+ getFormData?: () => ChooseTheCorrectAnswerGroupData;
30
+ } | null>;
31
+ }
32
+ export interface ChooseTheCorrectAnswerGroupClientProps {
33
+ questionData: ChooseTheCorrectAnswerGroupData;
34
+ isReviewMode?: boolean;
35
+ userAnswers?: string[];
36
+ }