@tinyweb_dev/oe-exam-sdk 0.1.23 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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 và MCP tools.
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.
4
4
 
5
5
  ## Cài đặt
6
6
 
@@ -91,7 +91,6 @@ 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
95
94
  @tinyweb_dev/oe-exam-sdk/components # shared UI components
96
95
  @tinyweb_dev/oe-exam-sdk/components/exams # màn tạo đề / câu hỏi / làm bài / vào phòng
97
96
  @tinyweb_dev/oe-exam-sdk/components/exams/entry # màn vào phòng (entry) + state machine
@@ -238,16 +237,16 @@ Các report shell, renderer, transform helper, polling/status helper và result-
238
237
 
239
238
  ## MCP server
240
239
 
241
- SDK expose bin:
240
+ MCP đã tách sang package riêng:
242
241
 
243
242
  ```bash
244
- oe-exam-mcp
243
+ npm install @tinyweb_dev/oe-exam-mcp-server
245
244
  ```
246
245
 
247
246
  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`.
248
247
 
249
248
  ```bash
250
- OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx oe-exam-mcp
249
+ OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx @tinyweb_dev/oe-exam-mcp-server
251
250
  ```
252
251
 
253
252
  Tools hiện có:
@@ -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-[7rem] max-w-[14rem] rounded border px-2 py-1 text-center":w?"h-7 w-7 rounded border-2 px-0 text-center uppercase":y?"min-w-[140px] max-w-[280px] rounded-t border-b-2 px-2 py-0.5 text-center":"min-w-[90px] max-w-[160px] rounded-t border-b-2 px-2 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"),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 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))})]})}
@@ -140,7 +140,9 @@ export declare function transformWriteCorrectVerbForm(questions: ApiQuestion[]):
140
140
  title: string;
141
141
  instruction: string;
142
142
  };
143
- export declare function transformChooseCorrectAnswer(questions: ApiQuestion[]): {
143
+ export declare function transformChooseCorrectAnswer(questions: ApiQuestion[], optionsConfig?: {
144
+ shuffleOptions?: boolean;
145
+ }): {
144
146
  questions: ChooseBestAnswerQuestion[];
145
147
  example?: import('../types').ChooseBestAnswerExample;
146
148
  imageUrl?: string;
@@ -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."}}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 transformChooseCorrectAdjective(e){return{questions:e.map(e=>{const n=e.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),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 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 n(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],o=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,o=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:o?.answers||{},caseSensitive:o?.caseSensitive??e?.caseSensitive??!1,blankStyle:n(e?.blankStyle),...l?{viewMode:l}:{},...s?{wordBank:s}:{}}}),instruction:o?.instructions||"COMPLETE THE FORM BELOW",groupTitle:o?.title,groupContent:o?.content,groupImageUrl:o?.imageUrl,audioUrl:e?.audio_url||o?.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+/),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 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import r,{useState as l,useEffect as n,useMemo as a,useCallback as i}from"react";import{Check as o,X as s}from"lucide-react";import{usePresignedFileUrl as d}from"../../../../shared/lib/hooks";import{cn as c}from"../../../../shared/lib/utils";export function WordFillStructuredFormClient({questionData:p,isReviewMode:m=!1,userAnswer:u,onAnswerChange:g,autoFillCorrectAnswers:b=!1,explanation:f,questionNumber:h}){const{title:x="",imageUrl:w,content:y="",answers:v={},blankStyle:k,caseSensitive:N=!1,wordBank:_}=p,A=function(e){const t=String(e||"").toLowerCase();return"letter"===t||"box"===t?"letter":"phrase"===t||"sentence"===t?"phrase":"word"}(k),C=function(e){if(!Array.isArray(e)||0===e.length)return;const t=e.map(e=>{if(null==e)return null;if("object"!=typeof e||Array.isArray(e))return null;const t=e;if(Array.isArray(t.options)){const e=t.options.map(e=>String(e??"").trim()).filter(e=>e.length>0);return e.length>=2?{options:e}:null}const r=String(t.word??"").trim();return r?t.isExample?{word:r,isExample:!0}:{word:r}:null});return t.some(e=>null!=e)?t:void 0}(_),S=a(()=>function(e){if(!e?.length)return[];const t=[];for(const r of e)if(r&&"word"in r&&"string"==typeof r.word&&r.word){const e="isExample"in r&&Boolean(r.isExample);t.push(e?{word:r.word,isExample:!0}:{word:r.word})}return t}(C),[C]),$=String(p.viewMode||""),B=S.length>0&&("WITH_WORD_BANK"===$||!C?.some(e=>null!=e&&"options"in e&&Array.isArray(e.options))),[E,W]=l(()=>u?{...u}:b?{...v}:{});n(()=>{u&&W({...u})},[u]);const{previewUrl:L,isLoading:j}=d(w||""),T=a(()=>{const e=new Set,t=/\{([\w\d]+)\}/g;let r;for(;null!==(r=t.exec(y));)e.add(r[1]);return Array.from(e).sort((e,t)=>{const r=parseInt(e),l=parseInt(t);return isNaN(r)||isNaN(l)?e.localeCompare(t):r-l})},[y]),F=T.every(e=>E[e]?.trim()),O=m&&T.every(e=>{const t=(E[e]||"").trim(),r=(v[e]||"").trim();return N?t===r:t.toLowerCase()===r.toLowerCase()}),D=String(f||p.explanation||"").trim(),H="number"==typeof h&&h>0?`Bài ${h}`:"",M=i((e,t)=>{m||(W(r=>({...r,[e]:t})),g?.(e,t))},[m,g]),z=i((r,l)=>{const n=E[r]||"",a=v[r]||"",i=N?n.trim():n.trim().toLowerCase(),d=N?a.trim():a.trim().toLowerCase(),p=m&&i===d,u=m&&!!n&&i!==d,g="letter"===A,b="phrase"===A,f=g?1:void 0,h=function(e,t,r){if(!e?.length)return null;const l=Number(t);let n;if(Number.isFinite(l)&&l>=0&&l<e.length)n=e[l];else{const l=r.indexOf(t);l>=0&&l<e.length&&(n=e[l])}return null!=n&&"options"in n&&n.options?.length?n.options:null}(C,r,T),x=Boolean(h&&h.length>=2),w=g?{display:"inline-block",width:"1.625rem",height:"1.625rem",minWidth:"1.625rem",maxWidth:"1.625rem",padding:0,margin:"0 1px",borderWidth:2,borderStyle:"solid",borderColor:m?p?"#10b981":u?"#f43f5e":"#f59e0b":"#94a3b8",borderRadius:4,textAlign:"center",fontSize:"0.8125rem",fontWeight:700,lineHeight:"1.375rem",textTransform:"uppercase",backgroundColor:m?p?"#ecfdf5":u?"#fff1f2":"#fffbeb":"#ffffff",color:m?p?"#065f46":u?"#9f1239":"#92400e":"#1e293b",verticalAlign:"middle",outline:"none",boxSizing:"border-box"}:void 0,y=m?p?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":u?"border-rose-500 bg-rose-50 text-rose-800 font-bold":"border-amber-500 bg-amber-50 text-amber-800":"border-slate-400 text-slate-800 focus:border-teal-600";return t("span",{className:c("relative inline-flex items-center",g?"mx-px":"mx-1 align-baseline"),style:g?{display:"inline-flex",verticalAlign:"middle",whiteSpace:"nowrap",flexShrink:0}:void 0,children:[!g&&e("span",{className:"absolute -top-4 left-1 text-[10px] font-semibold text-gray-400",children:r}),x&&h?t("select",{value:n,disabled:m,onChange:e=>M(r,e.target.value),"aria-label":`Blank ${r}`,className:c("inline-block min-w-[7rem] max-w-[14rem] rounded border bg-white px-2 py-1 text-sm font-semibold outline-none transition-all align-baseline",y,!m&&"hover:border-teal-500 focus:border-teal-600 focus:ring-1 focus:ring-teal-200"),children:[e("option",{value:"",children:"—"}),h.map(t=>e("option",{value:t,children:t},t))]}):e("input",{type:"text",value:n,onChange:e=>{const t=e.target.value,l=g?t.slice(-1).replace(/\s/g,""):t;M(r,l)},disabled:m,placeholder:"",maxLength:f,inputMode:g?"text":void 0,autoComplete:"off",spellCheck:!1,"aria-label":`Blank ${r}`,style:w,className:c(!g&&"inline-block bg-slate-50/40 text-center text-sm font-semibold outline-none transition-all align-baseline hover:bg-slate-100/60 focus:bg-teal-50/60 focus:ring-0",!g&&(b?"min-w-[140px] max-w-[280px] rounded-t border-b-2 px-2 py-0.5":"min-w-[90px] max-w-[160px] rounded-t border-b-2 px-2 py-0.5"),!g&&y)}),m&&n&&(p?e(o,{className:"ml-0.5 h-3.5 w-3.5 shrink-0 text-green-600"}):e(s,{className:"ml-0.5 h-3.5 w-3.5 shrink-0 text-red-600"}))]},l)},[v,A,N,T,E,M,m,C]),I=a(()=>{if("undefined"==typeof window)return y;const t=(new DOMParser).parseFromString(y||"<p></p>","text/html"),l=/\{([\w\d]+)\}/g,n="letter"===A,a=(t,i)=>{if(t.nodeType===Node.TEXT_NODE)return((t,a)=>{if(!t)return null;const i=[];let o,s=0;for(l.lastIndex=0;null!==(o=l.exec(t));)o.index>s&&i.push({kind:"text",value:t.slice(s,o.index)}),i.push({kind:"blank",key:o[1],index:o.index}),s=o.index+o[0].length;if(s<t.length&&i.push({kind:"text",value:t.slice(s)}),!i.length)return null;if(!n){const t=i.map((e,t)=>"text"===e.kind?e.value:z(e.key,`${a}-blank-${e.index}-${t}`));return 1===t.length?t[0]:e(r.Fragment,{children:t},a)}const d=[];let c=[],p=0;const m=()=>{c.length&&(d.push(e("span",{style:{display:"inline",whiteSpace:"nowrap",verticalAlign:"baseline"},children:c},`${a}-w${p}`)),p+=1,c=[])};for(let e=0;e<i.length;e+=1){const t=i[e];if("blank"===t.kind){c.push(z(t.key,`${a}-blank-${t.index}-${e}`));continue}const r=t.value.split(/(\s+)/);for(let e=0;e<r.length;e+=1){const t=r[e];t&&(/^\s+$/.test(t)?(m(),d.push(t)):c.push(t))}}return m(),d.length?1===d.length?d[0]:e(r.Fragment,{children:d},a):null})(t.textContent||"",i);if(t.nodeType!==Node.ELEMENT_NODE)return null;const o=t,s=o.tagName.toLowerCase(),d={key:i};let c="",p={};Array.from(o.attributes).forEach(e=>{var t;if("class"!==e.name)return"style"===e.name?(t=e.value,void(p=t.split(";").map(e=>e.trim()).filter(Boolean).reduce((e,t)=>{const[r,l]=t.split(":").map(e=>e.trim());return r&&l?(e[r.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())]=l,e):e},{}))):void(d[e.name]=e.value);c=e.value});const m=c.split(/\s+/).filter(Boolean);m.includes("wfsf-block")&&(p={display:"block",margin:"0 0 1.25rem 0",padding:"0.35rem 0 1rem 0",borderBottom:"1px solid #e2e8f0",...p}),m.includes("wfsf-item-no")&&(p={fontWeight:700,fontSize:"1rem",lineHeight:1.4,margin:"0 0 0.4rem 0",color:"#0f172a",...p}),"table"===s&&m.includes("dialogue")&&(p={width:"100%",borderCollapse:"collapse",tableLayout:"auto",...p}),"td"===s&&m.includes("speaker")?p={width:"1%",whiteSpace:"nowrap",verticalAlign:"top",paddingRight:"12px",paddingTop:"6px",paddingBottom:"6px",fontWeight:600,color:"#0f172a",...p}:"td"===s&&!m.includes("speaker")&&o.closest?.("table.dialogue")&&(p={verticalAlign:"top",paddingTop:"6px",paddingBottom:"6px",width:"auto",...p}),c&&(d.className=c),Object.keys(p).length>0&&(d.style=p);const u=Array.from(o.childNodes).map((e,t)=>a(e,`${i}-${t}`)).filter(e=>null!==e);return r.createElement(s,d,...u)};return Array.from(t.body.childNodes).map((e,t)=>a(e,`root-${t}`)).filter(e=>null!==e)},[A,y,z]);return e("div",{className:"space-y-4",children:t("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[(H||D||m&&F)&&e("div",{className:"border-b border-gray-100 bg-white px-5 py-4",children:t("div",{className:"flex items-start justify-between gap-3",children:[t("div",{className:"min-w-0 space-y-1.5",children:[H?e("h2",{className:"text-lg font-bold tracking-tight text-slate-900",children:H}):null,D?e("p",{className:"text-sm leading-relaxed whitespace-pre-line text-slate-700",children:D}):null]}),m&&F?t("div",{className:c("flex shrink-0 items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",O?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(O?o:s,{className:"h-3.5 w-3.5"}),O?"Đúng":"Sai"]}):null]})}),t("div",{className:"space-y-5 p-5",children:[x?e("h3",{className:"text-center text-base font-semibold text-gray-900",children:x}):null,(L||w)&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:j?e("div",{className:"flex h-48 w-48 items-center justify-center",children:e("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-teal-500"})}):e("img",{src:L||w,alt:x||H||"Hình minh họa",className:"max-h-56 w-auto object-contain p-2"})})}),B?t("div",{className:"word-bank-shared space-y-2",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-gray-500",children:"Word Bank"}),e("div",{className:"flex flex-wrap gap-2",children:S.map((t,r)=>e("span",{className:c("rounded-lg border-2 px-3 py-1.5 text-sm font-semibold",t.isExample?"border-amber-300 bg-amber-50 text-amber-800":"border-sky-200 bg-sky-50 text-sky-900"),children:t.word},`wb-${r}-${t.word}`))})]}):null,e("div",{className:c("structured-form-content space-y-2 rounded-lg border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-5 text-base leading-relaxed text-gray-800","[&_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 [&_table.dialogue_td]:leading-relaxed","[&_table.dialogue_td:not(.speaker)]:w-auto","[&_table:not(.dialogue)]:w-full [&_table:not(.dialogue)]:border-collapse"),style:"letter"===A?{wordBreak:"normal",overflowWrap:"break-word",lineHeight:1.7}:void 0,children:I}),m&&!O&&t("div",{className:"rounded-lg border border-green-200 bg-green-50 p-3",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-green-600",children:"Đáp án đúng"}),e("div",{className:"mt-2 flex flex-wrap gap-2",children:T.map(e=>t("span",{className:"rounded-lg border border-green-300 bg-green-100 px-3 py-1.5 text-sm font-semibold text-green-800",children:[`{${e}}`,": ",v[e]]},e))})]})]})]})})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import r,{useState as l,useEffect as n,useMemo as a,useCallback as i}from"react";import{Check as o,X as s}from"lucide-react";import{usePresignedFileUrl as d}from"../../../../shared/lib/hooks";import{cn as c}from"../../../../shared/lib/utils";export function WordFillStructuredFormClient({questionData:m,isReviewMode:p=!1,userAnswer:u,onAnswerChange:g,autoFillCorrectAnswers:b=!1,explanation:f,questionNumber:h}){const{title:x="",imageUrl:w,content:y="",answers:v={},blankStyle:k,caseSensitive:N=!1,wordBank:_}=m,A=function(e){const t=String(e||"").toLowerCase();return"letter"===t||"box"===t?"letter":"phrase"===t||"sentence"===t?"phrase":"word"}(k),C=function(e){if(!Array.isArray(e)||0===e.length)return;const t=e.map(e=>{if(null==e)return null;if("object"!=typeof e||Array.isArray(e))return null;const t=e;if(Array.isArray(t.options)){const e=t.options.map(e=>String(e??"").trim()).filter(e=>e.length>0);return e.length>=2?{options:e}:null}const r=String(t.word??"").trim();return r?t.isExample?{word:r,isExample:!0}:{word:r}:null});return t.some(e=>null!=e)?t:void 0}(_),S=a(()=>function(e){if(!e?.length)return[];const t=[];for(const r of e)if(r&&"word"in r&&"string"==typeof r.word&&r.word){const e="isExample"in r&&Boolean(r.isExample);t.push(e?{word:r.word,isExample:!0}:{word:r.word})}return t}(C),[C]),$=String(m.viewMode||""),B=S.length>0&&("WITH_WORD_BANK"===$||!C?.some(e=>null!=e&&"options"in e&&Array.isArray(e.options))),[E,W]=l(()=>u?{...u}:b?{...v}:{});n(()=>{u&&W({...u})},[u]);const{previewUrl:L,isLoading:j}=d(w||""),T=a(()=>{const e=new Set,t=/\{([\w\d]+)\}/g;let r;for(;null!==(r=t.exec(y));)e.add(r[1]);return Array.from(e).sort((e,t)=>{const r=parseInt(e),l=parseInt(t);return isNaN(r)||isNaN(l)?e.localeCompare(t):r-l})},[y]),F=T.every(e=>E[e]?.trim()),O=p&&T.every(e=>{const t=(E[e]||"").trim(),r=(v[e]||"").trim();return N?t===r:t.toLowerCase()===r.toLowerCase()}),z=String(f||m.explanation||"").trim(),D="number"==typeof h&&h>0?`Bài ${h}`:"",H=i((e,t)=>{p||(W(r=>({...r,[e]:t})),g?.(e,t))},[p,g]),M=i((r,l)=>{const n=E[r]||"",a=v[r]||"",i=N?n.trim():n.trim().toLowerCase(),d=N?a.trim():a.trim().toLowerCase(),m=p&&i===d,u=p&&!!n&&i!==d,g="letter"===A,b="phrase"===A,f=g?1:void 0,h=function(e,t,r){if(!e?.length)return null;const l=Number(t);let n;if(Number.isFinite(l)&&l>=0&&l<e.length)n=e[l];else{const l=r.indexOf(t);l>=0&&l<e.length&&(n=e[l])}return null!=n&&"options"in n&&n.options?.length?n.options:null}(C,r,T),x=Boolean(h&&h.length>=2),w=g?{display:"inline-block",width:"1.625rem",height:"1.625rem",minWidth:"1.625rem",maxWidth:"1.625rem",padding:0,margin:"0 1px",borderWidth:2,borderStyle:"solid",borderColor:p?m?"#10b981":u?"#f43f5e":"#f59e0b":"#94a3b8",borderRadius:4,textAlign:"center",fontSize:"0.8125rem",fontWeight:700,lineHeight:"1.375rem",textTransform:"uppercase",backgroundColor:p?m?"#ecfdf5":u?"#fff1f2":"#fffbeb":"#ffffff",color:p?m?"#065f46":u?"#9f1239":"#92400e":"#1e293b",verticalAlign:"middle",outline:"none",boxSizing:"border-box"}:void 0,y=p?m?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":u?"border-rose-500 bg-rose-50 text-rose-800 font-bold":"border-amber-500 bg-amber-50 text-amber-800":"border-slate-400 text-slate-800 focus:border-teal-600";return t("span",{className:c("relative inline-flex items-center",g?"mx-px":"mx-1 align-baseline"),style:g?{display:"inline-flex",verticalAlign:"middle",whiteSpace:"nowrap",flexShrink:0}:void 0,children:[!g&&e("span",{className:"absolute -top-4 left-1 text-[10px] font-semibold text-gray-400",children:r}),x&&h?t("select",{value:n,disabled:p,onChange:e=>H(r,e.target.value),"aria-label":`Blank ${r}`,className:c("inline-block min-w-[7rem] max-w-[14rem] rounded border bg-white px-2 py-1 text-sm font-semibold outline-none transition-all align-baseline",y,!p&&"hover:border-teal-500 focus:border-teal-600 focus:ring-1 focus:ring-teal-200"),children:[e("option",{value:"",children:"—"}),h.map(t=>e("option",{value:t,children:t},t))]}):e("input",{type:"text",value:n,onChange:e=>{const t=e.target.value,l=g?t.slice(-1).replace(/\s/g,""):t;H(r,l)},disabled:p,placeholder:"",maxLength:f,inputMode:g?"text":void 0,autoComplete:"off",spellCheck:!1,"aria-label":`Blank ${r}`,style:w,className:c(!g&&"inline-block bg-slate-50/40 text-center text-sm font-semibold outline-none transition-all align-baseline hover:bg-slate-100/60 focus:bg-teal-50/60 focus:ring-0",!g&&(b?"min-w-[9rem] max-w-[18rem] w-[14ch] rounded-t border-b-2 px-2 py-0.5":"min-w-[4.5rem] max-w-[7.5rem] w-[8ch] rounded-t border-b-2 px-1 py-0.5"),!g&&y),size:g?1:b?18:10}),p&&n&&(m?e(o,{className:"ml-0.5 h-3.5 w-3.5 shrink-0 text-green-600"}):e(s,{className:"ml-0.5 h-3.5 w-3.5 shrink-0 text-red-600"}))]},l)},[v,A,N,T,E,H,p,C]),I=a(()=>{if("undefined"==typeof window)return y;const t=(new DOMParser).parseFromString(y||"<p></p>","text/html"),l=/\{([\w\d]+)\}/g,n="letter"===A,a=(t,i)=>{if(t.nodeType===Node.TEXT_NODE)return((t,a)=>{if(!t)return null;const i=[];let o,s=0;for(l.lastIndex=0;null!==(o=l.exec(t));)o.index>s&&i.push({kind:"text",value:t.slice(s,o.index)}),i.push({kind:"blank",key:o[1],index:o.index}),s=o.index+o[0].length;if(s<t.length&&i.push({kind:"text",value:t.slice(s)}),!i.length)return null;if(!n){const t=i.map((e,t)=>"text"===e.kind?e.value:M(e.key,`${a}-blank-${e.index}-${t}`));return 1===t.length?t[0]:e(r.Fragment,{children:t},a)}const d=[];let c=[],m=0;const p=()=>{c.length&&(d.push(e("span",{style:{display:"inline",whiteSpace:"nowrap",verticalAlign:"baseline"},children:c},`${a}-w${m}`)),m+=1,c=[])};for(let e=0;e<i.length;e+=1){const t=i[e];if("blank"===t.kind){c.push(M(t.key,`${a}-blank-${t.index}-${e}`));continue}const r=t.value.split(/(\s+)/);for(let e=0;e<r.length;e+=1){const t=r[e];t&&(/^\s+$/.test(t)?(p(),d.push(t)):c.push(t))}}return p(),d.length?1===d.length?d[0]:e(r.Fragment,{children:d},a):null})(t.textContent||"",i);if(t.nodeType!==Node.ELEMENT_NODE)return null;const o=t,s=o.tagName.toLowerCase(),d={key:i};let c="",m={};Array.from(o.attributes).forEach(e=>{var t;if("class"!==e.name)return"style"===e.name?(t=e.value,void(m=t.split(";").map(e=>e.trim()).filter(Boolean).reduce((e,t)=>{const[r,l]=t.split(":").map(e=>e.trim());return r&&l?(e[r.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())]=l,e):e},{}))):void(d[e.name]=e.value);c=e.value});const p=c.split(/\s+/).filter(Boolean);p.includes("wfsf-block")&&(m={display:"block",margin:"0 0 1.25rem 0",padding:"0.35rem 0 1rem 0",borderBottom:"1px solid #e2e8f0",...m}),p.includes("wfsf-item-no")&&(m={fontWeight:700,fontSize:"1rem",lineHeight:1.4,margin:"0 0 0.4rem 0",color:"#0f172a",...m}),"table"===s&&p.includes("dialogue")&&(m={width:"100%",borderCollapse:"collapse",tableLayout:"auto",...m}),"td"===s&&p.includes("speaker")?m={width:"1%",whiteSpace:"nowrap",verticalAlign:"top",paddingRight:"12px",paddingTop:"6px",paddingBottom:"6px",fontWeight:600,color:"#0f172a",...m}:"td"===s&&!p.includes("speaker")&&o.closest?.("table.dialogue")&&(m={verticalAlign:"top",paddingTop:"6px",paddingBottom:"6px",width:"auto",...m}),c&&(d.className=c),Object.keys(m).length>0&&(d.style=m);const u=Array.from(o.childNodes).map((e,t)=>a(e,`${i}-${t}`)).filter(e=>null!==e);return r.createElement(s,d,...u)};return Array.from(t.body.childNodes).map((e,t)=>a(e,`root-${t}`)).filter(e=>null!==e)},[A,y,M]);return e("div",{className:"space-y-4",children:t("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[(D||z||p&&F)&&e("div",{className:"border-b border-gray-100 bg-white px-5 py-4",children:t("div",{className:"flex items-start justify-between gap-3",children:[t("div",{className:"min-w-0 space-y-1.5",children:[D?e("h2",{className:"text-lg font-bold tracking-tight text-slate-900",children:D}):null,z?e("p",{className:"text-sm leading-relaxed whitespace-pre-line text-slate-700",children:z}):null]}),p&&F?t("div",{className:c("flex shrink-0 items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",O?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(O?o:s,{className:"h-3.5 w-3.5"}),O?"Đúng":"Sai"]}):null]})}),t("div",{className:"space-y-5 p-5",children:[x?e("h3",{className:"text-center text-base font-semibold text-gray-900",children:x}):null,(L||w)&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:j?e("div",{className:"flex h-48 w-48 items-center justify-center",children:e("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-teal-500"})}):e("img",{src:L||w,alt:x||D||"Hình minh họa",className:"max-h-56 w-auto object-contain p-2"})})}),B?t("div",{className:"word-bank-shared space-y-2",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-gray-500",children:"Word Bank"}),e("div",{className:"flex flex-wrap gap-2",children:S.map((t,r)=>e("span",{className:c("rounded-lg border-2 px-3 py-1.5 text-sm font-semibold",t.isExample?"border-amber-300 bg-amber-50 text-amber-800":"border-sky-200 bg-sky-50 text-sky-900"),children:t.word},`wb-${r}-${t.word}`))})]}):null,e("div",{className:c("structured-form-content space-y-2 rounded-lg border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-5 text-base leading-relaxed text-gray-800","[&_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 [&_table.dialogue_td]:leading-relaxed","[&_table.dialogue_td:not(.speaker)]:w-auto","[&_table:not(.dialogue)]:w-full [&_table:not(.dialogue)]:border-collapse"),style:"letter"===A?{wordBreak:"normal",overflowWrap:"break-word",lineHeight:1.7}:void 0,children:I}),p&&!O&&t("div",{className:"rounded-lg border border-green-200 bg-green-50 p-3",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-green-600",children:"Đáp án đúng"}),e("div",{className:"mt-2 flex flex-wrap gap-2",children:T.map(e=>t("span",{className:"rounded-lg border border-green-300 bg-green-100 px-3 py-1.5 text-sm font-semibold text-green-800",children:[`{${e}}`,": ",v[e]]},e))})]})]})]})})}
@@ -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 s,useCallback as o,memo as l}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as i}from"../../../shared/lib/utils";import{transformWordFillStructuredForm as d}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as c}from"./english-cert-scroll";function b(e){const t=Number(e);return Number.isFinite(t)?String(t+1):e}function u(e,t){const r=e.trim();return t?r:r.toLowerCase()}function m(e,t){const r=Object.keys(e).map(e=>Number(e)).filter(e=>Number.isFinite(e)).sort((e,t)=>e-t);if(0===r.length)return`Question ${t}`;const n=r[0]+1,s=r[r.length-1]+1;return n===s?`Question ${n}`:`Questions ${n}–${s}`}const p={},x=l(function({question:o,initialAnswers:l,onBlankChange:d,isReviewMode:c}){const m=r(null),p=r(d);p.current=d;const x=r(!1),f=r(l),h=s(()=>o.content.replace(/\{([\w\d]+)\}/g,(e,t)=>`\n <span class="ec-blank-wrapper" data-blank-wrapper="${t}">\n <span class="ec-blank-number" data-blank-number="${t}">${b(t)}</span>\n <input type="text" data-blank-key="${t}" class="ec-blank-input" />\n </span>\n `),[o.content]);return n(()=>{const e=m.current;if(!e)return;x.current||(e.innerHTML=h,x.current=!0);const t=e.querySelectorAll("input.ec-blank-input"),r=[];return t.forEach(t=>{const n=t.getAttribute("data-blank-key")||"",s=e.querySelector(`[data-blank-wrapper="${n}"]`),l=f.current[n]||"",a=o.answers[n]||"",d=l.trim().length>0,m=d&&u(l,o.caseSensitive)===u(a,o.caseSensitive),x=c&&!m&&a.trim().length>0;t.value=x?`${d?l:"(empty)"} → ${a}`:l,t.disabled=c;const h=o.blankStyle||"word",g="letter"===h,w="phrase"===h;g&&(t.maxLength=Math.max(1,(a||" ").trim().length||1)),t.className=i("ec-blank-input inline-block bg-blue-50/30 text-base font-semibold leading-tight text-[#0f1730] align-baseline outline-none transition-all hover:bg-blue-50/60 focus:bg-blue-50/80",g?"h-8 w-8 rounded border-2 border-[#1167e8] px-0 text-center uppercase":w?"min-w-[140px] max-w-[280px] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-2 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]":"min-w-[100px] max-w-[200px] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-2 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]",c?m?"border-solid border-[#22c55e] bg-emerald-50 text-[#15803d]":d?"border-solid border-[#ef4444] bg-rose-50 text-red-700":"border-solid border-[#f97316] bg-amber-50 text-[#c2410c]":""),g&&(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");const y=e.querySelector(`[data-blank-number="${n}"]`);y&&(y.textContent=b(n),y.className=i("ec-blank-number mr-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[11px] font-bold leading-none text-white align-baseline shadow-xs",c?m?"bg-[#22c55e]":d?"bg-[#ef4444]":"bg-[#f97316]":"bg-[#0b57d0]")),s&&(s.className=i("ec-blank-wrapper inline-flex items-baseline whitespace-nowrap align-baseline",c?"mx-1":"mx-0.5"));const k=e=>{const t=e.target;p.current(n,t.value)};t.addEventListener("input",k),r.push({el:t,handler:k})}),()=>{r.forEach(({el:e,handler:t})=>{e.removeEventListener("input",t)})}},[h,c]),t("div",{className:"space-y-3",children:[o.title&&e("h3",{className:"text-base font-semibold text-[#0f1730]",children:o.title}),o.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-[#d9e4f2]",children:e(a,{src:o.imageUrl,alt:o.title||"Question image",className:"max-h-56 w-auto object-contain"})})}),e("div",{ref:m,className:"ec-structured-content w-full overflow-x-auto rounded-xl border border-[#d9e4f2] bg-[#f4f9ff] p-5 text-base leading-relaxed text-[#0f1730] [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-[#d9e4f2] [&_td]:px-4 [&_td]:py-3 [&_td]:align-top [&_th]:border [&_th]:border-[#d9e4f2] [&_th]:bg-[#e9f3ff] [&_th]:px-4 [&_th]:py-3 [&_th]:text-left [&_th]:font-semibold"}),c&&Object.keys(o.answers).length>0&&t("div",{className:"rounded-xl border border-[#d9e4f2] bg-white/70 p-3",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Correct answers"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(o.answers).map(([e,r])=>t("span",{className:"rounded border border-[#b9edc8] bg-[#ddf8e7] px-2 py-0.5 text-xs font-semibold text-[#15803d]",children:[e,": ",r]},e))})]})]})});export function EcWordFillStructuredForm({part:n,answers:l,onAnswerChange:i,isReviewMode:b=!1}){const{questions:u,instruction:f,groupTitle:h,groupContent:g,groupImageUrl:w}=s(()=>d(n.questions),[n.questions]),y=r(l);y.current=l;const k=r(i);k.current=i;const N=o((e,t,r)=>{const n=y.current[e]||{};k.current(e,{...n,[t]:r})},[]),v=s(()=>{const e={};return u.forEach(t=>{e[t.id]=(e,r)=>N(t.id,e,r)}),e},[u,N]);return t("div",{className:"flex flex-col gap-4",children:[f&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:f}),h&&e("h2",{className:"text-center text-lg font-bold uppercase text-[#0b57d0]",children:h}),w&&e("div",{className:"flex items-center justify-center",children:e(a,{src:w,alt:h||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-4",children:u.map(r=>t("div",{id:c(r.id),className:"scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)] backdrop-blur-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"inline-flex items-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] px-3 py-1 text-xs font-bold text-white shadow-sm",children:m(r.answers,r.questionNumber)})}),e(x,{question:r,initialAnswers:l[r.id]||p,onBlankChange:v[r.id],isReviewMode:b})]},r.id))})]})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useEffect as n,useMemo as s,useCallback as o,memo as l}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as i}from"../../../shared/lib/utils";import{transformWordFillStructuredForm as d}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as c}from"./english-cert-scroll";function b(e){const t=Number(e);return Number.isFinite(t)?String(t+1):e}function m(e,t){const r=e.trim();return t?r:r.toLowerCase()}function u(e,t){const r=Object.keys(e).map(e=>Number(e)).filter(e=>Number.isFinite(e)).sort((e,t)=>e-t);if(0===r.length)return`Question ${t}`;const n=r[0]+1,s=r[r.length-1]+1;return n===s?`Question ${n}`:`Questions ${n}–${s}`}const p={},f=l(function({question:o,initialAnswers:l,onBlankChange:d,isReviewMode:c}){const u=r(null),p=r(d);p.current=d;const f=r(!1),x=r(l),h=s(()=>o.content.replace(/\{([\w\d]+)\}/g,(e,t)=>`\n <span class="ec-blank-wrapper" data-blank-wrapper="${t}">\n <span class="ec-blank-number" data-blank-number="${t}">${b(t)}</span>\n <input type="text" data-blank-key="${t}" class="ec-blank-input" />\n </span>\n `),[o.content]);return n(()=>{const e=u.current;if(!e)return;f.current||(e.innerHTML=h,f.current=!0);const t=e.querySelectorAll("input.ec-blank-input"),r=[];return t.forEach(t=>{const n=t.getAttribute("data-blank-key")||"",s=e.querySelector(`[data-blank-wrapper="${n}"]`),l=x.current[n]||"",a=o.answers[n]||"",d=l.trim().length>0,u=d&&m(l,o.caseSensitive)===m(a,o.caseSensitive),f=c&&!u&&a.trim().length>0;t.value=f?`${d?l:"(empty)"} → ${a}`:l,t.disabled=c;const h=o.blankStyle||"word",g="letter"===h,w="phrase"===h;g&&(t.maxLength=Math.max(1,(a||" ").trim().length||1)),t.className=i("ec-blank-input inline-block bg-blue-50/30 text-base font-semibold leading-tight text-[#0f1730] align-baseline outline-none transition-all hover:bg-blue-50/60 focus:bg-blue-50/80",g?"h-8 w-8 rounded border-2 border-[#1167e8] px-0 text-center uppercase":w?"min-w-[9rem] max-w-[18rem] w-[14ch] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-2 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]":"min-w-[4.5rem] max-w-[7.5rem] w-[8ch] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-1 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]",c?u?"border-solid border-[#22c55e] bg-emerald-50 text-[#15803d]":d?"border-solid border-[#ef4444] bg-rose-50 text-red-700":"border-solid border-[#f97316] bg-amber-50 text-[#c2410c]":""),g||(t.size=w?18:10),g&&(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");const y=e.querySelector(`[data-blank-number="${n}"]`);y&&(y.textContent=b(n),y.className=i("ec-blank-number mr-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[11px] font-bold leading-none text-white align-baseline shadow-xs",c?u?"bg-[#22c55e]":d?"bg-[#ef4444]":"bg-[#f97316]":"bg-[#0b57d0]")),s&&(s.className=i("ec-blank-wrapper inline-flex items-baseline whitespace-nowrap align-baseline",c?"mx-1":"mx-0.5"));const k=e=>{const t=e.target;p.current(n,t.value)};t.addEventListener("input",k),r.push({el:t,handler:k})}),()=>{r.forEach(({el:e,handler:t})=>{e.removeEventListener("input",t)})}},[h,c]),t("div",{className:"space-y-3",children:[o.title&&e("h3",{className:"text-base font-semibold text-[#0f1730]",children:o.title}),o.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-[#d9e4f2]",children:e(a,{src:o.imageUrl,alt:o.title||"Question image",className:"max-h-56 w-auto object-contain"})})}),e("div",{ref:u,className:"ec-structured-content w-full overflow-x-auto rounded-xl border border-[#d9e4f2] bg-[#f4f9ff] p-5 text-base leading-relaxed text-[#0f1730] [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-[#d9e4f2] [&_td]:px-4 [&_td]:py-3 [&_td]:align-top [&_th]:border [&_th]:border-[#d9e4f2] [&_th]:bg-[#e9f3ff] [&_th]:px-4 [&_th]:py-3 [&_th]:text-left [&_th]:font-semibold"}),c&&Object.keys(o.answers).length>0&&t("div",{className:"rounded-xl border border-[#d9e4f2] bg-white/70 p-3",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Correct answers"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(o.answers).map(([e,r])=>t("span",{className:"rounded border border-[#b9edc8] bg-[#ddf8e7] px-2 py-0.5 text-xs font-semibold text-[#15803d]",children:[e,": ",r]},e))})]})]})});export function EcWordFillStructuredForm({part:n,answers:l,onAnswerChange:i,isReviewMode:b=!1}){const{questions:m,instruction:x,groupTitle:h,groupContent:g,groupImageUrl:w}=s(()=>d(n.questions),[n.questions]),y=r(l);y.current=l;const k=r(i);k.current=i;const N=o((e,t,r)=>{const n=y.current[e]||{};k.current(e,{...n,[t]:r})},[]),v=s(()=>{const e={};return m.forEach(t=>{e[t.id]=(e,r)=>N(t.id,e,r)}),e},[m,N]);return t("div",{className:"flex flex-col gap-4",children:[x&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:x}),h&&e("h2",{className:"text-center text-lg font-bold uppercase text-[#0b57d0]",children:h}),w&&e("div",{className:"flex items-center justify-center",children:e(a,{src:w,alt:h||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-4",children:m.map(r=>t("div",{id:c(r.id),className:"scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)] backdrop-blur-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"inline-flex items-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] px-3 py-1 text-xs font-bold text-white shadow-sm",children:u(r.answers,r.questionNumber)})}),e(f,{question:r,initialAnswers:l[r.id]||p,onBlankChange:v[r.id],isReviewMode:b})]},r.id))})]})}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * as Api from './api';
2
2
  export * as Components from './components';
3
- export * as Mcp from './mcp';
4
3
  export * as Exams from './components/exams';
5
4
  export * as Questions from './components/questions';
6
5
  export * as Results from './components/results';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*as Api from"./api";export*as Components from"./components";export*as Mcp from"./mcp";export*as Exams from"./components/exams";export*as Questions from"./components/questions";export*as Results from"./components/results";export*as Themes from"./components/themes";export*as Shared from"./shared";export{buildExamTemplatePayload,createContestRoomsApi,createExamCreateApi,createExamEntryApi,createExamQuestionsApi,createExamQuestionsFetchApi,createExamTakingApi,createMockContestRoomsApi,createMockCreateExamApi,createMockExamEntryApi,createMockExamQuestionsApi,createMockExamTakingApi,createMockResultReviewApi,createResultReviewApi}from"./api";export{CreateExamPageContainer,ExamPreviewDialog,ExamQuestionsPageContainer,ExamTakingPageContainer,ExamViewDialog,StudentContestRoomsPageContainer,StudentExamEntryPageContainer}from"./components/exams";export{ResultReviewPageContainer}from"./components/results";export{QuestionCreator}from"./components/questions/creator/QuestionCreator";export{QuestionGroupCreator}from"./components/questions/creator/QuestionGroupCreator";export{DifficultyLevel,EditQuestionBankDialog,QuestionBankEditorType,QuestionEditorRenderer}from"./components/questions/question-bank";export{renderDedicatedComponent}from"./components/questions/creator/dedicated-component-router";export{questionTypeRegistry}from"./components/questions/creator/question-type-registry";export{QUESTION_TYPE_CONFIG,QUESTION_TYPES_WITH_DEDICATED_COMPONENTS}from"./components/questions/_shared/config/question-types.config";export{validateQuestion}from"./components/questions/_shared/utils/question-validation";export{buildAnswerPayload}from"./components/questions/_shared/utils/answer-builder";export*from"./components/questions/_shared/types";
1
+ export*as Api from"./api";export*as Components from"./components";export*as Exams from"./components/exams";export*as Questions from"./components/questions";export*as Results from"./components/results";export*as Themes from"./components/themes";export*as Shared from"./shared";export{buildExamTemplatePayload,createContestRoomsApi,createExamCreateApi,createExamEntryApi,createExamQuestionsApi,createExamQuestionsFetchApi,createExamTakingApi,createMockContestRoomsApi,createMockCreateExamApi,createMockExamEntryApi,createMockExamQuestionsApi,createMockExamTakingApi,createMockResultReviewApi,createResultReviewApi}from"./api";export{CreateExamPageContainer,ExamPreviewDialog,ExamQuestionsPageContainer,ExamTakingPageContainer,ExamViewDialog,StudentContestRoomsPageContainer,StudentExamEntryPageContainer}from"./components/exams";export{ResultReviewPageContainer}from"./components/results";export{QuestionCreator}from"./components/questions/creator/QuestionCreator";export{QuestionGroupCreator}from"./components/questions/creator/QuestionGroupCreator";export{DifficultyLevel,EditQuestionBankDialog,QuestionBankEditorType,QuestionEditorRenderer}from"./components/questions/question-bank";export{renderDedicatedComponent}from"./components/questions/creator/dedicated-component-router";export{questionTypeRegistry}from"./components/questions/creator/question-type-registry";export{QUESTION_TYPE_CONFIG,QUESTION_TYPES_WITH_DEDICATED_COMPONENTS}from"./components/questions/_shared/config/question-types.config";export{validateQuestion}from"./components/questions/_shared/utils/question-validation";export{buildAnswerPayload}from"./components/questions/_shared/utils/answer-builder";export*from"./components/questions/_shared/types";
@@ -1393,9 +1393,6 @@ declare const admin: {
1393
1393
  readonly 'admin.exams.shuffle.info3': "Questions within the same Part are randomly shuffled";
1394
1394
  readonly 'admin.exams.shuffle.info4': "Variants are linked to the parent exam for management";
1395
1395
  readonly 'admin.exams.shuffle.countLabel': "Number of variants to create";
1396
- readonly 'admin.exams.shuffle.strategyLabel': "Existing exam handling option";
1397
- readonly 'admin.exams.shuffle.keepOld': "Keep existing exams and add new ones";
1398
- readonly 'admin.exams.shuffle.replaceAll': "Create a completely new set";
1399
1396
  readonly 'admin.exams.shuffle.existingVariants': "Existing exams ({count})";
1400
1397
  readonly 'admin.exams.shuffle.deleteAll': "Delete all ({count})";
1401
1398
  readonly 'admin.exams.shuffle.loading': "Loading...";