@tinyweb_dev/oe-exam-sdk 0.1.10 → 0.1.11

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.
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{useEffect as i,useRef as s,useState as r,useMemo as a,useCallback as o}from"react";import d from"next/image";import l from"../../../components/themes/summer-sky/assets/images/clock.png";import m from"../../../components/themes/summer-sky/assets/images/submit.png";import c from"../../../components/themes/summer-sky/assets/images/has_answered.png";import{toast as p}from"sonner";import{Loader2 as u}from"lucide-react";import{t as g}from"../../../shared/lib/i18n";import{transformAnswersForSubmission as h}from"./utils/answer-transformers";import{getThemeForLevel as x,normalizeExamTheme as b}from"../../../shared/lib/themes";import{useExamTakingStore as I}from"../../../shared/lib/stores/examTakingStore";import{useGradingTransientStore as f}from"../../../shared/lib/stores/gradingTransientStore";import{AlertDialog as w,AlertDialogAction as E,AlertDialogCancel as S,AlertDialogContent as _,AlertDialogDescription as y,AlertDialogFooter as v,AlertDialogHeader as N,AlertDialogTitle as A}from"../../../components/ui/alert-dialog";import{useExamTimer as T}from"./hooks/useExamTimer";import{useAutoSave as C}from"./hooks/useAutoSave";import{useProctoringCamera as k}from"./hooks/useProctoringCamera";import{getStandardExamTheme as P}from"../../../components/themes";import{QuestionRenderer as q}from"./components/QuestionRenderer";import{FullscreenLoading as M}from"../entry/fullscreen-loading";import{SummerSkySubmitModal as R}from"../../../components/themes/summer-sky/SummerSkySubmitModal";import{EnglishCertificationExamLayout as D,EnglishCertificationQuestionRenderer as L,scrollToEnglishCertQuestion as G}from"../../../components/themes/english-certification";import{groupQuestionsByPart as Q}from"./utils/question-transformers";import{unwrap as B,unwrapAttempt as O}from"./exam-taking.utils";import{ExamTakingApiProvider as Y}from"./ExamTakingApiContext";function F({roomId:Y,api:F,onNavigate:K,resultPath:U=e=>`/student/results/${e}`,fallbackPath:V="/student/contests/discover",proctoringEnabled:$=!1,achieversExamTitle:j,onSubmitted:H}){const z=I(),W=s(!1),J=o((e,t=!1)=>{K?K(e,{replace:t}):"undefined"!=typeof window&&(t?window.location.replace(e):window.location.href=e)},[K]),{isCameraActive:X}=k({api:F,attemptId:z.attemptId,intervalMs:1e4,enabled:$}),[Z,ee]=r(!0),te=z.currentPartIndex,ne=z.currentQuestionGlobalIndex,ie=o(e=>{const t=I.getState().currentPartIndex,n="function"==typeof e?e(t):e;I.getState().setCurrentPartIndex(n)},[]),se=o(e=>{const t=I.getState().currentQuestionGlobalIndex,n="function"==typeof e?e(t):e;I.getState().setCurrentQuestionGlobalIndex(n)},[]),[re,ae]=r([]),[oe,de]=r("SUMMER_SKY"),[le,me]=r(""),[ce,pe]=r(!1),[ue,ge]=r(null),[he,xe]=r(""),be=o(e=>{I.getState().markIntroPlayed(e)},[]),Ie="TOEIC"===z.examType||"ENGLISH_CERTIFICATION"===le,fe=a(()=>{if(!Ie||0===z.parts.length)return te;const e=z.currentIndex;for(let t=0;t<z.parts.length;t++){const n=z.parts[t],i=n.startIndex??0,s=n.endIndex??i;if(e>=i&&e<=s)return t}return 0},[Ie,z.currentIndex,z.parts,te]);i(()=>{(async()=>{try{ee(!0);let e=B(await F.getActiveAttempt(Y));e||(e=O(B(await F.startAttempt(Y))));let t=null;try{t=F.getRoom?B(await F.getRoom(Y)):null,t&&ge(t)}catch{}const{examTemplate:n,questions:i}=B(await F.getQuestions(e.id));n?.title&&xe(n.title);const s=n?.parts??e.exam?.template?.parts,r=Q(i,s),a=n?.subTitle??null,o=(r.every(e=>e.questions.every(e=>"SPEAKING"===e.question_skill_type)),r.some(e=>"SPEAKING"===e.category||e.questions.every(e=>"SPEAKING"===e.question_skill_type)));ae(r);const d=n?.theme||e?.exam?.template?.theme||e?.exam?.theme||t?.exam?.template?.theme||t?.exam?.theme||"",l=b(d);if(o){const e=["SUMMER_SKY"].includes(d);de(e?d:"SUMMER_SKY")}const m=new Date(e.startedAt),c=60*e.durationMinutes*1e3,u=m.getTime()+c,h=Date.now();if(0===Math.max(0,u-h)){p.info(g("student.exam.take.timeExpired"));try{await F.submitAttempt(e.id)}catch{}return I.persist.clearStorage(),void J(U(e.id))}z.hydrateFromServer({attemptId:e.id,examRoomId:Y,questions:i.map(e=>({id:e.id,question_type:e.question_type,content:e.content,is_example:e.is_example,total_points:e.total_points,part_id:e.part_id,part_no:e.part_no,question_number:e.question_number})),durationMinutes:e.durationMinutes,startedAt:e.startedAt,examType:a??void 0,examTitle:n?.title??void 0,parts:s}),a&&z.setExamType(a),me(l),s&&z.setParts(s),ee(!1)}catch(e){const t=e?.response?.data?.errorCode;if("ATTEMPT_ALREADY_SUBMITTED"===t)return p.info(g("student.exam.take.submitted")),void J(V,!0);console.error("Failed to load exam data:",e),p.error(g("student.exam.take.loadError")),J(V,!0)}})()},[Y]);const we=a(()=>re.length>0&&re.every(e=>e.questions.every(e=>"SPEAKING"===e.question_skill_type)),[re]),Ee=a(()=>{const e=re[te];return!!e&&(("SPEAKING_DESCRIBE_IMAGE"!==e.questionType&&"SPONTANEOUS_QA"!==e.questionType&&"SPEAKING_CUE_CARD"!==e.questionType&&"READ_DISPLAYED_CONTENT"!==e.questionType||"CAMBRIDGE_YLE"!==le)&&("SPEAKING"===e.category||e.questions.every(e=>"SPEAKING"===e.question_skill_type)))},[re,te,le]),{remainingSeconds:Se,warningLevel:_e}=T({onTimeExpired:async()=>{p.info(g("student.exam.take.autoSubmit")),await Ae()},onWarningThreshold:we||Ie?void 0:()=>{p.warning(g("student.exam.take.timeWarning"))},warningThresholdSeconds:we||Ie?void 0:300,warningThresholds:Ie?[{seconds:900,level:"warning",callback:()=>p.warning("Còn 15 phút!",{duration:3e3})},{seconds:300,level:"critical",callback:()=>p.warning("Còn 5 phút! Hãy nộp bài ngay!",{duration:5e3})}]:we?[{seconds:300,level:"warning",callback:()=>p.warning("Còn 5 phút! Hãy hoàn thành bài thi.",{duration:5e3})},{seconds:120,level:"critical",callback:()=>p.warning("Còn 2 phút! Bài thi sẽ được tự động nộp.",{duration:5e3})}]:void 0}),ye=C({api:F,attemptId:z.attemptId||"",parts:re,intervalMs:Ie?15e3:3e4,onSaveError:e=>{console.error("Save error:",e)}}),ve=s(ye.saveNow),Ne=s(re);i(()=>{ve.current=ye.saveNow,Ne.current=re}),i(()=>{const e=()=>{const e=I.getState();if(!e.attemptId||!e.isDirty||e.isSubmitting)return;const t=h(e.answers,Ne.current);if(0!==t.length)try{F.saveAnswers?.({attemptId:e.attemptId,answers:t,keepalive:!0})}catch{}},t=()=>{"hidden"===document.visibilityState&&e()},n=()=>{const e=I.getState();e.isDirty&&!e.isSubmitting&&ve.current()};return document.addEventListener("visibilitychange",t),window.addEventListener("pagehide",e),window.addEventListener("online",n),()=>{document.removeEventListener("visibilitychange",t),window.removeEventListener("pagehide",e),window.removeEventListener("online",n)}},[]),i(()=>{we||ve.current()},[z.currentIndex,te,ne,we]);const Ae=async()=>{if(!W.current){W.current=!0,z.setIsSubmitting(!0),pe(!1);try{z.isDirty&&await ye.saveNow();const e=B(await F.submitAttempt(z.attemptId)),t=e?.pendingAnswerIds??[];z.attemptId&&(f.getState().setPending(z.attemptId,t),H?.({attemptId:z.attemptId,pendingAnswerIds:t})),0===t.length?p.success(g("student.exam.take.submitSuccess")):p.success(g("student.exam.take.submittedAIGradingInProgress")),I.persist.clearStorage(),J(U(z.attemptId),!0)}catch(e){console.error("Failed to submit exam:",e);const t=e?.response?.data?.errorCode;if("ATTEMPT_ALREADY_SUBMITTED"===t)return I.persist.clearStorage(),void J(U(z.attemptId),!0);p.warning(g("student.exam.take.submitError")),W.current=!1,z.setIsSubmitting(!1)}}},Te=o(()=>{pe(!0)},[]),Ce=s(new Map),ke=s([]),Pe=o((e,t)=>{z.setAnswer(e,t);const n=Ce.current.get(e)||e,i=ke.current.findIndex(e=>e.questionId===n);-1!==i&&se(e=>e!==i?i:e)},[]),qe=s("forward"),Me=e=>{if("CAMBRIDGE_YLE"!==le)return!1;const t=re[e];return"SPEAKING_DESCRIBE_IMAGE"===t?.questionType||"SPONTANEOUS_QA"===t?.questionType||"SPEAKING_CUE_CARD"===t?.questionType||"READ_DISPLAYED_CONTENT"===t?.questionType},Re=()=>{const e=()=>{window.scrollTo({top:0,behavior:"smooth"});const e=document.getElementById("exam-main-scroll-area");if(e){e.scrollTo({top:0,behavior:"smooth"});e.querySelectorAll(".overflow-y-auto").forEach(e=>{e.scrollTo({top:0,behavior:"smooth"})})}};requestAnimationFrame(e),setTimeout(e,100),setTimeout(e,250)},De=()=>{if("ENGLISH_CERTIFICATION"===le){const e=z.parts[fe+1];e&&z.goToQuestion(e.startIndex??0)}else if(Ie)z.goToQuestion(Math.min(z.currentIndex+1,z.questions.length-1));else if("CAMBRIDGE_YLE"===le&&Me(te)){const e=ne+1,t=Ve[e];t&&(t.partIndex!==te&&(qe.current="forward",ie(t.partIndex)),se(e))}else qe.current="forward",ie(e=>{const t=Math.min(e+1,re.length-1);if("CAMBRIDGE_YLE"===le){const e=Ve.find(e=>e.partIndex===t);e&&se(e.globalIndex)}return t});Re()},Le=()=>{if("ENGLISH_CERTIFICATION"===le){const e=z.parts[fe-1];e&&z.goToQuestion(e.startIndex??0)}else if(Ie)z.goToQuestion(Math.max(z.currentIndex-1,0));else if("CAMBRIDGE_YLE"===le&&Me(te)){const e=ne-1,t=Ve[e];t&&(t.partIndex!==te&&(qe.current="backward",ie(t.partIndex)),se(e))}else qe.current="backward",ie(e=>{const t=Math.max(e-1,0);if("CAMBRIDGE_YLE"===le){const e=Ve.find(e=>e.partIndex===t);e&&se(e.globalIndex)}return t});Re()},Ge=()=>{J(V)},Qe=a(()=>re.reduce((e,t)=>e+("CAMBRIDGE_YLE"===le?t.questions.length:t.questions.filter(e=>!e.is_example).length),0),[re,le]),Be=a(()=>{const e=new Map;return re.forEach(t=>{t.questions.forEach(n=>{if(n.is_example)return;const i=n.content;if("FILL_MISSING_WORDS_IN_GRID"===t.questionType&&i?.grid&&i.grid.forEach((t,i)=>{t.forEach((t,s)=>{e.set(`${i}-${s}`,n.id)})}),"LABEL_THE_PICTURE"===t.questionType&&i?.labels&&i.labels.forEach(t=>{t.id&&e.set(t.id,n.id)}),"READ_AND_COLOR_OBJECTS"===t.questionType){const t=i?.regions||i?.regionNodes;t?.forEach(t=>{t.id&&e.set(t.id,n.id)})}if("IMAGE_OBJECT_MATCHING"===t.questionType){const t=i?.regions||i?.regionNodes;t?.forEach(t=>{t.id&&e.set(t.id,n.id)})}if("LOOK_PICTURE_FILL_WORD_HINT"===t.questionType){const t=i?.word;if(t&&"string"==typeof t){const i=/\{(\d+)\}/g;let s;for(;null!==(s=i.exec(t));){const t=s[1];e.set(`${n.id}-blank-${t}`,n.id)}}}})}),e},[re]);i(()=>{Ce.current=Be},[Be]);const Oe=a(()=>{if(!z.answers)return new Set;const e=new Set(re.flatMap(e=>e.questions.filter(e=>!e.is_example).map(e=>e.id))),t=new Set;return Object.keys(z.answers).forEach(n=>{const i=z.answers[n];if(void 0===i||""===i)return;if(e.has(n))return void t.add(n);const s=Be.get(n);s&&e.has(s)&&t.add(s)}),t},[z.answers,re,Be]),Ye=Oe.size+("CAMBRIDGE_YLE"===le?re.reduce((e,t)=>e+t.questions.filter(e=>e.is_example).length,0):0),Fe=a(()=>ue?.exam?.name||ue?.name||(Ie?"TOEIC Listening and Reading Test":"Bài thi"),[ue,Ie]),Ke=a(()=>x(ue?.exam?.level).displayName,[ue?.exam?.level]),{sidebarParts:Ue,sidebarQuestions:Ve}=a(()=>{const e=[],t=[];let n=0;return re.forEach((i,s)=>{const r="CAMBRIDGE_YLE"===le?i.questions:i.questions.filter(e=>!e.is_example);let a=0;r.forEach(e=>{const r=!("CAMBRIDGE_YLE"!==le||!e.is_example)||Oe.has(e.id);r&&a++;const o=i.questions.findIndex(t=>t.id===e.id);t.push({globalIndex:n,partIndex:s,indexInPart:o,questionNumber:e.question_number,isAnswered:r,questionId:e.id,isExample:e.is_example}),n++}),e.push({partIndex:s,partNo:i.partNo,name:i.name,category:i.category,points:i.points,totalQuestions:"CAMBRIDGE_YLE"===le?i.questions.length:i.questions.filter(e=>!e.is_example).length,answeredCount:a})}),{sidebarParts:e,sidebarQuestions:t}},[re,Oe,le]);if(i(()=>{ke.current=Ve},[Ve]),Z)return e(M,{});const $e=te,je=re[$e];if(!je)return e("div",{className:"flex min-h-screen items-center justify-center",children:t("div",{className:"text-center",children:[e("p",{className:"text-lg font-semibold text-red-500",children:"Không tìm thấy câu hỏi"}),e("button",{type:"button",onClick:()=>J(V),className:"mt-4 rounded-lg bg-blue-500 px-4 py-2 text-white hover:bg-blue-600",children:"Quay lại"})]})});if(Ee)return t(n,{children:[e(q,{part:je,answers:z.answers||{},onAnswerChange:Pe,isReviewMode:!1,onExit:Ge,onPartComplete:$e<re.length-1?De:Te,onPartBack:$e>0?Le:void 0,speakingTheme:oe,initialQuestionIndex:"backward"===qe.current?je.questions.length-1:0,skipTeacherVideo:z.playedIntroParts.has($e)||he!==j,onTeacherIntroPlayed:()=>be($e)},`${je.partId}-${$e}`),"SUMMER_SKY"===oe?ce&&e(R,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(_,{children:[t(N,{children:[e(A,{children:"Nộp bài thi"}),e(y,{children:"Bạn có chắc chắn muốn nộp bài không? Sau khi nộp, bạn sẽ không thể thay đổi câu trả lời."})]}),t(v,{children:[e(S,{disabled:z.isSubmitting,children:"Quay lại"}),e(E,{onClick:Ae,disabled:z.isSubmitting,children:z.isSubmitting?t(n,{children:[e(u,{className:"mr-2 h-4 w-4 animate-spin"}),"Đang nộp..."]}):"Nộp bài"})]})]})}),t("div",{className:"fixed top-8 right-6 z-[100] flex flex-col items-end gap-4 sm:gap-6 lg:top-10 lg:right-16",children:[t("div",{className:"flex items-center gap-4 sm:gap-6",children:[Se>0&&t("div",{className:"flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none shadow-[0_4px_20px_rgba(0,0,0,0.25)] "+("critical"===_e?"bg-[rgba(220,38,38,0.85)] shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse":"warning"===_e?"bg-[rgba(180,120,0,0.85)]":"bg-[#001590]"),children:[e(d,{src:l,alt:"clock",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),t("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:"'SVN-Volte Rounded', 'Quicksand', sans-serif",textShadow:"0 2px 4px rgba(0, 0, 0, 0.2)"},children:[Math.floor(Se/60).toString().padStart(2,"0"),":",(Se%60).toString().padStart(2,"0")]})]}),t("div",{className:"flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] bg-[#FF9900] shadow-[0_4px_20px_rgba(0,0,0,0.25)] border-none shrink-0",title:"Số câu hỏi đã hoàn thành",children:[e(d,{src:c,alt:"Progress",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),t("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:[Ye,"/",Qe]})]})]}),t("button",{onClick:Te,disabled:z.isSubmitting,className:"group cursor-pointer flex items-center h-[40px] sm:h-[50px] w-[130px] sm:w-[170px] rounded-[33.5px] shadow-[0_4px_20px_rgba(0,0,0,0.25)] transition-all duration-300 hover:scale-105 active:scale-95 disabled:pointer-events-none disabled:opacity-60 border-none "+(z.isSubmitting?"bg-slate-400":"bg-[#16CA3B] hover:bg-[#15b736]"),children:[e(d,{src:m,alt:"Submit",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none transition-transform duration-300 group-hover:scale-110 z-10"}),z.isSubmitting?e("div",{className:"flex-1 flex justify-center pr-[10px] sm:pr-[16px]",children:e(u,{className:"h-6 w-6 animate-spin text-white"})}):e("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:"Nộp bài"})]})]}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]});if(Ie){const i=re[fe],s=z.parts[fe],r=s?Math.max(0,z.currentIndex-(s.startIndex??0)):0,a=(s?.startIndex??0)+1,o=(s?.endIndex??a-1)+1,d={examName:Fe,remainingSeconds:z.remainingSeconds,totalQuestions:Qe,answeredCount:Ye,isSubmitting:z.isSubmitting,onSubmit:Ae,onClose:Ge,lastSavedAt:z.lastSavedAt,isSaving:ye.isSaving,partLabel:(s?.name||i?.name||"").toUpperCase()||void 0,partSubLabel:s?.category||void 0,questionRange:`${a}–${o}`},l=i?.questions?.[r],m="ENGLISH_CERTIFICATION"===le,c={onPrevious:Le,onClear:m?void 0:()=>{l&&Pe(l.id,{optionId:null})},onToggleMark:m?void 0:()=>{l&&z.toggleFlag(l.id)},onNext:De,isMarked:!!l&&z.flaggedQuestions.has(l.id),showSecondaryActions:!m,isPreviousDisabled:m?fe<=0:z.currentIndex<=0,isNextDisabled:m?fe>=z.parts.length-1:z.currentIndex>=z.questions.length-1},p={parts:z.parts,questions:z.questions,answers:z.answers,flaggedQuestions:z.flaggedQuestions,currentIndex:z.currentIndex,onQuestionClick:e=>{z.goToQuestion(e);const t=z.questions[e];t&&G(t.id,{behavior:"smooth",block:"start"})},onPartClick:e=>{const t=z.parts[e];t&&(z.goToQuestion(t.startIndex??0),z.setCurrentPartIndex(e))}};if(i&&s)return t(n,{children:[e(D,{headerProps:d,navigationProps:p,footerProps:c,children:e(L,{part:i,partConfig:s,currentQuestionIndex:r,answers:z.answers,flaggedQuestions:z.flaggedQuestions,onAnswerChange:Pe,onToggleFlag:e=>z.toggleFlag(e),isReviewMode:!1,isAudioPlayed:z.playedListeningAudioParts.has(i.partId),onAudioFirstPlay:()=>z.markListeningAudioPlayed(i.partId)})}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]})}return t(n,{children:[(()=>{const{Layout:n,QuestionCard:i}=P(le),s={headerProps:{examName:Fe,examType:"EXAM",levelLabel:Ke,totalQuestions:Qe,answeredCount:Ye,remainingSeconds:z.remainingSeconds,isSubmitting:z.isSubmitting,isCameraActive:X,onSubmit:Te},onPrevious:Le,onNext:De,onClose:Ge,isNavDisabled:z.isNavDisabled,partName:je?.name||(je?.partNo?`PART ${je.partNo}`:void 0)};if("CAMBRIDGE_YLE"===le){const e=Me($e);s.isFirstQuestion=e?0===ne:0===$e,s.isLastQuestion=e?ne===Ve.length-1:$e===re.length-1,s.sidebarProps={parts:Ue,questions:Ve,currentQuestionGlobalIndex:ne,isNavDisabled:z.isNavDisabled,onPartClick:e=>{if(z.isNavDisabled)return;qe.current=e>$e?"forward":"backward",ie(e);const t=Ve.find(t=>t.partIndex===e);t&&se(t.globalIndex),Re()},onQuestionClick:e=>{if(z.isNavDisabled)return;const t=Ve[e];t&&t.partIndex!==$e&&(qe.current=t.partIndex>$e?"forward":"backward",ie(t.partIndex)),se(e),t&&setTimeout(()=>{const e=document.getElementById(`question-${t.questionId}`);e&&e.scrollIntoView({behavior:"smooth",block:"center"})},100)}}}else s.isFirstQuestion=0===$e,s.isLastQuestion=$e===re.length-1;const r="CAMBRIDGE_YLE"===le&&("SPEAKING_DESCRIBE_IMAGE"===je?.questionType||"SPONTANEOUS_QA"===je?.questionType||"SPEAKING_CUE_CARD"===je?.questionType||"READ_DISPLAYED_CONTENT"===je?.questionType),a=Ve[ne],o=r&&a?.partIndex===$e?a.indexInPart:void 0;return t(n,{...s,children:[e(i,{partName:je?.name||(je?.partNo?`PART ${je.partNo}`:void 0),children:e(q,{part:je,answers:z.answers||{},onAnswerChange:Pe,isReviewMode:!1,currentQuestionIndex:o,onExit:Ge,onPartComplete:$e<re.length-1?De:Te,onPartBack:$e>0?Le:void 0,speakingTheme:"CAMBRIDGE_YLE"===le?"CAMBRIDGE_YLE":oe,initialQuestionIndex:"backward"===qe.current?je?.questions.length-1:0,skipTeacherVideo:z.playedIntroParts.has($e)||he!==j,onTeacherIntroPlayed:()=>be($e)})}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]})})(),"CAMBRIDGE_YLE"===le?ce&&e(R,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(_,{children:[t(N,{children:[e(A,{children:"Nộp bài thi"}),e(y,{children:"Bạn có chắc chắn muốn nộp bài không? Sau khi nộp, bạn sẽ không thể thay đổi câu trả lời."})]}),t(v,{children:[e(S,{disabled:z.isSubmitting,children:"Quay lại"}),e(E,{onClick:Ae,disabled:z.isSubmitting,children:z.isSubmitting?t(n,{children:[e(u,{className:"mr-2 h-4 w-4 animate-spin"}),"Đang nộp..."]}):"Nộp bài"})]})]})})]})}export function ExamTakingPageContainer(t){return e(Y,{api:t.api,children:e(F,{...t})})}
1
+ "use client";import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{useEffect as i,useRef as s,useState as r,useMemo as a,useCallback as o}from"react";import d from"next/image";import l from"../../../components/themes/summer-sky/assets/images/clock.png";import m from"../../../components/themes/summer-sky/assets/images/submit.png";import c from"../../../components/themes/summer-sky/assets/images/has_answered.png";import{toast as p}from"sonner";import{Loader2 as u}from"lucide-react";import{t as g}from"../../../shared/lib/i18n";import{transformAnswersForSubmission as h}from"./utils/answer-transformers";import{getThemeForLevel as x,normalizeExamTheme as b}from"../../../shared/lib/themes";import{useExamTakingStore as I}from"../../../shared/lib/stores/examTakingStore";import{useGradingTransientStore as f}from"../../../shared/lib/stores/gradingTransientStore";import{AlertDialog as w,AlertDialogAction as E,AlertDialogCancel as S,AlertDialogContent as _,AlertDialogDescription as y,AlertDialogFooter as v,AlertDialogHeader as N,AlertDialogTitle as A}from"../../../components/ui/alert-dialog";import{useExamTimer as T}from"./hooks/useExamTimer";import{useAutoSave as C}from"./hooks/useAutoSave";import{useProctoringCamera as k}from"./hooks/useProctoringCamera";import{getStandardExamTheme as P}from"../../../components/themes";import{QuestionRenderer as q}from"./components/QuestionRenderer";import{FullscreenLoading as M}from"../entry/fullscreen-loading";import{SummerSkySubmitModal as R}from"../../../components/themes/summer-sky/SummerSkySubmitModal";import{EnglishCertificationExamLayout as D,EnglishCertificationQuestionRenderer as L,scrollToEnglishCertQuestion as G}from"../../../components/themes/english-certification";import{groupQuestionsByPart as Q}from"./utils/question-transformers";import{unwrap as B,unwrapAttempt as O}from"./exam-taking.utils";import{ExamTakingApiProvider as Y}from"./ExamTakingApiContext";function F({roomId:Y,api:F,onNavigate:K,resultPath:U=e=>`/student/results/${e}`,fallbackPath:V="/student/contests/discover",proctoringEnabled:$=!1,achieversExamTitle:j,onSubmitted:H}){const z=I(),W=s(!1),J=o((e,t=!1)=>{K?K(e,{replace:t}):"undefined"!=typeof window&&(t?window.location.replace(e):window.location.href=e)},[K]),{isCameraActive:X}=k({api:F,attemptId:z.attemptId,intervalMs:1e4,enabled:$}),[Z,ee]=r(!0),te=z.currentPartIndex,ne=z.currentQuestionGlobalIndex,ie=o(e=>{const t=I.getState().currentPartIndex,n="function"==typeof e?e(t):e;I.getState().setCurrentPartIndex(n)},[]),se=o(e=>{const t=I.getState().currentQuestionGlobalIndex,n="function"==typeof e?e(t):e;I.getState().setCurrentQuestionGlobalIndex(n)},[]),[re,ae]=r([]),[oe,de]=r("SUMMER_SKY"),[le,me]=r(""),[ce,pe]=r(!1),[ue,ge]=r(null),[he,xe]=r(""),be=o(e=>{I.getState().markIntroPlayed(e)},[]),Ie="TOEIC"===z.examType||"ENGLISH_CERTIFICATION"===le,fe=a(()=>{if(!Ie||0===z.parts.length)return te;const e=z.currentIndex;for(let t=0;t<z.parts.length;t++){const n=z.parts[t],i=n.startIndex??0,s=n.endIndex??i;if(e>=i&&e<=s)return t}return 0},[Ie,z.currentIndex,z.parts,te]);i(()=>{(async()=>{try{ee(!0);let e=B(await F.getActiveAttempt(Y));e||(e=O(B(await F.startAttempt(Y))));let t=null;try{t=F.getRoom?B(await F.getRoom(Y)):null,t&&ge(t)}catch{}const{examTemplate:n,questions:i}=B(await F.getQuestions(e.id));n?.title&&xe(n.title);const s=n?.parts??e.exam?.template?.parts,r=Q(i,s),a=n?.subTitle??null,o=(r.every(e=>e.questions.every(e=>"SPEAKING"===e.question_skill_type)),r.some(e=>"SPEAKING"===e.category||e.questions.every(e=>"SPEAKING"===e.question_skill_type)));ae(r);const d=n?.theme||e?.exam?.template?.theme||e?.exam?.theme||t?.exam?.template?.theme||t?.exam?.theme||"",l=b(d);if(o){const e=["SUMMER_SKY"].includes(d);de(e?d:"SUMMER_SKY")}const m=new Date(e.startedAt),c=60*e.durationMinutes*1e3,u=m.getTime()+c,h=Date.now();if(0===Math.max(0,u-h)){p.info(g("student.exam.take.timeExpired"));try{await F.submitAttempt(e.id)}catch{}return I.persist.clearStorage(),void J(U(e.id))}z.hydrateFromServer({attemptId:e.id,examRoomId:Y,questions:i.map(e=>({id:e.id,question_type:e.question_type,content:e.content,is_example:e.is_example,total_points:e.total_points,part_id:e.part_id,part_no:e.part_no,question_number:e.question_number})),durationMinutes:e.durationMinutes,startedAt:e.startedAt,examType:a??void 0,examTitle:n?.title??void 0,parts:s}),a&&z.setExamType(a),me(l),s&&z.setParts(s),ee(!1)}catch(e){const t=e?.response?.data?.errorCode;if("ATTEMPT_ALREADY_SUBMITTED"===t)return p.info(g("student.exam.take.submitted")),void J(V,!0);console.error("Failed to load exam data:",e),p.error(g("student.exam.take.loadError")),J(V,!0)}})()},[Y]);const we=a(()=>re.length>0&&re.every(e=>e.questions.every(e=>"SPEAKING"===e.question_skill_type)),[re]),Ee=a(()=>{const e=re[te];return!!e&&(("SPEAKING_DESCRIBE_IMAGE"!==e.questionType&&"SPONTANEOUS_QA"!==e.questionType&&"SPEAKING_CUE_CARD"!==e.questionType&&"READ_DISPLAYED_CONTENT"!==e.questionType||"CAMBRIDGE_YLE"!==le)&&("SPEAKING"===e.category||e.questions.every(e=>"SPEAKING"===e.question_skill_type)))},[re,te,le]),{remainingSeconds:Se,warningLevel:_e}=T({onTimeExpired:async()=>{p.info(g("student.exam.take.autoSubmit")),await Ae()},onWarningThreshold:we||Ie?void 0:()=>{p.warning(g("student.exam.take.timeWarning"))},warningThresholdSeconds:we||Ie?void 0:300,warningThresholds:Ie?[{seconds:900,level:"warning",callback:()=>p.warning("Còn 15 phút!",{duration:3e3})},{seconds:300,level:"critical",callback:()=>p.warning("Còn 5 phút! Hãy nộp bài ngay!",{duration:5e3})}]:we?[{seconds:300,level:"warning",callback:()=>p.warning("Còn 5 phút! Hãy hoàn thành bài thi.",{duration:5e3})},{seconds:120,level:"critical",callback:()=>p.warning("Còn 2 phút! Bài thi sẽ được tự động nộp.",{duration:5e3})}]:void 0}),ye=C({api:F,attemptId:z.attemptId||"",parts:re,intervalMs:Ie?15e3:3e4,onSaveError:e=>{console.error("Save error:",e)}}),ve=s(ye.saveNow),Ne=s(re);i(()=>{ve.current=ye.saveNow,Ne.current=re}),i(()=>{const e=()=>{const e=I.getState();if(!e.attemptId||!e.isDirty||e.isSubmitting)return;const t=h(e.answers,Ne.current);if(0!==t.length)try{F.saveAnswers?.({attemptId:e.attemptId,answers:t,keepalive:!0})}catch{}},t=()=>{"hidden"===document.visibilityState&&e()},n=()=>{const e=I.getState();e.isDirty&&!e.isSubmitting&&ve.current()};return document.addEventListener("visibilitychange",t),window.addEventListener("pagehide",e),window.addEventListener("online",n),()=>{document.removeEventListener("visibilitychange",t),window.removeEventListener("pagehide",e),window.removeEventListener("online",n)}},[]),i(()=>{we||ve.current()},[z.currentIndex,te,ne,we]);const Ae=async()=>{if(!W.current){W.current=!0,z.setIsSubmitting(!0),pe(!1);try{z.isDirty&&await ye.saveNow();const e=B(await F.submitAttempt(z.attemptId)),t=e?.pendingAnswerIds??[];z.attemptId&&(f.getState().setPending(z.attemptId,t),H?.({attemptId:z.attemptId,pendingAnswerIds:t})),0===t.length?p.success(g("student.exam.take.submitSuccess")):p.success(g("student.exam.take.submittedAIGradingInProgress")),I.persist.clearStorage(),J(U(z.attemptId),!0)}catch(e){console.error("Failed to submit exam:",e);const t=e?.response?.data?.errorCode;if("ATTEMPT_ALREADY_SUBMITTED"===t)return I.persist.clearStorage(),void J(U(z.attemptId),!0);p.warning(g("student.exam.take.submitError")),W.current=!1,z.setIsSubmitting(!1)}}},Te=o(()=>{pe(!0)},[]),Ce=s(new Map),ke=s([]),Pe=o((e,t)=>{z.setAnswer(e,t);const n=Ce.current.get(e)||e,i=ke.current.findIndex(e=>e.questionId===n);-1!==i&&se(e=>e!==i?i:e)},[]),qe=s("forward"),Me=e=>{if("CAMBRIDGE_YLE"!==le)return!1;const t=re[e];return"SPEAKING_DESCRIBE_IMAGE"===t?.questionType||"SPONTANEOUS_QA"===t?.questionType||"SPEAKING_CUE_CARD"===t?.questionType||"READ_DISPLAYED_CONTENT"===t?.questionType},Re=()=>{const e=()=>{window.scrollTo({top:0,behavior:"smooth"});const e=document.getElementById("exam-main-scroll-area");if(e){e.scrollTo({top:0,behavior:"smooth"});e.querySelectorAll(".overflow-y-auto").forEach(e=>{e.scrollTo({top:0,behavior:"smooth"})})}};requestAnimationFrame(e),setTimeout(e,100),setTimeout(e,250)},De=()=>{if("ENGLISH_CERTIFICATION"===le){const e=z.parts[fe+1];e&&z.goToQuestion(e.startIndex??0)}else if(Ie)z.goToQuestion(Math.min(z.currentIndex+1,z.questions.length-1));else if("CAMBRIDGE_YLE"===le&&Me(te)){const e=ne+1,t=Ve[e];t&&(t.partIndex!==te&&(qe.current="forward",ie(t.partIndex)),se(e))}else qe.current="forward",ie(e=>{const t=Math.min(e+1,re.length-1);if("CAMBRIDGE_YLE"===le){const e=Ve.find(e=>e.partIndex===t);e&&se(e.globalIndex)}return t});Re()},Le=()=>{if("ENGLISH_CERTIFICATION"===le){const e=z.parts[fe-1];e&&z.goToQuestion(e.startIndex??0)}else if(Ie)z.goToQuestion(Math.max(z.currentIndex-1,0));else if("CAMBRIDGE_YLE"===le&&Me(te)){const e=ne-1,t=Ve[e];t&&(t.partIndex!==te&&(qe.current="backward",ie(t.partIndex)),se(e))}else qe.current="backward",ie(e=>{const t=Math.max(e-1,0);if("CAMBRIDGE_YLE"===le){const e=Ve.find(e=>e.partIndex===t);e&&se(e.globalIndex)}return t});Re()},Ge=()=>{J(V)},Qe=a(()=>re.reduce((e,t)=>e+("CAMBRIDGE_YLE"===le?t.questions.length:t.questions.filter(e=>!e.is_example).length),0),[re,le]),Be=a(()=>{const e=new Map;return re.forEach(t=>{t.questions.forEach(n=>{if(n.is_example)return;const i=n.content;if("FILL_MISSING_WORDS_IN_GRID"===t.questionType&&i?.grid&&i.grid.forEach((t,i)=>{t.forEach((t,s)=>{e.set(`${i}-${s}`,n.id)})}),"LABEL_THE_PICTURE"===t.questionType&&i?.labels&&i.labels.forEach(t=>{t.id&&e.set(t.id,n.id)}),"READ_AND_COLOR_OBJECTS"===t.questionType){const t=i?.regions||i?.regionNodes;t?.forEach(t=>{t.id&&e.set(t.id,n.id)})}if("IMAGE_OBJECT_MATCHING"===t.questionType){const t=i?.regions||i?.regionNodes;t?.forEach(t=>{t.id&&e.set(t.id,n.id)})}if("LOOK_PICTURE_FILL_WORD_HINT"===t.questionType){const t=i?.word;if(t&&"string"==typeof t){const i=/\{(\d+)\}/g;let s;for(;null!==(s=i.exec(t));){const t=s[1];e.set(`${n.id}-blank-${t}`,n.id)}}}})}),e},[re]);i(()=>{Ce.current=Be},[Be]);const Oe=a(()=>{if(!z.answers)return new Set;const e=new Set(re.flatMap(e=>e.questions.filter(e=>!e.is_example).map(e=>e.id))),t=new Set;return Object.keys(z.answers).forEach(n=>{const i=z.answers[n];if(void 0===i||""===i)return;if(e.has(n))return void t.add(n);const s=Be.get(n);s&&e.has(s)&&t.add(s)}),t},[z.answers,re,Be]),Ye=Oe.size+("CAMBRIDGE_YLE"===le?re.reduce((e,t)=>e+t.questions.filter(e=>e.is_example).length,0):0),Fe=a(()=>ue?.exam?.name||ue?.name||(Ie?"TOEIC Listening and Reading Test":"Bài thi"),[ue,Ie]),Ke=a(()=>x(ue?.exam?.level).displayName,[ue?.exam?.level]),{sidebarParts:Ue,sidebarQuestions:Ve}=a(()=>{const e=[],t=[];let n=0;return re.forEach((i,s)=>{const r="CAMBRIDGE_YLE"===le?i.questions:i.questions.filter(e=>!e.is_example);let a=0;r.forEach(e=>{const r=!("CAMBRIDGE_YLE"!==le||!e.is_example)||Oe.has(e.id);r&&a++;const o=i.questions.findIndex(t=>t.id===e.id);t.push({globalIndex:n,partIndex:s,indexInPart:o,questionNumber:e.question_number,isAnswered:r,questionId:e.id,isExample:e.is_example}),n++}),e.push({partIndex:s,partNo:i.partNo,name:i.name,category:i.category,points:i.points,totalQuestions:"CAMBRIDGE_YLE"===le?i.questions.length:i.questions.filter(e=>!e.is_example).length,answeredCount:a})}),{sidebarParts:e,sidebarQuestions:t}},[re,Oe,le]);if(i(()=>{ke.current=Ve},[Ve]),Z)return e(M,{});const $e=te,je=re[$e];if(!je)return e("div",{className:"flex min-h-screen items-center justify-center",children:t("div",{className:"text-center",children:[e("p",{className:"text-lg font-semibold text-red-500",children:"Không tìm thấy câu hỏi"}),e("button",{type:"button",onClick:()=>J(V),className:"mt-4 rounded-lg bg-blue-500 px-4 py-2 text-white hover:bg-blue-600",children:"Quay lại"})]})});if(Ee)return t(n,{children:[e(q,{part:je,answers:z.answers||{},onAnswerChange:Pe,isReviewMode:!1,onExit:Ge,onPartComplete:$e<re.length-1?De:Te,onPartBack:$e>0?Le:void 0,speakingTheme:oe,initialQuestionIndex:"backward"===qe.current?je.questions.length-1:0,skipTeacherVideo:z.playedIntroParts.has($e)||he!==j,onTeacherIntroPlayed:()=>be($e)},`${je.partId}-${$e}`),"SUMMER_SKY"===oe?ce&&e(R,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(_,{children:[t(N,{children:[e(A,{children:"Nộp bài thi"}),e(y,{children:"Bạn có chắc chắn muốn nộp bài không? Sau khi nộp, bạn sẽ không thể thay đổi câu trả lời."})]}),t(v,{children:[e(S,{disabled:z.isSubmitting,children:"Quay lại"}),e(E,{onClick:Ae,disabled:z.isSubmitting,children:z.isSubmitting?t(n,{children:[e(u,{className:"mr-2 h-4 w-4 animate-spin"}),"Đang nộp..."]}):"Nộp bài"})]})]})}),t("div",{className:"fixed top-8 right-6 z-[100] flex flex-col items-end gap-4 sm:gap-6 lg:top-10 lg:right-16",children:[t("div",{className:"flex items-center gap-4 sm:gap-6",children:[Se>0&&t("div",{className:"flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none shadow-[0_4px_20px_rgba(0,0,0,0.25)] "+("critical"===_e?"bg-[rgba(220,38,38,0.85)] shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse":"warning"===_e?"bg-[rgba(180,120,0,0.85)]":"bg-[#001590]"),children:[e(d,{src:l,alt:"clock",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),t("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:"'SVN-Volte Rounded', 'Quicksand', sans-serif",textShadow:"0 2px 4px rgba(0, 0, 0, 0.2)"},children:[Math.floor(Se/60).toString().padStart(2,"0"),":",(Se%60).toString().padStart(2,"0")]})]}),t("div",{className:"flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] bg-[#FF9900] shadow-[0_4px_20px_rgba(0,0,0,0.25)] border-none shrink-0",title:"Số câu hỏi đã hoàn thành",children:[e(d,{src:c,alt:"Progress",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),t("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:[Ye,"/",Qe]})]})]}),t("button",{onClick:Te,disabled:z.isSubmitting,className:"group cursor-pointer flex items-center h-[40px] sm:h-[50px] w-[130px] sm:w-[170px] rounded-[33.5px] shadow-[0_4px_20px_rgba(0,0,0,0.25)] transition-all duration-300 hover:scale-105 active:scale-95 disabled:pointer-events-none disabled:opacity-60 border-none "+(z.isSubmitting?"bg-slate-400":"bg-[#16CA3B] hover:bg-[#15b736]"),children:[e(d,{src:m,alt:"Submit",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none transition-transform duration-300 group-hover:scale-110 z-10"}),z.isSubmitting?e("div",{className:"flex-1 flex justify-center pr-[10px] sm:pr-[16px]",children:e(u,{className:"h-6 w-6 animate-spin text-white"})}):e("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',textShadow:"0 2px 4px rgba(0,0,0,0.2)"},children:"Nộp bài"})]})]}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]});if(Ie){const i=re[fe],s=z.parts[fe],r=s?Math.max(0,z.currentIndex-(s.startIndex??0)):0,a=(s?.startIndex??0)+1,o=(s?.endIndex??a-1)+1,d={examName:Fe,remainingSeconds:z.remainingSeconds,totalQuestions:Qe,answeredCount:Ye,isSubmitting:z.isSubmitting,onSubmit:Ae,onClose:Ge,lastSavedAt:z.lastSavedAt,isSaving:ye.isSaving,partLabel:(s?.name||i?.name||"").toUpperCase()||void 0,partSubLabel:s?.category||void 0,questionRange:`${a}–${o}`},l=i?.questions?.[r],m="ENGLISH_CERTIFICATION"===le,c={onPrevious:Le,onClear:m?void 0:()=>{l&&Pe(l.id,{optionId:null})},onToggleMark:m?void 0:()=>{l&&z.toggleFlag(l.id)},onNext:De,isMarked:!!l&&z.flaggedQuestions.has(l.id),showSecondaryActions:!m,isPreviousDisabled:m?fe<=0:z.currentIndex<=0,isNextDisabled:m?fe>=z.parts.length-1:z.currentIndex>=z.questions.length-1},p={parts:z.parts,questions:z.questions,answers:z.answers,flaggedQuestions:z.flaggedQuestions,currentIndex:z.currentIndex,onQuestionClick:e=>{z.goToQuestion(e);const t=z.questions[e];t&&G(t.id,{behavior:"smooth",block:"start"})},onPartClick:e=>{const t=z.parts[e];if(t){const n=t.startIndex??0;z.goToQuestion(n),z.setCurrentPartIndex(e);const i=z.questions[n];i&&G(i.id,{behavior:"smooth",block:"start"})}}};if(i&&s)return t(n,{children:[e(D,{headerProps:d,navigationProps:p,footerProps:c,children:e(L,{part:i,partConfig:s,currentQuestionIndex:r,answers:z.answers,flaggedQuestions:z.flaggedQuestions,onAnswerChange:Pe,onToggleFlag:e=>z.toggleFlag(e),isReviewMode:!1,isAudioPlayed:z.playedListeningAudioParts.has(i.partId),onAudioFirstPlay:()=>z.markListeningAudioPlayed(i.partId)})}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]})}return t(n,{children:[(()=>{const{Layout:n,QuestionCard:i}=P(le),s={headerProps:{examName:Fe,examType:"EXAM",levelLabel:Ke,totalQuestions:Qe,answeredCount:Ye,remainingSeconds:z.remainingSeconds,isSubmitting:z.isSubmitting,isCameraActive:X,onSubmit:Te},onPrevious:Le,onNext:De,onClose:Ge,isNavDisabled:z.isNavDisabled,partName:je?.name||(je?.partNo?`PART ${je.partNo}`:void 0)};if("CAMBRIDGE_YLE"===le){const e=Me($e);s.isFirstQuestion=e?0===ne:0===$e,s.isLastQuestion=e?ne===Ve.length-1:$e===re.length-1,s.sidebarProps={parts:Ue,questions:Ve,currentQuestionGlobalIndex:ne,isNavDisabled:z.isNavDisabled,onPartClick:e=>{if(z.isNavDisabled)return;qe.current=e>$e?"forward":"backward",ie(e);const t=Ve.find(t=>t.partIndex===e);t&&se(t.globalIndex),Re()},onQuestionClick:e=>{if(z.isNavDisabled)return;const t=Ve[e];t&&t.partIndex!==$e&&(qe.current=t.partIndex>$e?"forward":"backward",ie(t.partIndex)),se(e),t&&setTimeout(()=>{const e=document.getElementById(`question-${t.questionId}`);e&&e.scrollIntoView({behavior:"smooth",block:"center"})},100)}}}else s.isFirstQuestion=0===$e,s.isLastQuestion=$e===re.length-1;const r="CAMBRIDGE_YLE"===le&&("SPEAKING_DESCRIBE_IMAGE"===je?.questionType||"SPONTANEOUS_QA"===je?.questionType||"SPEAKING_CUE_CARD"===je?.questionType||"READ_DISPLAYED_CONTENT"===je?.questionType),a=Ve[ne],o=r&&a?.partIndex===$e?a.indexInPart:void 0;return t(n,{...s,children:[e(i,{partName:je?.name||(je?.partNo?`PART ${je.partNo}`:void 0),children:e(q,{part:je,answers:z.answers||{},onAnswerChange:Pe,isReviewMode:!1,currentQuestionIndex:o,onExit:Ge,onPartComplete:$e<re.length-1?De:Te,onPartBack:$e>0?Le:void 0,speakingTheme:"CAMBRIDGE_YLE"===le?"CAMBRIDGE_YLE":oe,initialQuestionIndex:"backward"===qe.current?je?.questions.length-1:0,skipTeacherVideo:z.playedIntroParts.has($e)||he!==j,onTeacherIntroPlayed:()=>be($e)})}),z.isSubmitting&&e("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:t("div",{className:"rounded-xl bg-white p-8 text-center shadow-2xl",children:[e(u,{className:"mx-auto h-12 w-12 animate-spin text-green-500"}),e("p",{className:"mt-4 text-lg font-semibold text-gray-700",children:"Đang nộp bài..."}),e("p",{className:"mt-2 text-sm text-gray-500",children:"Vui lòng đợi trong giây lát"})]})})]})})(),"CAMBRIDGE_YLE"===le?ce&&e(R,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(_,{children:[t(N,{children:[e(A,{children:"Nộp bài thi"}),e(y,{children:"Bạn có chắc chắn muốn nộp bài không? Sau khi nộp, bạn sẽ không thể thay đổi câu trả lời."})]}),t(v,{children:[e(S,{disabled:z.isSubmitting,children:"Quay lại"}),e(E,{onClick:Ae,disabled:z.isSubmitting,children:z.isSubmitting?t(n,{children:[e(u,{className:"mr-2 h-4 w-4 animate-spin"}),"Đang ná»™p..."]}):"Nộp bài"})]})]})})]})}export function ExamTakingPageContainer(t){return e(Y,{api:t.api,children:e(F,{...t})})}
@@ -1 +1 @@
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={},g=l(function({question:s,initialAnswers:l,onBlankChange:o,isReviewMode:d}){const c=t(null),p=t(o);p.current=o;const g=t(!1),b=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;g.current||(e.innerHTML=x,g.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=b.current[n]||"",o=s.answers[n]||"",c=i.trim().length>0,g=c&&u(i,s.caseSensitive)===u(o,s.caseSensitive),x=d&&!g&&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-[88px] max-w-[180px] border-b-2 bg-transparent px-1 py-0.5 text-sm font-semibold outline-none transition-all align-baseline",d?g?"border-green-500 bg-green-50 text-green-700":c?"border-red-500 bg-red-50 text-red-700":"border-amber-500 bg-amber-50 text-amber-700":"border-gray-300 text-gray-800 focus:border-teal-500"),a&&(a.className=m("structured-blank-wrapper inline-flex flex-col align-top",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-top [&_.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:b,groupTitle:x,groupContent:h,groupImageUrl:f,questions:w,answers:N,onAnswerChange:v,isReviewMode:y=!1}){const k=t(N);k.current=N;const C=t(v);C.current=v;const _=s((e,r,t)=>{const n=k.current[e]||{};C.current(e,{...n,[r]:t})},[]),q=a(()=>{const e={};return w.forEach(r=>{e[r.id]=(e,t)=>_(r.id,e,t)}),e},[w,_]);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}),b&&e(c,{audioSrc:b,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(g,{question:t,initialAnswers:N[t.id]||p,onBlankChange:q[t.id],isReviewMode:y})]},t.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))})]})}
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as s}from"react";import a from"next/image";import{Pause as r,Play as n}from"lucide-react";import{ResolvedImage as i}from"../../../../../../components/common/ResolvedImage";import{useSpeakingRendererSetup as l}from"../../../hooks/useSpeakingRendererSetup";import{useSpeakingConversationAudio as o}from"../../../hooks/useSpeakingConversationAudio";import{getSpeakingLayout as c}from"../../../../../../components/themes";import d from"../../../../../../components/themes/summer-sky/assets/styles/SummerSkyLayout.module.css";import m from"../../../../../../components/themes/summer-sky/assets/images/big-blue-badge-sunset.png";import p from"../../../../../../components/themes/summer-sky/assets/images/teacher-play-sunset.png";import u from"../../../../../../components/themes/summer-sky/assets/images/question-badge-sunset.png";import h from"../../../../../../components/themes/summer-sky/assets/images/red-badge-sunset.png";import x from"../../../../../../components/themes/summer-sky/assets/images/blue-badge-sunset.png";import g from"../../../../../../components/themes/summer-sky/assets/images/red-wrapper-sunset.png";import f from"../../../../../../components/themes/summer-sky/assets/images/blue-wrapper-sunset.png";import N from"../../../../../../components/themes/summer-sky/assets/images/robot-avatar.png";import y from"../../../../../../components/themes/summer-sky/assets/images/student-avatar.png";import v from"../../../../../../components/themes/summer-sky/assets/images/next-small.webp";function b(e){if(!isFinite(e)||e<0)return"0:00";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`}function w({phase:s,isPlaying:i,togglePlayPause:l,partNumber:o,partnerName:c,currentTime:u,duration:h}){const x="playing-partner"===s?c||"Bạn thi":`PART ${o}`,g=h>0?u/h*100:0;return e("div",{className:d.examAudioContainer,children:t("div",{className:d.bigBlueBadge,children:[e(a,{src:m,alt:"Audio Badge",className:d.bigBlueBadgeBg,priority:!0}),e("div",{className:d.audioBarContent,children:t("div",{className:d.audioBarInner,children:[e("span",{className:d.partLabel,children:x}),t("div",{className:d.teacherAvatarContainer,onClick:l,title:i?"Tạm dừng":"Phát",children:[e("img",{src:p.src,alt:"Speaker",className:d.teacherPlayIcon}),e("div",{className:"absolute inset-0 flex items-center justify-center",children:i?e(r,{className:"h-5 w-5 text-white drop-shadow-md",fill:"currentColor"}):e(n,{className:"h-5 w-5 text-white drop-shadow-md ml-0.5",fill:"currentColor"})})]}),t("div",{className:d.audioControlsWrapper,children:[t("span",{className:d.audioTime,children:["idle"===s&&"0:00 / 0:00",i&&`${b(u)} / ${b(h)}`,"ready"===s&&`${b(h)} / ${b(h)}`]}),e("div",{className:d.sliderTrack,children:e("div",{className:d.sliderFill,style:{width:`${g}%`,transition:"width 0.25s linear"}})})]})]})})]})})}function P({text:r}){const[n,i]=s(!0);return r?e("div",{className:"flex flex-col items-center w-full",style:{maxWidth:"882px"},children:t("div",n?{className:"relative flex flex-col justify-center items-center",style:{width:"882px",maxWidth:"90%",paddingLeft:"77px",paddingRight:"77px",paddingTop:"26px",paddingBottom:"26px",backgroundColor:"rgba(232, 136, 154, 0.15)",borderRadius:"20px"},children:[t("div",{className:"absolute cursor-pointer",style:{top:"-19px"},onClick:()=>i(!1),children:[e(a,{src:u,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Ấn câu hỏi"})})]}),e("p",{className:"text-black font-bold leading-[26px] text-center m-0",style:{fontSize:"18px",fontFamily:'"Open Sans", sans-serif'},children:r})]}:{className:"relative cursor-pointer",onClick:()=>i(!0),children:[e(a,{src:u,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Hiện câu hỏi"})})]})}):null}function k({images:s}){if(!s||0===s.length)return null;const a=1===s.length,r=a?"grid-cols-1":2===s.length||4===s.length?"grid-cols-2":"grid-cols-3";return e("div",{className:`grid ${r} gap-4 w-full`,style:{maxWidth:a?"650px":"800px",margin:"0 auto"},children:s.map(s=>t("div",{className:"flex flex-col items-center gap-2",children:[e("div",{className:`relative w-full ${a?"":"aspect-square"} flex justify-center items-center rounded-xl overflow-hidden border-2 border-white/40 shadow-md bg-white/20`,children:e(i,{src:s.url,alt:s.label||"Image",className:"object-contain pointer-events-none "+(a?"max-h-[350px] w-auto":"w-full h-full p-1"),draggable:!1})}),s.label&&e("span",{className:"text-center font-bold",style:{fontSize:"14px",color:"#333"},children:s.label})]},s.id))})}function S({partnerName:s,partnerAvatarUrl:r,studentName:n,activeCharacter:l,isPartnerQuestion:o}){const c="partner"===l,d="student"===l;return t("div",{className:"flex justify-between select-none",style:{width:"990px",maxWidth:"95%",paddingBottom:"10px",paddingLeft:"20px",paddingRight:"20px"},children:[t("div",{className:"relative select-none",style:{opacity:c?1:.55},children:[t("div",{className:"relative flex",children:[e(a,{src:h,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("p",{className:"m-0 truncate select-none text-white font-normal text-center leading-5",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:s||"Bạn thi"})})]}),t("div",{className:"absolute",style:{top:"7px",right:"-58px"},children:[e(a,{src:g,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[r?e(i,{src:r,alt:s||"Partner",className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1}):e(a,{src:N,alt:s||"Partner",width:68,height:68,className:"object-cover rounded-full select-none",draggable:!1}),c&&e("div",{className:"absolute inset-0 rounded-full border-4 border-yellow-400 shadow-[0_0_12px_4px_rgba(250,204,21,0.6)]"})]})})]})]}),t("div",{className:"relative select-none",style:{opacity:d||!o?1:.55},children:[t("div",{className:"relative flex",children:[e(a,{src:x,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("p",{className:"m-0 truncate select-none text-white font-normal text-center leading-5",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:n||"Bạn"})})]}),t("div",{className:"absolute",style:{top:"7px",left:"-58px"},children:[e(a,{src:f,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[e(a,{src:y,alt:n||"Bạn",width:68,height:68,className:"object-cover rounded-full select-none",draggable:!1}),d&&e("div",{className:"absolute inset-0 rounded-full border-4 border-sky-400 shadow-[0_0_12px_4px_rgba(56,189,248,0.6)]"})]})})]})]})]})}function B({audioReady:s,onNext:r}){return s?e("div",{className:"flex flex-col items-center text-center",style:{maxWidth:"291px",marginTop:"-10px",marginBottom:"10px"},children:t("div",{className:"flex items-center gap-1",children:[e("p",{className:"m-0",style:{color:"#333",fontSize:"13px"},children:"Ấn nút"}),e("div",{className:"cursor-pointer",onClick:r,children:e(a,{src:v,alt:"next",width:30,height:30})}),e("p",{className:"m-0",style:{color:"#333",fontSize:"13px"},children:"để tiếp tục."})]})}):null}export function SpeakingConversationRenderer(a){const[r,n]=s(!1),i=l({...a,maxDurationMs:3e4,hasMic:!0}),d=c("SUMMER_SKY"),m=i.currentQuestion?.content,p=i.currentQuestion?.questionGroup?.payload,u="PARTNER"===m?.responder,h=o({interlocutorAudioUrl:m?.interlocutorAudioUrl,partnerAudioUrl:m?.partnerAudioUrl,onSequenceComplete:()=>n(!0)});if(!i.currentQuestion||!m)return null;const x="playing-interlocutor"===h.phase?"interlocutor":"playing-partner"===h.phase||u?"partner":r?"student":"none",g=()=>{n(!1),i.handleNext()};return e(d,{onExit:a.onExit,partName:a.part.name||`Part ${a.part.partNo}`,instruction:a.part.instructions||"SPEAKING CONVERSATION",audioUrl:"",questionNumber:i.nav.questionNumberInPart,onPrev:()=>{n(!1),i.handlePrev()},onNext:g,showPrev:i.nav.showPrev,showNext:i.nav.showNext,canGoPrev:i.nav.canGoPrev,canGoNext:i.nav.canGoNext,onAudioPlayingChange:i.onAudioPlayingChange,recorder:a.isReviewMode||u?null:i.recorder,showExistingBadge:!u&&i.showExistingBadge,teacherVideoUrl:a.teacherVideoUrl,onTeacherVideoEnded:a.onTeacherIntroPlayed,skipTeacherVideo:a.skipTeacherVideo,hideAudioBar:!0,hideFooterTitle:u,children:t("div",{className:"w-full h-full flex flex-col items-center relative",style:{paddingBottom:u?"0":"50px"},children:[e(w,{phase:h.phase,isPlaying:h.isPlaying,togglePlayPause:h.togglePlayPause,partNumber:i.nav.currentPartNo,partnerName:p?.partnerName,currentTime:h.currentTime,duration:h.duration}),e(P,{text:m.questionText}),p?.images&&p.images.length>0&&e("div",{className:"mt-4 w-full flex justify-center",children:e(k,{images:p.images})}),e("div",{className:"flex-1"}),u&&e(B,{audioReady:r,onNext:g}),e(S,{partnerName:p?.partnerName,partnerAvatarUrl:p?.partnerAvatarUrl,activeCharacter:x,isPartnerQuestion:u})]},i.currentQuestion.id)})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as s}from"react";import a from"next/image";import{Pause as r,Play as n}from"lucide-react";import{ResolvedImage as i}from"../../../../../../components/common/ResolvedImage";import{useSpeakingRendererSetup as l}from"../../../hooks/useSpeakingRendererSetup";import{useSpeakingConversationAudio as o}from"../../../hooks/useSpeakingConversationAudio";import{getSpeakingLayout as c}from"../../../../../../components/themes";import d from"../../../../../../components/themes/summer-sky/assets/styles/SummerSkyLayout.module.css";import m from"../../../../../../components/themes/summer-sky/assets/images/big-blue-badge-sunset.png";import p from"../../../../../../components/themes/summer-sky/assets/images/teacher-play-sunset.png";import u from"../../../../../../components/themes/summer-sky/assets/images/question-badge-sunset.png";import h from"../../../../../../components/themes/summer-sky/assets/images/red-badge-sunset.png";import x from"../../../../../../components/themes/summer-sky/assets/images/blue-badge-sunset.png";import g from"../../../../../../components/themes/summer-sky/assets/images/red-wrapper-sunset.png";import f from"../../../../../../components/themes/summer-sky/assets/images/blue-wrapper-sunset.png";import N from"../../../../../../components/themes/summer-sky/assets/images/robot-avatar.png";import y from"../../../../../../components/themes/summer-sky/assets/images/student-avatar.png";import v from"../../../../../../components/themes/summer-sky/assets/images/next-small.webp";function b(e){if(!isFinite(e)||e<0)return"0:00";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`}function w({phase:s,isPlaying:i,togglePlayPause:l,partNumber:o,partnerName:c,currentTime:u,duration:h}){const x="playing-partner"===s?c||"Bạn thi":`PART ${o}`,g=h>0?u/h*100:0;return e("div",{className:d.examAudioContainer,children:t("div",{className:d.bigBlueBadge,children:[e(a,{src:m,alt:"Audio Badge",className:d.bigBlueBadgeBg,priority:!0}),e("div",{className:d.audioBarContent,children:t("div",{className:d.audioBarInner,children:[e("span",{className:d.partLabel,children:x}),t("div",{className:d.teacherAvatarContainer,onClick:l,title:i?"Tạm dừng":"Phát",children:[e("img",{src:p.src,alt:"Speaker",className:d.teacherPlayIcon}),e("div",{className:"absolute inset-0 flex items-center justify-center",children:i?e(r,{className:"h-5 w-5 text-white drop-shadow-md",fill:"currentColor"}):e(n,{className:"h-5 w-5 text-white drop-shadow-md ml-0.5",fill:"currentColor"})})]}),t("div",{className:d.audioControlsWrapper,children:[t("span",{className:d.audioTime,children:["idle"===s&&"0:00 / 0:00",i&&`${b(u)} / ${b(h)}`,"ready"===s&&`${b(h)} / ${b(h)}`]}),e("div",{className:d.sliderTrack,children:e("div",{className:d.sliderFill,style:{width:`${g}%`,transition:"width 0.25s linear"}})})]})]})})]})})}function P({text:r}){const[n,i]=s(!0);return r?e("div",{className:"flex flex-col items-center w-full",style:{maxWidth:"882px"},children:t("div",n?{className:"relative flex flex-col justify-center items-center",style:{width:"882px",maxWidth:"90%",paddingLeft:"77px",paddingRight:"77px",paddingTop:"26px",paddingBottom:"26px",backgroundColor:"rgba(232, 136, 154, 0.15)",borderRadius:"20px"},children:[t("div",{className:"absolute cursor-pointer",style:{top:"-19px"},onClick:()=>i(!1),children:[e(a,{src:u,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Ấn câu hỏi"})})]}),e("p",{className:"text-black font-bold leading-[26px] text-center m-0",style:{fontSize:"18px",fontFamily:'"Open Sans", sans-serif'},children:r})]}:{className:"relative cursor-pointer",onClick:()=>i(!0),children:[e(a,{src:u,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Hiện câu hỏi"})})]})}):null}function k({images:s}){if(!s||0===s.length)return null;const a=1===s.length,r=a?"grid-cols-1":2===s.length||4===s.length?"grid-cols-2":"grid-cols-3";return e("div",{className:`grid ${r} gap-4 w-full`,style:{maxWidth:a?"650px":"800px",margin:"0 auto"},children:s.map(s=>t("div",{className:"flex flex-col items-center gap-2",children:[e("div",{className:`relative w-full ${a?"":"aspect-square"} flex justify-center items-center rounded-xl overflow-hidden border-2 border-white/40 shadow-md bg-white/20`,children:e(i,{src:s.url,alt:s.label||"Image",className:"object-contain pointer-events-none "+(a?"max-h-[350px] w-auto":"w-full h-full p-1"),draggable:!1})}),s.label&&e("span",{className:"text-center font-bold",style:{fontSize:"14px",color:"#333"},children:s.label})]},s.id))})}function S({partnerName:s,partnerAvatarUrl:r,studentName:n,activeCharacter:l,isPartnerQuestion:o}){const c="partner"===l,d="student"===l;return t("div",{className:"flex justify-between select-none",style:{width:"990px",maxWidth:"95%",paddingBottom:"10px",paddingLeft:"20px",paddingRight:"20px"},children:[t("div",{className:"relative select-none",style:{opacity:c?1:.55},children:[t("div",{className:"relative flex",children:[e(a,{src:h,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("p",{className:"m-0 truncate select-none text-white font-normal text-center leading-5",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:s||"Bạn thi"})})]}),t("div",{className:"absolute",style:{top:"7px",right:"-58px"},children:[e(a,{src:g,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[r?e(i,{src:r,alt:s||"Partner",className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1}):e(a,{src:N,alt:s||"Partner",width:68,height:68,className:"object-cover rounded-full select-none",draggable:!1}),c&&e("div",{className:"absolute inset-0 rounded-full border-4 border-yellow-400 shadow-[0_0_12px_4px_rgba(250,204,21,0.6)]"})]})})]})]}),t("div",{className:"relative select-none",style:{opacity:d||!o?1:.55},children:[t("div",{className:"relative flex",children:[e(a,{src:x,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("p",{className:"m-0 truncate select-none text-white font-normal text-center leading-5",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:n||"Bạn"})})]}),t("div",{className:"absolute",style:{top:"7px",left:"-58px"},children:[e(a,{src:f,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[e(a,{src:y,alt:n||"Bạn",width:68,height:68,className:"object-cover rounded-full select-none",draggable:!1}),d&&e("div",{className:"absolute inset-0 rounded-full border-4 border-sky-400 shadow-[0_0_12px_4px_rgba(56,189,248,0.6)]"})]})})]})]})]})}function B({audioReady:s,onNext:r}){return s?e("div",{className:"flex flex-col items-center text-center",style:{maxWidth:"291px",marginTop:"-10px",marginBottom:"10px"},children:t("div",{className:"flex items-center gap-1",children:[e("p",{className:"m-0",style:{color:"#333",fontSize:"13px"},children:"Ấn nút"}),e("div",{className:"cursor-pointer",onClick:r,children:e(a,{src:v,alt:"next",width:30,height:30})}),e("p",{className:"m-0",style:{color:"#333",fontSize:"13px"},children:"để tiếp tục."})]})}):null}export function SpeakingConversationRenderer(a){const[r,n]=s(!1),i=l({...a,maxDurationMs:3e4,hasMic:!0}),d=c("SUMMER_SKY"),m=i.currentQuestion?.content,p=i.currentQuestion?.questionGroup?.payload,u="PARTNER"===m?.responder,h=o({interlocutorAudioUrl:m?.interlocutorAudioUrl,partnerAudioUrl:m?.partnerAudioUrl,onSequenceComplete:()=>n(!0)});if(!i.currentQuestion||!m)return null;const x="playing-interlocutor"===h.phase?"interlocutor":"playing-partner"===h.phase||u?"partner":r?"student":"none",g=()=>{n(!1),i.handleNext()};return e(d,{onExit:a.onExit,partName:a.part.name||`Part ${a.part.partNo}`,instruction:a.part.instructions||"SPEAKING CONVERSATION",audioUrl:"",questionNumber:i.nav.questionNumberInPart,onPrev:()=>{n(!1),i.handlePrev()},onNext:g,showPrev:i.nav.showPrev,showNext:i.nav.showNext,canGoPrev:i.nav.canGoPrev,canGoNext:i.nav.canGoNext,onAudioPlayingChange:i.onAudioPlayingChange,recorder:a.isReviewMode||u?null:i.recorder,showExistingBadge:!u&&i.showExistingBadge,teacherVideoUrl:a.teacherVideoUrl,onTeacherVideoEnded:a.onTeacherIntroPlayed,skipTeacherVideo:a.skipTeacherVideo,hideAudioBar:!0,hideFooterTitle:u,children:t("div",{className:"w-full h-full flex flex-col items-center relative",style:{paddingBottom:u?"0":"50px"},children:[e(w,{phase:h.phase,isPlaying:h.isPlaying,togglePlayPause:h.togglePlayPause,partNumber:i.nav.currentPartNo,partnerName:p?.partnerName,currentTime:h.currentTime,duration:h.duration}),e(P,{text:m.questionText}),p?.images&&p.images.length>0&&e("div",{className:"mt-4 w-full flex justify-center",children:e(k,{images:p.images})}),e("div",{className:"flex-1"}),u&&e(B,{audioReady:r,onNext:g}),e(S,{partnerName:p?.partnerName,partnerAvatarUrl:p?.partnerAvatarUrl,activeCharacter:x,isPartnerQuestion:u})]},i.currentQuestion.id)})}
@@ -1 +1 @@
1
- "use client";import{jsxs as e,jsx as r}from"react/jsx-runtime";import{usePresignedFileUrl as t}from"../../../../../../shared/lib/hooks";import{useSpeakingRendererSetup as a}from"../../../hooks/useSpeakingRendererSetup";import n from"../../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import{getSpeakingLayout as i}from"../../../../../../components/themes";import{SpeakingAudioPlayer as o}from"../../../../../../components/shared/audio/SpeakingAudioPlayer";import{useEffect as s,useRef as d,useState as l}from"react";import c from"next/image";import{useExamTakingStore as m}from"../../../../../../shared/lib/stores/examTakingStore";import u from"../../../../../../components/themes/summer-sky/assets/images/mic_ver2_icon.png";import h from"../../../../../../components/themes/summer-sky/assets/images/stop_audio_ver2_icon.png";import p from"../../../../../../components/themes/summer-sky/assets/images/audio_ver2_icon.png";import g from"../../../../../../components/themes/summer-sky/assets/images/pause_audio_ver2_icon.png";import x from"../../../../../../components/themes/summer-sky/assets/images/lock_mic_ver2_icon.png";function f({total:t,currentIndex:a,answeredIds:n,questionIds:i}){return e("div",{className:"flex items-center gap-2 font-bold text-[#78350f] font-['Quicksand'] z-10",children:[e("span",{className:"text-sm",children:["Question ",a+1,"/ ",t]}),r("div",{className:"flex gap-1.5",children:Array.from({length:t},(e,t)=>{const o=t===a,s=n.has(i[t]);return r("div",{className:"w-2.5 h-2.5 rounded-full "+(o?"bg-[#FF9900] scale-125 shadow-sm":s?"bg-[#16CA3B]":"bg-white/60")},t)})})]})}const b=new Set(["/speaking/video/read_displayed_content.webm","/speaking/video/speaking_describe_image.webm","/speaking/video/spontaneous_qa.webm"]);function w(e){const r=Math.floor(e/60),t=Math.floor(e%60);return`${r.toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}export function SpeakingDescribeImageRenderer(x){const{currentQuestionIndex:v}=x,y=a({...x,maxDurationMs:6e4,currentQuestionIndex:v}),N=m(e=>e.examTitle),k=N?.toLowerCase().includes("placement test")||!1,_=y.currentQuestion?.content,{previewUrl:C,isLoading:E}=t(_?.imageUrl||""),P=d(null),[S,F]=l(!!x.skipTeacherVideo),I=d(null),[T,U]=l(!1),[j,q]=l(0),[A,z]=l(0);if(s(()=>{const e=P.current;e&&x.teacherVideoUrl&&(e.playbackRate=b.has(x.teacherVideoUrl)?1.25:1)},[x.teacherVideoUrl]),s(()=>{const e=I.current;if(!e)return;const r=()=>{U(!0),y.onAudioPlayingChange?.(!0)},t=()=>{U(!1),y.onAudioPlayingChange?.(!1)},a=()=>{U(!1),q(0),y.onAudioPlayingChange?.(!1)},n=()=>{q(e.currentTime),e.duration&&isFinite(e.duration)&&z(e.duration)},i=()=>{e.duration&&isFinite(e.duration)&&z(e.duration)};return e.addEventListener("play",r),e.addEventListener("pause",t),e.addEventListener("ended",a),e.addEventListener("timeupdate",n),e.addEventListener("loadedmetadata",i),e.addEventListener("durationchange",i),()=>{e.removeEventListener("play",r),e.removeEventListener("pause",t),e.removeEventListener("ended",a),e.removeEventListener("timeupdate",n),e.removeEventListener("loadedmetadata",i),e.removeEventListener("durationchange",i),y.onAudioPlayingChange?.(!1)}},[y.recorder?.previewUrl,y.onAudioPlayingChange]),!y.currentQuestion||!_)return null;const L=new Set(x.part.questions.map(e=>e.id).filter(e=>!!x.answers[e])),V=x.part.questions.map(e=>e.id);if(x.speakingTheme&&"CAMBRIDGE_YLE"!==x.speakingTheme){const t=i(x.speakingTheme),a=r(f,{total:x.part.questions.length,currentIndex:y.nav.currentIndex,answeredIds:L,questionIds:V});return r(t,{onExit:x.onExit,partName:x.part.name||`Part ${x.part.partNo}`,instruction:x.part.instructions||"DESCRIBE THE IMAGE",audioUrl:"",questionNumber:y.nav.questionNumberInPart,onPrev:y.handlePrev,onNext:y.handleNext,showPrev:y.nav.showPrev,showNext:y.nav.showNext,canGoPrev:y.nav.canGoPrev,canGoNext:y.nav.canGoNext,onAudioPlayingChange:y.onAudioPlayingChange,recorder:x.isReviewMode?null:y.recorder,showExistingBadge:y.showExistingBadge,headerRight:a,teacherVideoUrl:x.teacherVideoUrl,waitForTeacherVideo:x.waitForTeacherVideo,onTeacherVideoEnded:x.onTeacherIntroPlayed,skipTeacherVideo:x.skipTeacherVideo,children:r("div",{className:"w-full h-full flex flex-col items-center relative",children:r("div",{className:"w-full flex-1",style:{minHeight:0},children:r("div",{className:"mx-auto",style:{width:"900px",maxWidth:"95%",height:"calc(100% - 40px)"},children:e("div",{className:"w-full h-full flex flex-col items-center justify-center",style:{paddingTop:"10px"},children:[_.isBackup&&r("div",{className:"bg-amber-500 text-white px-3 py-1 rounded-md text-xs font-bold border border-white shadow-md z-10 shrink-0 mb-4",children:"Câu hỏi dự phòng"}),_.question&&r("div",{className:"z-10 mx-auto px-8 py-2.5 bg-white/80 backdrop-blur-md rounded-full shadow-sm border border-slate-100 w-fit shrink-0 mb-4",children:r("h3",{className:"text-[17px] md:text-lg font-bold text-[#343C55] font-['Quicksand'] text-center whitespace-pre-wrap leading-tight",children:_.question})}),_.audioUrl&&r("div",{className:"z-10 mx-auto w-full max-w-[280px] shrink-0 mb-4",children:r(o,{audioUrl:_.audioUrl,onPlayingChange:y.onAudioPlayingChange,autoPlay:!x.waitForTeacherVideo})}),y.showExistingBadge&&e("div",{className:"absolute right-12 top-12 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"flex-1 flex justify-center items-center min-h-0 w-full",children:r("div",E?{className:"flex justify-center items-center w-full max-w-[60%] h-full max-h-[300px] border-4 border-dashed border-gray-300 rounded-xl bg-gray-50/50",children:r("div",{className:"animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"})}:C?{className:"bg-white rounded-2xl shadow-[0_4px_15px_rgba(0,0,0,0.08)] p-2 h-full max-w-[90%] flex justify-center items-center",children:r("img",{src:C,alt:"Scene to describe",className:"max-h-full max-w-full object-contain rounded-xl",draggable:!1})}:{className:"flex justify-center items-center text-orange-800 font-semibold opacity-70 w-full h-full max-h-[300px] border-4 border-dashed border-orange-900/30 rounded-xl bg-orange-900/10",children:"Chưa có hình ảnh mô tả"})})]})})})})})}const B=x.teacherVideoUrl?r("div",{className:"fixed bottom-6 left-6 z-40 flex flex-col items-start w-[12vw] min-w-[150px] pointer-events-none",children:e("div",{className:"relative w-full",children:[r("video",{ref:P,src:x.teacherVideoUrl,autoPlay:!x.skipTeacherVideo,playsInline:!0,onEnded:()=>{F(!0),x.onTeacherIntroPlayed?.()},className:"w-full h-auto drop-shadow-[0_4px_16px_rgba(0,0,0,0.2)] transition-opacity duration-700",style:{opacity:S?0:1}}),!k&&"CAMBRIDGE_YLE"!==x.speakingTheme&&r("img",{src:"/speaking/image/teacher_ai_smile.png",alt:"AI Teacher",className:"absolute top-0 left-0 w-full h-auto drop-shadow-[0_4px_16px_rgba(0,0,0,0.2)] transition-opacity duration-700",style:{opacity:S?1:0}})]})}):null;return e("div",{className:"flex flex-col w-full h-full relative",style:{background:"linear-gradient(180deg, #E6F3FF 0%, #FFFFFF 100%)"},children:[e("div",{className:"relative w-full flex justify-between items-start pt-6 px-6 z-20 shrink-0",children:[r("div",{className:"flex-1"}),r("div",{className:"flex-none drop-shadow-md",children:r(n,{partNumber:x.part.partNo,questionCount:x.part.questions.length,partName:x.part.name||`Part ${x.part.partNo}`})}),r("div",{className:"flex-1 flex justify-end mt-2 z-20",children:r(f,{total:x.part.questions.length,currentIndex:y.nav.currentIndex,answeredIds:L,questionIds:V})})]}),e("div",{className:"flex-1 w-full flex flex-col items-center min-h-0 px-4 pb-6 pt-2",children:[_.isBackup&&r("div",{className:"bg-amber-500 text-white px-3 py-1 rounded-md text-xs font-bold border border-white shadow-md z-10 shrink-0 mb-4",children:"Câu hỏi dự phòng"}),_.question&&r("div",{className:"z-10 mx-auto px-8 py-2.5 bg-white backdrop-blur-md rounded-full shadow-[0_2px_10px_rgba(0,0,0,0.05)] border border-slate-100 w-fit shrink-0 mb-4",children:r("h3",{className:"text-[17px] md:text-lg font-bold text-[#343C55] font-['Quicksand'] text-center whitespace-pre-wrap leading-tight",children:_.question})}),_.audioUrl&&r("div",{className:"z-10 mx-auto w-full max-w-[280px] shrink-0 mb-4",children:r(o,{audioUrl:_.audioUrl,onPlayingChange:y.onAudioPlayingChange,autoPlay:!x.waitForTeacherVideo})}),e("div",{className:"flex-1 w-full flex justify-center items-center min-h-[320px] relative mb-4",children:[y.showExistingBadge&&e("div",{className:"absolute right-4 top-0 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-lg border-2 border-white transform -translate-y-1/2",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",E?{className:"flex justify-center items-center w-full max-w-[60%] h-full max-h-[300px] border-4 border-dashed border-gray-300 rounded-xl bg-gray-50/50",children:r("div",{className:"animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"})}:C?{className:"bg-white rounded-2xl shadow-[0_4px_15px_rgba(0,0,0,0.08)] p-2 h-full max-w-[92%] flex justify-center items-center",children:r("img",{src:C,alt:"Scene to describe",className:"h-full w-auto max-w-full object-contain rounded-xl",draggable:!1})}:{className:"flex justify-center items-center text-orange-800 font-semibold opacity-70 w-full h-full max-h-[300px] border-4 border-dashed border-orange-900/30 rounded-xl bg-orange-900/10",children:"Chưa có hình ảnh mô tả"})]}),y.recorder&&!x.isReviewMode&&e("div",{className:"shrink-0 flex flex-col items-center z-50 gap-3",children:[r("div",{className:"bg-white rounded-[100px] shadow-[0_4px_10px_rgba(0,0,0,0.1)] whitespace-nowrap flex items-center justify-center",style:{padding:"10px 30px",color:"recording"===y.recorder.status?"#FF4D4D":["recorded","uploading","uploaded"].includes(y.recorder.status)?"#16CA3B":"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:"recording"===y.recorder.status?"Ấn lần nữa để lưu kết quả":["recorded","uploading","uploaded"].includes(y.recorder.status)?"Câu trả lời đã được ghi nhận !":"Ấn biểu tượng Micro để trả lời"}),e("div",{className:"relative flex flex-col items-center",children:["recording"===y.recorder.status?e("div",{className:"relative flex flex-col justify-center items-center cursor-pointer drop-shadow-[0_0_15px_rgba(255,100,100,0.8)] transition-transform hover:scale-[1.05] active:scale-[0.95]",onClick:y.recorder.stopRecording,children:[r(c,{src:h,alt:"stop recording",className:"animate-pulse",style:{width:"120px",height:"120px"}}),e("span",{className:"absolute text-white text-[16px] font-bold font-['Quicksand']",style:{bottom:"30px"},children:[Math.floor(y.recorder.remainingSeconds/60),":",(y.recorder.remainingSeconds%60).toString().padStart(2,"0")]})]}):r(c,{src:["recorded","uploading","uploaded"].includes(y.recorder.status)?T?g:p:u,alt:"mic",className:"transition-transform cursor-pointer hover:scale-[1.05] active:scale-[0.95]",style:{width:"120px",height:"120px"},onClick:()=>{if("recording"===y.recorder?.status)y.recorder.stopRecording();else if("idle"===y.recorder?.status||"error"===y.recorder?.status)y.recorder.startRecording();else if("uploaded"===y.recorder?.status||"recorded"===y.recorder?.status){const e=I.current;e&&(T?e.pause():e.play().catch(console.error))}}}),y.recorder?.previewUrl&&r("audio",{ref:I,src:y.recorder.previewUrl}),"recording"===y.recorder.status&&r("div",{className:"absolute whitespace-nowrap text-center",style:{top:"100%",marginTop:"16px",color:"#FF4D4D",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em",textShadow:"0 1px 3px rgba(0,0,0,0.15)"},children:"Đang ghi âm câu hỏi . . ."}),["recorded","uploading","uploaded"].includes(y.recorder.status)&&r("div",{className:"absolute whitespace-nowrap text-center flex flex-col items-center",style:{top:"100%",marginTop:"16px",color:"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:T?`${w(j)}/${A?w(A):"--:--"}`:"Nghe đáp án"})]})]})]}),B]})}
1
+ "use client";import{jsxs as e,jsx as r}from"react/jsx-runtime";import{usePresignedFileUrl as t}from"../../../../../../shared/lib/hooks";import{useSpeakingRendererSetup as a}from"../../../hooks/useSpeakingRendererSetup";import n from"../../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import{getSpeakingLayout as i}from"../../../../../../components/themes";import{SpeakingAudioPlayer as o}from"../../../../../../components/shared/audio/SpeakingAudioPlayer";import{useEffect as s,useRef as d,useState as l}from"react";import c from"next/image";import{useExamTakingStore as m}from"../../../../../../shared/lib/stores/examTakingStore";import u from"../../../../../../components/themes/summer-sky/assets/images/mic_ver2_icon.png";import p from"../../../../../../components/themes/summer-sky/assets/images/stop_audio_ver2_icon.png";import h from"../../../../../../components/themes/summer-sky/assets/images/audio_ver2_icon.png";import g from"../../../../../../components/themes/summer-sky/assets/images/pause_audio_ver2_icon.png";import x from"../../../../../../components/themes/summer-sky/assets/images/lock_mic_ver2_icon.png";function f({total:t,currentIndex:a,answeredIds:n,questionIds:i}){return e("div",{className:"flex items-center gap-2 font-bold text-[#78350f] font-['Quicksand'] z-10",children:[e("span",{className:"text-sm",children:["Question ",a+1,"/ ",t]}),r("div",{className:"flex gap-1.5",children:Array.from({length:t},(e,t)=>{const o=t===a,s=n.has(i[t]);return r("div",{className:"w-2.5 h-2.5 rounded-full "+(o?"bg-[#FF9900] scale-125 shadow-sm":s?"bg-[#16CA3B]":"bg-white/60")},t)})})]})}const b=new Set(["/speaking/video/read_displayed_content.webm","/speaking/video/speaking_describe_image.webm","/speaking/video/spontaneous_qa.webm"]);function w(e){const r=Math.floor(e/60),t=Math.floor(e%60);return`${r.toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}export function SpeakingDescribeImageRenderer(x){const{currentQuestionIndex:v}=x,y=a({...x,maxDurationMs:6e4,currentQuestionIndex:v}),N=m(e=>e.examTitle),k=N?.toLowerCase().includes("placement test")||!1,_=y.currentQuestion?.content,{previewUrl:C,isLoading:E}=t(_?.imageUrl||""),P=d(null),[S,F]=l(!!x.skipTeacherVideo),I=d(null),[T,U]=l(!1),[j,q]=l(0),[A,z]=l(0);if(s(()=>{const e=P.current;e&&x.teacherVideoUrl&&(e.playbackRate=b.has(x.teacherVideoUrl)?1.25:1)},[x.teacherVideoUrl]),s(()=>{const e=I.current;if(!e)return;const r=()=>{U(!0),y.onAudioPlayingChange?.(!0)},t=()=>{U(!1),y.onAudioPlayingChange?.(!1)},a=()=>{U(!1),q(0),y.onAudioPlayingChange?.(!1)},n=()=>{q(e.currentTime),e.duration&&isFinite(e.duration)&&z(e.duration)},i=()=>{e.duration&&isFinite(e.duration)&&z(e.duration)};return e.addEventListener("play",r),e.addEventListener("pause",t),e.addEventListener("ended",a),e.addEventListener("timeupdate",n),e.addEventListener("loadedmetadata",i),e.addEventListener("durationchange",i),()=>{e.removeEventListener("play",r),e.removeEventListener("pause",t),e.removeEventListener("ended",a),e.removeEventListener("timeupdate",n),e.removeEventListener("loadedmetadata",i),e.removeEventListener("durationchange",i),y.onAudioPlayingChange?.(!1)}},[y.recorder?.previewUrl,y.onAudioPlayingChange]),!y.currentQuestion||!_)return null;const L=new Set(x.part.questions.map(e=>e.id).filter(e=>!!x.answers[e])),V=x.part.questions.map(e=>e.id);if(x.speakingTheme&&"CAMBRIDGE_YLE"!==x.speakingTheme){const t=i(x.speakingTheme),a=r(f,{total:x.part.questions.length,currentIndex:y.nav.currentIndex,answeredIds:L,questionIds:V});return r(t,{onExit:x.onExit,partName:x.part.name||`Part ${x.part.partNo}`,instruction:x.part.instructions||"DESCRIBE THE IMAGE",audioUrl:"",questionNumber:y.nav.questionNumberInPart,onPrev:y.handlePrev,onNext:y.handleNext,showPrev:y.nav.showPrev,showNext:y.nav.showNext,canGoPrev:y.nav.canGoPrev,canGoNext:y.nav.canGoNext,onAudioPlayingChange:y.onAudioPlayingChange,recorder:x.isReviewMode?null:y.recorder,showExistingBadge:y.showExistingBadge,headerRight:a,teacherVideoUrl:x.teacherVideoUrl,waitForTeacherVideo:x.waitForTeacherVideo,onTeacherVideoEnded:x.onTeacherIntroPlayed,skipTeacherVideo:x.skipTeacherVideo,children:r("div",{className:"w-full h-full relative overflow-y-auto custom-scrollbar flex flex-col items-center",children:e("div",{className:"w-full shrink-0 flex flex-col items-center",style:{width:"900px",maxWidth:"95%",padding:"20px 0 100px 0"},children:[_.isBackup&&r("div",{className:"bg-amber-500 text-white px-3 py-1 rounded-md text-xs font-bold border border-white shadow-md z-10 shrink-0 mb-4",children:"Câu hỏi dự phòng"}),_.question&&r("div",{className:"z-10 mx-auto px-8 py-2.5 bg-white/80 backdrop-blur-md rounded-full shadow-sm border border-slate-100 w-fit shrink-0 mb-4",children:r("h3",{className:"text-[17px] md:text-lg font-bold text-[#343C55] font-['Quicksand'] text-center whitespace-pre-wrap leading-tight",children:_.question})}),_.audioUrl&&r("div",{className:"z-10 mx-auto w-full max-w-[280px] shrink-0 mb-4",children:r(o,{audioUrl:_.audioUrl,onPlayingChange:y.onAudioPlayingChange,autoPlay:!x.waitForTeacherVideo})}),y.showExistingBadge&&e("div",{className:"absolute right-12 top-12 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"w-full flex justify-center items-center mt-2 relative",children:r("div",E?{className:"flex justify-center items-center w-full max-w-[60%] h-[300px] border-4 border-dashed border-gray-300 rounded-xl bg-gray-50/50",children:r("div",{className:"animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"})}:C?{className:"bg-white rounded-2xl shadow-[0_4px_15px_rgba(0,0,0,0.08)] p-2 w-[80%] max-w-[700px] flex justify-center items-center",children:r("img",{src:C,alt:"Scene to describe",className:"w-full h-auto object-contain rounded-xl",draggable:!1})}:{className:"flex justify-center items-center text-orange-800 font-semibold opacity-70 w-full h-[300px] border-4 border-dashed border-orange-900/30 rounded-xl bg-orange-900/10",children:"Chưa có hình ảnh mô tả"})})]})})})}const B=x.teacherVideoUrl?r("div",{className:"fixed bottom-6 left-6 z-40 flex flex-col items-start w-[12vw] min-w-[150px] pointer-events-none",children:e("div",{className:"relative w-full",children:[r("video",{ref:P,src:x.teacherVideoUrl,autoPlay:!x.skipTeacherVideo,playsInline:!0,onEnded:()=>{F(!0),x.onTeacherIntroPlayed?.()},className:"w-full h-auto drop-shadow-[0_4px_16px_rgba(0,0,0,0.2)] transition-opacity duration-700",style:{opacity:S?0:1}}),!k&&"CAMBRIDGE_YLE"!==x.speakingTheme&&r("img",{src:"/speaking/image/teacher_ai_smile.png",alt:"AI Teacher",className:"absolute top-0 left-0 w-full h-auto drop-shadow-[0_4px_16px_rgba(0,0,0,0.2)] transition-opacity duration-700",style:{opacity:S?1:0}})]})}):null;return e("div",{className:"flex flex-col w-full h-full relative",style:{background:"linear-gradient(180deg, #E6F3FF 0%, #FFFFFF 100%)"},children:[e("div",{className:"relative w-full flex justify-between items-start pt-6 px-6 z-20 shrink-0",children:[r("div",{className:"flex-1"}),r("div",{className:"flex-none drop-shadow-md",children:r(n,{partNumber:x.part.partNo,questionCount:x.part.questions.length,partName:x.part.name||`Part ${x.part.partNo}`})}),r("div",{className:"flex-1 flex justify-end mt-2 z-20",children:r(f,{total:x.part.questions.length,currentIndex:y.nav.currentIndex,answeredIds:L,questionIds:V})})]}),e("div",{className:"flex-1 w-full flex flex-col min-h-0",children:[e("div",{className:"flex-1 w-full overflow-y-auto custom-scrollbar px-4 pb-6 pt-2 flex flex-col items-center relative",children:[_.isBackup&&r("div",{className:"bg-amber-500 text-white px-3 py-1 rounded-md text-xs font-bold border border-white shadow-md z-10 shrink-0 mb-4 mt-2",children:"Câu hỏi dự phòng"}),_.question&&r("div",{className:"z-10 mx-auto px-8 py-2.5 bg-white backdrop-blur-md rounded-full shadow-[0_2px_10px_rgba(0,0,0,0.05)] border border-slate-100 w-fit shrink-0 mb-4 mt-2",children:r("h3",{className:"text-[17px] md:text-lg font-bold text-[#343C55] font-['Quicksand'] text-center whitespace-pre-wrap leading-tight",children:_.question})}),_.audioUrl&&r("div",{className:"z-10 mx-auto w-full max-w-[280px] shrink-0 mb-4",children:r(o,{audioUrl:_.audioUrl,onPlayingChange:y.onAudioPlayingChange,autoPlay:!x.waitForTeacherVideo})}),y.showExistingBadge&&e("div",{className:"absolute right-[5%] lg:right-[15%] top-4 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-lg border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"w-full flex justify-center items-center relative mb-4 shrink-0",children:r("div",E?{className:"flex justify-center items-center w-full max-w-[60%] h-[300px] border-4 border-dashed border-gray-300 rounded-xl bg-white/50 backdrop-blur-sm shadow-[0_4px_15px_rgba(0,0,0,0.05)]",children:r("div",{className:"animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"})}:C?{className:"bg-white rounded-2xl shadow-[0_4px_15px_rgba(0,0,0,0.08)] p-2 w-[80%] max-w-[650px] flex justify-center items-center",children:r("img",{src:C,alt:"Scene to describe",className:"w-full h-auto object-contain rounded-xl",draggable:!1})}:{className:"flex justify-center items-center text-orange-800 font-semibold opacity-70 w-full max-w-[800px] h-[300px] border-4 border-dashed border-orange-900/30 rounded-xl bg-orange-900/10",children:"Chưa có hình ảnh mô tả"})})]}),y.recorder&&!x.isReviewMode&&e("div",{className:"shrink-0 flex flex-col items-center z-50 gap-3 px-4 py-6 border-t border-slate-200/50 bg-white/40 backdrop-blur-md",children:[r("div",{className:"bg-white rounded-[100px] shadow-[0_4px_10px_rgba(0,0,0,0.1)] whitespace-nowrap flex items-center justify-center",style:{padding:"10px 30px",color:"recording"===y.recorder.status?"#FF4D4D":["recorded","uploading","uploaded"].includes(y.recorder.status)?"#16CA3B":"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:"recording"===y.recorder.status?"Ấn lần nữa để lưu kết quả":["recorded","uploading","uploaded"].includes(y.recorder.status)?"Câu trả lời đã được ghi nhận !":"Ấn biểu tượng Micro để trả lời"}),e("div",{className:"relative flex flex-col items-center",children:["recording"===y.recorder.status?e("div",{className:"relative flex flex-col justify-center items-center cursor-pointer drop-shadow-[0_0_15px_rgba(255,100,100,0.8)] transition-transform hover:scale-[1.05] active:scale-[0.95]",onClick:y.recorder.stopRecording,children:[r(c,{src:p,alt:"stop recording",className:"animate-pulse",style:{width:"120px",height:"120px"}}),e("span",{className:"absolute text-white text-[16px] font-bold font-['Quicksand']",style:{bottom:"30px"},children:[Math.floor(y.recorder.remainingSeconds/60),":",(y.recorder.remainingSeconds%60).toString().padStart(2,"0")]})]}):r(c,{src:["recorded","uploading","uploaded"].includes(y.recorder.status)?T?g:h:u,alt:"mic",className:"transition-transform cursor-pointer hover:scale-[1.05] active:scale-[0.95]",style:{width:"120px",height:"120px"},onClick:()=>{if("recording"===y.recorder?.status)y.recorder.stopRecording();else if("idle"===y.recorder?.status||"error"===y.recorder?.status)y.recorder.startRecording();else if("uploaded"===y.recorder?.status||"recorded"===y.recorder?.status){const e=I.current;e&&(T?e.pause():e.play().catch(console.error))}}}),y.recorder?.previewUrl&&r("audio",{ref:I,src:y.recorder.previewUrl}),"recording"===y.recorder.status&&r("div",{className:"absolute whitespace-nowrap text-center",style:{top:"100%",marginTop:"16px",color:"#FF4D4D",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em",textShadow:"0 1px 3px rgba(0,0,0,0.15)"},children:"Đang ghi âm câu hỏi . . ."}),["recorded","uploading","uploaded"].includes(y.recorder.status)&&r("div",{className:"absolute whitespace-nowrap text-center flex flex-col items-center",style:{top:"100%",marginTop:"16px",color:"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:T?`${w(j)}/${A?w(A):"--:--"}`:"Nghe đáp án"})]})]})]}),B]})}
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as s,useEffect as i,useRef as n,useCallback as a,useMemo as r}from"react";import l from"next/image";import{usePresignedFileUrl as o}from"../../../../../../shared/lib/hooks";import{useSpeakingRendererSetup as c}from"../../../hooks/useSpeakingRendererSetup";import{getSpeakingLayout as d}from"../../../../../../components/themes";import p from"../../../../../../components/themes/summer-sky/assets/images/question-badge-sunset.png";import m from"../../../../../../components/themes/summer-sky/assets/images/red-badge-sunset.png";import h from"../../../../../../components/themes/summer-sky/assets/images/blue-badge-sunset.png";import u from"../../../../../../components/themes/summer-sky/assets/images/red-wrapper-sunset.png";import x from"../../../../../../components/themes/summer-sky/assets/images/blue-wrapper-sunset.png";import f from"../../../../../../components/themes/summer-sky/assets/images/robot-avatar.png";import g from"../../../../../../components/themes/summer-sky/assets/images/student-avatar.png";import y from"../../../../../../components/themes/summer-sky/assets/images/ic-play-sunset.png";import v from"../../../../../../components/themes/summer-sky/assets/images/ic-play-violet.webp";import w from"../../../../../../components/themes/summer-sky/assets/images/next-small.webp";function N({total:t,currentIndex:s,answeredIds:i,questionIds:n,virtualIndices:a}){return e("div",{className:"flex items-center gap-1.5 flex-wrap justify-center",children:Array.from({length:t},(t,r)=>{const l=r===s,o=i.has(n[r]),c=a.has(r);return e("div",{className:"h-2.5 w-2.5 rounded-full border-2 transition-all "+(l?"scale-125 border-yellow-300 bg-yellow-400 shadow-lg":o?"border-green-400 bg-green-400":c?"border-white/30 bg-white/10":"border-white/50 bg-white/20"),title:c?"Câu HS ảo":`Câu ${r+1}`},r)})})}export function SpeakingGNInterviewRenderer(b){const[S,k]=s(!0),[R,j]=s(!1),I=n(null),T=b.part.groupPayload,P=T?.virtualStudentName||"Học sinh AI",W=r(()=>{const e=new Set;return b.part.questions.forEach((t,s)=>{const i=t.content;"VIRTUAL"===i?.targetCandidate&&e.add(s)}),e},[b.part.questions]),q=c({...b,maxDurationMs:6e4,hasMic:!0}),U=d("SUMMER_SKY"),z=q.currentQuestion?.content,A="VIRTUAL"===z?.targetCandidate,C=!A,{previewUrl:E}=o(z?.virtualAnswer?.audioUrl??""),{previewUrl:B}=o(z?.imageUrl??""),L=!!z?.imageUrl&&!!B;i(()=>{I.current&&(I.current.pause(),I.current.currentTime=0),j(!1)},[q.currentQuestion?.id]);const V=a(()=>{if(E){if(R&&I.current)return I.current.pause(),void j(!1);I.current?I.current.src=E:(I.current=new Audio(E),I.current.onended=()=>j(!1),I.current.onerror=()=>j(!1)),I.current.play(),j(!0)}},[E,R]);i(()=>()=>{I.current&&(I.current.pause(),I.current=null)},[]);const Y=a(()=>{if(!A||!E)return;const e=setTimeout(()=>{V()},1e3);return()=>clearTimeout(e)},[A,E,V]);if(!q.currentQuestion||!z)return null;const F=new Set(b.part.questions.map(e=>e.id).filter(e=>!!b.answers[e])),H=b.part.questions.map(e=>e.id),D=e(N,{total:b.part.questions.length,currentIndex:q.nav.currentIndex,answeredIds:F,questionIds:H,virtualIndices:W});return t(U,{onExit:b.onExit,partName:b.part.name||`Part ${b.part.partNo}`,instruction:b.part.instructions||"LISTEN AND ANSWER",audioUrl:z.audioUrl??"",questionNumber:q.nav.questionNumberInPart,onPrev:q.handlePrev,onNext:q.handleNext,showPrev:q.nav.showPrev,showNext:q.nav.showNext,canGoPrev:q.nav.canGoPrev,canGoNext:q.nav.canGoNext,onAudioPlayingChange:q.onAudioPlayingChange,recorder:b.isReviewMode||A?null:q.recorder,showExistingBadge:C&&q.showExistingBadge,teacherVideoUrl:b.teacherVideoUrl,onTeacherVideoEnded:b.onTeacherIntroPlayed,skipTeacherVideo:b.skipTeacherVideo,headerRight:D,onAudioEnded:Y,children:[t("div",{className:"w-full h-full flex flex-col items-center relative",children:[e("div",{className:"w-full flex-1",style:{minHeight:0},children:e("div",{className:"mx-auto",style:{width:"850px",maxWidth:"90%",height:L?"auto":"calc(100% - 100px)"},children:t("div",{className:`w-full ${L?"":"h-full"} flex flex-col items-center`,style:L?{}:{paddingTop:"30px"},children:[S&&z.questionText&&t("div",{className:"relative flex flex-col justify-center items-center",style:{width:"882px",maxWidth:"90%",maxHeight:"80%",paddingLeft:"77px",paddingRight:"77px",paddingTop:"26px",paddingBottom:"26px",backgroundColor:"rgba(232, 136, 154, 0.15)",borderRadius:"20px"},children:[t("div",{className:"absolute cursor-pointer",style:{top:"-19px"},onClick:()=>k(!1),children:[e(l,{src:p,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Ẩn câu hỏi"})})]}),e("div",{className:"max-w-full",children:e("div",{className:"text-black font-bold leading-[26px] text-center max-w-full",style:{fontSize:"18px",fontFamily:'"Open Sans", sans-serif'},children:e("p",{children:z.questionText})})})]}),!S&&t("div",{className:"cursor-pointer",onClick:()=>k(!0),children:[e(l,{src:p,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",style:{position:"relative",top:"-30px"},children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Hiện câu hỏi"})})]}),L&&e("div",{className:"flex justify-center",style:{marginTop:"12px"},children:e("div",{className:"relative overflow-hidden",style:{maxWidth:"100%",borderRadius:"16px",border:"3px solid rgba(230, 99, 93, 0.3)",boxShadow:"0 4px 15px rgba(0,0,0,0.08)"},children:e("img",{src:B,alt:"Booklet",style:{width:"100%",height:"100%",objectFit:"cover"}})})})]})})}),t("div",{className:"flex justify-between select-none items-end",style:{width:"990px",maxWidth:"95%",paddingBottom:"40px",paddingLeft:"20px",paddingRight:"20px"},children:[t("div",{className:"relative select-none transition-opacity duration-300 "+(A?"opacity-100":"opacity-50 grayscale"),children:[e("div",{children:t("div",{className:"relative flex",children:[e(l,{src:m,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("div",{className:"text-white leading-5 font-normal text-center m-0 w-full select-none",children:e("p",{className:"m-0 truncate select-none",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:P})})})]})}),t("div",{className:"absolute",style:{top:"7px",right:"-58px"},children:[e(l,{src:u,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[e(l,{src:f,alt:P,width:68,height:68,className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1}),e("div",{className:"flex items-center justify-center absolute w-full h-full top-0 rounded-full text-white cursor-pointer",onClick:A?V:void 0,children:e(l,{src:y,alt:"play",width:16,height:16,className:"opacity-80"})})]})})]}),R&&e("div",{className:"absolute pointer-events-none",style:{top:"0px",right:"-130px",width:"70px",height:"84px",display:"flex",alignItems:"center"},children:t("div",{className:"relative",style:{width:"70px",height:"70px"},children:[e("div",{style:{position:"absolute",left:"0px",top:"50%",transform:"translateY(-50%)",width:"20px",height:"34px",borderRight:"3px solid rgba(30, 64, 175, 0.95)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0s"}}),e("div",{style:{position:"absolute",left:"12px",top:"50%",transform:"translateY(-50%)",width:"28px",height:"50px",borderRight:"3px solid rgba(30, 64, 175, 0.7)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0.2s"}}),e("div",{style:{position:"absolute",left:"24px",top:"50%",transform:"translateY(-50%)",width:"36px",height:"66px",borderRight:"3px solid rgba(30, 64, 175, 0.45)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0.4s"}})]})})]}),R&&e("div",{className:"flex-1 flex justify-center items-center text-center",style:{paddingLeft:"40px",paddingRight:"40px",paddingBottom:"40px"},children:t("p",{className:"m-0 select-none",style:{fontSize:"16px",fontWeight:700,fontStyle:"italic",color:"#1a1a2e",lineHeight:"1.5",fontFamily:'"Open Sans", sans-serif'},children:["Người chơi khác đang trả lời.",e("br",{}),"Vui lòng nghe xong để tiếp tục."]})}),A&&!R&&t("div",{className:"flex-1 flex flex-col justify-center items-center text-center",style:{paddingLeft:"40px",paddingRight:"40px",paddingBottom:"40px"},children:[t("p",{className:"m-0 whitespace-nowrap",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:["Ấn biểu tượng"," ",e(l,{src:v,alt:"",width:20,height:20,className:"inline-block"})," ","trên avatar để nghe lại."]}),t("div",{className:"flex items-center",style:{gap:"4px"},children:[e("p",{className:"m-0",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:"Ấn nút"}),e(l,{src:w,alt:"next",width:34,height:34}),e("p",{className:"m-0",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:"để tiếp tục."})]})]}),t("div",{className:"relative select-none transition-opacity duration-300 "+(C?"opacity-100":"opacity-50 grayscale"),children:[e("div",{children:t("div",{className:"relative flex",children:[e(l,{src:h,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("div",{className:"text-white leading-5 font-normal text-center m-0 w-full select-none",children:e("p",{className:"m-0 truncate select-none",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:"Bạn"})})})]})}),t("div",{className:"absolute",style:{top:"7px",left:"-58px"},children:[e(l,{src:x,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:e("div",{className:"relative",style:{width:"68px",height:"68px"},children:e(l,{src:g,alt:"Bạn",width:68,height:68,className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1})})})]})]})]})]}),e("style",{jsx:!0,children:"\n @keyframes soundWavePulse {\n 0% {\n opacity: 0.2;\n transform: translateY(-50%) scaleX(0.7);\n }\n 50% {\n opacity: 1;\n transform: translateY(-50%) scaleX(1);\n }\n 100% {\n opacity: 0.2;\n transform: translateY(-50%) scaleX(0.7);\n }\n }\n "})]})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as s,useEffect as i,useRef as n,useCallback as a,useMemo as r}from"react";import l from"next/image";import{usePresignedFileUrl as o}from"../../../../../../shared/lib/hooks";import{useSpeakingRendererSetup as c}from"../../../hooks/useSpeakingRendererSetup";import{getSpeakingLayout as d}from"../../../../../../components/themes";import p from"../../../../../../components/themes/summer-sky/assets/images/question-badge-sunset.png";import m from"../../../../../../components/themes/summer-sky/assets/images/red-badge-sunset.png";import h from"../../../../../../components/themes/summer-sky/assets/images/blue-badge-sunset.png";import u from"../../../../../../components/themes/summer-sky/assets/images/red-wrapper-sunset.png";import x from"../../../../../../components/themes/summer-sky/assets/images/blue-wrapper-sunset.png";import f from"../../../../../../components/themes/summer-sky/assets/images/robot-avatar.png";import g from"../../../../../../components/themes/summer-sky/assets/images/student-avatar.png";import y from"../../../../../../components/themes/summer-sky/assets/images/ic-play-sunset.png";import v from"../../../../../../components/themes/summer-sky/assets/images/ic-play-violet.webp";import w from"../../../../../../components/themes/summer-sky/assets/images/next-small.webp";function N({total:t,currentIndex:s,answeredIds:i,questionIds:n,virtualIndices:a}){return e("div",{className:"flex items-center gap-1.5 flex-wrap justify-center",children:Array.from({length:t},(t,r)=>{const l=r===s,o=i.has(n[r]),c=a.has(r);return e("div",{className:"h-2.5 w-2.5 rounded-full border-2 transition-all "+(l?"scale-125 border-yellow-300 bg-yellow-400 shadow-lg":o?"border-green-400 bg-green-400":c?"border-white/30 bg-white/10":"border-white/50 bg-white/20"),title:c?"Câu HS ảo":`Câu ${r+1}`},r)})})}export function SpeakingGNInterviewRenderer(b){const[S,k]=s(!0),[R,j]=s(!1),I=n(null),T=b.part.groupPayload,P=T?.virtualStudentName||"Học sinh AI",W=r(()=>{const e=new Set;return b.part.questions.forEach((t,s)=>{const i=t.content;"VIRTUAL"===i?.targetCandidate&&e.add(s)}),e},[b.part.questions]),q=c({...b,maxDurationMs:6e4,hasMic:!0}),U=d("SUMMER_SKY"),z=q.currentQuestion?.content,A="VIRTUAL"===z?.targetCandidate,C=!A,{previewUrl:E}=o(z?.virtualAnswer?.audioUrl??""),{previewUrl:B}=o(z?.imageUrl??""),L=!!z?.imageUrl&&!!B;i(()=>{I.current&&(I.current.pause(),I.current.currentTime=0),j(!1)},[q.currentQuestion?.id]);const V=a(()=>{if(E){if(R&&I.current)return I.current.pause(),void j(!1);I.current?I.current.src=E:(I.current=new Audio(E),I.current.onended=()=>j(!1),I.current.onerror=()=>j(!1)),I.current.play(),j(!0)}},[E,R]);i(()=>()=>{I.current&&(I.current.pause(),I.current=null)},[]);const Y=a(()=>{if(!A||!E)return;const e=setTimeout(()=>{V()},1e3);return()=>clearTimeout(e)},[A,E,V]);if(!q.currentQuestion||!z)return null;const F=new Set(b.part.questions.map(e=>e.id).filter(e=>!!b.answers[e])),H=b.part.questions.map(e=>e.id),D=e(N,{total:b.part.questions.length,currentIndex:q.nav.currentIndex,answeredIds:F,questionIds:H,virtualIndices:W});return t(U,{onExit:b.onExit,partName:b.part.name||`Part ${b.part.partNo}`,instruction:b.part.instructions||"LISTEN AND ANSWER",audioUrl:z.audioUrl??"",questionNumber:q.nav.questionNumberInPart,onPrev:q.handlePrev,onNext:q.handleNext,showPrev:q.nav.showPrev,showNext:q.nav.showNext,canGoPrev:q.nav.canGoPrev,canGoNext:q.nav.canGoNext,onAudioPlayingChange:q.onAudioPlayingChange,recorder:b.isReviewMode||A?null:q.recorder,showExistingBadge:C&&q.showExistingBadge,teacherVideoUrl:b.teacherVideoUrl,onTeacherVideoEnded:b.onTeacherIntroPlayed,skipTeacherVideo:b.skipTeacherVideo,headerRight:D,onAudioEnded:Y,children:[t("div",{className:"w-full h-full flex flex-col items-center relative",children:[e("div",{className:"w-full flex-1",style:{minHeight:0},children:e("div",{className:"mx-auto",style:{width:"850px",maxWidth:"90%",height:L?"auto":"calc(100% - 100px)"},children:t("div",{className:`w-full ${L?"":"h-full"} flex flex-col items-center`,style:L?{}:{paddingTop:"30px"},children:[S&&z.questionText&&t("div",{className:"relative flex flex-col justify-center items-center",style:{width:"882px",maxWidth:"90%",maxHeight:"80%",paddingLeft:"77px",paddingRight:"77px",paddingTop:"26px",paddingBottom:"26px",backgroundColor:"rgba(232, 136, 154, 0.15)",borderRadius:"20px"},children:[t("div",{className:"absolute cursor-pointer",style:{top:"-19px"},onClick:()=>k(!1),children:[e(l,{src:p,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Ẩn câu hỏi"})})]}),e("div",{className:"max-w-full",children:e("div",{className:"text-black font-bold leading-[26px] text-center max-w-full",style:{fontSize:"18px",fontFamily:'"Open Sans", sans-serif'},children:e("p",{children:z.questionText})})})]}),!S&&t("div",{className:"cursor-pointer",onClick:()=>k(!0),children:[e(l,{src:p,alt:"",style:{width:"169px",height:"38px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center select-none",style:{position:"relative",top:"-30px"},children:e("span",{className:"font-normal text-center leading-5 text-white",style:{fontSize:"18px"},children:"Hiện câu hỏi"})})]}),L&&e("div",{className:"flex justify-center",style:{marginTop:"12px"},children:e("div",{className:"relative overflow-hidden",style:{maxWidth:"100%",borderRadius:"16px",border:"3px solid rgba(230, 99, 93, 0.3)",boxShadow:"0 4px 15px rgba(0,0,0,0.08)"},children:e("img",{src:B,alt:"Booklet",style:{width:"100%",height:"100%",objectFit:"cover"}})})})]})})}),t("div",{className:"flex justify-between select-none items-end",style:{width:"990px",maxWidth:"95%",paddingBottom:"40px",paddingLeft:"20px",paddingRight:"20px"},children:[t("div",{className:"relative select-none transition-opacity duration-300 "+(A?"opacity-100":"opacity-50 grayscale"),children:[e("div",{children:t("div",{className:"relative flex",children:[e(l,{src:m,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("div",{className:"text-white leading-5 font-normal text-center m-0 w-full select-none",children:e("p",{className:"m-0 truncate select-none",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:P})})})]})}),t("div",{className:"absolute",style:{top:"7px",right:"-58px"},children:[e(l,{src:u,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:t("div",{className:"relative",style:{width:"68px",height:"68px"},children:[e(l,{src:f,alt:P,width:68,height:68,className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1}),e("div",{className:"flex items-center justify-center absolute w-full h-full top-0 rounded-full text-white cursor-pointer",onClick:A?V:void 0,children:e(l,{src:y,alt:"play",width:16,height:16,className:"opacity-80"})})]})})]}),R&&e("div",{className:"absolute pointer-events-none",style:{top:"0px",right:"-130px",width:"70px",height:"84px",display:"flex",alignItems:"center"},children:t("div",{className:"relative",style:{width:"70px",height:"70px"},children:[e("div",{style:{position:"absolute",left:"0px",top:"50%",transform:"translateY(-50%)",width:"20px",height:"34px",borderRight:"3px solid rgba(30, 64, 175, 0.95)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0s"}}),e("div",{style:{position:"absolute",left:"12px",top:"50%",transform:"translateY(-50%)",width:"28px",height:"50px",borderRight:"3px solid rgba(30, 64, 175, 0.7)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0.2s"}}),e("div",{style:{position:"absolute",left:"24px",top:"50%",transform:"translateY(-50%)",width:"36px",height:"66px",borderRight:"3px solid rgba(30, 64, 175, 0.45)",borderRadius:"0 50% 50% 0",animation:"soundWavePulse 1s ease-in-out infinite",animationDelay:"0.4s"}})]})})]}),R&&e("div",{className:"flex-1 flex justify-center items-center text-center",style:{paddingLeft:"40px",paddingRight:"40px",paddingBottom:"40px"},children:t("p",{className:"m-0 select-none",style:{fontSize:"16px",fontWeight:700,fontStyle:"italic",color:"#1a1a2e",lineHeight:"1.5",fontFamily:'"Open Sans", sans-serif'},children:["Người chÆ¡i khác Ä‘ang trả lời.",e("br",{}),"Vui lòng nghe xong để tiếp tục."]})}),A&&!R&&t("div",{className:"flex-1 flex flex-col justify-center items-center text-center",style:{paddingLeft:"40px",paddingRight:"40px",paddingBottom:"40px"},children:[t("p",{className:"m-0 whitespace-nowrap",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:["Ấn biểu tượng"," ",e(l,{src:v,alt:"",width:20,height:20,className:"inline-block"})," ","trên avatar để nghe lại."]}),t("div",{className:"flex items-center",style:{gap:"4px"},children:[e("p",{className:"m-0",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:"Ấn nút"}),e(l,{src:w,alt:"next",width:34,height:34}),e("p",{className:"m-0",style:{color:"#1a1a2e",fontSize:"16px",fontWeight:700,fontStyle:"italic",fontFamily:'"Open Sans", sans-serif'},children:"để tiếp tục."})]})]}),t("div",{className:"relative select-none transition-opacity duration-300 "+(C?"opacity-100":"opacity-50 grayscale"),children:[e("div",{children:t("div",{className:"relative flex",children:[e(l,{src:h,alt:"",style:{height:"57px",width:"258px"}}),e("div",{className:"absolute inset-0 flex justify-center items-center",style:{paddingTop:"12px"},children:e("div",{className:"text-white leading-5 font-normal text-center m-0 w-full select-none",children:e("p",{className:"m-0 truncate select-none",style:{fontSize:"18px",paddingLeft:"60px",paddingRight:"60px"},children:"Bạn"})})})]})}),t("div",{className:"absolute",style:{top:"7px",left:"-58px"},children:[e(l,{src:x,alt:"",className:"relative",style:{width:"115px",height:"84px",zIndex:0}}),e("div",{className:"absolute inset-0 flex justify-center items-center w-full h-full",children:e("div",{className:"relative",style:{width:"68px",height:"68px"},children:e(l,{src:g,alt:"Bạn",width:68,height:68,className:"object-cover rounded-full select-none",style:{width:"68px",height:"68px"},draggable:!1})})})]})]})]})]}),e("style",{jsx:!0,children:"\n @keyframes soundWavePulse {\n 0% {\n opacity: 0.2;\n transform: translateY(-50%) scaleX(0.7);\n }\n 50% {\n opacity: 1;\n transform: translateY(-50%) scaleX(1);\n }\n 100% {\n opacity: 0.2;\n transform: translateY(-50%) scaleX(0.7);\n }\n }\n "})]})}
@@ -1 +1 @@
1
- "use client";import{jsxs as e,jsx as r}from"react/jsx-runtime";import{useEffect as t,useRef as i,useState as n}from"react";import{useSpeakingRendererSetup as s}from"../../../hooks/useSpeakingRendererSetup";import{getSpeakingLayout as a}from"../../../../../../components/themes";import l from"../../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import o from"next/image";import d from"../../../../../../components/themes/summer-sky/assets/images/mic_ver2_icon.png";import c from"../../../../../../components/themes/summer-sky/assets/images/stop_audio_ver2_icon.png";import m from"../../../../../../components/themes/summer-sky/assets/images/audio_ver2_icon.png";import u from"../../../../../../components/themes/summer-sky/assets/images/pause_audio_ver2_icon.png";import p from"../SpeakingReadDisplayedContent.module.css";import{SpeakingAudioPlayer as h}from"../../../../../../components/shared/audio/SpeakingAudioPlayer";function f(e){switch(e){case"BASIC_PHONICS":return p.difficultyBasicPhonics;case"DAILY_ROUTINE":return p.difficultyDailyRoutine;case"DESCRIPTIVE_EMOTIONAL":return p.difficultyDescriptiveEmotional;default:return""}}function g(e){switch(e){case"BASIC_PHONICS":return"📖 Basic Phonics";case"DAILY_ROUTINE":return"🕐 Daily Routine & Time";case"DESCRIPTIVE_EMOTIONAL":return"🌄 Descriptive & Emotional";default:return""}}function x({total:t,currentIndex:i,answeredIds:n,questionIds:s,isSpeakingShell:a}){return e("div",{className:p.taskIndicator,style:a?{color:"#78350f",textShadow:"none",fontWeight:800}:void 0,children:[e("span",{children:["Question ",i+1,"/ ",t]}),r("div",{className:"flex gap-2",children:Array.from({length:t},(e,t)=>{const a=t===i,l=n.has(s[t]);return r("div",{className:`${p.taskDot} ${a?p.taskDotActive:""} ${l&&!a?p.taskDotCompleted:""}`},t)})})]})}function v({total:t,currentIndex:i,answeredIds:n,questionIds:s}){return e("div",{className:"flex items-center gap-2 font-bold text-[#78350f] font-['Quicksand'] z-10",children:[e("span",{className:"text-sm",children:["Question ",i+1,"/ ",t]}),r("div",{className:"flex gap-1.5",children:Array.from({length:t},(e,t)=>{const a=t===i,l=n.has(s[t]);return r("div",{className:"w-2.5 h-2.5 rounded-full "+(a?"bg-[#FF9900] scale-125 shadow-sm":l?"bg-[#16CA3B]":"bg-white/60")},t)})})]})}export function SpeakingReadDisplayedContentRenderer(w){const N=s({...w,maxDurationMs:3e4}),y=i(null),[b,k]=n(!1);t(()=>{const e=y.current;if(!e)return;const r=()=>{k(!0),N.onAudioPlayingChange?.(!0)},t=()=>{k(!1),N.onAudioPlayingChange?.(!1)},i=()=>{k(!1),N.onAudioPlayingChange?.(!1)};return e.addEventListener("play",r),e.addEventListener("pause",t),e.addEventListener("ended",i),()=>{e.removeEventListener("play",r),e.removeEventListener("pause",t),e.removeEventListener("ended",i),N.onAudioPlayingChange?.(!1)}},[N.recorder?.previewUrl,N.onAudioPlayingChange]);const S=a(w.speakingTheme),E="SUMMER_SKY"===w.speakingTheme,I=N.currentQuestion?.content;if(!N.currentQuestion||!I)return null;const C=I.referenceText??"",A=I.modelAudioUrl??"",_=I.difficultyTag,P=C.length>700?"clamp(15px, 1.6vw, 19px)":C.length>400?"clamp(18px, 2vw, 24px)":"clamp(22px, 2.2vw, 30px)",T=new Set(w.part.questions.map(e=>e.id).filter(e=>!!w.answers[e])),F=w.part.questions.map(e=>e.id);if(w.speakingTheme&&"CAMBRIDGE_YLE"!==w.speakingTheme){const t=r(x,{total:w.part.questions.length,currentIndex:N.nav.currentIndex,answeredIds:T,questionIds:F,isSpeakingShell:E}),i=A?e("div",{className:p.modelAudioSection,children:[r("span",{className:p.modelAudioLabel,children:"🔊 Model pronunciation:"}),r(h,{audioUrl:A})]}):null;return r(S,{onExit:w.onExit,partName:w.part.name||`Part ${w.part.partNo}`,instruction:w.part.instructions||"READ THE PASSAGE ALOUD",audioUrl:E&&A||"",questionNumber:N.nav.questionNumberInPart,onPrev:N.handlePrev,onNext:N.handleNext,showPrev:N.nav.showPrev,showNext:N.nav.showNext,canGoPrev:N.nav.canGoPrev,canGoNext:N.nav.canGoNext,onAudioPlayingChange:N.onAudioPlayingChange,recorder:w.isReviewMode?null:N.recorder,showExistingBadge:N.showExistingBadge,headerRight:t,audioBarRight:E?null:i,teacherVideoUrl:w.teacherVideoUrl,waitForTeacherVideo:w.waitForTeacherVideo,onTeacherVideoEnded:w.onTeacherIntroPlayed,skipTeacherVideo:w.skipTeacherVideo,children:E?r("div",{className:"w-full h-full flex flex-col items-center relative",children:r("div",{className:"w-full flex-1",style:{minHeight:0},children:r("div",{className:"mx-auto",style:{width:"900px",maxWidth:"95%",height:"calc(100% - 100px)"},children:r("div",{className:"w-full h-full flex flex-col items-center justify-center",style:{paddingTop:"10px"},children:e("div",{className:"relative flex flex-col justify-center items-center",style:{width:"100%",paddingLeft:"60px",paddingRight:"60px",paddingTop:"20px",paddingBottom:"20px"},children:[N.showExistingBadge&&e("div",{className:"absolute right-12 top-12 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"max-w-full",children:r("div",{className:"text-center max-w-full",style:{fontSize:"40px",fontFamily:'"SVN-Volte Rounded", sans-serif',fontWeight:600,lineHeight:"52px",letterSpacing:"-0.01em",color:"#2C38B6"},children:r("p",{className:"m-0 break-words whitespace-pre-wrap",children:`"${C}"`})})})]})})})})}):e("div",{className:"flex flex-col items-center justify-center h-full w-full gap-4 px-4",children:[_&&r("div",{className:`${p.difficultyBadge} ${f(_)}`,children:g(_)}),e("div",{className:p.referenceTextCard,children:[N.showExistingBadge&&e("div",{className:"absolute right-4 top-4 z-10 rounded-full bg-green-500 px-4 py-1 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("p",{className:p.referenceText,children:`"${C}"`})]})]})})}return e("div",{className:"flex flex-col w-full h-full relative",style:{background:"linear-gradient(180deg, #E6F3FF 0%, #FFFFFF 100%)"},children:[e("div",{className:"relative w-full flex justify-between items-start pt-6 px-6 z-20 shrink-0",children:[r("div",{className:"flex-1"}),r("div",{className:"flex-none drop-shadow-md",children:r(l,{partNumber:w.part.partNo,questionCount:w.part.questions.length,partName:w.part.name||`Part ${w.part.partNo}`})}),r("div",{className:"flex-1 flex justify-end mt-2 z-20",children:r(v,{total:w.part.questions.length,currentIndex:N.nav.currentIndex,answeredIds:T,questionIds:F})})]}),e("div",{className:"flex-1 w-full flex flex-col items-center min-h-0 px-4 pb-6 pt-5",children:[w.part.instructions&&e("div",{className:"shrink-0 w-full max-w-[760px] flex items-center gap-3 rounded-2xl px-5 py-3 mb-4",style:{background:"rgba(255, 255, 255, 0.9)",border:"2px solid #FCD34D",boxShadow:"0 3px 12px rgba(180, 130, 20, 0.12)"},children:[r("div",{className:"shrink-0 flex items-center justify-center rounded-full",style:{width:42,height:42,background:"#FEF3C7"},children:r("span",{style:{fontSize:22,lineHeight:1},children:"💡"})}),r("div",{className:"flex flex-col text-left min-w-0",children:r("p",{className:"m-0",style:{color:"#78350F",fontSize:16,fontWeight:600,lineHeight:1.35,fontFamily:'"Quicksand", sans-serif'},children:w.part.instructions})})]}),_&&r("div",{className:"shrink-0 mb-3",children:r("div",{className:`${p.difficultyBadge} ${f(_)}`,children:g(_)})}),r("div",{className:"flex-1 w-full flex flex-col items-center justify-center min-h-0 relative mb-8",children:e("div",{className:"w-full max-w-[850px] max-h-full relative bg-white/60 backdrop-blur-md rounded-2xl shadow-[0_2px_15px_rgba(0,0,0,0.04)] border border-blue-50 p-8 flex flex-col min-h-0",children:[N.showExistingBadge&&e("div",{className:"absolute right-4 top-0 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-lg border-2 border-white transform -translate-y-1/2",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"w-full min-h-0 overflow-y-auto",children:r("p",{className:"text-center break-words whitespace-pre-wrap m-0",style:{fontSize:P,fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',fontWeight:600,lineHeight:1.4,letterSpacing:"-0.01em",color:"#2C38B6"},children:`"${C}"`})}),A&&e("div",{className:"mt-6 flex items-center justify-center gap-2 shrink-0",children:[r("span",{className:"text-sm font-semibold text-[#283593] font-['Quicksand']",children:"🔊 Model pronunciation:"}),r(h,{audioUrl:A})]})]})}),N.recorder&&!w.isReviewMode&&e("div",{className:"shrink-0 flex flex-col items-center z-50 gap-3",children:[r("div",{className:"bg-white rounded-[100px] shadow-[0_4px_10px_rgba(0,0,0,0.1)] whitespace-nowrap flex items-center justify-center",style:{padding:"10px 30px",color:"recording"===N.recorder.status?"#FF4D4D":["recorded","uploading","uploaded"].includes(N.recorder.status)?"#16CA3B":"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:"recording"===N.recorder.status?"Ấn lần nữa để lưu kết quả":["recorded","uploading","uploaded"].includes(N.recorder.status)?"Câu trả lời đã được ghi nhận !":"Ấn biểu tượng Micro để trả lời"}),r("div",{className:"relative flex flex-col items-center",children:"recording"===N.recorder.status?e("div",{className:"relative flex flex-col justify-center items-center cursor-pointer drop-shadow-[0_0_15px_rgba(255,100,100,0.8)] transition-transform hover:scale-[1.05] active:scale-[0.95]",onClick:N.recorder.stopRecording,children:[r(o,{src:c,alt:"stop audio",className:"animate-pulse",style:{width:"120px",height:"120px"}}),e("span",{className:"absolute text-white text-[16px] font-bold font-['Quicksand']",style:{bottom:"30px"},children:[Math.floor(N.recorder.remainingSeconds/60),":",(N.recorder.remainingSeconds%60).toString().padStart(2,"0")]})]}):r(o,{src:["recorded","uploading","uploaded"].includes(N.recorder.status)?b?u:m:d,alt:"micro",className:"transition-transform cursor-pointer hover:scale-[1.05] active:scale-[0.95]",style:{width:"120px",height:"120px"},onClick:()=>{if("recording"===N.recorder?.status)N.recorder.stopRecording();else if("idle"===N.recorder?.status||"error"===N.recorder?.status)N.recorder.startRecording();else if("uploaded"===N.recorder?.status||"recorded"===N.recorder?.status){const e=y.current;e&&(b?e.pause():e.play().catch(console.error))}}})}),N.recorder.previewUrl&&r("audio",{ref:y,src:N.recorder.previewUrl})]})]})]})}
1
+ "use client";import{jsxs as e,jsx as r}from"react/jsx-runtime";import{useEffect as t,useRef as i,useState as n}from"react";import{useSpeakingRendererSetup as s}from"../../../hooks/useSpeakingRendererSetup";import{getSpeakingLayout as a}from"../../../../../../components/themes";import l from"../../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import o from"next/image";import d from"../../../../../../components/themes/summer-sky/assets/images/mic_ver2_icon.png";import c from"../../../../../../components/themes/summer-sky/assets/images/stop_audio_ver2_icon.png";import m from"../../../../../../components/themes/summer-sky/assets/images/audio_ver2_icon.png";import u from"../../../../../../components/themes/summer-sky/assets/images/pause_audio_ver2_icon.png";import p from"../SpeakingReadDisplayedContent.module.css";import{SpeakingAudioPlayer as h}from"../../../../../../components/shared/audio/SpeakingAudioPlayer";function f(e){switch(e){case"BASIC_PHONICS":return p.difficultyBasicPhonics;case"DAILY_ROUTINE":return p.difficultyDailyRoutine;case"DESCRIPTIVE_EMOTIONAL":return p.difficultyDescriptiveEmotional;default:return""}}function g(e){switch(e){case"BASIC_PHONICS":return"📖 Basic Phonics";case"DAILY_ROUTINE":return"🕐 Daily Routine & Time";case"DESCRIPTIVE_EMOTIONAL":return"🌄 Descriptive & Emotional";default:return""}}function x({total:t,currentIndex:i,answeredIds:n,questionIds:s,isSpeakingShell:a}){return e("div",{className:p.taskIndicator,style:a?{color:"#78350f",textShadow:"none",fontWeight:800}:void 0,children:[e("span",{children:["Question ",i+1,"/ ",t]}),r("div",{className:"flex gap-2",children:Array.from({length:t},(e,t)=>{const a=t===i,l=n.has(s[t]);return r("div",{className:`${p.taskDot} ${a?p.taskDotActive:""} ${l&&!a?p.taskDotCompleted:""}`},t)})})]})}function v({total:t,currentIndex:i,answeredIds:n,questionIds:s}){return e("div",{className:"flex items-center gap-2 font-bold text-[#78350f] font-['Quicksand'] z-10",children:[e("span",{className:"text-sm",children:["Question ",i+1,"/ ",t]}),r("div",{className:"flex gap-1.5",children:Array.from({length:t},(e,t)=>{const a=t===i,l=n.has(s[t]);return r("div",{className:"w-2.5 h-2.5 rounded-full "+(a?"bg-[#FF9900] scale-125 shadow-sm":l?"bg-[#16CA3B]":"bg-white/60")},t)})})]})}export function SpeakingReadDisplayedContentRenderer(w){const N=s({...w,maxDurationMs:3e4}),y=i(null),[b,k]=n(!1);t(()=>{const e=y.current;if(!e)return;const r=()=>{k(!0),N.onAudioPlayingChange?.(!0)},t=()=>{k(!1),N.onAudioPlayingChange?.(!1)},i=()=>{k(!1),N.onAudioPlayingChange?.(!1)};return e.addEventListener("play",r),e.addEventListener("pause",t),e.addEventListener("ended",i),()=>{e.removeEventListener("play",r),e.removeEventListener("pause",t),e.removeEventListener("ended",i),N.onAudioPlayingChange?.(!1)}},[N.recorder?.previewUrl,N.onAudioPlayingChange]);const S=a(w.speakingTheme),E="SUMMER_SKY"===w.speakingTheme,I=N.currentQuestion?.content;if(!N.currentQuestion||!I)return null;const C=I.referenceText??"",A=I.modelAudioUrl??"",_=I.difficultyTag,P=C.length>700?"clamp(15px, 1.6vw, 19px)":C.length>400?"clamp(18px, 2vw, 24px)":"clamp(22px, 2.2vw, 30px)",T=new Set(w.part.questions.map(e=>e.id).filter(e=>!!w.answers[e])),F=w.part.questions.map(e=>e.id);if(w.speakingTheme&&"CAMBRIDGE_YLE"!==w.speakingTheme){const t=r(x,{total:w.part.questions.length,currentIndex:N.nav.currentIndex,answeredIds:T,questionIds:F,isSpeakingShell:E}),i=A?e("div",{className:p.modelAudioSection,children:[r("span",{className:p.modelAudioLabel,children:"🔊 Model pronunciation:"}),r(h,{audioUrl:A})]}):null;return r(S,{onExit:w.onExit,partName:w.part.name||`Part ${w.part.partNo}`,instruction:w.part.instructions||"READ THE PASSAGE ALOUD",audioUrl:E&&A||"",questionNumber:N.nav.questionNumberInPart,onPrev:N.handlePrev,onNext:N.handleNext,showPrev:N.nav.showPrev,showNext:N.nav.showNext,canGoPrev:N.nav.canGoPrev,canGoNext:N.nav.canGoNext,onAudioPlayingChange:N.onAudioPlayingChange,recorder:w.isReviewMode?null:N.recorder,showExistingBadge:N.showExistingBadge,headerRight:t,audioBarRight:E?null:i,teacherVideoUrl:w.teacherVideoUrl,waitForTeacherVideo:w.waitForTeacherVideo,onTeacherVideoEnded:w.onTeacherIntroPlayed,skipTeacherVideo:w.skipTeacherVideo,children:E?r("div",{className:"w-full h-full flex flex-col items-center relative",children:r("div",{className:"w-full flex-1",style:{minHeight:0},children:r("div",{className:"mx-auto",style:{width:"900px",maxWidth:"95%",height:"calc(100% - 100px)"},children:r("div",{className:"w-full h-full flex flex-col items-center justify-center",style:{paddingTop:"10px"},children:e("div",{className:"relative flex flex-col justify-center items-center",style:{width:"100%",paddingLeft:"60px",paddingRight:"60px",paddingTop:"20px",paddingBottom:"20px"},children:[N.showExistingBadge&&e("div",{className:"absolute right-12 top-12 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"max-w-full",children:r("div",{className:"text-center max-w-full",style:{fontSize:"40px",fontFamily:'"SVN-Volte Rounded", sans-serif',fontWeight:600,lineHeight:"52px",letterSpacing:"-0.01em",color:"#2C38B6"},children:r("p",{className:"m-0 break-words whitespace-pre-wrap",children:`"${C}"`})})})]})})})})}):e("div",{className:"flex flex-col items-center justify-center h-full w-full gap-4 px-4",children:[_&&r("div",{className:`${p.difficultyBadge} ${f(_)}`,children:g(_)}),e("div",{className:p.referenceTextCard,children:[N.showExistingBadge&&e("div",{className:"absolute right-4 top-4 z-10 rounded-full bg-green-500 px-4 py-1 flex items-center gap-2 text-sm font-bold text-white shadow-md border-2 border-white",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("p",{className:p.referenceText,children:`"${C}"`})]})]})})}return e("div",{className:"flex flex-col w-full h-full relative",style:{background:"linear-gradient(180deg, #E6F3FF 0%, #FFFFFF 100%)"},children:[e("div",{className:"relative w-full flex justify-between items-start pt-6 px-6 z-20 shrink-0",children:[r("div",{className:"flex-1"}),r("div",{className:"flex-none drop-shadow-md",children:r(l,{partNumber:w.part.partNo,questionCount:w.part.questions.length,partName:w.part.name||`Part ${w.part.partNo}`})}),r("div",{className:"flex-1 flex justify-end mt-2 z-20",children:r(v,{total:w.part.questions.length,currentIndex:N.nav.currentIndex,answeredIds:T,questionIds:F})})]}),e("div",{className:"flex-1 w-full flex flex-col items-center min-h-0 px-4 pb-6 pt-5",children:[w.part.instructions&&e("div",{className:"shrink-0 w-full max-w-[760px] flex items-center gap-3 rounded-2xl px-5 py-3 mb-4",style:{background:"rgba(255, 255, 255, 0.9)",border:"2px solid #FCD34D",boxShadow:"0 3px 12px rgba(180, 130, 20, 0.12)"},children:[r("div",{className:"shrink-0 flex items-center justify-center rounded-full",style:{width:42,height:42,background:"#FEF3C7"},children:r("span",{style:{fontSize:22,lineHeight:1},children:"💡"})}),r("div",{className:"flex flex-col text-left min-w-0",children:r("p",{className:"m-0",style:{color:"#78350F",fontSize:16,fontWeight:600,lineHeight:1.35,fontFamily:'"Quicksand", sans-serif'},children:w.part.instructions})})]}),_&&r("div",{className:"shrink-0 mb-3",children:r("div",{className:`${p.difficultyBadge} ${f(_)}`,children:g(_)})}),r("div",{className:"flex-1 w-full flex flex-col items-center justify-center min-h-0 relative mb-8",children:e("div",{className:"w-full max-w-[850px] max-h-full relative bg-white/60 backdrop-blur-md rounded-2xl shadow-[0_2px_15px_rgba(0,0,0,0.04)] border border-blue-50 p-8 flex flex-col min-h-0",children:[N.showExistingBadge&&e("div",{className:"absolute right-4 top-0 z-10 rounded-full bg-green-500 px-4 py-1.5 flex items-center gap-2 text-sm font-bold text-white shadow-lg border-2 border-white transform -translate-y-1/2",children:[r("span",{className:"h-2.5 w-2.5 rounded-full bg-white animate-pulse"}),"Đã ghi âm"]}),r("div",{className:"w-full min-h-0 overflow-y-auto",children:r("p",{className:"text-center break-words whitespace-pre-wrap m-0",style:{fontSize:P,fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif',fontWeight:600,lineHeight:1.4,letterSpacing:"-0.01em",color:"#2C38B6"},children:`"${C}"`})}),A&&e("div",{className:"mt-6 flex items-center justify-center gap-2 shrink-0",children:[r("span",{className:"text-sm font-semibold text-[#283593] font-['Quicksand']",children:"🔊 Model pronunciation:"}),r(h,{audioUrl:A})]})]})}),N.recorder&&!w.isReviewMode&&e("div",{className:"shrink-0 flex flex-col items-center z-50 gap-3",children:[r("div",{className:"bg-white rounded-[100px] shadow-[0_4px_10px_rgba(0,0,0,0.1)] whitespace-nowrap flex items-center justify-center",style:{padding:"10px 30px",color:"recording"===N.recorder.status?"#FF4D4D":["recorded","uploading","uploaded"].includes(N.recorder.status)?"#16CA3B":"#343C55",fontSize:"18px",fontFamily:'"Quicksand", sans-serif',fontWeight:700,lineHeight:"100%",letterSpacing:"-0.01em"},children:"recording"===N.recorder.status?"Ấn lần nữa để lưu kết quả":["recorded","uploading","uploaded"].includes(N.recorder.status)?"Câu trả lời đã được ghi nhận !":"Ấn biểu tượng Micro để trả lời"}),r("div",{className:"relative flex flex-col items-center",children:"recording"===N.recorder.status?e("div",{className:"relative flex flex-col justify-center items-center cursor-pointer drop-shadow-[0_0_15px_rgba(255,100,100,0.8)] transition-transform hover:scale-[1.05] active:scale-[0.95]",onClick:N.recorder.stopRecording,children:[r(o,{src:c,alt:"stop audio",className:"animate-pulse",style:{width:"120px",height:"120px"}}),e("span",{className:"absolute text-white text-[16px] font-bold font-['Quicksand']",style:{bottom:"30px"},children:[Math.floor(N.recorder.remainingSeconds/60),":",(N.recorder.remainingSeconds%60).toString().padStart(2,"0")]})]}):r(o,{src:["recorded","uploading","uploaded"].includes(N.recorder.status)?b?u:m:d,alt:"micro",className:"transition-transform cursor-pointer hover:scale-[1.05] active:scale-[0.95]",style:{width:"120px",height:"120px"},onClick:()=>{if("recording"===N.recorder?.status)N.recorder.stopRecording();else if("idle"===N.recorder?.status||"error"===N.recorder?.status)N.recorder.startRecording();else if("uploaded"===N.recorder?.status||"recorded"===N.recorder?.status){const e=y.current;e&&(b?e.pause():e.play().catch(console.error))}}})}),N.recorder.previewUrl&&r("audio",{ref:y,src:N.recorder.previewUrl})]})]})]})}
@@ -1 +1 @@
1
- import{useState as r,useRef as e,useEffect as n,useCallback as t}from"react";import{usePresignedFileUrl as u}from"../../../../shared/lib/hooks";import{useExamTakingApiOptional as o}from"../ExamTakingApiContext";export function useSpeakingRecorder(i){const c=i.maxDurationMs??3e4,a=Math.floor(c/1e3),d=o(),s=e(d);s.current=d;const l=e(i.onRecordingComplete),p=e(i.onError);l.current=i.onRecordingComplete,p.current=i.onError;const g=e(i.attemptId),m=e(i.questionId);g.current=i.attemptId,m.current=i.questionId;const[h,y]=r("idle"),[w,f]=r(a),[A,v]=r(0),[R,T]=r(null),[E,x]=r(null),[I,b]=r(null),[K,M]=r(!1),k=e(null),P=e(null),D=e([]),S=e(null),U=e(null),O=e(""),_=e(0),q=e(null),L=e(void 0),B=e(0),V=e(!0),C=e(""),G="undefined"!=typeof MediaRecorder,{previewUrl:j}=u(i.existingAnswerKey),N=t(()=>{S.current&&(clearInterval(S.current),S.current=null)},[]),F=t(()=>{U.current&&(U.current.startsWith("blob:")&&URL.revokeObjectURL(U.current),U.current=null)},[]),W=t(()=>{P.current&&(P.current.getTracks().forEach(r=>r.stop()),P.current=null)},[]),X=t(async(r,e,n,t)=>{if(!V.current)return;const u=t||C.current||m.current;m.current===u&&y("uploading");const o=g.current;if("mock-attempt-speaking"===o){if(await new Promise(r=>setTimeout(r,500)),!V.current)return;const r=`mock-audio-key-${u}`;return m.current===u&&(y("uploaded"),x(r)),l.current(r,u),q.current=null,void(L.current=void 0)}try{if(!s.current?.uploadAudioAnswer)throw new Error("uploadAudioAnswer is not implemented by the provided API adapter.");const n=(i=await s.current.uploadAudioAnswer({attemptId:o,questionId:u,audioBlob:r,durationMs:e}))&&"object"==typeof i&&"data"in i?i.data:i;if(!V.current)return;const t=n.audioKey??"";m.current===u&&(y("uploaded"),x(t)),l.current(t,u),q.current=null,L.current=void 0,B.current=0,s.current.realtimeGradeSingle?.({attemptId:o,questionId:u,audioKey:t}).catch(r=>{console.debug("[Realtime Grading] Skipped or failed:",r?.response?.status??r?.message)})}catch(u){if(!V.current)return;const o=u,i=o?.response?.data?.code;if("ATTEMPT_EXPIRED"===i||"ATTEMPT_NOT_IN_PROGRESS"===i){const r="ATTEMPT_EXPIRED"===i?"Bài thi đã hết giờ":"Bài thi đã được nộp.";return y("error"),b(r),M(!0),void p.current?.(r)}if("AUDIO_FILE_TOO_LARGE"===i){const r="Bài ghi âm quá dài. Vui lòng ghi âm ngắn hơn.";return y("error"),b(r),void p.current?.(r)}if(n<3){const u=1e3*Math.pow(2,n);if(await new Promise(r=>setTimeout(r,u)),!V.current)return;B.current=n+1,await X(r,e,n+1,t)}else{const r="Tải lên bản ghi âm thất bại. Vui lòng thử lại.";y("error"),b(r),p.current?.(r)}}var i},[]),z=t(async(r,e,n)=>{q.current=r,L.current=e,B.current=0,await X(r,e,0,n)},[X]),$=t(async()=>{if(i.existingAnswerKey)return y("uploaded"),void x(i.existingAnswerKey);if(!G){const r="Trình duyệt này không hỗ trợ ghi âm. Vui lòng dùng Chrome, Firefox hoặc Edge.";return y("error"),b(r),void p.current?.(r)}const r=function(){if("undefined"==typeof MediaRecorder)return null;const r=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg;codecs=opus","audio/ogg"];for(const e of r)if(MediaRecorder.isTypeSupported(e))return e;return null}();if(!r){const r="Trình duyệt không hỗ trợ định dạng ghi âm.";return y("error"),b(r),void p.current?.(r)}try{const e=await navigator.mediaDevices.getUserMedia({audio:!0});P.current=e,O.current=r;const n=new MediaRecorder(e,{mimeType:r});k.current=n,D.current=[],n.ondataavailable=r=>{r.data.size>0&&D.current.push(r.data)},n.onstop=()=>{const r=Date.now()-_.current,e=new Blob(D.current,{type:O.current}),n=URL.createObjectURL(e),t=C.current;F(),U.current=n,T(n),y("recorded"),z(e,r,t)},n.start(),_.current=Date.now(),C.current=m.current,y("recording"),v(0),f(a),b(null),x(null),T(null),M(!1),S.current=setInterval(()=>{v(r=>r+1),f(r=>{const e=Math.max(0,r-1);return 0===e&&(N(),k.current&&"recording"===k.current.state&&k.current.stop(),W()),e})},1e3)}catch(r){W();const e=r instanceof DOMException&&("NotAllowedError"===r.name||"PermissionDeniedError"===r.name)?"Vui lòng cấp quyền truy cập microphone trong trình duyệt.":"Không thể truy cập microphone. Vui lòng thử lại.";y("error"),b(e),p.current?.(e)}},[G,a,i.existingAnswerKey,N,W,z,F]),H=t(()=>{N(),k.current&&"recording"===k.current.state&&k.current.stop(),W()},[N,W]),J=t(()=>{N(),W(),k.current&&"recording"===k.current.state&&k.current.stop(),k.current=null,D.current=[],q.current=null,L.current=void 0,B.current=0,F(),T(null),x(null),v(0),f(a),b(null),y("idle"),M(!1)},[N,W,F,a]),Q=t(async()=>{if(i.existingAnswerKey)return y("uploaded"),void x(i.existingAnswerKey);J(),await $()},[i.existingAnswerKey,J,$]),Y=t(async()=>{const r=q.current;r&&(B.current=0,await X(r,L.current,0,C.current||void 0))},[X]);n(()=>{J()},[i.questionId]),n(()=>{"idle"===h&&j&&i.existingAnswerKey&&!R&&(T(j),U.current=j,x(i.existingAnswerKey),y("uploaded"))},[h,j,i.existingAnswerKey,R]),n(()=>(V.current=!0,()=>{V.current=!1,N(),k.current&&"recording"===k.current.state&&k.current.stop(),W(),F()}),[]);return{status:h,remainingSeconds:w,isWarning:w<=5&&"recording"===h,durationSeconds:A,previewUrl:R,uploadedKey:E,error:I,isSupported:G,isAttemptExpired:K,liveTranscript:null,startRecording:$,stopRecording:H,resetRecording:J,reRecord:Q,retryUpload:Y}}
1
+ import{useState as r,useRef as e,useEffect as n,useCallback as t}from"react";import{usePresignedFileUrl as o}from"../../../../shared/lib/hooks";import{useExamTakingApiOptional as u}from"../ExamTakingApiContext";export function useSpeakingRecorder(i){const c=i.maxDurationMs??3e4,a=Math.floor(c/1e3),d=u(),s=e(d);s.current=d;const l=e(i.onRecordingComplete),p=e(i.onError);l.current=i.onRecordingComplete,p.current=i.onError;const g=e(i.attemptId),h=e(i.questionId);g.current=i.attemptId,h.current=i.questionId;const[m,y]=r("idle"),[f,w]=r(a),[v,A]=r(0),[T,E]=r(null),[R,x]=r(null),[b,k]=r(null),[I,M]=r(!1),K=e(null),D=e(null),P=e([]),S=e(null),U=e(null),O=e(""),_=e(0),q=e(null),L=e(void 0),N=e(0),B=e(!0),V=e(""),C="undefined"!=typeof MediaRecorder,{previewUrl:F}=o(i.existingAnswerKey),G=t(()=>{S.current&&(clearInterval(S.current),S.current=null)},[]),j=t(()=>{U.current&&(U.current.startsWith("blob:")&&URL.revokeObjectURL(U.current),U.current=null)},[]),W=t(()=>{D.current&&(D.current.getTracks().forEach(r=>r.stop()),D.current=null)},[]),X=t(async(r,e,n,t)=>{if(!B.current)return;const o=t||V.current||h.current;h.current===o&&y("uploading");const u=g.current;if("mock-attempt-speaking"===u){if(await new Promise(r=>setTimeout(r,500)),!B.current)return;const r=`mock-audio-key-${o}`;return h.current===o&&(y("uploaded"),x(r)),l.current(r,o),q.current=null,void(L.current=void 0)}try{if(!s.current?.uploadAudioAnswer)throw new Error("uploadAudioAnswer is not implemented by the provided API adapter.");const n=(i=await s.current.uploadAudioAnswer({attemptId:u,questionId:o,audioBlob:r,durationMs:e}))&&"object"==typeof i&&"data"in i?i.data:i;if(!B.current)return;const t=n.audioKey??"";h.current===o&&(y("uploaded"),x(t)),l.current(t,o),q.current=null,L.current=void 0,N.current=0,s.current.realtimeGradeSingle?.({attemptId:u,questionId:o,audioKey:t}).catch(r=>{console.debug("[Realtime Grading] Skipped or failed:",r?.response?.status??r?.message)})}catch(o){if(!B.current)return;const u=o,i=u?.response?.data?.code;if("ATTEMPT_EXPIRED"===i||"ATTEMPT_NOT_IN_PROGRESS"===i){const r="ATTEMPT_EXPIRED"===i?"Bài thi đã hết giờ":"Bài thi đã được nộp.";return y("error"),k(r),M(!0),void p.current?.(r)}if("AUDIO_FILE_TOO_LARGE"===i){const r="Bài ghi âm quá dài. Vui lòng ghi âm ngắn hơn.";return y("error"),k(r),void p.current?.(r)}if(n<3){const o=1e3*Math.pow(2,n);if(await new Promise(r=>setTimeout(r,o)),!B.current)return;N.current=n+1,await X(r,e,n+1,t)}else{const r="Tải lên bản ghi âm thất bại. Vui lòng thử lại.";y("error"),k(r),p.current?.(r)}}var i},[]),z=t(async(r,e,n)=>{q.current=r,L.current=e,N.current=0,await X(r,e,0,n)},[X]),H=t(async()=>{if(i.existingAnswerKey)return y("uploaded"),void x(i.existingAnswerKey);if(!C){const r="Trình duyệt này không hỗ trợ ghi âm. Vui lòng dùng Chrome, Firefox hoặc Edge.";return y("error"),k(r),void p.current?.(r)}const r=function(){if("undefined"==typeof MediaRecorder)return null;const r=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg;codecs=opus","audio/ogg"];for(const e of r)if(MediaRecorder.isTypeSupported(e))return e;return null}();if(!r){const r="Trình duyệt không hỗ trợ định dạng ghi âm.";return y("error"),k(r),void p.current?.(r)}if("undefined"==typeof navigator||!navigator.mediaDevices?.getUserMedia){const r="Trình duyệt hoặc kết nối (HTTP) không hỗ trợ truy cập microphone.";return y("error"),k(r),void p.current?.(r)}try{const e=await navigator.mediaDevices.getUserMedia({audio:!0});D.current=e,O.current=r;const n=new MediaRecorder(e,{mimeType:r});K.current=n,P.current=[],n.ondataavailable=r=>{r.data.size>0&&P.current.push(r.data)},n.onstop=()=>{const r=Date.now()-_.current,e=new Blob(P.current,{type:O.current}),n=URL.createObjectURL(e),t=V.current;j(),U.current=n,E(n),y("recorded"),z(e,r,t)},n.start(),_.current=Date.now(),V.current=h.current,y("recording"),A(0),w(a),k(null),x(null),E(null),M(!1),S.current=setInterval(()=>{A(r=>r+1),w(r=>{const e=Math.max(0,r-1);return 0===e&&(G(),K.current&&"recording"===K.current.state&&K.current.stop(),W()),e})},1e3)}catch(r){W();const e=r instanceof DOMException?r.name:r?.name;let n="Không thể truy cập microphone. Vui lòng thử lại.";"NotAllowedError"===e||"PermissionDeniedError"===e?n="Vui lòng cấp quyền truy cập microphone trong cài đặt trình duyệt.":"NotFoundError"===e||"DevicesNotFoundError"===e?n="Không tìm thấy thiết bị microphone nào kết nối với máy tính.":"NotReadableError"!==e&&"TrackStartError"!==e||(n="Microphone đang được ứng dụng khác sử dụng hoặc gặp lỗi phần cứng."),y("error"),k(n),p.current?.(n)}},[C,a,i.existingAnswerKey,G,W,z,j]),$=t(()=>{G(),K.current&&"recording"===K.current.state&&K.current.stop(),W()},[G,W]),J=t(()=>{G(),W(),K.current&&"recording"===K.current.state&&K.current.stop(),K.current=null,P.current=[],q.current=null,L.current=void 0,N.current=0,j(),E(null),x(null),A(0),w(a),k(null),y("idle"),M(!1)},[G,W,j,a]),Q=t(async()=>{if(i.existingAnswerKey)return y("uploaded"),void x(i.existingAnswerKey);J(),await H()},[i.existingAnswerKey,J,H]),Y=t(async()=>{const r=q.current;r&&(N.current=0,await X(r,L.current,0,V.current||void 0))},[X]);n(()=>{J()},[i.questionId]),n(()=>{"idle"===m&&F&&i.existingAnswerKey&&!T&&(E(F),U.current=F,x(i.existingAnswerKey),y("uploaded"))},[m,F,i.existingAnswerKey,T]),n(()=>(B.current=!0,()=>{B.current=!1,G(),K.current&&"recording"===K.current.state&&K.current.stop(),W(),j()}),[]);return{status:m,remainingSeconds:f,isWarning:f<=5&&"recording"===m,durationSeconds:v,previewUrl:T,uploadedKey:R,error:b,isSupported:C,isAttemptExpired:I,liveTranscript:null,startRecording:H,stopRecording:$,resetRecording:J,reRecord:Q,retryUpload:Y}}
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import t,{useState as a,useEffect as n,useMemo as s,useCallback as l}from"react";import{Check as o,X as i,FileText as d}from"lucide-react";import{usePresignedFileUrl as c}from"../../../../shared/lib/hooks";import{cn as m}from"../../../../shared/lib/utils";export function WordFillStructuredFormClient({questionData:g,isReviewMode:u=!1,userAnswer:p,onAnswerChange:x,autoFillCorrectAnswers:b=!1,explanation:h}){const{title:f="",imageUrl:y,content:N="",answers:w={},caseSensitive:v=!1}=g,[C,j]=a(()=>p?{...p}:b?{...w}:{});n(()=>{p&&j({...p})},[p]);const{previewUrl:E,isLoading:_}=c(y||""),A=s(()=>{const e=new Set,r=/\{([\w\d]+)\}/g;let t;for(;null!==(t=r.exec(N));)e.add(t[1]);return Array.from(e).sort((e,r)=>{const t=parseInt(e),a=parseInt(r);return isNaN(t)||isNaN(a)?e.localeCompare(r):t-a})},[N]),L=A.every(e=>C[e]?.trim()),k=u&&A.every(e=>{const r=(C[e]||"").trim(),t=(w[e]||"").trim();return v?r===t:r.toLowerCase()===t.toLowerCase()}),$=h||g.explanation,F=l((e,r)=>{u||(j(t=>({...t,[e]:r})),x?.(e,r))},[u,x]),S=l((t,a)=>{const n=C[t]||"",s=w[t]||"",l=v?n.trim():n.trim().toLowerCase(),d=v?s.trim():s.trim().toLowerCase(),c=u&&l===d,g=u&&!!n&&l!==d;return r("span",{className:"relative mx-1 inline-flex items-center align-baseline",children:[e("span",{className:"absolute -top-4 left-1 text-[10px] font-semibold text-gray-400",children:t}),e("input",{type:"text",value:n,onChange:e=>F(t,e.target.value),disabled:u,placeholder:"______",className:m("inline-block min-w-[90px] max-w-[160px] border-b-2 bg-transparent px-1 py-0.5 text-center text-sm font-semibold outline-none transition-all",u?c?"border-green-400 text-green-700":g?"border-red-400 text-red-700":"border-gray-300 text-gray-400":"border-gray-300 text-gray-800 focus:border-teal-500 focus:ring-0")}),u&&n&&(c?e(o,{className:"ml-0.5 h-3.5 w-3.5 text-green-600"}):e(i,{className:"ml-0.5 h-3.5 w-3.5 text-red-600"}))]},a)},[w,v,C,F,u]),T=s(()=>{if("undefined"==typeof window)return N;const r=(new DOMParser).parseFromString(N||"<p></p>","text/html"),a=/\{([\w\d]+)\}/g,n=(r,s)=>{if(r.nodeType===Node.TEXT_NODE){const n=r.textContent||"",l=[];let o,i=0;for(a.lastIndex=0;null!==(o=a.exec(n));)o.index>i&&l.push(n.slice(i,o.index)),l.push(S(o[1],`${s}-blank-${o.index}`)),i=o.index+o[0].length;return i<n.length&&l.push(n.slice(i)),0===l.length?null:1===l.length?l[0]:e(t.Fragment,{children:l},s)}if(r.nodeType!==Node.ELEMENT_NODE)return null;const l=r,o=l.tagName.toLowerCase(),i={key:s};Array.from(l.attributes).forEach(e=>{"class"!==e.name?"style"!==e.name?i[e.name]=e.value:i.style=e.value.split(";").map(e=>e.trim()).filter(Boolean).reduce((e,r)=>{const[t,a]=r.split(":").map(e=>e.trim());return t&&a?(e[t.replace(/-([a-z])/g,(e,r)=>r.toUpperCase())]=a,e):e},{}):i.className=e.value});const d=Array.from(l.childNodes).map((e,r)=>n(e,`${s}-${r}`)).filter(e=>null!==e);return t.createElement(o,i,...d)};return Array.from(r.body.childNodes).map((e,r)=>n(e,`root-${r}`)).filter(e=>null!==e)},[N,S]);return e("div",{className:"space-y-4",children:r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-teal-500 to-cyan-600 text-white shadow-sm",children:e(d,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Điền từ vào biểu mẫu có cấu trúc"})]}),u&&L&&r("div",{className:m("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",k?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e(k?o:i,{className:"h-3.5 w-3.5"}),k?"Đúng":"Sai"]})]}),r("div",{className:"space-y-5 p-5",children:[f&&e("h2",{className:"text-center text-xl font-bold text-gray-900",children:f}),(E||y)&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:_?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:E||y,alt:f,className:"max-h-56 w-auto object-contain p-2"})})}),e("div",{className:"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-loose text-gray-800",children:T}),u&&!k&&r("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:A.map(e=>r("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}}`,": ",w[e]]},e))})]}),u&&$&&r("div",{className:"rounded-lg border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-3",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-blue-600",children:"Giải thích"}),e("p",{className:"mt-1 text-sm text-blue-800",children:$})]})]})]})})}
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import t,{useState as a,useEffect as n,useMemo as s,useCallback as l}from"react";import{Check as o,X as i,FileText as d}from"lucide-react";import{usePresignedFileUrl as c}from"../../../../shared/lib/hooks";import{cn as m}from"../../../../shared/lib/utils";export function WordFillStructuredFormClient({questionData:g,isReviewMode:u=!1,userAnswer:b,onAnswerChange:p,autoFillCorrectAnswers:x=!1,explanation:h}){const{title:f="",imageUrl:N,content:w="",answers:y={},caseSensitive:v=!1}=g,[C,j]=a(()=>b?{...b}:x?{...y}:{});n(()=>{b&&j({...b})},[b]);const{previewUrl:E,isLoading:A}=c(N||""),L=s(()=>{const e=new Set,r=/\{([\w\d]+)\}/g;let t;for(;null!==(t=r.exec(w));)e.add(t[1]);return Array.from(e).sort((e,r)=>{const t=parseInt(e),a=parseInt(r);return isNaN(t)||isNaN(a)?e.localeCompare(r):t-a})},[w]),k=L.every(e=>C[e]?.trim()),$=u&&L.every(e=>{const r=(C[e]||"").trim(),t=(y[e]||"").trim();return v?r===t:r.toLowerCase()===t.toLowerCase()}),F=h||g.explanation,S=l((e,r)=>{u||(j(t=>({...t,[e]:r})),p?.(e,r))},[u,p]),T=l((t,a)=>{const n=C[t]||"",s=y[t]||"",l=v?n.trim():n.trim().toLowerCase(),d=v?s.trim():s.trim().toLowerCase(),c=u&&l===d,g=u&&!!n&&l!==d;return r("span",{className:"relative mx-1 inline-flex items-baseline align-baseline",children:[e("span",{className:"absolute -top-4 left-1 text-[10px] font-semibold text-gray-400",children:t}),e("input",{type:"text",value:n,onChange:e=>S(t,e.target.value),disabled:u,placeholder:"",className:m("inline-block min-w-[90px] max-w-[200px] rounded-t border-b-2 bg-slate-50/40 px-2 py-0.5 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",u?c?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":g?"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")}),u&&n&&(c?e(o,{className:"ml-0.5 h-3.5 w-3.5 text-green-600"}):e(i,{className:"ml-0.5 h-3.5 w-3.5 text-red-600"}))]},a)},[y,v,C,S,u]),D=s(()=>{if("undefined"==typeof window)return w;const r=(new DOMParser).parseFromString(w||"<p></p>","text/html"),a=/\{([\w\d]+)\}/g,n=(r,s)=>{if(r.nodeType===Node.TEXT_NODE){const n=r.textContent||"",l=[];let o,i=0;for(a.lastIndex=0;null!==(o=a.exec(n));)o.index>i&&l.push(n.slice(i,o.index)),l.push(T(o[1],`${s}-blank-${o.index}`)),i=o.index+o[0].length;return i<n.length&&l.push(n.slice(i)),0===l.length?null:1===l.length?l[0]:e(t.Fragment,{children:l},s)}if(r.nodeType!==Node.ELEMENT_NODE)return null;const l=r,o=l.tagName.toLowerCase(),i={key:s};Array.from(l.attributes).forEach(e=>{"class"!==e.name?"style"!==e.name?i[e.name]=e.value:i.style=e.value.split(";").map(e=>e.trim()).filter(Boolean).reduce((e,r)=>{const[t,a]=r.split(":").map(e=>e.trim());return t&&a?(e[t.replace(/-([a-z])/g,(e,r)=>r.toUpperCase())]=a,e):e},{}):i.className=e.value});const d=Array.from(l.childNodes).map((e,r)=>n(e,`${s}-${r}`)).filter(e=>null!==e);return t.createElement(o,i,...d)};return Array.from(r.body.childNodes).map((e,r)=>n(e,`root-${r}`)).filter(e=>null!==e)},[w,T]);return e("div",{className:"space-y-4",children:r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center justify-between border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[r("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-teal-500 to-cyan-600 text-white shadow-sm",children:e(d,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Điền từ vào biểu mẫu có cấu trúc"})]}),u&&k&&r("div",{className:m("flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold",$?"bg-green-100 text-green-700":"bg-red-100 text-red-700"),children:[e($?o:i,{className:"h-3.5 w-3.5"}),$?"Đúng":"Sai"]})]}),r("div",{className:"space-y-5 p-5",children:[f&&e("h2",{className:"text-center text-xl font-bold text-gray-900",children:f}),(E||N)&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:A?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:E||N,alt:f,className:"max-h-56 w-auto object-contain p-2"})})}),e("div",{className:"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-loose text-gray-800",children:D}),u&&!$&&r("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:L.map(e=>r("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}}`,": ",y[e]]},e))})]}),u&&F&&r("div",{className:"rounded-lg border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 p-3",children:[e("span",{className:"text-xs font-medium uppercase tracking-wider text-blue-600",children:"Giải thích"}),e("p",{className:"mt-1 text-sm text-blue-800",children:F})]})]})]})})}
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{cn as r}from"../../../shared/lib/utils";import s from"next/image";import{useEffect as l,useRef as a}from"react";import n from"./assets/images/phao.png";import o from"./assets/images/sanho.png";import i from"./assets/images/sao.png";import c from"./assets/images/vooc.png";const d=[n,o,i,c];export function CambridgeYleSidebar({parts:n,questions:o,currentQuestionGlobalIndex:i,onPartClick:c,onQuestionClick:p,isNavDisabled:m,className:h}){const u=o[i],b=u?u.partIndex:0,x=a(null),f=a([]);return l(()=>{const e=x.current,t=f.current[b];if(!e||!t)return;const r=e.getBoundingClientRect(),s=t.getBoundingClientRect(),l=s.top<r.top,a=s.bottom>r.bottom;(l||a)&&t.scrollIntoView({block:"nearest",behavior:"smooth"})},[b]),t("div",{className:r("flex flex-col w-full h-full pb-4",h),children:[t("div",{ref:x,className:"flex-1 overflow-y-auto custom-scrollbar p-4 lg:p-6 pb-2",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px]",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("polygon",{points:"12 2 2 7 12 12 22 7 12 2"}),e("polyline",{points:"2 17 12 22 22 17"}),e("polyline",{points:"2 12 12 17 22 12"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Parts"})]}),e("div",{className:"flex flex-col gap-2.5",children:n.map((l,a)=>{const o=a===b,i=d[a%d.length],p=a>0?n[a-1].category:null,h=l.category&&l.category!==p;return t("div",{ref:e=>{f.current[a]=e},className:"flex flex-col",children:[h&&t("div",{className:"flex items-center gap-2 mt-5 mb-3 px-1",children:[e("div",{className:"h-[4px] w-4 rounded-full bg-blue-500"}),e("span",{className:"text-[14px] font-black uppercase tracking-[0.15em] text-blue-800",children:l.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>c(a),disabled:m,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",o?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",o||m?"":"hover:border-blue-200",m?"opacity-50 cursor-not-allowed":"cursor-pointer"),children:[t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex items-center justify-center w-8 h-8 shrink-0",children:e(s,{src:i,alt:`part icon ${a}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:l.name||`Part ${l.partNo}`})]}),t("div",{className:"flex items-center gap-2 shrink-0",children:[null!=l.points&&l.points>0&&t("span",{className:r("text-[12px] font-black tracking-wide whitespace-nowrap",o?"text-yellow-200":"text-amber-500"),children:[l.points," điểm"]}),t("span",{className:r("text-[13px] font-bold tracking-wide",o?"text-blue-100":"text-blue-900/60"),children:[l.answeredCount,"/",l.totalQuestions]})]})]})]},a)})})]}),e("div",{className:"px-6",children:e("hr",{className:"border-t-2 border-dashed border-blue-100"})}),t("div",{className:"flex-1 p-4 lg:p-6 pt-4 flex flex-col min-h-0",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px] shrink-0",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}),e("path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}),e("path",{d:"M12 11h4"}),e("path",{d:"M12 16h4"}),e("path",{d:"M8 11h.01"}),e("path",{d:"M8 16h.01"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Question List"})]}),e("div",{className:"flex-1 overflow-y-auto custom-scrollbar pr-1",children:e("div",{className:"grid grid-cols-5 gap-2",children:o.map(t=>{const s=t.globalIndex===i,l=t.isAnswered;let a="bg-white text-slate-800 shadow-sm border-transparent";return s?a="bg-blue-600 text-white border-blue-600 shadow-md":l&&(a="bg-[#4ade80] text-white border-transparent shadow-sm"),s||m||(a+=" hover:shadow-md hover:text-blue-600"),a+=m?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{type:"button",onClick:()=>p(t.globalIndex),disabled:m,className:r("h-[44px] w-full rounded-[10px] flex items-center justify-center font-bold text-[15px] transition-all border",a),children:t.questionNumber},t.globalIndex)})})}),e("div",{className:"shrink-0 mt-4 pt-4 border-t border-blue-200/50",children:t("div",{className:"flex items-center justify-between text-[11px] xl:text-[11.5px] font-bold text-gray-700",children:[t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-blue-600 shadow-sm"}),e("span",{children:"Current"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-green-500 shadow-sm"}),e("span",{children:"Answered"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-[#f4f9ff] border border-blue-200 shadow-sm"}),e("span",{children:"Not answered"})]})]})})]})]})}
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{cn as r}from"../../../shared/lib/utils";import l from"next/image";import{useEffect as s,useRef as n}from"react";import a from"./assets/images/phao.png";import o from"./assets/images/sanho.png";import i from"./assets/images/sao.png";import c from"./assets/images/vooc.png";const d=[a,o,i,c];export function CambridgeYleSidebar({parts:a,questions:o,currentQuestionGlobalIndex:i,onPartClick:c,onQuestionClick:p,isNavDisabled:m,className:u}){const h=o[i],b=h?h.partIndex:0,x=n(null),f=n([]),g=(n(null),n(new Map));return s(()=>{const e=x.current,t=f.current[b];if(!e||!t)return;const r=e.getBoundingClientRect(),l=t.getBoundingClientRect(),s=l.top<r.top,n=l.bottom>r.bottom;(s||n)&&t.scrollIntoView({block:"nearest",behavior:"smooth"})},[b]),s(()=>{const e=g.current.get(i);e?.scrollIntoView({block:"center",behavior:"smooth"})},[i]),t("div",{className:r("flex flex-col w-full h-full pb-4",u),children:[t("div",{ref:x,className:"flex-1 overflow-y-auto custom-scrollbar p-4 lg:p-6 pb-2",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px]",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("polygon",{points:"12 2 2 7 12 12 22 7 12 2"}),e("polyline",{points:"2 17 12 22 22 17"}),e("polyline",{points:"2 12 12 17 22 12"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Parts"})]}),e("div",{className:"flex flex-col gap-2.5",children:a.map((s,n)=>{const o=n===b,i=d[n%d.length],p=n>0?a[n-1].category:null,u=s.category&&s.category!==p;return t("div",{ref:e=>{f.current[n]=e},className:"flex flex-col",children:[u&&t("div",{className:"flex items-center gap-2 mt-5 mb-3 px-1",children:[e("div",{className:"h-[4px] w-4 rounded-full bg-blue-500"}),e("span",{className:"text-[14px] font-black uppercase tracking-[0.15em] text-blue-800",children:s.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>c(n),disabled:m,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",o?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",o||m?"":"hover:border-blue-200",m?"opacity-50 cursor-not-allowed":"cursor-pointer"),children:[t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex items-center justify-center w-8 h-8 shrink-0",children:e(l,{src:i,alt:`part icon ${n}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:s.name||`Part ${s.partNo}`})]}),t("div",{className:"flex items-center gap-2 shrink-0",children:[null!=s.points&&s.points>0&&t("span",{className:r("text-[12px] font-black tracking-wide whitespace-nowrap",o?"text-yellow-200":"text-amber-500"),children:[s.points," điểm"]}),t("span",{className:r("text-[13px] font-bold tracking-wide",o?"text-blue-100":"text-blue-900/60"),children:[s.answeredCount,"/",s.totalQuestions]})]})]})]},n)})})]}),e("div",{className:"px-6",children:e("hr",{className:"border-t-2 border-dashed border-blue-100"})}),t("div",{className:"flex-1 p-4 lg:p-6 pt-4 flex flex-col min-h-0",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px] shrink-0",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}),e("path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}),e("path",{d:"M12 11h4"}),e("path",{d:"M12 16h4"}),e("path",{d:"M8 11h.01"}),e("path",{d:"M8 16h.01"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Question List"})]}),e("div",{className:"flex-1 overflow-y-auto custom-scrollbar pr-1",children:e("div",{className:"grid grid-cols-5 gap-2",children:o.map(t=>{const l=t.globalIndex===i,s=t.isAnswered;let n="bg-white text-slate-800 shadow-sm border-transparent";return l?n="bg-blue-600 text-white border-blue-600 shadow-md":s&&(n="bg-[#4ade80] text-white border-transparent shadow-sm"),l||m||(n+=" hover:shadow-md hover:text-blue-600"),n+=m?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{ref:e=>{e?g.current.set(t.globalIndex,e):g.current.delete(t.globalIndex)},type:"button",onClick:()=>p(t.globalIndex),disabled:m,className:r("h-[44px] w-full rounded-[10px] flex items-center justify-center font-bold text-[15px] transition-all border",n),children:t.questionNumber},t.globalIndex)})})}),e("div",{className:"shrink-0 mt-4 pt-4 border-t border-blue-200/50",children:t("div",{className:"flex items-center justify-between text-[11px] xl:text-[11.5px] font-bold text-gray-700",children:[t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-blue-600 shadow-sm"}),e("span",{children:"Current"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-green-500 shadow-sm"}),e("span",{children:"Answered"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-[#f4f9ff] border border-blue-200 shadow-sm"}),e("span",{children:"Not answered"})]})]})})]})]})}
@@ -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 a,memo as o}from"react";import{ResolvedImage as i}from"../../../components/common/ResolvedImage";import{cn as l}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={},f=o(function({question:a,initialAnswers:o,onBlankChange:d,isReviewMode:c}){const m=r(null),p=r(d);p.current=d;const f=r(!1),x=r(o),h=s(()=>a.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 `),[a.content]);return n(()=>{const e=m.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}"]`),o=x.current[n]||"",i=a.answers[n]||"",d=o.trim().length>0,m=d&&u(o,a.caseSensitive)===u(i,a.caseSensitive),f=c&&!m&&i.trim().length>0;t.value=f?`${d?o:"(empty)"} → ${i}`:o,t.disabled=c,t.className=l("ec-blank-input inline-block w-[110px] border-0 border-b-2 border-dashed bg-transparent px-1 py-0 text-base font-semibold leading-tight align-middle outline-none transition-colors",c?m?"border-[#22c55e] text-[#15803d]":d?"border-[#ef4444] text-red-700":"border-[#f97316] text-[#c2410c]":"border-[#1167e8] text-[#0f1730] hover:border-[#0b57d0] focus:border-[#0b57d0]");const h=e.querySelector(`[data-blank-number="${n}"]`);h&&(h.textContent=b(n),h.className=l("ec-blank-number mr-1 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full px-1 text-[11px] font-bold leading-none text-white align-middle",c?m?"bg-[#22c55e]":d?"bg-[#ef4444]":"bg-[#f97316]":"bg-[#0b57d0]")),s&&(s.className=l("ec-blank-wrapper inline-flex items-center whitespace-nowrap align-middle",c?"mx-1":"mx-0.5"));const g=e=>{const t=e.target;p.current(n,t.value)};t.addEventListener("input",g),r.push({el:t,handler:g})}),()=>{r.forEach(({el:e,handler:t})=>{e.removeEventListener("input",t)})}},[h,c]),t("div",{className:"space-y-3",children:[a.title&&e("h3",{className:"text-base font-semibold text-[#0f1730]",children:a.title}),a.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-[#d9e4f2]",children:e(i,{src:a.imageUrl,alt:a.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(a.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(a.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:o,onAnswerChange:l,isReviewMode:b=!1}){const{questions:u,instruction:x,groupTitle:h,groupContent:g,groupImageUrl:w}=s(()=>d(n.questions),[n.questions]),N=r(o);N.current=o;const v=r(l);v.current=l;const k=a((e,t,r)=>{const n=N.current[e]||{};v.current(e,{...n,[t]:r})},[]),y=s(()=>{const e={};return u.forEach(t=>{e[t.id]=(e,r)=>k(t.id,e,r)}),e},[u,k]);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(i,{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(f,{question:r,initialAnswers:o[r.id]||p,onBlankChange:y[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 a,memo as o}from"react";import{ResolvedImage as l}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={},f=o(function({question:a,initialAnswers:o,onBlankChange:d,isReviewMode:c}){const m=r(null),p=r(d);p.current=d;const f=r(!1),x=r(o),g=s(()=>a.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 `),[a.content]);return n(()=>{const e=m.current;if(!e)return;f.current||(e.innerHTML=g,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}"]`),o=x.current[n]||"",l=a.answers[n]||"",d=o.trim().length>0,m=d&&u(o,a.caseSensitive)===u(l,a.caseSensitive),f=c&&!m&&l.trim().length>0;t.value=f?`${d?o:"(empty)"} → ${l}`:o,t.disabled=c,t.className=i("ec-blank-input inline-block min-w-[100px] max-w-[200px] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] bg-blue-50/30 px-2 py-0.5 text-base font-semibold leading-tight text-[#0f1730] align-baseline outline-none transition-all hover:bg-blue-50/60 focus:border-solid focus:border-[#0b57d0] focus:bg-blue-50/80",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]":"");const g=e.querySelector(`[data-blank-number="${n}"]`);g&&(g.textContent=b(n),g.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 h=e=>{const t=e.target;p.current(n,t.value)};t.addEventListener("input",h),r.push({el:t,handler:h})}),()=>{r.forEach(({el:e,handler:t})=>{e.removeEventListener("input",t)})}},[g,c]),t("div",{className:"space-y-3",children:[a.title&&e("h3",{className:"text-base font-semibold text-[#0f1730]",children:a.title}),a.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-[#d9e4f2]",children:e(l,{src:a.imageUrl,alt:a.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(a.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(a.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:o,onAnswerChange:i,isReviewMode:b=!1}){const{questions:u,instruction:x,groupTitle:g,groupContent:h,groupImageUrl:w}=s(()=>d(n.questions),[n.questions]),N=r(o);N.current=o;const v=r(i);v.current=i;const k=a((e,t,r)=>{const n=N.current[e]||{};v.current(e,{...n,[t]:r})},[]),y=s(()=>{const e={};return u.forEach(t=>{e[t.id]=(e,r)=>k(t.id,e,r)}),e},[u,k]);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}),g&&e("h2",{className:"text-center text-lg font-bold uppercase text-[#0b57d0]",children:g}),w&&e("div",{className:"flex items-center justify-center",children:e(l,{src:w,alt:g||"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(f,{question:r,initialAnswers:o[r.id]||p,onBlankChange:y[r.id],isReviewMode:b})]},r.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}from"react";import{cn as d}from"../../../shared/lib/utils";function i(e){return null!=e&&""!==e&&("object"!=typeof e||!("optionId"in e)||Boolean(e.optionId))}export function EnglishCertificationNavigationPanel({parts:o,questions:c,answers:u,flaggedQuestions:b,currentIndex:m,onQuestionClick:f,onPartClick:x}){const h=r(new Map);n(()=>{const e=h.current.get(m);e?.scrollIntoView({block:"nearest",behavior:"smooth"})},[m]);const{answeredCount:p,markedCount:g,unansweredCount:w}=a(()=>{const e=c.filter(e=>i(u[e.id])).length;return{answeredCount:e,markedCount:c.filter(e=>b.has(e.id)).length,unansweredCount:c.length-e}},[c,u,b]);return t("div",{className:"flex h-full flex-col",children:[t("div",{className:"grid grid-cols-3 gap-3 p-4 pb-2",children:[e(s,{label:"Answered",value:p,variant:"answered"}),e(s,{label:"Unanswered",value:w,variant:"unanswered"}),e(s,{label:"Marked",value:g,variant:"marked"})]}),t("div",{className:"flex-1 overflow-y-auto px-4 pb-4",children:[o.map((r,n)=>{const a=r.startIndex??0,s=r.endIndex??a,l=s-a+1;return t("section",{className:"mb-5",children:[e("button",{type:"button",onClick:()=>x(n),className:d("mb-3 w-full text-left text-[15px] font-black text-[#17213a] transition-colors hover:text-[#0b57d0]",m>=a&&m<=s&&"text-[#0b57d0]"),children:r.name||`Part ${n+1}`}),e("div",{className:"grid grid-cols-5 gap-2.5",children:Array.from({length:l},(r,n)=>{const s=a+n,l=c[s];if(!l)return null;const o=i(u[l.id]),x=b.has(l.id),p=s===m,g=s+1;return t("button",{ref:e=>{e?h.current.set(s,e):h.current.delete(s)},type:"button",onClick:()=>f(s),className:d("relative flex h-[50px] items-center justify-center rounded-md border text-[15px] font-bold transition-all","focus-visible:ring-2 focus-visible:ring-[#1167e8] focus-visible:ring-offset-1",o?"border-[#b9edc8] bg-[#ddf8e7] text-[#111827]":"border-[#d9e4f2] bg-white text-[#111827]",p&&"border-[#1167e8] text-[#0b57d0] shadow-[inset_0_0_0_1px_#1167e8]"),"aria-label":`Question ${g}${o?", answered":", unanswered"}${x?", marked":""}`,"aria-current":p?"true":void 0,children:[g,x&&e("span",{className:"absolute -top-px right-2 h-[18px] w-[9px] bg-[#ff8a00]",style:{clipPath:"polygon(0 0, 100% 0, 100% 100%, 50% 70%, 0 100%)"},"aria-hidden":"true"})]},l.id)})})]},n)}),t("div",{className:"mt-2 rounded-md border border-[#d9e4f2] bg-white/70 p-4",children:[e(l,{variant:"current",children:"Current Question"}),e(l,{variant:"answered",children:"Answered"}),e(l,{variant:"none",children:"Not Answered"}),e(l,{variant:"marked",children:"Marked for Review"})]})]})]})}function s({label:r,value:n,variant:a}){return e("div",{className:"grid min-h-[78px] place-items-center rounded-md border border-[#d9e4f2] bg-white text-center",children:t("div",{children:[e("span",{className:d("block text-[11px] font-black uppercase tracking-wide","answered"===a&&"text-[#0a3d9a]","unanswered"===a&&"text-[#17213a]","marked"===a&&"text-[#f97316]"),children:r}),e("strong",{className:d("mt-2 block text-[28px] leading-none","answered"===a&&"text-[#0b57d0]","unanswered"===a&&"text-[#17213a]","marked"===a&&"text-[#f97316]"),children:n})]})})}function l({variant:r,children:n}){return t("div",{className:"my-3 flex items-center gap-3.5 text-sm font-semibold text-[#334155]",children:[e("span","marked"===r?{className:"h-[18px] w-2.5 bg-[#ff8a00]",style:{clipPath:"polygon(0 0, 100% 0, 100% 100%, 50% 70%, 0 100%)"}}:{className:d("h-[22px] w-[22px] rounded border border-[#d9e4f2] bg-white","current"===r&&"border-[#1167e8] shadow-[inset_0_0_0_1px_#1167e8]","answered"===r&&"border-[#b9edc8] bg-[#ddf8e7]")}),n]})}
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useEffect as n,useMemo as a}from"react";import{cn as d}from"../../../shared/lib/utils";function i(e){return null!=e&&""!==e&&("object"!=typeof e||!("optionId"in e)||Boolean(e.optionId))}export function EnglishCertificationNavigationPanel({parts:o,questions:c,answers:u,flaggedQuestions:b,currentIndex:m,onQuestionClick:f,onPartClick:x}){const h=r(new Map);n(()=>{const e=h.current.get(m);e?.scrollIntoView({block:"center",behavior:"smooth"})},[m]);const{answeredCount:p,markedCount:g,unansweredCount:w}=a(()=>{const e=c.filter(e=>i(u[e.id])).length;return{answeredCount:e,markedCount:c.filter(e=>b.has(e.id)).length,unansweredCount:c.length-e}},[c,u,b]);return t("div",{className:"flex h-full flex-col",children:[t("div",{className:"grid grid-cols-3 gap-3 p-4 pb-2",children:[e(s,{label:"Answered",value:p,variant:"answered"}),e(s,{label:"Unanswered",value:w,variant:"unanswered"}),e(s,{label:"Marked",value:g,variant:"marked"})]}),t("div",{className:"flex-1 overflow-y-auto px-4 pb-4",children:[o.map((r,n)=>{const a=r.startIndex??0,s=r.endIndex??a,l=s-a+1;return t("section",{className:"mb-5",children:[e("button",{type:"button",onClick:()=>x(n),className:d("mb-3 w-full text-left text-[15px] font-black text-[#17213a] transition-colors hover:text-[#0b57d0]",m>=a&&m<=s&&"text-[#0b57d0]"),children:r.name||`Part ${n+1}`}),e("div",{className:"grid grid-cols-5 gap-2.5",children:Array.from({length:l},(r,n)=>{const s=a+n,l=c[s];if(!l)return null;const o=i(u[l.id]),x=b.has(l.id),p=s===m,g=s+1;return t("button",{ref:e=>{e?h.current.set(s,e):h.current.delete(s)},type:"button",onClick:()=>f(s),className:d("relative flex h-[50px] items-center justify-center rounded-md border text-[15px] font-bold transition-all","focus-visible:ring-2 focus-visible:ring-[#1167e8] focus-visible:ring-offset-1",o?"border-[#b9edc8] bg-[#ddf8e7] text-[#111827]":"border-[#d9e4f2] bg-white text-[#111827]",p&&"border-[#1167e8] text-[#0b57d0] shadow-[inset_0_0_0_1px_#1167e8]"),"aria-label":`Question ${g}${o?", answered":", unanswered"}${x?", marked":""}`,"aria-current":p?"true":void 0,children:[g,x&&e("span",{className:"absolute -top-px right-2 h-[18px] w-[9px] bg-[#ff8a00]",style:{clipPath:"polygon(0 0, 100% 0, 100% 100%, 50% 70%, 0 100%)"},"aria-hidden":"true"})]},l.id)})})]},n)}),t("div",{className:"mt-2 rounded-md border border-[#d9e4f2] bg-white/70 p-4",children:[e(l,{variant:"current",children:"Current Question"}),e(l,{variant:"answered",children:"Answered"}),e(l,{variant:"none",children:"Not Answered"}),e(l,{variant:"marked",children:"Marked for Review"})]})]})]})}function s({label:r,value:n,variant:a}){return e("div",{className:"grid min-h-[78px] place-items-center rounded-md border border-[#d9e4f2] bg-white text-center",children:t("div",{children:[e("span",{className:d("block text-[11px] font-black uppercase tracking-wide","answered"===a&&"text-[#0a3d9a]","unanswered"===a&&"text-[#17213a]","marked"===a&&"text-[#f97316]"),children:r}),e("strong",{className:d("mt-2 block text-[28px] leading-none","answered"===a&&"text-[#0b57d0]","unanswered"===a&&"text-[#17213a]","marked"===a&&"text-[#f97316]"),children:n})]})})}function l({variant:r,children:n}){return t("div",{className:"my-3 flex items-center gap-3.5 text-sm font-semibold text-[#334155]",children:[e("span","marked"===r?{className:"h-[18px] w-2.5 bg-[#ff8a00]",style:{clipPath:"polygon(0 0, 100% 0, 100% 100%, 50% 70%, 0 100%)"}}:{className:d("h-[22px] w-[22px] rounded border border-[#d9e4f2] bg-white","current"===r&&"border-[#1167e8] shadow-[inset_0_0_0_1px_#1167e8]","answered"===r&&"border-[#b9edc8] bg-[#ddf8e7]")}),n]})}
@@ -1 +1 @@
1
- "use client";import{jsx as t,jsxs as e}from"react/jsx-runtime";import{useState as i,useEffect as n,useRef as r}from"react";import a from"next/image";import{SummerSkyLayout as o}from"./SummerSkyLayout";import{useSpeakingRecorder as s}from"../../../components/exams/take/hooks/useSpeakingRecorder";import c from"./assets/styles/SummerSkyWaitingRoom.module.css";import l from"./assets/images/instruction-step.png";import d from"./assets/images/oceanedu-mascot.png";import m from"./assets/images/radio-check.png";import h from"./assets/images/next-btn.png";import p from"./assets/images/start-exam.png";import u from"./assets/images/check-mic-btn.png";import g from"./assets/images/stop-mic.png";import y from"./assets/images/mic-icon.png";import v from"./assets/images/audio-icon.png";const x=1.25;export function SummerSkyWaitingRoom({room:f,onStart:N,isStarting:w,onExit:k}){const[b,I]=i("instructions"),[R,S]=i(0),B=r(null),[C,F]=i(!1),[T,A]=i(0),[M,U]=i(null),E=r(null),[j,D]=i(!1),P="true"===process.env.NEXT_PUBLIC_SKIP_WAITING_ROOM_AUDIO,V=j||P;n(()=>{const t=E.current;if(!t)return;t.muted=!1,t.playbackRate=x;const e=t.play();void 0!==e&&e.catch(()=>{if(E.current){E.current.muted=!0,E.current.playbackRate=x;const t=E.current.play();void 0!==t&&t.catch(()=>{D(!0)})}})},[b]),n(()=>{D(!1),E.current&&(E.current.currentTime=0,E.current.playbackRate=x)},[b]);const W=s({attemptId:"mock-attempt-speaking",questionId:"mock-question",maxDurationMs:1e4,onRecordingComplete:()=>{}});n(()=>{let t;if("recording"===W.status){const e=Date.now();t=setInterval(()=>{S(Date.now()-e)},50)}else S(0);return()=>clearInterval(t)},[W.status]);const _=f.exam?.name||"BÀI THI NÓI";return t(o,{onExit:k,partName:_,instruction:"",audioUrl:"",canGoPrev:!1,canGoNext:!1,onPrev:()=>{"mic-test"===b&&I("instructions")},onNext:()=>{"instructions"===b&&I("mic-test")},hideAudioBar:!0,hideFooterTitle:!0,questionNumber:1,recorder:null,headerRight:null,children:e("div",{className:c.waitingRoomContainer,children:[e("div",{className:c.teacherFloating,children:[t("div",{className:c.teacherGlow}),e("div",{style:{position:"relative"},children:[t("video",{ref:E,className:c.teacherVideo,src:"mic-test"===b?"/speaking/video/check_microphone.webm":"/speaking/video/instruction.webm",autoPlay:!0,muted:!0,playsInline:!0,onEnded:()=>D(!0),onError:()=>{D(!0)},style:{opacity:j?0:1,transition:"opacity 0.6s ease-in-out"}}),t("img",{className:c.teacherVideo,src:"/speaking/image/teacher_ai_smile.png",alt:"AI Teacher",style:{position:"absolute",top:0,left:0,opacity:j?1:0,transition:"opacity 0.6s ease-in-out"}})]})]}),"instructions"===b&&e("div",{className:c.introBoard,children:[t("h2",{className:c.title,children:"Hướng dẫn chung"}),t("div",{className:c.instructionIconsWrap,style:{display:"flex",justifyContent:"center",width:"100%",marginBottom:"48px",marginTop:"5%"},children:t(a,{src:l,alt:"Hướng dẫn các bước",style:{width:"75%",height:"auto",objectFit:"contain"}})}),e("div",{className:c.aiBanner,children:[t("div",{className:c.aiBannerIcon,children:t(a,{src:d,alt:"OceanEdu Mascot",width:100,height:100,style:{borderRadius:"50%",objectFit:"cover"}})}),e("div",{className:c.aiBannerContent,children:[t("p",{className:c.aiBannerTitle,children:"Yêu cầu Ocean Edu AI Chấm điểm"}),t("p",{className:c.aiBannerDesc,children:"Hệ thống AI chuyên gia sẽ tự động chấm điểm bài thi của bạn 1 cách chính xác và khách quan nhất."})]}),t("div",{className:c.aiBannerRadio,children:t(a,{src:m,alt:"Radio Check",width:56,height:56})})]}),t("div",{className:c.stepButtonContainer,children:t("div",{className:"transition-transform "+(V?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-50 grayscale"),tabIndex:V?0:-1,onClick:()=>{V&&I("mic-test")},children:t(a,{src:h,alt:"Bước tiếp theo",style:{width:"280px",height:"auto"}})})}),t("div",{className:c.spacer})]}),"mic-test"===b&&e("div",{className:c.introBoard,children:[t("h2",{className:c.title,style:{marginBottom:"40px"},children:"KIỂM TRA MIC"}),e("div",{className:c.micTestContainer,children:[e("div",{className:c.micTestInstructionWrap,style:{margin:"-100px auto 48px auto",width:"fit-content",textAlign:"left"},children:[t("h3",{style:{color:"#2C38B6",fontFamily:'"SVN-Volte Rounded", sans-serif',fontSize:"28px",fontWeight:700,lineHeight:"1.5",textTransform:"uppercase",marginBottom:"24px",letterSpacing:"-0.01em"},children:"HƯỚNG DẪN"}),e("ul",{style:{listStyle:"none",padding:0,margin:0,color:"#343A40",fontFamily:'"SVN-Volte Rounded", sans-serif',fontSize:"20px",fontWeight:600,lineHeight:"1.8",letterSpacing:"-0.01em"},children:[t("li",{children:"1. Nhấn nút Kiểm tra mic bên dưới"}),t("li",{children:"2. Chọn Cho Phép (Allow) khi trình duyệt yêu cầu quyền truy cập"}),t("li",{children:"3. Sau khi kiểm tra Micro thành công, nhấn nút Bắt đầu bài thi"})]})]}),e("div",{className:"transition-transform hover:scale-[1.02] active:scale-[0.98] "+("recording"===W.status?"animate-pulse":""),style:{background:"#044E96",borderRadius:"28px",width:"700px",height:"56px",display:"flex",alignItems:"center",cursor:"pointer",padding:"0 24px 0 2px",gap:"16px",margin:"0 auto"},onClick:t=>{W.previewUrl?(t=>{t.stopPropagation(),B.current&&(C?(B.current.pause(),F(!1)):(B.current.play().catch(()=>{F(!1)}),F(!0)))})(t):"recording"===W.status?W.stopRecording():W.startRecording()},children:[W.previewUrl&&t("audio",{ref:B,src:W.previewUrl,onTimeUpdate:()=>{B.current&&B.current.duration&&A(B.current.currentTime/B.current.duration*100)},onEnded:()=>{F(!1),A(0)},onLoadedMetadata:t=>{U(Math.round(t.target.duration))},style:{display:"none"}}),W.previewUrl?t(a,{src:v,alt:"Phát âm thanh",style:{width:"72px",height:"72px",objectFit:"contain",marginLeft:"-16px"}}):t(a,{src:y,alt:"Microphone",style:{width:"72px",height:"72px",objectFit:"contain",marginLeft:"-16px"}}),t("div",{style:{flex:1,height:"12px",background:"#FFF",borderRadius:"6px",overflow:"hidden"},children:t("div",{style:{height:"100%",background:"#7DB5FA",width:W.previewUrl?`${T}%`:`${Math.min(R/1e4*100,100)}%`,transition:"width 0.1s linear"}})}),e("div",{style:{color:"#FFF",fontSize:"20px",fontWeight:600,fontFamily:'"SVN-Volte Rounded", sans-serif',width:"60px",textAlign:"right",letterSpacing:"1px"},children:["00:",(W.previewUrl?M||0:Math.min(Math.floor(R/1e3),10)).toString().padStart(2,"0")]})]})]}),t("div",{className:c.stepButtonContainer,children:W.previewUrl?t("div",{className:"transition-transform "+(!w&&V?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-70 grayscale"),tabIndex:!w&&V?0:-1,onClick:!w&&V?N:void 0,children:t(a,{src:p,alt:"Bắt đầu bài thi",style:{width:"280px",height:"auto"}})}):t("div",{className:"transition-transform "+(V?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-70 grayscale"),tabIndex:V?0:-1,onClick:V?"recording"===W.status?W.stopRecording:W.startRecording:void 0,children:t(a,{src:"recording"===W.status?g:u,alt:"recording"===W.status?"Dừng kiểm tra":"Kiểm tra mic",style:{width:"280px",height:"auto"}})})})]})]})})}
1
+ "use client";import{jsx as t,jsxs as e}from"react/jsx-runtime";import{useState as i,useEffect as r,useRef as n}from"react";import a from"next/image";import{toast as o}from"sonner";import{SummerSkyLayout as s}from"./SummerSkyLayout";import{useSpeakingRecorder as c}from"../../../components/exams/take/hooks/useSpeakingRecorder";import l from"./assets/styles/SummerSkyWaitingRoom.module.css";import d from"./assets/images/instruction-step.png";import m from"./assets/images/oceanedu-mascot.png";import h from"./assets/images/radio-check.png";import p from"./assets/images/next-btn.png";import u from"./assets/images/start-exam.png";import g from"./assets/images/check-mic-btn.png";import v from"./assets/images/stop-mic.png";import y from"./assets/images/mic-icon.png";import f from"./assets/images/audio-icon.png";const x=1.25;export function SummerSkyWaitingRoom({room:N,onStart:w,isStarting:k,onExit:b}){const[I,S]=i("instructions"),[B,R]=i(0),C=n(null),[F,T]=i(!1),[U,A]=i(0),[M,E]=i(null),j=n(null),[D,P]=i(!1),V="true"===process.env.NEXT_PUBLIC_SKIP_WAITING_ROOM_AUDIO,W=D||V;r(()=>{const t=j.current;if(!t)return;t.muted=!1,t.playbackRate=x;const e=t.play();void 0!==e&&e.catch(()=>{if(j.current){j.current.muted=!0,j.current.playbackRate=x;const t=j.current.play();void 0!==t&&t.catch(()=>{P(!0)})}})},[I]),r(()=>{P(!1),j.current&&(j.current.currentTime=0,j.current.playbackRate=x)},[I]);const _=c({attemptId:"mock-attempt-speaking",questionId:"mock-question",maxDurationMs:1e4,onRecordingComplete:()=>{},onError:t=>o.error(t)});r(()=>{let t;if("recording"===_.status){const e=Date.now();t=setInterval(()=>{R(Date.now()-e)},50)}else R(0);return()=>clearInterval(t)},[_.status]);const H=N.exam?.name||"BÀI THI NÓI";return t(s,{onExit:b,partName:H,instruction:"",audioUrl:"",canGoPrev:!1,canGoNext:!1,onPrev:()=>{"mic-test"===I&&S("instructions")},onNext:()=>{"instructions"===I&&S("mic-test")},hideAudioBar:!0,hideFooterTitle:!0,questionNumber:1,recorder:null,headerRight:null,children:e("div",{className:l.waitingRoomContainer,children:[e("div",{className:l.teacherFloating,children:[t("div",{className:l.teacherGlow}),e("div",{style:{position:"relative"},children:[t("video",{ref:j,className:l.teacherVideo,src:"mic-test"===I?"/speaking/video/check_microphone.webm":"/speaking/video/instruction.webm",autoPlay:!0,muted:!0,playsInline:!0,onEnded:()=>P(!0),onError:()=>{P(!0)},style:{opacity:D?0:1,transition:"opacity 0.6s ease-in-out"}}),t("img",{className:l.teacherVideo,src:"/speaking/image/teacher_ai_smile.png",alt:"AI Teacher",style:{position:"absolute",top:0,left:0,opacity:D?1:0,transition:"opacity 0.6s ease-in-out"}})]})]}),"instructions"===I&&e("div",{className:l.introBoard,children:[t("h2",{className:l.title,children:"Hướng dẫn chung"}),t("div",{className:l.instructionIconsWrap,style:{display:"flex",justifyContent:"center",width:"100%",marginBottom:"48px",marginTop:"5%"},children:t(a,{src:d,alt:"Hướng dẫn các bước",style:{width:"75%",height:"auto",objectFit:"contain"}})}),e("div",{className:l.aiBanner,children:[t("div",{className:l.aiBannerIcon,children:t(a,{src:m,alt:"OceanEdu Mascot",width:100,height:100,style:{borderRadius:"50%",objectFit:"cover"}})}),e("div",{className:l.aiBannerContent,children:[t("p",{className:l.aiBannerTitle,children:"Yêu cầu Ocean Edu AI Chấm điểm"}),t("p",{className:l.aiBannerDesc,children:"Hệ thống AI chuyên gia sẽ tự động chấm điểm bài thi của bạn 1 cách chính xác và khách quan nhất."})]}),t("div",{className:l.aiBannerRadio,children:t(a,{src:h,alt:"Radio Check",width:56,height:56})})]}),t("div",{className:l.stepButtonContainer,children:t("div",{className:"transition-transform "+(W?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-50 grayscale"),tabIndex:W?0:-1,onClick:()=>{W&&S("mic-test")},children:t(a,{src:p,alt:"Bước tiếp theo",style:{width:"280px",height:"auto"}})})}),t("div",{className:l.spacer})]}),"mic-test"===I&&e("div",{className:l.introBoard,children:[t("h2",{className:l.title,style:{marginBottom:"40px"},children:"KIỂM TRA MIC"}),e("div",{className:l.micTestContainer,children:[e("div",{className:l.micTestInstructionWrap,style:{margin:"-100px auto 48px auto",width:"fit-content",textAlign:"left"},children:[t("h3",{style:{color:"#2C38B6",fontFamily:'"SVN-Volte Rounded", sans-serif',fontSize:"28px",fontWeight:700,lineHeight:"1.5",textTransform:"uppercase",marginBottom:"24px",letterSpacing:"-0.01em"},children:"HƯỚNG DẪN"}),e("ul",{style:{listStyle:"none",padding:0,margin:0,color:"#343A40",fontFamily:'"SVN-Volte Rounded", sans-serif',fontSize:"20px",fontWeight:600,lineHeight:"1.8",letterSpacing:"-0.01em"},children:[t("li",{children:"1. Nhấn nút Kiểm tra mic bên dưới"}),t("li",{children:"2. Chọn Cho Phép (Allow) khi trình duyệt yêu cầu quyền truy cập"}),t("li",{children:"3. Sau khi kiểm tra Micro thành công, nhấn nút Bắt đầu bài thi"})]})]}),e("div",{className:`transition-transform ${_.previewUrl?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-default"} ${"recording"===_.status?"animate-pulse":""}`,style:{background:"#044E96",borderRadius:"28px",width:"700px",height:"56px",display:"flex",alignItems:"center",cursor:_.previewUrl?"pointer":"default",padding:"0 24px 0 2px",gap:"16px",margin:"0 auto"},onClick:t=>{_.previewUrl&&(t=>{t.stopPropagation(),C.current&&(F?(C.current.pause(),T(!1)):(C.current.play().catch(()=>{T(!1)}),T(!0)))})(t)},children:[_.previewUrl&&t("audio",{ref:C,src:_.previewUrl,onTimeUpdate:()=>{C.current&&C.current.duration&&A(C.current.currentTime/C.current.duration*100)},onEnded:()=>{T(!1),A(0)},onLoadedMetadata:t=>{E(Math.round(t.target.duration))},style:{display:"none"}}),_.previewUrl?t(a,{src:f,alt:"Phát âm thanh",style:{width:"72px",height:"72px",objectFit:"contain",marginLeft:"-16px"}}):t(a,{src:y,alt:"Microphone",style:{width:"72px",height:"72px",objectFit:"contain",marginLeft:"-16px"}}),t("div",{style:{flex:1,height:"12px",background:"#FFF",borderRadius:"6px",overflow:"hidden"},children:t("div",{style:{height:"100%",background:"#7DB5FA",width:_.previewUrl?`${U}%`:`${Math.min(B/1e4*100,100)}%`,transition:"width 0.1s linear"}})}),e("div",{style:{color:"#FFF",fontSize:"20px",fontWeight:600,fontFamily:'"SVN-Volte Rounded", sans-serif',width:"60px",textAlign:"right",letterSpacing:"1px"},children:["00:",(_.previewUrl?M||0:Math.min(Math.floor(B/1e3),10)).toString().padStart(2,"0")]})]})]}),t("div",{className:l.stepButtonContainer,children:_.previewUrl?t("div",{className:"transition-transform "+(!k&&W?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-70 grayscale"),tabIndex:!k&&W?0:-1,onClick:!k&&W?w:void 0,children:t(a,{src:u,alt:"Bắt đầu bài thi",style:{width:"280px",height:"auto"}})}):t("div",{className:"transition-transform "+(W?"cursor-pointer hover:scale-[1.02] active:scale-[0.98]":"cursor-not-allowed opacity-70 grayscale"),tabIndex:W?0:-1,onClick:W?"recording"===_.status?_.stopRecording:_.startRecording:void 0,children:t(a,{src:"recording"===_.status?v:g,alt:"recording"===_.status?"Dừng kiểm tra":"Kiểm tra mic",style:{width:"280px",height:"auto"}})})})]})]})})}
@@ -2,7 +2,8 @@ export declare enum AttemptStatus {
2
2
  IN_PROGRESS = "IN_PROGRESS",
3
3
  SUBMITTED = "SUBMITTED",
4
4
  GRADED = "GRADED",
5
- PUBLISHED = "PUBLISHED"
5
+ PUBLISHED = "PUBLISHED",
6
+ CANCELLED = "CANCELLED"
6
7
  }
7
8
  export declare enum ExamRoomStatus {
8
9
  UPCOMING = "UPCOMING",
@@ -1 +1 @@
1
- export var AttemptStatus;!function(t){t.IN_PROGRESS="IN_PROGRESS",t.SUBMITTED="SUBMITTED",t.GRADED="GRADED",t.PUBLISHED="PUBLISHED"}(AttemptStatus||(AttemptStatus={}));export var ExamRoomStatus;!function(t){t.UPCOMING="UPCOMING",t.IN_PROGRESS="IN_PROGRESS",t.COMPLETED="COMPLETED"}(ExamRoomStatus||(ExamRoomStatus={}));export var AnswerGradingStatus;!function(t){t.PENDING="PENDING",t.AUTO_GRADED="AUTO_GRADED",t.QUEUED="QUEUED",t.PROCESSING="PROCESSING",t.GRADED="GRADED",t.FAILED="FAILED",t.MANUAL_REVIEW="MANUAL_REVIEW",t.COMPLETED="COMPLETED",t.NOT_ANSWERED="NOT_ANSWERED"}(AnswerGradingStatus||(AnswerGradingStatus={}));export const TERMINAL_GRADING_STATUSES=new Set([AnswerGradingStatus.AUTO_GRADED,AnswerGradingStatus.GRADED,AnswerGradingStatus.COMPLETED,AnswerGradingStatus.FAILED,AnswerGradingStatus.MANUAL_REVIEW]);export function getGradingStatusGroup(t){switch(t){case AnswerGradingStatus.AUTO_GRADED:case AnswerGradingStatus.GRADED:case AnswerGradingStatus.COMPLETED:return"done";case AnswerGradingStatus.FAILED:return"failed";case AnswerGradingStatus.MANUAL_REVIEW:return"manual";default:return"pending"}}export var ExamRoomType;!function(t){t.PRACTICE_TEST="PRACTICE_TEST",t.CONTEST="CONTEST"}(ExamRoomType||(ExamRoomType={}));
1
+ export var AttemptStatus;!function(E){E.IN_PROGRESS="IN_PROGRESS",E.SUBMITTED="SUBMITTED",E.GRADED="GRADED",E.PUBLISHED="PUBLISHED",E.CANCELLED="CANCELLED"}(AttemptStatus||(AttemptStatus={}));export var ExamRoomStatus;!function(E){E.UPCOMING="UPCOMING",E.IN_PROGRESS="IN_PROGRESS",E.COMPLETED="COMPLETED"}(ExamRoomStatus||(ExamRoomStatus={}));export var AnswerGradingStatus;!function(E){E.PENDING="PENDING",E.AUTO_GRADED="AUTO_GRADED",E.QUEUED="QUEUED",E.PROCESSING="PROCESSING",E.GRADED="GRADED",E.FAILED="FAILED",E.MANUAL_REVIEW="MANUAL_REVIEW",E.COMPLETED="COMPLETED",E.NOT_ANSWERED="NOT_ANSWERED"}(AnswerGradingStatus||(AnswerGradingStatus={}));export const TERMINAL_GRADING_STATUSES=new Set([AnswerGradingStatus.AUTO_GRADED,AnswerGradingStatus.GRADED,AnswerGradingStatus.COMPLETED,AnswerGradingStatus.FAILED,AnswerGradingStatus.MANUAL_REVIEW]);export function getGradingStatusGroup(E){switch(E){case AnswerGradingStatus.AUTO_GRADED:case AnswerGradingStatus.GRADED:case AnswerGradingStatus.COMPLETED:return"done";case AnswerGradingStatus.FAILED:return"failed";case AnswerGradingStatus.MANUAL_REVIEW:return"manual";default:return"pending"}}export var ExamRoomType;!function(E){E.PRACTICE_TEST="PRACTICE_TEST",E.CONTEST="CONTEST"}(ExamRoomType||(ExamRoomType={}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinyweb_dev/oe-exam-sdk",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Reusable OceanEdu question components.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",