@tinyweb_dev/oe-exam-sdk 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/exam-entry.d.ts +1 -1
- package/dist/api/exam-entry.types.d.ts +14 -0
- package/dist/api/exam-taking.types.d.ts +2 -0
- package/dist/components/exams/take/ExamTakingPageContainer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.js +1 -1
- package/dist/components/exams/take/exam-taking.utils.d.ts +8 -2
- package/dist/components/exams/take/exam-taking.utils.js +1 -1
- package/dist/components/exams/take/utils/question-transformers.d.ts +4 -0
- package/dist/components/exams/take/utils/question-transformers.js +1 -1
- package/dist/components/features/exam-entry/themed/CambridgeYleWaitingRoom.js +1 -1
- package/dist/components/features/exam-entry/themed/cambridge-yle-waiting-parts.d.ts +18 -0
- package/dist/components/features/exam-entry/themed/cambridge-yle-waiting-parts.js +1 -0
- package/dist/components/features/exam-entry/themed/index.d.ts +3 -0
- package/dist/components/features/exam-entry/themed/index.js +1 -1
- package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +1 -1
- package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.d.ts +2 -0
- package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +1 -1
- package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +1 -1
- package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +1 -1
- package/dist/components/themes/english-certification/EcWordFillParagraph.js +1 -1
- package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
- package/dist/components/themes/english-certification/EcWritingTask.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.d.ts +17 -0
- package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.js +1 -0
- package/dist/components/themes/english-certification/EnglishCertificationPartHeader.d.ts +24 -0
- package/dist/components/themes/english-certification/EnglishCertificationPartHeader.js +1 -0
- package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.d.ts +3 -1
- package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +1 -1
- package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.d.ts +0 -2
- package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +1 -1
- package/dist/components/themes/english-certification/english-cert-scroll.d.ts +32 -0
- package/dist/components/themes/english-certification/english-cert-scroll.js +1 -0
- package/dist/components/themes/english-certification/index.d.ts +4 -1
- package/dist/components/themes/english-certification/index.js +1 -1
- package/dist/shared/lib/html-content.d.ts +14 -0
- package/dist/shared/lib/html-content.js +1 -0
- package/dist/shared/types/exam-taking.types.d.ts +2 -0
- package/dist/shared/types/student.types.d.ts +14 -0
- package/package.json +1 -1
package/dist/api/exam-entry.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export declare function createMockExamEntryApi(seed: {
|
|
|
11
11
|
room: ExamEntryRoom;
|
|
12
12
|
attempt?: ExamEntryAttempt | null;
|
|
13
13
|
}): ExamEntrySdkApi;
|
|
14
|
-
export type { ExamEntryAttempt, ExamEntryContest, ExamEntryExam, ExamEntryFetchApiOptions, ExamEntryRegistrationField, ExamEntryRegistrationFormConfig, ExamEntryRoom, ExamEntrySdkApi, } from './exam-entry.types';
|
|
14
|
+
export type { ExamEntryAttempt, ExamEntryContest, ExamEntryExam, ExamEntryFetchApiOptions, ExamEntryPartSummary, ExamEntryRegistrationField, ExamEntryRegistrationFormConfig, ExamEntryRoom, ExamEntrySdkApi, } from './exam-entry.types';
|
|
@@ -18,6 +18,17 @@ export interface ExamEntryRegistrationFormConfig {
|
|
|
18
18
|
enabled: boolean;
|
|
19
19
|
fields: ExamEntryRegistrationField[];
|
|
20
20
|
}
|
|
21
|
+
/** Summary of one exam part for student waiting room / room detail. */
|
|
22
|
+
export interface ExamEntryPartSummary {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
skill?: string;
|
|
26
|
+
category?: string;
|
|
27
|
+
points: number;
|
|
28
|
+
questionCount: number;
|
|
29
|
+
instructions?: string;
|
|
30
|
+
questionType?: string;
|
|
31
|
+
}
|
|
21
32
|
/** Exam summary nested inside a room. */
|
|
22
33
|
export interface ExamEntryExam {
|
|
23
34
|
id: string;
|
|
@@ -26,6 +37,7 @@ export interface ExamEntryExam {
|
|
|
26
37
|
durationMinutes?: number;
|
|
27
38
|
totalScore?: number;
|
|
28
39
|
passScore?: number;
|
|
40
|
+
numberOfParts?: number | null;
|
|
29
41
|
level?: string;
|
|
30
42
|
theme?: string;
|
|
31
43
|
template?: {
|
|
@@ -33,6 +45,8 @@ export interface ExamEntryExam {
|
|
|
33
45
|
subTitle?: string;
|
|
34
46
|
title?: string;
|
|
35
47
|
};
|
|
48
|
+
/** Summary parts from exams.template.parts */
|
|
49
|
+
parts?: ExamEntryPartSummary[];
|
|
36
50
|
}
|
|
37
51
|
/** Contest summary nested inside a room. */
|
|
38
52
|
export interface ExamEntryContest {
|
|
@@ -46,6 +46,8 @@ export interface ExamTakingTemplatePart {
|
|
|
46
46
|
endIndex?: number;
|
|
47
47
|
audioUrl?: string;
|
|
48
48
|
category?: string;
|
|
49
|
+
/** Max points for this part from exams.template.parts */
|
|
50
|
+
points?: number;
|
|
49
51
|
questionType?: string;
|
|
50
52
|
sections?: Array<Record<string, unknown>>;
|
|
51
53
|
isGroup?: boolean;
|
|
@@ -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 y,AlertDialogDescription as _,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 R}from"../entry/fullscreen-loading";import{SummerSkySubmitModal as M}from"../../../components/themes/summer-sky/SummerSkySubmitModal";import{EnglishCertificationExamLayout as D,EnglishCertificationQuestionRenderer as L,englishCertQuestionDomId 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=>{K?K(e):"undefined"!=typeof window&&(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){console.error("Failed to load exam data:",e),p.error(g("student.exam.take.loadError")),J(V)}})()},[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:ye}=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}),_e=C({api:F,attemptId:z.attemptId||"",parts:re,intervalMs:Ie?15e3:3e4,onSaveError:e=>{console.error("Save error:",e)}}),ve=s(_e.saveNow),Ne=s(re);i(()=>{ve.current=_e.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 _e.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))}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));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"),Re=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},Me=()=>{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&&Re(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});Me()},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&&Re(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});Me()},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,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(R,{});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(M,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(y,{children:[t(N,{children:[e(A,{children:"Ná»™p bà i thi"}),e(_,{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"===ye?"bg-[rgba(220,38,38,0.85)] shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse":"warning"===ye?"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:_e.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&&setTimeout(()=>{document.getElementById(G(t.id))?.scrollIntoView({behavior:"smooth",block:"start"})},80)},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=Re($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),Me()},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(M,{onClose:()=>pe(!1),onSubmit:Ae,isSubmitting:z.isSubmitting}):e(w,{open:ce,onOpenChange:pe,children:t(y,{children:[t(N,{children:[e(A,{children:"Ná»™p bà i thi"}),e(_,{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 R}from"../entry/fullscreen-loading";import{SummerSkySubmitModal as M}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=>{K?K(e):"undefined"!=typeof window&&(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){console.error("Failed to load exam data:",e),p.error(g("student.exam.take.loadError")),J(V)}})()},[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))}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));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"),Re=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},Me=()=>{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&&Re(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});Me()},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&&Re(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});Me()},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(R,{});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(M,{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=Re($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),Me()},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(M,{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,Fragment as t}from"react/jsx-runtime";import{useMemo as s}from"react";import{ResolvedImage as a}from"../../../../../components/common/ResolvedImage";import l from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import i from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";export function MoversWritingRenderer({partNumber:
|
|
1
|
+
"use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useMemo as s}from"react";import{ResolvedImage as a}from"../../../../../components/common/ResolvedImage";import l from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import i from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import{HtmlOrText as d}from"../../../../../shared/lib/html-content";export function MoversWritingRenderer({partNumber:n,partName:m,instruction:o,prompt:c,requirements:x,minWords:p,maxWords:b,answer:h,onAnswerChange:g,isReviewMode:u=!1,guideImages:f,teacherScore:N,maxScore:v,teacherFeedback:w}){const y=s(()=>h&&h.trim()?h.trim().split(/\s+/).filter(Boolean).length:0,[h]);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative",children:[r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-4",children:[e(l,{partNumber:n,questionCount:1,partName:m,isReviewMode:u}),o&&e(i,{instruction:o,isReviewMode:u})]}),e("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100",children:r("div",{className:"flex flex-col gap-4",children:[e("div",{className:"rounded-2xl border border-slate-200 bg-white p-5 shadow-sm",children:r("div",{className:"flex flex-col gap-4 text-base leading-relaxed text-gray-800",children:[r("div",{className:"space-y-3",children:[e("p",{className:"text-lg font-semibold text-slate-900",children:"Writing task"}),e(d,{value:c,className:"text-base leading-relaxed text-gray-800"})]}),x&&x.length>0&&r("div",{className:"rounded-xl bg-slate-50 p-4",children:[e("p",{className:"text-sm font-bold uppercase tracking-wide text-slate-700",children:"Include"}),e("ul",{className:"mt-3 space-y-2",children:x.map((t,s)=>r("li",{className:"flex items-start gap-2 text-sm text-slate-700",children:[e("span",{className:"mt-1.5 h-2 w-2 rounded-full bg-blue-500"}),e(d,{value:t,as:"span"})]},s))})]}),(p||b)&&r("div",{className:"flex flex-wrap gap-2",children:[p&&r("div",{className:"inline-flex items-center rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-sm font-medium text-blue-700",children:["Minimum: ",p," words"]}),b&&r("div",{className:"inline-flex items-center rounded-full border border-slate-200 bg-white px-3 py-1 text-sm font-medium text-slate-600",children:["Suggested max: ",b," words"]})]})]})}),f&&f.length>0&&r("div",{className:"rounded-2xl border border-slate-200 bg-white p-4 shadow-sm",children:[r("div",{className:"mb-3 flex items-center justify-between gap-3",children:[e("p",{className:"text-sm font-semibold uppercase tracking-wide text-slate-600",children:"Story pictures"}),e("p",{className:"text-xs text-slate-400",children:"Read the sequence from left to right"})]}),e("div",{className:"grid gap-4 "+(1===f.length?"grid-cols-1":"grid-cols-1 sm:grid-cols-2"),children:f.map((t,s)=>r("div",{className:"rounded-xl border border-slate-200 bg-slate-50/80 p-2 shadow-sm",children:[e(a,{src:t,alt:`Picture ${s+1}`,className:"w-full rounded-lg bg-white object-contain "+(1===f.length?"max-h-[400px]":"aspect-[4/3]")}),e("div",{className:"pt-2 text-center text-[13px] font-medium text-slate-500",children:f.length>1?`Picture ${s+1}`:"Reference Image"})]},s))})]})]})}),r("div",{className:"flex flex-col gap-3 p-3 sm:px-6 sm:pb-6",children:[r("div",{className:"rounded-2xl border border-slate-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center justify-between gap-3 border-b border-slate-100 px-5 py-3 bg-slate-50/50 rounded-t-2xl",children:[r("div",{children:[e("p",{className:"text-sm font-semibold uppercase tracking-wide text-slate-500",children:"Your answer"}),e("p",{className:"text-xs text-slate-400",children:"Write clearly and organise your ideas in order."})]}),r("div",{className:"rounded-full px-3 py-1 text-sm font-semibold "+(p&&y<p?"border border-amber-200 bg-amber-50 text-amber-700":"border border-emerald-200 bg-emerald-50 text-emerald-700"),children:[y," words"]})]}),r("div",{className:"p-4",children:[e("textarea",{id:"writing-answer",name:"writing-answer",value:h,onChange:e=>{const r=e.target.value;if(b){const e=Number(b);if((r.trim()?r.trim().split(/\s+/).filter(Boolean).length:0)>e&&r.length>=(h?.length||0))return}g(r)},disabled:u,placeholder:"Write your answer here...",className:"min-h-[340px] w-full resize-y rounded-xl border border-slate-200 bg-slate-50/50 p-4 text-base leading-8 text-gray-800 outline-none transition focus:border-blue-400 focus:bg-white focus:ring-2 focus:ring-blue-100 disabled:bg-gray-50 disabled:text-gray-700"}),r("div",{className:"mt-3 flex flex-wrap items-center justify-between gap-3 text-sm",children:[e("p",{className:"text-slate-500",children:p||b?r(t,{children:[p&&r("span",{children:["Minimum required: ",r("span",{className:"font-semibold text-slate-700",children:[p," words"]})]}),p&&b&&e("span",{className:"mx-2 text-slate-300",children:"|"}),b&&r("span",{children:["Maximum allowed: ",r("span",{className:"font-semibold text-slate-700",children:[b," words"]})]})]}):"Write a complete answer."}),r("p",{className:"font-medium "+(b&&y>=b?"text-red-500":"text-slate-500"),children:["Word count: ",y," ",b&&`/ ${b}`]})]})]})]}),u&&(null!=N?r("div",{className:"mt-1 rounded-2xl border border-green-200 bg-green-50 p-4",children:[e("div",{className:"mb-2 flex items-center gap-2",children:r("span",{className:"text-lg font-semibold text-green-700",children:["Điểm: ",N,"/",v]})}),w&&r("div",{className:"text-sm text-gray-700",children:[e("span",{className:"font-medium",children:"Nhận xét:"})," ",w]})]}):e("div",{className:"mt-1 rounded-2xl border border-amber-200 bg-amber-50 p-4",children:r("div",{className:"flex items-center gap-2",children:[e("svg",{className:"h-5 w-5 shrink-0 text-amber-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}),e("span",{className:"text-sm font-medium text-amber-700",children:"Bài viết đang chờ giáo viên chấm điểm"})]})}))]})]})}
|
|
@@ -91,11 +91,17 @@ export declare function transformWordFillParagraph(questions: ExamTakingQuestion
|
|
|
91
91
|
viewMode: string;
|
|
92
92
|
instruction: string;
|
|
93
93
|
};
|
|
94
|
+
/**
|
|
95
|
+
* WRITE_A_SHORT_LETTER — mirrors utils/question-transformers.transformWriteShortLetter.
|
|
96
|
+
*
|
|
97
|
+
* New API shape: instructions.mainInstruction + informations[]
|
|
98
|
+
* Legacy shape: contexts[] (type=text) as prompt
|
|
99
|
+
*/
|
|
94
100
|
export declare function transformWriteShortLetter(question: ExamTakingQuestion | undefined): {
|
|
95
101
|
prompt: string;
|
|
96
102
|
requirements: string[];
|
|
97
|
-
minWords: number;
|
|
98
|
-
maxWords: number;
|
|
103
|
+
minWords: number | undefined;
|
|
104
|
+
maxWords: number | undefined;
|
|
99
105
|
guideImages: string[];
|
|
100
106
|
};
|
|
101
107
|
export declare function transformWordFillStructuredForm(questions: ExamTakingQuestion[]): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const
|
|
1
|
+
export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const r=n.find(n=>String(n.id)===t);return{id:t,name:r?.name??`Part ${e[0]?.part_no??t}`,template:r,partId:t,partNo:e[0]?.part_no,instructions:r?.instructions,audioUrl:r?.audioUrl,questionType:r?.questionType??e[0]?.question_type,isGroup:r?.isGroup,group:r?.group,sections:r?.sections,viewMode:"string"==typeof r?.group?.viewMode?r.group.viewMode:void 0,startIndex:r?.startIndex,endIndex:r?.endIndex,questions:e.sort((t,n)=>t.question_number-n.question_number)}})}export function transformAnswerTheQuestion(t){return{instruction:n(t[0]?.content,"instruction"),imageUrl:n(t[0]?.content,"imageUrl"),title:n(t[0]?.content,"title"),groupContent:n(t[0]?.content,"groupContent"),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),prefixText:n(t.content,"prefixText"),suffixText:n(t.content,"suffixText"),exampleAnswer:n(t.content,"exampleAnswer"),suggestedAnswers:r(t.content,"suggestedAnswers"),isExample:Boolean(t.is_example)}))}}export function transformMatchByWritingAnswer(t){return{instruction:n(t[0]?.content,"instruction"),groupImageUrl:n(t[0]?.content,"groupImageUrl"),options:o(t[0]?.content,"options").map(t=>({answer:String(t.answer??t.value??""),text:String(t.text??t.label??""),content:String(t.content??t.text??t.label??""),imageUrl:"string"==typeof t.imageUrl?t.imageUrl:void 0})),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),exampleAnswer:n(t.content,"exampleAnswer"),isExample:Boolean(t.is_example)}))}}export function transformWordFillParagraph(t){const e=t[0];return{questionId:e?.id??"",paragraph:n(e?.content,"paragraph")||n(e?.content,"text"),title:n(e?.content,"title"),imageUrl:n(e?.content,"imageUrl"),wordBank:o(e?.content,"wordBank").map(t=>({word:String(t.word??t.text??""),isExample:Boolean(t.isExample)})),viewMode:n(e?.content,"viewMode"),instruction:n(e?.content,"instruction")}}export function transformWriteShortLetter(o){if(!o)return{prompt:"",requirements:[],minWords:void 0,maxWords:void 0,guideImages:[]};const i=t(o.content),s=t(i.instructions),u="string"==typeof s.mainInstruction?s.mainInstruction:"",a=Array.isArray(i.informations)?i.informations.filter(t=>"string"==typeof t):[],c=r(o.content,"guideImages"),p=e(o.content,"minWords"),m=e(o.content,"maxWords");if(u||a.length)return{prompt:u,requirements:a,minWords:p,maxWords:m,guideImages:c};return{prompt:(Array.isArray(i.contexts)?i.contexts:[]).map(t).filter(t=>"text"===t.type&&"string"==typeof t.text).map(t=>String(t.text)).join("\n")||n(o.content,"prompt")||n(o.content,"question"),requirements:r(o.content,"requirements"),minWords:p,maxWords:m,guideImages:c}}export function transformWordFillStructuredForm(e){return{instruction:n(e[0]?.content,"instruction"),groupTitle:n(e[0]?.content,"groupTitle"),groupContent:n(e[0]?.content,"groupContent"),groupImageUrl:n(e[0]?.content,"groupImageUrl"),questions:e.map(e=>({id:e.id,title:n(e.content,"title"),content:n(e.content,"content")||n(e.content,"html")||n(e.content,"text"),answers:i(e.content,"answers"),caseSensitive:Boolean(t(e.content).caseSensitive),imageUrl:n(e.content,"imageUrl"),questionNumber:e.question_number}))}}function t(t){return"object"==typeof t&&null!==t?t:{}}function n(n,e){const r=t(n)[e];return"string"==typeof r?r:""}function e(n,e){const r=t(n)[e];return"number"==typeof r?r:void 0}function r(n,e){const r=t(n)[e];return Array.isArray(r)?r.filter(t=>"string"==typeof t):[]}function o(n,e){const r=t(n)[e];return Array.isArray(r)?r.map(t):[]}function i(n,e){const r=t(n)[e],o=t(r);return Object.fromEntries(Object.entries(o).map(([t,n])=>[t,String(n??"")]))}
|
|
@@ -45,6 +45,8 @@ export interface QuestionPart {
|
|
|
45
45
|
audioUrl?: string;
|
|
46
46
|
templateOrder?: number;
|
|
47
47
|
category?: string;
|
|
48
|
+
/** Max points for this part from template.parts[].points */
|
|
49
|
+
points?: number;
|
|
48
50
|
/** Section-level metadata carried from the template when a part is split by sections. */
|
|
49
51
|
sectionId?: number;
|
|
50
52
|
isGroup?: boolean;
|
|
@@ -104,6 +106,8 @@ export interface TemplatePart {
|
|
|
104
106
|
sections?: TemplateSection[];
|
|
105
107
|
audioUrl?: string;
|
|
106
108
|
category?: string;
|
|
109
|
+
/** Max points for this part from exams.template.parts */
|
|
110
|
+
points?: number;
|
|
107
111
|
}
|
|
108
112
|
/**
|
|
109
113
|
* Group questions by part_id AND questionGroup.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function groupQuestionsByPart(e,t){const n=new Map,o=new Map;for(const t of e){const e=o.get(t.part_id)||[];e.push(t),o.set(t.part_id,e)}for(const[e,r]of o.entries()){const o=[...r].sort((e,t)=>e.question_number-t.question_number),i=o[0];if(!i)continue;const s=t?.find(t=>String(t.id)===String(e)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),c=u?parseInt(u[0],10):i.part_no,l=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===l?.type,p=s?.sections??[],d=new Set(p.map(e=>e.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const t=`${e}_part`;n.set(t,{partId:e,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,isGroup:!0,group:l,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const t=`${e}_part`;n.set(t,{partId:e,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[t,r]of s.sections.entries()){const i=o.filter(e=>{const t=e.question_number-1;return t>=r.startIndex&&t<=r.endIndex});if(!i.length)continue;const u=`${e}_section_${t}`,l=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:e,partNo:c,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,sectionId:r.sectionId,isGroup:l,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((e,t)=>{const n=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder,o=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder;return n!==o?n-o:(e.questions[0]?.question_number||0)-(t.questions[0]?.question_number||0)})}export function transformFillInBlank(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload,r=[];for(const t of e){const e=t.content,n=t.is_example||!1,o=e.question||e.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const i=o.split("\n").filter(e=>e.trim());for(const o of i){const i=o.match(/\{(\d+)\}/);if(!i)continue;const s=parseInt(i[1],10),a=o.split(/\{\d+\}/),u=a[0]?.trim()||"",c=a[1]?.trim()||"";r.push({id:`${t.id}-blank-${s}`,questionNumber:t.question_number,textBefore:u,textAfter:c,imageUrl:e.imageUrl,hints:e.hints,isExample:n,correctAnswer:n?t.correct_answer?.answers?.[s]:void 0})}}else{const i=o.match(/^(.*?)\{0\}(.*)$/),s=i?i[1].trim():o,a=i?i[2].trim():"";r.push({id:t.id,questionNumber:t.question_number,textBefore:s,textAfter:a,imageUrl:e.imageUrl,hints:e.hints,isExample:n,correctAnswer:n?t.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"FILL IN THE BLANK",imageUrl:n?.imageUrl,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(e){const t=e[0],n=t?.content;return{questions:e.map(e=>{const t=e.content,n=t.sentence||"",o=n.match(/^(.*?)\{0\}(.*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:e.id,questionNumber:e.question_number,textBefore:r,textAfter:i,verbHint:t.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}const e=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(t){const n=t[0]?.content,o=t[0]?.questionGroup?.payload,r=t.find(e=>e.is_example),i=t.filter(e=>!e.is_example);let s;if(r){const t=r.content,n=(t.options||[]).map((t,n)=>({id:`${r.id}-opt-${n}`,label:e[n]||String(n+1),text:t})),o="number"==typeof r.correct_answer?.answer?r.correct_answer.answer:-1;s={questionNumber:r.question_number,questionText:t.question||"",options:n,correctOptionId:o>=0?n[o]?.id||"":n[0]?.id||"",optionType:t.optionType||"text",imageUrl:t.imageUrl}}return{questions:i.map(t=>{const n=t.content,o=n.optionType||"text",r=(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n})),i=t.correct_answer?.answer,s=Array.isArray(i)?i.filter(e=>"number"==typeof e).map(e=>r[e]?.id).filter(e=>Boolean(e)):"number"==typeof i?[r[i]?.id].filter(e=>Boolean(e)):[];return{id:t.id,questionNumber:t.question_number,questionText:n.question||"",options:r,correctOptionId:s[0],correctOptionIds:s,imageUrl:n.imageUrl,optionType:o,multipleAnswers:Boolean(n.multipleAnswers||Array.isArray(i)),explanation:t.explanation}}),example:s,imageUrl:n?.imageUrl,groupImageUrl:o?.mainImageUrl||o?.imageUrl,groupTitle:o?.title,groupContent:o?.content,articles:o?.articles,audioUrl:n?.audioUrl,instruction:n?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseCorrectAdjective(t){return{questions:t.map(t=>{const n=t.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:t.id,questionNumber:t.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(e){const t=e.content;if(t.instructions?.mainInstruction||t.informations?.length)return{prompt:t.instructions?.mainInstruction||"",requirements:t.informations,minWords:t.minWords,maxWords:t.maxWords,guideImages:t.guideImages};return{prompt:t.contexts?.filter(e=>"text"===e.type).map(e=>e.text).join("\n")||"",minWords:t.minWords,maxWords:t.maxWords,guideImages:t.guideImages}}export function transformColorObjects(e){const t=e[0],n=t?.content,o=n?.colorNodes?.map(e=>({id:e.id,color:e.color,label:e.label}))||n?.hintItems||[],r=n?.regionNodes?.map(e=>({id:e.id,x:e.x,y:e.y,width:e.width,height:e.height,correctHintId:e.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(t){if(function(e){const t=e[0];if(!t)return!1;const n=t.content;return void 0!==n?.question&&!n?.questions&&void 0!==t.questionGroup?.payload?.passage}(t)){const n=t[0],o=n.questionGroup?.payload||{},r=t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=t[0],o=n?.content,r=o?.questions?.map((t,o)=>({id:t.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:t.question,options:(t.options||[]).map((o,r)=>({id:`${t.id||n.id}-opt-${r}`,label:e[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(e){const t=e[0],n=t?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(e=>({id:e.id,number:e.number,isPreFilled:e.isPreFilled||!1,correctAnswer:e.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function t(e){return e&&"string"==typeof e.word&&!e.subQuestions}export function transformFillWordHint(e){const n=e[0],o=n?.content;if(e.length>1&&e.every(e=>t(e.content))){const t=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:e.map(e=>{const t=e.content,n=t.word.replace(/\{\d+\}/,"_");return{id:e.id,questionNumber:e.question_number,imageUrl:t.imageUrl||"",word:n}}),hintLetters:t,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(t(o)){const e=o,t=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(e){const t=[],n=e.split(",").map(e=>e.trim());for(const e of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(e));){const o=parseInt(n[1],10),r=e.replace(n[0],"_");t.push({index:o,displayWord:r})}}return t.sort((e,t)=>e.index-t.index),t}(e.word).map(t=>({id:`${n.id}-blank-${t.index}`,questionNumber:n.question_number,imageUrl:e.imageUrl||"",word:t.displayWord,blankIndex:t.index})),hintLetters:t,instruction:e.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((e,t)=>({id:e.id,questionNumber:n.question_number+t,imageUrl:e.imageUrl||"",word:e.word||""}))||[],hintLetters:r?.hintLetters||n.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(e){const t=e[0],n=t?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(e){const t=e[0],n=t?.questionGroup?.payload,o=t?.content;return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1;return{id:e.id,questionNumber:e.question_number,question:(t.question||"").replace(/\{\d+\}/g,"______"),imageUrl:t.imageUrl,prefixText:t.prefixText,suffixText:t.suffixText,suggestedAnswers:t.suggestedAnswers,isExample:n,exampleAnswer:n?e.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(e){const t=e[0]?.questionGroup?.payload;return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1,o=n&&"boolean"==typeof e.correct_answer?.answer?e.correct_answer.answer:void 0;return{id:e.id,questionNumber:e.question_number,question:t.question||"",imageUrl:t.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:t?.mainImageUrl||t?.imageUrl,groupContent:t?.content||t?.groupContent}}export function transformWordOrdering(e){return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1,o=Array.isArray(e.correct_answer?.answer)?e.correct_answer.answer:Array.isArray(t.answer)?t.answer:void 0;return{id:e.id,questionNumber:e.question_number,words:t.words||[],imageUrl:t.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(e){const t=e[0],n=t?.questionGroup?.payload,o=t?.content,r=o?.title||n?.title||e.find(e=>e.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(e=>"string"==typeof e?{word:e}:e),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let c;c="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const l=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:t?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:c,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:l,emailTo:m}}export function transformMatchByWritingAnswer(e){const t=e[0]?.questionGroup?.payload,n=e.some(e=>!!e.content?.askerName),o=e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1;return{id:e.id,questionNumber:e.question_number,question:t.question||"",imageUrl:t.imageUrl,isExample:n,exampleAnswer:n?e.correct_answer?.answer:void 0,askerName:t.askerName,answererName:t.answererName}}),r=t?.options?.map(e=>({answer:e.answer,imageUrl:e.imageUrl||"",content:e.content||""}))||[],i=n?e[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:t?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload;return{questions:e.map(e=>({id:e.id,questionNumber:e.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}export function transformWordFillStructuredForm(e){const t=e[0],n=t?.questionGroup?.payload;return{questions:e.map(e=>{const t=e.content,n=e.correct_answer||{};let o=t?.content||"";const r=t?.blocks;return!o&&r?.length&&(o=r.map(e=>(e.heading?`<h3>${e.heading}</h3>`:"")+(e.content||"")).join("")),{id:e.id,questionNumber:e.question_number,title:t?.title||"",imageUrl:t?.imageUrl,content:o,answers:n?.answers||{},caseSensitive:n?.caseSensitive??t?.caseSensitive??!1}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:t?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:t?.correctAnswer?.objectId||t?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(e){return{questions:e.map(e=>{const t=e.content,n=e.questionGroup?.payload||{};return{id:e.id,questionNumber:e.question_number,audioUrl:t?.audioUrl||"",arrowNode:t?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:t?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
|
|
1
|
+
export function groupQuestionsByPart(e,t){const n=new Map,o=new Map;for(const t of e){const e=o.get(t.part_id)||[];e.push(t),o.set(t.part_id,e)}for(const[e,r]of o.entries()){const o=[...r].sort((e,t)=>e.question_number-t.question_number),i=o[0];if(!i)continue;const s=t?.find(t=>String(t.id)===String(e)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),c=u?parseInt(u[0],10):i.part_no,l=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===l?.type,p=s?.sections??[],d=new Set(p.map(e=>e.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const t=`${e}_part`;n.set(t,{partId:e,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:l,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const t=`${e}_part`;n.set(t,{partId:e,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[t,r]of s.sections.entries()){const i=o.filter(e=>{const t=e.question_number-1;return t>=r.startIndex&&t<=r.endIndex});if(!i.length)continue;const u=`${e}_section_${t}`,l=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:e,partNo:c,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:l,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((e,t)=>{const n=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder,o=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder;return n!==o?n-o:(e.questions[0]?.question_number||0)-(t.questions[0]?.question_number||0)})}export function transformFillInBlank(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload,r=[];for(const t of e){const e=t.content,n=t.is_example||!1,o=e.question||e.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const i=o.split("\n").filter(e=>e.trim());for(const o of i){const i=o.match(/\{(\d+)\}/);if(!i)continue;const s=parseInt(i[1],10),a=o.split(/\{\d+\}/),u=a[0]?.trim()||"",c=a[1]?.trim()||"";r.push({id:`${t.id}-blank-${s}`,questionNumber:t.question_number,textBefore:u,textAfter:c,imageUrl:e.imageUrl,hints:e.hints,isExample:n,correctAnswer:n?t.correct_answer?.answers?.[s]:void 0})}}else{const i=o.match(/^(.*?)\{0\}(.*)$/),s=i?i[1].trim():o,a=i?i[2].trim():"";r.push({id:t.id,questionNumber:t.question_number,textBefore:s,textAfter:a,imageUrl:e.imageUrl,hints:e.hints,isExample:n,correctAnswer:n?t.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"FILL IN THE BLANK",imageUrl:n?.imageUrl,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(e){const t=e[0],n=t?.content;return{questions:e.map(e=>{const t=e.content,n=t.sentence||"",o=n.match(/^(.*?)\{0\}(.*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:e.id,questionNumber:e.question_number,textBefore:r,textAfter:i,verbHint:t.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}const e=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(t){const n=t[0]?.content,o=t[0]?.questionGroup?.payload,r=t.find(e=>e.is_example),i=t.filter(e=>!e.is_example);let s;if(r){const t=r.content,n=(t.options||[]).map((t,n)=>({id:`${r.id}-opt-${n}`,label:e[n]||String(n+1),text:t})),o="number"==typeof r.correct_answer?.answer?r.correct_answer.answer:-1;s={questionNumber:r.question_number,questionText:t.question||"",options:n,correctOptionId:o>=0?n[o]?.id||"":n[0]?.id||"",optionType:t.optionType||"text",imageUrl:t.imageUrl}}return{questions:i.map(t=>{const n=t.content,o=n.optionType||"text",r=(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n})),i=t.correct_answer?.answer,s=Array.isArray(i)?i.filter(e=>"number"==typeof e).map(e=>r[e]?.id).filter(e=>Boolean(e)):"number"==typeof i?[r[i]?.id].filter(e=>Boolean(e)):[];return{id:t.id,questionNumber:t.question_number,questionText:n.question||"",options:r,correctOptionId:s[0],correctOptionIds:s,imageUrl:n.imageUrl,optionType:o,multipleAnswers:Boolean(n.multipleAnswers||Array.isArray(i)),explanation:t.explanation}}),example:s,imageUrl:n?.imageUrl,groupImageUrl:o?.mainImageUrl||o?.imageUrl,groupTitle:o?.title,groupContent:o?.content,articles:o?.articles,audioUrl:n?.audioUrl,instruction:n?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseCorrectAdjective(t){return{questions:t.map(t=>{const n=t.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:t.id,questionNumber:t.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(e){const t=e.content;if(t.instructions?.mainInstruction||t.informations?.length)return{prompt:t.instructions?.mainInstruction||"",requirements:t.informations,minWords:t.minWords,maxWords:t.maxWords,guideImages:t.guideImages};return{prompt:t.contexts?.filter(e=>"text"===e.type).map(e=>e.text).join("\n")||"",minWords:t.minWords,maxWords:t.maxWords,guideImages:t.guideImages}}export function transformColorObjects(e){const t=e[0],n=t?.content,o=n?.colorNodes?.map(e=>({id:e.id,color:e.color,label:e.label}))||n?.hintItems||[],r=n?.regionNodes?.map(e=>({id:e.id,x:e.x,y:e.y,width:e.width,height:e.height,correctHintId:e.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(t){if(function(e){const t=e[0];if(!t)return!1;const n=t.content;return void 0!==n?.question&&!n?.questions&&void 0!==t.questionGroup?.payload?.passage}(t)){const n=t[0],o=n.questionGroup?.payload||{},r=t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=t[0],o=n?.content,r=o?.questions?.map((t,o)=>({id:t.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:t.question,options:(t.options||[]).map((o,r)=>({id:`${t.id||n.id}-opt-${r}`,label:e[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(e){const t=e[0],n=t?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(e=>({id:e.id,number:e.number,isPreFilled:e.isPreFilled||!1,correctAnswer:e.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function t(e){return e&&"string"==typeof e.word&&!e.subQuestions}export function transformFillWordHint(e){const n=e[0],o=n?.content;if(e.length>1&&e.every(e=>t(e.content))){const t=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:e.map(e=>{const t=e.content,n=t.word.replace(/\{\d+\}/,"_");return{id:e.id,questionNumber:e.question_number,imageUrl:t.imageUrl||"",word:n}}),hintLetters:t,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(t(o)){const e=o,t=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(e){const t=[],n=e.split(",").map(e=>e.trim());for(const e of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(e));){const o=parseInt(n[1],10),r=e.replace(n[0],"_");t.push({index:o,displayWord:r})}}return t.sort((e,t)=>e.index-t.index),t}(e.word).map(t=>({id:`${n.id}-blank-${t.index}`,questionNumber:n.question_number,imageUrl:e.imageUrl||"",word:t.displayWord,blankIndex:t.index})),hintLetters:t,instruction:e.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((e,t)=>({id:e.id,questionNumber:n.question_number+t,imageUrl:e.imageUrl||"",word:e.word||""}))||[],hintLetters:r?.hintLetters||n.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(e){const t=e[0],n=t?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(e){const t=e[0],n=t?.questionGroup?.payload,o=t?.content;return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1;return{id:e.id,questionNumber:e.question_number,question:(t.question||"").replace(/\{\d+\}/g,"______"),imageUrl:t.imageUrl,prefixText:t.prefixText,suffixText:t.suffixText,suggestedAnswers:t.suggestedAnswers,isExample:n,exampleAnswer:n?e.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(e){const t=e[0]?.questionGroup?.payload;return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1,o=n&&"boolean"==typeof e.correct_answer?.answer?e.correct_answer.answer:void 0;return{id:e.id,questionNumber:e.question_number,question:t.question||"",imageUrl:t.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:t?.mainImageUrl||t?.imageUrl,groupContent:t?.content||t?.groupContent}}export function transformWordOrdering(e){return{questions:e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1,o=Array.isArray(e.correct_answer?.answer)?e.correct_answer.answer:Array.isArray(t.answer)?t.answer:void 0;return{id:e.id,questionNumber:e.question_number,words:t.words||[],imageUrl:t.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(e){const t=e[0],n=t?.questionGroup?.payload,o=t?.content,r=o?.title||n?.title||e.find(e=>e.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(e=>"string"==typeof e?{word:e}:e),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let c;c="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const l=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:t?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:c,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:l,emailTo:m}}export function transformMatchByWritingAnswer(e){const t=e[0]?.questionGroup?.payload,n=e.some(e=>!!e.content?.askerName),o=e.map(e=>{const t=e.content,n=e.is_example||t.isExample||!1;return{id:e.id,questionNumber:e.question_number,question:t.question||"",imageUrl:t.imageUrl,isExample:n,exampleAnswer:n?e.correct_answer?.answer:void 0,askerName:t.askerName,answererName:t.answererName}}),r=t?.options?.map(e=>({answer:e.answer,imageUrl:e.imageUrl||"",content:e.content||""}))||[],i=n?e[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:t?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload;return{questions:e.map(e=>({id:e.id,questionNumber:e.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}export function transformWordFillStructuredForm(e){const t=e[0],n=t?.questionGroup?.payload;return{questions:e.map(e=>{const t=e.content,n=e.correct_answer||{};let o=t?.content||"";const r=t?.blocks;return!o&&r?.length&&(o=r.map(e=>(e.heading?`<h3>${e.heading}</h3>`:"")+(e.content||"")).join("")),{id:e.id,questionNumber:e.question_number,title:t?.title||"",imageUrl:t?.imageUrl,content:o,answers:n?.answers||{},caseSensitive:n?.caseSensitive??t?.caseSensitive??!1}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:t?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(e){const t=e[0],n=t?.content,o=t?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:t?.correctAnswer?.objectId||t?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(e){return{questions:e.map(e=>{const t=e.content,n=e.questionGroup?.payload||{};return{id:e.id,questionNumber:e.question_number,audioUrl:t?.audioUrl||"",arrowNode:t?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:t?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as n}from"react";import a from"next/image";import{Loader2 as i,FileText as l,Clock as s,Trophy as r,Layers as c,Target as h,HelpCircle as o,ChevronDown as m,X as d}from"lucide-react";import x from"../../../../components/themes/cambridge-yle/assets/images/background-ocean-edu-2.png";import g from"../../../../components/themes/cambridge-yle/assets/images/frame.png";import p from"../../../../components/themes/cambridge-yle/assets/images/bg-title.png";import u from"../../../../components/themes/cambridge-yle/assets/images/close.png";import b from"../../../../components/themes/cambridge-yle/assets/images/rocket.png";const f=[{q:"Bài test này kéo dài bao lâu?",a:"Thời gian làm bài sẽ được hiển thị trên màn hình. Hãy theo dõi đồng hồ để phân bổ thời gian hợp lý."},{q:"Em có cần hoàn thành tất cả câu hỏi không?",a:"Để kết quả phản ánh chính xác nhất năng lực hiện tại, em cố gắng hoàn thành toàn bộ câu hỏi trong thời gian quy định."},{q:"Nếu mất mạng giữa chừng thì sao?",a:"Trong một số trường hợp, hệ thống có thể tự động lưu tiến trình làm bài. Hãy kết nối lại internet sớm nhất có thể. Tuy nhiên để tránh gián đoạn, em nên sử dụng kết nối internet ổn định trong suốt quá trình làm bài."},{q:"Em không nghe được audio thì phải làm sao?",a:"Em hãy kiểm tra loa, tai nghe và âm lượng thiết bị trước. Nếu vẫn gặp lỗi, hãy thử tải lại trang hoặc đổi sang trình duyệt khác để tiếp tục làm bài."},{q:"Trang web bị lag hoặc không tải được câu hỏi?",a:"Em có thể thử làm mới trang, kiểm tra lại kết nối internet hoặc đổi trình duyệt/thiết bị khác. Nếu tình trạng vẫn tiếp diễn, hãy liên hệ trung tâm để được hỗ trợ nhanh nhất."},{q:"Em có thể xem lại đáp án sau khi nộp bài không?",a:"Sau khi nộp bài, sẽ có phiếu kết quả AI chấm điểm trả về, phân tích từng câu hỏi em đã làm."},{q:"Nếu em nộp nhầm thì sao?",a:"Sau khi nộp bài, em sẽ không thể chỉnh sửa câu trả lời. Em có thể liên hệ thầy cô ở trung tâm để hỗ trợ làm lại bài khác."},{q:"Em có được dùng từ điển hoặc tài liệu không?",a:"Để kết quả phản ánh đúng năng lực hiện tại, em nên làm bài trong điều kiện tương tự một bài kiểm tra thực tế và hạn chế sử dụng tài liệu hỗ trợ."},{q:"Em cần chuẩn bị gì trước khi bắt đầu?",a:"Em nên chuẩn bị thiết bị có kết nối internet ổn định, tai nghe (nếu có phần Listening), không gian yên tĩnh và dành đủ thời gian để hoàn thành bài test liên tục."},{q:"Em nên làm gì nếu gặp lỗi hệ thống?",a:"Nếu gặp lỗi trong quá trình làm bài, em hãy chụp lại màn hình lỗi (nếu có) và liên hệ trung tâm để được hỗ trợ xử lý nhanh nhất."}];function w({className:t="",size:n=18}){return e("svg",{width:n,height:n,viewBox:"0 0 24 24",className:t,fill:"currentColor",children:e("path",{d:"M12 0l2.4 9.6L24 12l-9.6 2.4L12 24l-2.4-9.6L0 12l9.6-2.4L12 0z"})})}export function CambridgeYleWaitingRoom({room:i,onStart:b,isStarting:y,showCountdown:k,autoStartCountdown:_,closeRedirectUrl:C,onClose:z}){const j=i.exam?.name||"",q=i.contest?.name||"",S=i.exam?.numberOfParts||1,E=i.exam?.durationMinutes||45,B=i.exam?.totalScore||100,L=i.exam?.passScore||0,[T,W]=n(!1),[O,P]=n(0);return t("div",{className:"fixed inset-0 z-50 flex items-center justify-center overflow-hidden",children:[e("div",{className:"absolute inset-0 scale-105 bg-cover bg-center",style:{backgroundImage:`url(${x.src})`,filter:"blur(2px) brightness(0.8) saturate(0.9)"}}),e("div",{className:"absolute inset-0 bg-gradient-to-b from-blue-950/50 via-blue-900/40 to-blue-950/60"}),e(w,{className:"absolute left-[8%] top-[14%] text-yellow-300 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:22}),e(w,{className:"absolute right-[10%] top-[10%] text-yellow-200 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:16}),e(w,{className:"absolute left-[15%] bottom-[18%] text-white/80",size:14}),e(w,{className:"absolute right-[6%] bottom-[24%] text-yellow-300 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:20}),e(w,{className:"absolute left-[45%] top-[8%] text-white/70",size:12}),e("div",{className:"relative z-10",style:{width:"min(98vw, calc(98vh * 1552 / 672), 1800px)"},children:t("div",{className:"relative aspect-[1552/672] w-full",children:[e(a,{src:g,alt:"",fill:!0,className:"object-contain",priority:!0,unoptimized:!0}),e("div",{className:"absolute left-1/2 top-0 z-20 -translate-x-1/2 -translate-y-1/2",children:t("div",{className:"relative",children:[e(a,{src:p,alt:"",width:320,height:72,className:"drop-shadow-xl",priority:!0,unoptimized:!0}),e("div",{className:"absolute inset-0 flex items-center justify-center px-10 pt-1",title:q,children:e("span",{className:"block truncate text-center text-base font-extrabold uppercase tracking-[0.15em] text-white drop-shadow",children:q})})]})}),e("button",{onClick:()=>{z?z():C&&(window.location.href=C)},className:"absolute right-[7%] top-[-2%] z-30 cursor-pointer transition-transform hover:scale-110 active:scale-95","aria-label":"Close",children:e(a,{src:u,alt:"Close",width:56,height:56,unoptimized:!0})}),e("div",{className:"absolute inset-0 z-10 flex items-stretch overflow-hidden px-[9%] py-[10%]",children:t("div",{className:"flex h-full w-full items-stretch gap-4",children:[t("div",{className:"mx-auto flex w-full max-w-[560px] flex-[0_0_46%] flex-col justify-center gap-1",children:[e("h1",{className:"whitespace-nowrap text-center text-3xl font-black uppercase tracking-wide text-white md:text-4xl lg:text-5xl 2xl:text-6xl",style:{fontWeight:900,margin:"0.2em 0",textShadow:["0 1px 0 #cfe3ff","0 2px 0 #a8c8ee","0 3px 0 #6f9cd4","0 4px 0 #4a7cb8","0 5px 0 #2f5e9c","0 6px 0 #1a4480","0 8px 12px rgba(0,0,0,0.45)","0 0 22px rgba(120,180,255,0.55)"].join(", ")},children:i.name}),e("p",{className:"mt-1 hidden text-center text-sm font-bold text-[#21cffb] md:text-base 2xl:block 2xl:text-lg",children:"Đánh giá năng lực • Xác định lộ trình • Bứt phá tương lai"}),e("p",{className:"mx-auto mt-1 hidden max-w-2xl text-center text-xs text-white/95 md:text-sm 2xl:block",children:"Bài thi giúp bạn biết chính xác trình độ hiện tại và được Ocean Edu tư vấn lộ trình học tập phù hợp nhất."}),t("div",{className:"mt-4 flex items-center justify-center gap-2 2xl:mt-6",children:[e("span",{className:"h-px w-10 bg-white"}),e(w,{className:"text-white",size:12}),e("span",{className:"text-xs font-extrabold uppercase tracking-[0.3em] text-white md:text-sm",children:"Bài thi bao gồm"}),e(w,{className:"text-white",size:12}),e("span",{className:"h-px w-10 bg-white"})]}),t("div",{className:"mt-4 grid grid-cols-3 gap-2.5",children:[e(v,{icon:e(c,{className:"h-6 w-6"}),value:S,label:"Phần thi"}),e(v,{icon:e(s,{className:"h-6 w-6"}),value:E,label:"Phút"}),e(v,{icon:e(r,{className:"h-6 w-6"}),value:B,label:"Thang điểm"})]}),t("div",{className:"mt-4 space-y-2.5",children:[t("div",{className:"flex items-center gap-3 rounded-xl bg-[#0000001c] px-3 py-2.5",children:[e("span",{className:"flex h-9 w-9 flex-none items-center justify-center rounded-full bg-[#00000021] text-white",children:e(l,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-bold text-white md:text-base",children:"Đề thi"}),e("span",{className:"ml-auto truncate text-sm font-bold text-white md:text-base",children:j})]}),L>0&&t("div",{className:"flex items-center gap-3 rounded-xl bg-[#0000001c] px-3 py-2.5",children:[e("span",{className:"flex h-9 w-9 flex-none items-center justify-center rounded-full bg-[#00000021] text-white",children:e(h,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-bold text-white md:text-base",children:"Điểm tối thiểu cần đạt"}),t("span",{className:"ml-auto text-sm font-black text-yellow-300 md:text-lg",children:[L,"/",B]})]})]}),e("div",{className:"mt-5 flex justify-center",children:e(N,{onClick:b,isStarting:y,showCountdown:k,autoStartCountdown:_})})]}),e("div",{className:"relative hidden flex-[0_0_42%] md:block",children:e("div",{className:"absolute left-0 top-[4%] z-20 max-w-[60%]",children:t("div",{className:"relative rounded-2xl bg-white px-3 py-2 text-center text-[11px] font-semibold text-sky-900 shadow-xl ring-2 ring-sky-200 md:text-xs",children:["Cùng mình khám phá trình độ của bạn nhé!",e("span",{className:"absolute -bottom-1.5 right-6 h-3 w-3 rotate-45 bg-white ring-2 ring-sky-200"})]})})})]})})]})}),t("button",{type:"button",onClick:()=>W(!0),"aria-label":"Câu hỏi thường gặp",className:"group fixed bottom-5 right-5 z-40 inline-flex cursor-pointer items-center gap-2 rounded-full bg-gradient-to-b from-cyan-300 via-sky-500 to-sky-700 px-4 py-3 text-sm font-bold text-white shadow-[0_6px_0_0_#0c4a6e,0_10px_22px_rgba(14,165,233,0.45)] ring-2 ring-cyan-200/50 transition-all duration-150 hover:-translate-y-0.5 hover:brightness-110 active:translate-y-1 active:shadow-[0_1px_0_0_#0c4a6e,0_3px_8px_rgba(14,165,233,0.3)]",children:[e(o,{className:"h-5 w-5",strokeWidth:2.5}),e("span",{className:"hidden sm:inline",style:{textShadow:"0 1px 0 rgba(12,74,110,0.5)"},children:"Câu hỏi thường gặp"})]}),T&&t("div",{className:"fixed inset-0 z-[60] flex items-center justify-center p-4",role:"dialog","aria-modal":"true","aria-label":"Câu hỏi thường gặp",children:[e("div",{className:"absolute inset-0 bg-blue-950/70 backdrop-blur-sm",onClick:()=>W(!1)}),t("div",{className:"relative z-10 flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-3xl bg-gradient-to-br from-cyan-300/20 via-white/5 to-white/0 p-px shadow-[0_20px_60px_-15px_rgba(10,75,140,0.7)] backdrop-blur-xl",children:[e("div",{className:"pointer-events-none absolute -left-12 -top-12 h-40 w-40 rounded-full bg-cyan-400/30 blur-3xl"}),e("div",{className:"pointer-events-none absolute -right-12 -bottom-12 h-40 w-40 rounded-full bg-sky-500/25 blur-3xl"}),t("div",{className:"relative flex max-h-[85vh] flex-col overflow-hidden rounded-[calc(1.5rem-1px)] bg-gradient-to-b from-[#0e3d70]/95 via-[#0a4b8c]/95 to-[#0a3866]/95 ring-1 ring-cyan-300/20",children:[t("div",{className:"flex items-center gap-3 px-6 py-5",children:[e("div",{className:"flex h-12 w-12 flex-none items-center justify-center rounded-full bg-gradient-to-br from-cyan-300 to-sky-600 shadow-[0_6px_18px_-4px_rgba(34,211,238,0.6)] ring-4 ring-cyan-300/20",children:e(o,{className:"h-6 w-6 text-white",strokeWidth:2.5})}),t("div",{className:"flex-1",children:[e("h2",{className:"text-lg font-extrabold tracking-tight text-white drop-shadow-md",children:"Câu hỏi thường gặp"}),e("p",{className:"mt-0.5 text-xs font-medium text-cyan-100/70",children:"Những điều cần biết trước khi làm bài"})]}),e("button",{type:"button",onClick:()=>W(!1),"aria-label":"Đóng",className:"flex h-9 w-9 flex-none cursor-pointer items-center justify-center rounded-full bg-white/10 text-white/80 ring-1 ring-white/15 transition-all duration-150 hover:bg-white/20 hover:text-white",children:e(d,{className:"h-5 w-5"})})]}),e("div",{className:"mx-6 h-px bg-gradient-to-r from-transparent via-cyan-300/25 to-transparent"}),e("div",{className:"flex-1 overflow-y-auto px-4 py-4 sm:px-6",children:e("ul",{className:"space-y-2",children:f.map((n,a)=>{const i=O===a;return t("li",{className:"overflow-hidden rounded-2xl ring-1 transition-colors duration-200 "+(i?"bg-white/[0.08] ring-cyan-300/30":"bg-white/[0.04] ring-white/10 hover:bg-white/[0.06]"),children:[t("button",{type:"button",onClick:()=>P(i?null:a),className:"flex w-full cursor-pointer items-center gap-3 px-4 py-3 text-left","aria-expanded":i,children:[e("span",{className:"flex h-7 w-7 flex-none items-center justify-center rounded-full text-xs font-black transition-colors "+(i?"bg-gradient-to-br from-yellow-300 to-orange-500 text-white":"bg-white/10 text-cyan-100"),children:a+1}),e("span",{className:"flex-1 text-sm font-bold text-white",children:n.q}),e(m,{className:"h-5 w-5 flex-none text-cyan-200 transition-transform duration-200 "+(i?"rotate-180":"")})]}),e("div",{className:"grid transition-all duration-200 "+(i?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0"),children:e("div",{className:"overflow-hidden",children:e("p",{className:"px-4 pb-4 pl-14 text-sm leading-relaxed text-cyan-50/90",children:n.a})})})]},a)})})}),e("div",{className:"border-t border-white/10 bg-white/[0.03] px-6 py-3 text-center text-xs text-cyan-100/60",children:"Cần hỗ trợ thêm? Liên hệ trung tâm Ocean Edu để được giải đáp."})]})]})]})]})}function v({icon:n,value:a,label:i}){return t("div",{className:"flex items-center justify-center gap-3 rounded-2xl bg-[#0000001c] px-2 py-4",children:[e("span",{className:"flex h-12 w-12 flex-none items-center justify-center rounded-full bg-[#00bdff1a] text-white",children:n}),t("div",{className:"flex flex-col items-start leading-tight",children:[e("div",{className:"text-2xl font-black text-white md:text-3xl",children:a}),e("div",{className:"text-xs font-bold text-white/90 md:text-sm",children:i})]})]})}function N({onClick:n,isStarting:l,showCountdown:s,autoStartCountdown:r}){return s?e("div",{className:"inline-flex h-14 w-48 items-center justify-center rounded-full bg-yellow-400 text-2xl font-black text-[#1a3a6e]",children:r}):t("button",{onClick:n,disabled:l,className:"group relative mt-5 inline-flex cursor-pointer items-center gap-3 rounded-full bg-gradient-to-b from-[#ffd54a] via-[#ffb733] to-[#ff8a1f] py-2.5 pl-8 pr-10 shadow-[0_6px_0_0_#c46410,0_10px_18px_rgba(0,0,0,0.4)] ring-2 ring-orange-300/60 transition-all duration-150 hover:-translate-y-0.5 hover:brightness-110 hover:shadow-[0_8px_0_0_#c46410,0_14px_22px_rgba(0,0,0,0.45)] active:translate-y-1.5 active:shadow-[0_1px_0_0_#c46410,0_2px_6px_rgba(0,0,0,0.3)] disabled:cursor-not-allowed disabled:opacity-70",children:[l?e(i,{className:"h-7 w-7 animate-spin text-white"}):e(a,{src:b,alt:"",width:36,height:36,unoptimized:!0}),e("span",{className:"text-xl font-black text-white",style:{color:"#685030"},children:"Bắt đầu"})]})}
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as n}from"react";import a from"next/image";import{Loader2 as i,Clock as l,Trophy as r,Layers as s,Target as c,HelpCircle as o,ChevronDown as h,X as m}from"lucide-react";import{PartRow as d,groupPartsByCategory as x}from"./cambridge-yle-waiting-parts";import p from"../../../../components/themes/cambridge-yle/assets/images/background-ocean-edu-2.png";import g from"../../../../components/themes/cambridge-yle/assets/images/frame.png";import u from"../../../../components/themes/cambridge-yle/assets/images/bg-title.png";import b from"../../../../components/themes/cambridge-yle/assets/images/close.png";import f from"../../../../components/themes/cambridge-yle/assets/images/rocket.png";const w=[{q:"Bài test này kéo dài bao lâu?",a:"Thời gian làm bài sẽ được hiển thị trên màn hình. Hãy theo dõi đồng hồ để phân bổ thời gian hợp lý."},{q:"Em có cần hoàn thành tất cả câu hỏi không?",a:"Để kết quả phản ánh chính xác nhất năng lực hiện tại, em cố gắng hoàn thành toàn bộ câu hỏi trong thời gian quy định."},{q:"Nếu mất mạng giữa chừng thì sao?",a:"Trong một số trường hợp, hệ thống có thể tự động lưu tiến trình làm bài. Hãy kết nối lại internet sớm nhất có thể. Tuy nhiên để tránh gián đoạn, em nên sử dụng kết nối internet ổn định trong suốt quá trình làm bài."},{q:"Em không nghe được audio thì phải làm sao?",a:"Em hãy kiểm tra loa, tai nghe và âm lượng thiết bị trước. Nếu vẫn gặp lỗi, hãy thử tải lại trang hoặc đổi sang trình duyệt khác để tiếp tục làm bài."},{q:"Trang web bị lag hoặc không tải được câu hỏi?",a:"Em có thể thử làm mới trang, kiểm tra lại kết nối internet hoặc đổi trình duyệt/thiết bị khác. Nếu tình trạng vẫn tiếp diễn, hãy liên hệ trung tâm để được hỗ trợ nhanh nhất."},{q:"Em có thể xem lại đáp án sau khi nộp bài không?",a:"Sau khi nộp bài, sẽ có phiếu kết quả AI chấm điểm trả về, phân tích từng câu hỏi em đã làm."},{q:"Nếu em nộp nhầm thì sao?",a:"Sau khi nộp bài, em sẽ không thể chỉnh sửa câu trả lời. Em có thể liên hệ thầy cô ở trung tâm để hỗ trợ làm lại bài khác."},{q:"Em có được dùng từ điển hoặc tài liệu không?",a:"Để kết quả phản ánh đúng năng lực hiện tại, em nên làm bài trong điều kiện tương tự một bài kiểm tra thực tế và hạn chế sử dụng tài liệu hỗ trợ."},{q:"Em cần chuẩn bị gì trước khi bắt đầu?",a:"Em nên chuẩn bị thiết bị có kết nối internet ổn định, tai nghe (nếu có phần Listening), không gian yên tĩnh và dành đủ thời gian để hoàn thành bài test liên tục."},{q:"Em nên làm gì nếu gặp lỗi hệ thống?",a:"Nếu gặp lỗi trong quá trình làm bài, em hãy chụp lại màn hình lỗi (nếu có) và liên hệ trung tâm để được hỗ trợ xử lý nhanh nhất."}];function v({className:t="",size:n=18}){return e("svg",{width:n,height:n,viewBox:"0 0 24 24",className:t,fill:"currentColor",children:e("path",{d:"M12 0l2.4 9.6L24 12l-9.6 2.4L12 24l-2.4-9.6L0 12l9.6-2.4L12 0z"})})}export function CambridgeYleWaitingRoom({room:i,onStart:f,isStarting:k,showCountdown:_,autoStartCountdown:C,closeRedirectUrl:z,onClose:j}){const q=i.exam?.name||"",S=i.contest?.name||"",E=i.exam?.parts??[],B=E.length>0?E.length:i.exam?.numberOfParts||1,I=i.exam?.durationMinutes||45,L=i.exam?.totalScore||100,W=i.exam?.passScore||0,P=i.exam?.level?.trim()||"",[T,$]=n(!1),[O,R]=n(0);return t("div",{className:"fixed inset-0 z-50 flex items-center justify-center overflow-hidden",children:[e("div",{className:"absolute inset-0 scale-105 bg-cover bg-center",style:{backgroundImage:`url(${p.src})`,filter:"blur(2px) brightness(0.8) saturate(0.9)"}}),e("div",{className:"absolute inset-0 bg-gradient-to-b from-blue-950/50 via-blue-900/40 to-blue-950/60"}),e(v,{className:"absolute left-[8%] top-[14%] text-yellow-300 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:22}),e(v,{className:"absolute right-[10%] top-[10%] text-yellow-200 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:16}),e(v,{className:"absolute left-[15%] bottom-[18%] text-white/80",size:14}),e(v,{className:"absolute right-[6%] bottom-[24%] text-yellow-300 drop-shadow-[0_0_8px_rgba(255,255,150,0.8)]",size:20}),e(v,{className:"absolute left-[45%] top-[8%] text-white/70",size:12}),e("div",{className:"relative z-10",style:{width:"min(98vw, calc(98vh * 1552 / 672), 1800px)"},children:t("div",{className:"relative aspect-[1552/672] w-full",children:[e(a,{src:g,alt:"",fill:!0,className:"object-contain",priority:!0,unoptimized:!0}),e("div",{className:"absolute left-1/2 top-0 z-20 max-w-[min(92%,720px,calc(100%-7rem))] -translate-x-1/2 -translate-y-1/2",children:e("div",{className:"relative flex h-[clamp(52px,7vw,72px)] min-w-[240px] max-w-full items-center justify-center px-6 pt-0.5 drop-shadow-xl sm:px-15",style:{borderStyle:"solid",borderColor:"transparent",borderWidth:0,borderImageSource:`url(${u.src})`,borderImageSlice:"10 85 fill",borderImageWidth:"0 calc(clamp(52px, 7vw, 72px) / 2)",borderImageRepeat:"stretch"},children:e("span",{className:"relative z-10 whitespace-nowrap text-center text-sm font-extrabold uppercase tracking-[0.12em] text-white drop-shadow sm:text-base sm:tracking-[0.15em]",children:S})})}),e("button",{onClick:()=>{j?j():z&&(window.location.href=z)},className:"absolute right-[7%] top-[-2%] z-30 cursor-pointer transition-transform hover:scale-110 active:scale-95","aria-label":"Close",children:e(a,{src:b,alt:"Close",width:56,height:56,unoptimized:!0})}),t("div",{className:"absolute inset-0 z-10 overflow-hidden px-[9%] pt-[4%] pb-[calc(7%+1.75rem)]",children:[t("div",{className:"flex h-full min-h-0 items-stretch gap-4",children:[t("div",{className:"mx-auto flex h-full w-full max-w-[560px] min-h-0 flex-[0_0_46%] flex-col gap-1",children:[e("h1",{className:"shrink-0 text-center text-2xl font-black uppercase tracking-wide text-white sm:text-3xl md:text-4xl lg:text-5xl 2xl:text-5xl",style:{fontWeight:900,margin:"0.1em 0",textShadow:["0 1px 0 #cfe3ff","0 2px 0 #a8c8ee","0 3px 0 #6f9cd4","0 4px 0 #4a7cb8","0 5px 0 #2f5e9c","0 6px 0 #1a4480","0 8px 12px rgba(0,0,0,0.45)","0 0 22px rgba(120,180,255,0.55)"].join(", ")},children:i.name}),P?e("div",{className:"flex w-full min-w-0 shrink-0 flex-col items-center gap-1 px-1",children:e("span",{className:"rounded-full bg-cyan-400/25 px-2 py-0.5 text-[10px] font-black uppercase tracking-wide text-white ring-1 ring-cyan-300/40",children:P})}):null,e("p",{className:"mt-0.5 hidden shrink-0 text-center text-sm font-bold text-[#21cffb] md:text-base 2xl:block 2xl:text-lg",children:"Đánh giá năng lực • Xác định lộ trình • Bứt phá tương lai"}),e("p",{className:"mx-auto mt-0.5 hidden max-w-2xl shrink-0 text-center text-xs text-white/95 md:text-sm 2xl:block",children:"Bài thi giúp bạn biết chính xác trình độ hiện tại và được Ocean Edu tư vấn lộ trình học tập phù hợp nhất."}),t("div",{className:"mt-1.5 hidden shrink-0 items-center justify-center gap-2 2xl:flex",children:[e("span",{className:"h-px w-10 bg-white"}),e(v,{className:"text-white",size:12}),e("span",{className:"text-xs font-extrabold uppercase tracking-[0.3em] text-white md:text-sm",children:"Bài thi bao gồm"}),e(v,{className:"text-white",size:12}),e("span",{className:"h-px w-10 bg-white"})]}),t("div",{className:"mt-1.5 grid shrink-0 grid-cols-3 gap-2",children:[e(y,{icon:e(s,{className:"h-5 w-5"}),value:B,label:"Phần thi"}),e(y,{icon:e(l,{className:"h-5 w-5"}),value:I,label:"Phút"}),e(y,{icon:e(r,{className:"h-5 w-5"}),value:L,label:"Tổng điểm"})]}),E.length>0?t("div",{className:"mt-1.5 flex min-h-0 flex-1 flex-col overflow-hidden rounded-2xl bg-black/15 p-2 ring-1 ring-white/10",children:[q?t("div",{className:"mb-1.5 flex w-full shrink-0 flex-col items-center gap-0.5 rounded-xl bg-gradient-to-r from-cyan-400/20 via-sky-300/25 to-cyan-400/20 px-2.5 py-1.5 ring-1 ring-cyan-200/40",title:q,children:[e("span",{className:"text-[10px] font-extrabold uppercase tracking-[0.2em] text-cyan-200",children:"Đề thi"}),e("p",{className:"w-full truncate text-center text-sm font-black leading-snug text-white drop-shadow-sm md:text-base",children:q})]}):null,t("div",{className:"mb-1 flex shrink-0 items-center justify-between px-1.5 pt-0.5",children:[e("span",{className:"text-xs font-extrabold uppercase tracking-[0.18em] text-white",children:"Cấu trúc bài thi"}),W>0&&t("span",{className:"text-xs font-semibold text-white",children:["Điểm đạt:"," ",t("span",{className:"font-black text-yellow-300",children:[W,"/",L]})]})]}),e("div",{className:"cambridge-scrollbar min-h-0 flex-1 overflow-y-auto pr-1.5",children:e("div",{className:"space-y-2.5",children:x(E).map(n=>t("div",{className:"space-y-1.5",children:[t("div",{className:"flex items-center gap-2 px-1",children:[e("span",{className:"flex-none text-[11px] font-extrabold uppercase tracking-[0.14em] text-cyan-200",children:n.label}),e("span",{className:"h-px flex-1 bg-white/15"}),n.totalPoints>0&&t("span",{className:"flex-none text-[11px] font-bold text-white/75",children:[n.totalPoints," điểm"]})]}),n.parts.map((t,a)=>e(d,{part:t,showSkill:!1},t.id||`${n.key}-${a}`))]},n.key))})})]}):W>0&&t("div",{className:"mt-1.5 flex shrink-0 items-center gap-3 rounded-xl bg-[#0000001c] px-3 py-2.5",children:[e("span",{className:"flex h-9 w-9 flex-none items-center justify-center rounded-full bg-[#00000021] text-white",children:e(c,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-bold text-white md:text-base",children:"Điểm tối thiểu cần đạt"}),t("span",{className:"ml-auto text-sm font-black text-yellow-300 md:text-lg",children:[W,"/",L]})]})]}),e("div",{className:"relative hidden flex-[0_0_42%] md:block",children:e("div",{className:"absolute left-0 top-[4%] z-20 max-w-[60%]",children:t("div",{className:"relative rounded-2xl bg-white px-3 py-2 text-center text-[11px] font-semibold text-sky-900 shadow-xl ring-2 ring-sky-200 md:text-xs",children:["Cùng mình khám phá trình độ của bạn nhé!",e("span",{className:"absolute -bottom-1.5 right-6 h-3 w-3 rotate-45 bg-white ring-2 ring-sky-200"})]})})})]}),e("div",{className:"pointer-events-none absolute inset-x-[9%] bottom-[6%] z-20 flex justify-center",children:e("div",{className:"pointer-events-auto",children:e(N,{onClick:f,isStarting:k,showCountdown:_,autoStartCountdown:C})})})]})]})}),t("button",{type:"button",onClick:()=>$(!0),"aria-label":"Câu hỏi thường gặp",className:"group fixed bottom-5 right-5 z-40 inline-flex cursor-pointer items-center gap-2 rounded-full bg-gradient-to-b from-cyan-300 via-sky-500 to-sky-700 px-4 py-3 text-sm font-bold text-white shadow-[0_6px_0_0_#0c4a6e,0_10px_22px_rgba(14,165,233,0.45)] ring-2 ring-cyan-200/50 transition-all duration-150 hover:-translate-y-0.5 hover:brightness-110 active:translate-y-1 active:shadow-[0_1px_0_0_#0c4a6e,0_3px_8px_rgba(14,165,233,0.3)]",children:[e(o,{className:"h-5 w-5",strokeWidth:2.5}),e("span",{className:"hidden sm:inline",style:{textShadow:"0 1px 0 rgba(12,74,110,0.5)"},children:"Câu hỏi thường gặp"})]}),T&&t("div",{className:"fixed inset-0 z-[60] flex items-center justify-center p-4",role:"dialog","aria-modal":"true","aria-label":"Câu hỏi thường gặp",children:[e("div",{className:"absolute inset-0 bg-blue-950/70 backdrop-blur-sm",onClick:()=>$(!1)}),t("div",{className:"relative z-10 flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-3xl bg-gradient-to-br from-cyan-300/20 via-white/5 to-white/0 p-px shadow-[0_20px_60px_-15px_rgba(10,75,140,0.7)] backdrop-blur-xl",children:[e("div",{className:"pointer-events-none absolute -left-12 -top-12 h-40 w-40 rounded-full bg-cyan-400/30 blur-3xl"}),e("div",{className:"pointer-events-none absolute -right-12 -bottom-12 h-40 w-40 rounded-full bg-sky-500/25 blur-3xl"}),t("div",{className:"relative flex max-h-[85vh] flex-col overflow-hidden rounded-[calc(1.5rem-1px)] bg-gradient-to-b from-[#0e3d70]/95 via-[#0a4b8c]/95 to-[#0a3866]/95 ring-1 ring-cyan-300/20",children:[t("div",{className:"flex items-center gap-3 px-6 py-5",children:[e("div",{className:"flex h-12 w-12 flex-none items-center justify-center rounded-full bg-gradient-to-br from-cyan-300 to-sky-600 shadow-[0_6px_18px_-4px_rgba(34,211,238,0.6)] ring-4 ring-cyan-300/20",children:e(o,{className:"h-6 w-6 text-white",strokeWidth:2.5})}),t("div",{className:"flex-1",children:[e("h2",{className:"text-lg font-extrabold tracking-tight text-white drop-shadow-md",children:"Câu hỏi thường gặp"}),e("p",{className:"mt-0.5 text-xs font-medium text-cyan-100/70",children:"Những điều cần biết trước khi làm bài"})]}),e("button",{type:"button",onClick:()=>$(!1),"aria-label":"Đóng",className:"flex h-9 w-9 flex-none cursor-pointer items-center justify-center rounded-full bg-white/10 text-white/80 ring-1 ring-white/15 transition-all duration-150 hover:bg-white/20 hover:text-white",children:e(m,{className:"h-5 w-5"})})]}),e("div",{className:"mx-6 h-px bg-gradient-to-r from-transparent via-cyan-300/25 to-transparent"}),e("div",{className:"flex-1 overflow-y-auto px-4 py-4 sm:px-6",children:e("ul",{className:"space-y-2",children:w.map((n,a)=>{const i=O===a;return t("li",{className:"overflow-hidden rounded-2xl ring-1 transition-colors duration-200 "+(i?"bg-white/[0.08] ring-cyan-300/30":"bg-white/[0.04] ring-white/10 hover:bg-white/[0.06]"),children:[t("button",{type:"button",onClick:()=>R(i?null:a),className:"flex w-full cursor-pointer items-center gap-3 px-4 py-3 text-left","aria-expanded":i,children:[e("span",{className:"flex h-7 w-7 flex-none items-center justify-center rounded-full text-xs font-black transition-colors "+(i?"bg-gradient-to-br from-yellow-300 to-orange-500 text-white":"bg-white/10 text-cyan-100"),children:a+1}),e("span",{className:"flex-1 text-sm font-bold text-white",children:n.q}),e(h,{className:"h-5 w-5 flex-none text-cyan-200 transition-transform duration-200 "+(i?"rotate-180":"")})]}),e("div",{className:"grid transition-all duration-200 "+(i?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0"),children:e("div",{className:"overflow-hidden",children:e("p",{className:"px-4 pb-4 pl-14 text-sm leading-relaxed text-cyan-50/90",children:n.a})})})]},a)})})}),e("div",{className:"border-t border-white/10 bg-white/[0.03] px-6 py-3 text-center text-xs text-cyan-100/60",children:"Cần hỗ trợ thêm? Liên hệ trung tâm Ocean Edu để được giải đáp."})]})]})]})]})}function y({icon:n,value:a,label:i}){return t("div",{className:"flex items-center justify-center gap-2 rounded-2xl bg-[#0000001c] px-2 py-2",children:[e("span",{className:"flex h-8 w-8 flex-none items-center justify-center rounded-full bg-[#00bdff1a] text-white md:h-9 md:w-9",children:n}),t("div",{className:"flex flex-col items-start leading-tight",children:[e("div",{className:"text-xl font-black text-white md:text-2xl",children:a}),e("div",{className:"text-[11px] font-bold text-white/90 md:text-xs",children:i})]})]})}function N({onClick:n,isStarting:l,showCountdown:r,autoStartCountdown:s}){return r?e("div",{className:"inline-flex h-14 w-48 items-center justify-center rounded-full bg-yellow-400 text-2xl font-black text-[#1a3a6e]",children:s}):t("button",{onClick:n,disabled:l,className:"group relative inline-flex cursor-pointer items-center gap-3 rounded-full bg-gradient-to-b from-[#ffd54a] via-[#ffb733] to-[#ff8a1f] py-2.5 pl-8 pr-10 shadow-[0_6px_0_0_#c46410,0_10px_18px_rgba(0,0,0,0.4)] ring-2 ring-orange-300/60 transition-all duration-150 hover:-translate-y-0.5 hover:brightness-110 hover:shadow-[0_8px_0_0_#c46410,0_14px_22px_rgba(0,0,0,0.45)] active:translate-y-1.5 active:shadow-[0_1px_0_0_#c46410,0_2px_6px_rgba(0,0,0,0.3)] disabled:cursor-not-allowed disabled:opacity-70",children:[l?e(i,{className:"h-7 w-7 animate-spin text-white"}):e(a,{src:f,alt:"",width:36,height:36,unoptimized:!0}),e("span",{className:"text-xl font-black text-white",style:{color:"#685030"},children:"Bắt đầu"})]})}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StudentExamPartSummary } from '../../../../shared/types/student.types';
|
|
2
|
+
export type PartCategoryGroup = {
|
|
3
|
+
/** Uppercase key used for React keys / de-duping */
|
|
4
|
+
key: string;
|
|
5
|
+
/** Display label, e.g. "Reading & Writing" */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Sum of points across parts in this category */
|
|
8
|
+
totalPoints: number;
|
|
9
|
+
parts: StudentExamPartSummary[];
|
|
10
|
+
};
|
|
11
|
+
/** Groups parts by their `category` (falling back to skill), preserving first-seen order. */
|
|
12
|
+
export declare function groupPartsByCategory(parts: StudentExamPartSummary[]): PartCategoryGroup[];
|
|
13
|
+
export declare function PartRow({ part, showSkill, }: {
|
|
14
|
+
part: StudentExamPartSummary;
|
|
15
|
+
index?: number;
|
|
16
|
+
/** Hide the inline skill label when the parent already shows a category header. */
|
|
17
|
+
showSkill?: boolean;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{BookOpen as n,Mic as a,Headphones as s,PenLine as i,MessageSquareText as r}from"lucide-react";const o={READING:{label:"Reading",Icon:n,iconWrap:"bg-emerald-400/20 text-emerald-200 ring-emerald-300/30"},WRITING:{label:"Writing",Icon:i,iconWrap:"bg-orange-400/20 text-orange-200 ring-orange-300/30"},LISTENING:{label:"Listening",Icon:s,iconWrap:"bg-sky-400/20 text-sky-200 ring-sky-300/30"},SPEAKING:{label:"Speaking",Icon:a,iconWrap:"bg-fuchsia-400/20 text-fuchsia-200 ring-fuchsia-300/30"}},l={label:"",Icon:r,iconWrap:"bg-white/15 text-white ring-white/20"};function c(e){const t=e?.trim();return t?t.replace(/_/g," ").toLowerCase().replace(/\band\b/g,"&").replace(/\s+/g," ").trim().replace(/\b\w/g,e=>e.toUpperCase()):"Khác"}export function groupPartsByCategory(e){const t=[],n=new Map;for(const a of e){const e=a.category||a.skill||"OTHER",s=e.toUpperCase();let i=n.get(s);i||(i={key:s,label:c(e),totalPoints:0,parts:[]},n.set(s,i),t.push(s)),i.parts.push(a),a.points>0&&(i.totalPoints+=a.points)}return t.map(e=>n.get(e))}export function PartRow({part:n,showSkill:a=!0}){const s=function(e){const t=(e.skill||"").toUpperCase();if(o[t])return o[t];const n=`${e.skill??""} ${e.category??""}`.toUpperCase();for(const e of Object.keys(o))if(n.includes(e))return o[e];return l}(n),{Icon:i}=s,r=s.label,c=n.questionCount>0?`${n.questionCount} câu`:"";return t("div",{className:"flex items-center gap-3 rounded-xl bg-white/[0.06] px-3 py-1.5 ring-1 ring-white/10 transition-colors hover:bg-white/[0.1]",children:[e("span",{className:`flex h-8 w-8 flex-none items-center justify-center rounded-full ring-1 ${s.iconWrap}`,children:e(i,{className:"h-4 w-4",strokeWidth:2.2})}),t("div",{className:"min-w-0 flex-1 truncate text-sm leading-tight",children:[e("span",{className:"font-bold text-white",children:n.name}),a&&r&&t("span",{className:"font-semibold text-white/75",children:[" · ",r]}),c&&t("span",{className:"font-medium text-white/90",children:[" · ",c]})]}),n.points>0&&t("div",{className:"flex flex-none items-baseline gap-1",children:[e("span",{className:"text-base font-black text-yellow-300",children:n.points}),e("span",{className:"text-[10px] font-bold uppercase tracking-wide text-yellow-100",children:"điểm"})]})]})}
|
|
@@ -1 +1,4 @@
|
|
|
1
1
|
export { ThemedWaitingRoom } from './ThemedWaitingRoom';
|
|
2
|
+
export { CambridgeYleWaitingRoom } from './CambridgeYleWaitingRoom';
|
|
3
|
+
export { PartRow, groupPartsByCategory } from './cambridge-yle-waiting-parts';
|
|
4
|
+
export type { PartCategoryGroup } from './cambridge-yle-waiting-parts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{ThemedWaitingRoom}from"./ThemedWaitingRoom";
|
|
1
|
+
export{ThemedWaitingRoom}from"./ThemedWaitingRoom";export{CambridgeYleWaitingRoom}from"./CambridgeYleWaitingRoom";export{PartRow,groupPartsByCategory}from"./cambridge-yle-waiting-parts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as a,useEffect as s,useMemo as i}from"react";import{Textarea as d}from"../../../../components/ui/textarea";import{cn as l}from"../../../../shared/lib/utils";import{FileText as
|
|
1
|
+
"use client";import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useState as a,useEffect as s,useMemo as i}from"react";import{Textarea as d}from"../../../../components/ui/textarea";import{cn as l}from"../../../../shared/lib/utils";import{HtmlOrText as n}from"../../../../shared/lib/html-content";import{FileText as o,PenLine as m,Check as c,AlertCircle as g,BookOpen as h,Lightbulb as b,ImageIcon as x}from"lucide-react";import{usePresignedFileUrl as f}from"../../../../shared/lib/hooks/usePresignedFileUrl";function u({imageKey:t}){const{previewUrl:a}=f(t);return e("div",a?{className:"mx-auto w-full max-w-sm overflow-hidden rounded-lg border border-gray-200 bg-white shadow-sm",children:e("img",{src:a,alt:"Ảnh hướng dẫn",className:"h-auto w-full object-contain",onError:e=>{e.target.src="/images/placeholder-image.svg"}})}:{className:"flex aspect-[4/3] w-full items-center justify-center rounded-lg border border-gray-200 bg-gray-50",children:r("div",{className:"flex flex-col items-center gap-2 text-gray-400",children:[e(x,{className:"h-8 w-8"}),e("span",{className:"text-xs",children:"Đang tải..."})]})})}export function WriteAShortLetterClient({questionData:f,onSubmit:p,isReviewMode:v=!1,userAnswer:w,explanation:N}){const{informations:y,minWords:j,maxWords:k,instructions:B,guideImages:$}=f,C=B?.mainInstruction||"",[T,M]=a("string"==typeof w?w:"");s(()=>{void 0!==w&&"string"==typeof w&&M(w)},[w]);const W=i(()=>{const e="string"==typeof T?T:"";return e.trim()?e.trim().split(/\s+/).filter(e=>e.length>0).length:0},[T]),q=i(()=>!(W<j)&&!(k&&W>k),[W,j,k]),A=i(()=>k&&W>k,[W,k]),F=i(()=>{const e=j;return Math.min(W/e*100,100)},[W,j]);return r("div",{className:"space-y-5",children:[C&&e("div",{className:"overflow-hidden rounded-xl border border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50 shadow-sm",children:r("div",{className:"flex items-center gap-3 px-5 py-4",children:[e("div",{className:"flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-blue-500 to-indigo-600 text-white shadow-sm",children:e(h,{className:"h-5 w-5"})}),r("div",{children:[e("h3",{className:"text-sm font-semibold text-blue-900",children:"Hướng dẫn"}),e(n,{value:C,className:"text-sm text-blue-700"})]})]})}),$&&$.length>0&&r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-violet-500 to-purple-600 text-white shadow-sm",children:e(x,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Ảnh hướng dẫn"})]}),e("div",{className:"p-5",children:e("div",{className:"flex flex-col gap-4",children:$.map((r,t)=>e(u,{imageKey:r},`${r}-${t}`))})})]}),y&&y.filter(e=>e?.trim()).length>0&&r("div",{className:"overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm",children:[r("div",{className:"flex items-center gap-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white px-5 py-3",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-emerald-500 to-teal-600 text-white shadow-sm",children:e(o,{className:"h-4 w-4"})}),r("span",{className:"text-sm font-medium text-gray-700",children:["Thông tin cần bao gồm (",y.length,")"]})]}),e("div",{className:"p-5",children:e("div",{className:"space-y-3",children:y.filter(e=>e?.trim()).map((t,a)=>r("div",{className:"flex items-start gap-3 rounded-lg border border-gray-100 bg-gradient-to-r from-white to-gray-50 p-3 transition-all hover:border-gray-200 hover:shadow-sm",children:[e("div",{className:"flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-emerald-400 to-teal-500 text-xs font-bold text-white shadow-sm",children:a+1}),e(n,{value:t,className:"text-sm text-gray-700 leading-relaxed pt-0.5"})]},a))})})]}),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-purple-500 to-violet-600 text-white shadow-sm",children:e(m,{className:"h-4 w-4"})}),e("span",{className:"text-sm font-medium text-gray-700",children:"Viết thư của bạn"})]}),r("div",{className:l("flex items-center gap-2 rounded-full px-3 py-1.5 text-xs font-semibold transition-all",A?"bg-red-100 text-red-700":q?"bg-green-100 text-green-700":"bg-amber-100 text-amber-700"),children:[q&&!A&&e(c,{className:"h-3.5 w-3.5"}),A&&e(g,{className:"h-3.5 w-3.5"}),r("span",{children:[W," / ",j,k?` - ${k}`:"+"," từ"]})]})]}),r("div",{className:"p-5 space-y-4",children:[!v&&r("div",{className:"space-y-2",children:[r("div",{className:"flex items-center justify-between text-xs text-gray-500",children:[e("span",{children:"Tiến độ viết"}),r("span",{children:[Math.round(F),"%"]})]}),e("div",{className:"h-2 w-full overflow-hidden rounded-full bg-gray-100",children:e("div",{className:l("h-full transition-all duration-300 ease-out rounded-full",A?"bg-gradient-to-r from-red-400 to-rose-500":q?"bg-gradient-to-r from-green-400 to-emerald-500":"bg-gradient-to-r from-amber-400 to-orange-500"),style:{width:`${F}%`}})})]}),r("div",{className:"relative",children:[e(d,{id:"writing-answer",value:T,onChange:e=>{return r=e.target.value,void(v||(M(r),p?.(r)));var r},placeholder:"Bắt đầu viết thư của bạn tại đây...",className:l("min-h-[280px] resize-none rounded-xl border-2 p-4 text-base leading-relaxed transition-all","focus:ring-2 focus:ring-offset-1",v?"bg-gray-50 cursor-not-allowed":"bg-white hover:border-gray-300",A?"border-red-300 focus:border-red-400 focus:ring-red-100":q?"border-green-300 focus:border-green-400 focus:ring-green-100":"border-gray-200 focus:border-purple-400 focus:ring-purple-100"),rows:12,disabled:v}),e("div",{className:"absolute bottom-3 right-3 pointer-events-none",children:e("div",{className:"flex items-center gap-1 text-gray-300",children:e(m,{className:"h-4 w-4"})})})]}),!v&&e("div",{className:l("rounded-xl border p-4 transition-all",A?"border-red-200 bg-gradient-to-r from-red-50 to-rose-50":q?"border-green-200 bg-gradient-to-r from-green-50 to-emerald-50":"border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50"),children:r("div",{className:"flex items-start gap-3",children:[e("div",{className:l("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-white shadow-sm",A?"bg-gradient-to-br from-red-500 to-rose-600":q?"bg-gradient-to-br from-green-500 to-emerald-600":"bg-gradient-to-br from-amber-500 to-orange-600"),children:e(A?g:q?c:g,{className:"h-4 w-4"})}),r("div",{className:"flex-1",children:[e("p",{className:l("text-sm font-semibold",A?"text-red-800":q?"text-green-800":"text-amber-800"),children:A?"Vượt quá số từ cho phép!":q?"Tuyệt vời! Đã đủ số từ yêu cầu":"Chưa đủ số từ yêu cầu"}),e("p",{className:l("text-xs mt-0.5",A?"text-red-600":q?"text-green-600":"text-amber-600"),children:r(t,A?{children:["Bạn đã viết ",W," từ. Tối đa ",k," từ."]}:q?{children:["Bạn đã viết ",W," từ. Yêu cầu: ",j,k?` - ${k}`:"+"," từ."]}:{children:["Bạn đã viết ",W," từ. Cần ít nhất ",j," từ."]})})]})]})}),v&&T&&r("div",{className:"rounded-xl border border-gray-200 bg-gradient-to-r from-slate-50 to-gray-50 p-4",children:[r("div",{className:"flex items-center gap-2 mb-3 pb-3 border-b border-gray-200",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-lg bg-gray-200",children:e(o,{className:"h-3.5 w-3.5 text-gray-600"})}),e("span",{className:"text-sm font-medium text-gray-600",children:"Bài viết đã nộp"}),r("span",{className:l("ml-auto text-xs font-semibold px-2 py-1 rounded-full",q?"bg-green-100 text-green-700":"bg-amber-100 text-amber-700"),children:[W," từ"]})]}),e("p",{className:"text-sm text-gray-700 whitespace-pre-wrap leading-relaxed",children:T})]}),v&&N&&e("div",{className:"rounded-xl bg-gradient-to-r from-blue-50 to-indigo-50 p-4 border border-blue-200",children:r("div",{className:"flex items-start gap-3",children:[e("div",{className:"flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-blue-500 text-white",children:e(b,{className:"h-3.5 w-3.5"})}),r("div",{className:"flex-1",children:[e("span",{className:"text-xs font-semibold text-blue-700 uppercase tracking-wider",children:"Giải thích"}),e("p",{className:"mt-1 text-sm text-gray-700 leading-relaxed",children:N})]})]})})]})]})]})}
|
|
@@ -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 l from"./assets/images/phao.png";import a from"./assets/images/sanho.png";import n from"./assets/images/sao.png";import i from"./assets/images/vooc.png";const o=[l,a,n,i];export function CambridgeYleSidebar({parts:l,questions:a,currentQuestionGlobalIndex:n,onPartClick:i,onQuestionClick:d,isNavDisabled:c,className:p}){const m=a[n],h=m?m.partIndex:0;return t("div",{className:r("flex flex-col w-full h-full pb-4",p),children:[t("div",{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:l.map((a,n)=>{const d=n===h,p=o[n%o.length],m=n>0?l[n-1].category:null,b=a.category&&a.category!==m;return t("div",{className:"flex flex-col",children:[b&&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:a.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>i(n),disabled:c,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",d?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",d||c?"":"hover:border-blue-200",c?"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:p,alt:`part icon ${n}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:a.name||`Part ${a.partNo}`})]}),t("span",{className:r("text-[13px] font-bold tracking-wide",d?"text-blue-100":"text-blue-900/60"),children:[a.answeredCount,"/",a.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:a.map(t=>{const s=t.globalIndex===n,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||c||(a+=" hover:shadow-md hover:text-blue-600"),a+=c?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{type:"button",onClick:()=>d(t.globalIndex),disabled:c,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 s from"next/image";import l from"./assets/images/phao.png";import a from"./assets/images/sanho.png";import n from"./assets/images/sao.png";import i from"./assets/images/vooc.png";const o=[l,a,n,i];export function CambridgeYleSidebar({parts:l,questions:a,currentQuestionGlobalIndex:n,onPartClick:i,onQuestionClick:d,isNavDisabled:c,className:p}){const m=a[n],h=m?m.partIndex:0;return t("div",{className:r("flex flex-col w-full h-full pb-4",p),children:[t("div",{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:l.map((a,n)=>{const d=n===h,p=o[n%o.length],m=n>0?l[n-1].category:null,b=a.category&&a.category!==m;return t("div",{className:"flex flex-col",children:[b&&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:a.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>i(n),disabled:c,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",d?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",d||c?"":"hover:border-blue-200",c?"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:p,alt:`part icon ${n}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:a.name||`Part ${a.partNo}`})]}),t("div",{className:"flex items-center gap-2 shrink-0",children:[null!=a.points&&a.points>0&&t("span",{className:r("text-[12px] font-black tracking-wide whitespace-nowrap",d?"text-yellow-200":"text-amber-500"),children:[a.points," điểm"]}),t("span",{className:r("text-[13px] font-bold tracking-wide",d?"text-blue-100":"text-blue-900/60"),children:[a.answeredCount,"/",a.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:a.map(t=>{const s=t.globalIndex===n,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||c||(a+=" hover:shadow-md hover:text-blue-600"),a+=c?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{type:"button",onClick:()=>d(t.globalIndex),disabled:c,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 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useMemo as t}from"react";import{ResolvedImage as r}from"../../../components/common/ResolvedImage";import{cn as a}from"../../../shared/lib/utils";import{transformAnswerTheQuestion as
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useMemo as t}from"react";import{ResolvedImage as r}from"../../../components/common/ResolvedImage";import{cn as a}from"../../../shared/lib/utils";import{transformAnswerTheQuestion as i}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as n}from"./english-cert-scroll";export function EcAnswerTheQuestion({part:l,answers:o,onAnswerChange:d,isReviewMode:c=!1}){const{questions:m,instruction:x,imageUrl:p,title:f,groupContent:u}=t(()=>i(l.questions),[l.questions]);return s("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}),p&&e("div",{className:"flex items-center justify-center",children:e(r,{src:p,alt:f||"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-3",children:m.map(t=>{const i=o[t.id]?.answer??t.exampleAnswer??"";return e("div",{id:n(t.id),className:a("scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",t.isExample&&"opacity-90"),children:s("div",{className:"flex items-start gap-3",children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:t.questionNumber}),s("div",{className:"min-w-0 flex-1 space-y-2",children:[t.imageUrl&&e(r,{src:t.imageUrl,alt:`Question ${t.questionNumber}`,className:"max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:t.question}),s("div",{className:"flex flex-wrap items-center gap-2",children:[t.prefixText&&e("span",{className:"text-sm text-[#64748b]",children:t.prefixText}),t.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:t.exampleAnswer}):e("input",{type:"text",value:i,disabled:c,placeholder:"Nhập câu trả lời…",onChange:e=>{return s=t.id,r=e.target.value,void d(s,{answer:r});var s,r},className:a("min-w-[200px] flex-1 rounded-lg border-2 border-[#9cc4f5] bg-white px-3 py-2 text-sm font-medium text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",c&&"cursor-not-allowed opacity-70")}),t.suffixText&&e("span",{className:"text-sm text-[#64748b]",children:t.suffixText})]}),t.suggestedAnswers&&t.suggestedAnswers.length>0&&e("div",{className:"flex flex-wrap gap-1.5",children:t.suggestedAnswers.map((s,r)=>e("span",{className:"rounded-full border border-[#e2ecf8] bg-[#f4f9ff] px-2.5 py-0.5 text-xs text-[#0b57d0]",children:s},`${t.id}-sa-${r}`))})]})]})},t.id)})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as n}from"../../../components/common/ResolvedImage";import{cn as s}from"../../../shared/lib/utils";import{transformMatchByWritingAnswer as a}from"../../../components/exams/take/exam-taking.utils";const
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as n}from"../../../components/common/ResolvedImage";import{cn as s}from"../../../shared/lib/utils";import{transformMatchByWritingAnswer as a}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as o}from"./english-cert-scroll";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),d={empty:"bg-[#eef3fb] text-[#94a3b8] border border-[#dbe5f2]",filled:"bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-white border border-transparent",correct:"bg-[#16a34a] text-white border border-transparent",wrong:"bg-[#ef4444] text-white border border-transparent"};function l({letter:t,tone:r}){return e("span",{className:s("flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-base font-bold transition-colors",d[r]),children:t||"—"})}export function EcMatchByWritingAnswer({part:d,answers:c,onAnswerChange:m,isReviewMode:f=!1}){const{questions:b,options:p,instruction:x,groupImageUrl:u}=r(()=>a(d.questions),[d.questions]),g=r(()=>{const e=new Map;return p.forEach((t,r)=>{e.set(t.answer,i[r]??String(r+1))}),e},[p]),h=e=>c[e.id]?.answer??e.exampleAnswer??"",w=r(()=>{const e=new Set;return b.forEach(t=>{const r=h(t),n=g.get(r);n&&e.add(n)}),e},[b,c,g]);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}),u&&e("div",{className:"flex items-center justify-center",children:e(n,{src:u,alt:"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),p.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"ANSWER OPTIONS"}),e("div",{className:"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2",children:p.map((r,a)=>{const o=i[a]??String(a+1),d=!f&&w.has(o);return t("div",{className:s("flex items-start gap-2.5 rounded-xl border border-[#e2ecf8] bg-[#f4f9ff] px-3 py-2 transition-opacity",d&&"opacity-50"),children:[t("span",{className:"relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:[o,d&&e("span",{className:"absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-[#16a34a] text-[8px] text-white",children:"✓"})]}),t("div",{className:"min-w-0 text-sm text-[#0f1730]",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:r.answer,className:"mb-1 max-h-24 w-auto rounded object-contain"}),e("span",{className:"font-medium",children:r.content||r.answer})]})]},`${r.answer}-${a}`)})})]}),e("div",{className:"flex flex-col gap-3",children:b.map(r=>{const a=h(r),d=g.get(a)??"",c=f&&r.isExample?a===(r.exampleAnswer??""):void 0,b=!0===c?"border-[#bbf7d0] bg-[#f0fdf4]":!1===c?"border-[#fecaca] bg-[#fef2f2]":"border-[#d9e4f2] bg-white/90",x=!0===c?"correct":!1===c?"wrong":d?"filled":"empty";return t("div",{id:o(r.id),className:s("scroll-mt-24 flex items-center gap-3 rounded-xl border p-3 shadow-sm transition-colors",b,r.isExample&&"opacity-90"),children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:r.questionNumber}),t("div",{className:"min-w-0 flex-1",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:`Question ${r.questionNumber}`,className:"mb-2 max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:r.question})]}),t("div",{className:"flex shrink-0 items-center gap-2",children:[e(l,{letter:d,tone:x}),r.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:r.exampleAnswer}):t("select",{value:a,disabled:f,onChange:e=>{return t=r.id,n=e.target.value,void m(t,{answer:n});var t,n},className:s("h-9 min-w-[150px] rounded-lg border-2 border-[#9cc4f5] bg-white px-3 text-sm font-semibold text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",f&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"—"}),p.map((t,n)=>{const s=i[n]??String(n+1),a=t.content||t.answer;return e("option",{value:t.answer,children:a?`${s} — ${a}`:s},`${r.id}-${n}`)})]})]})]},r.id)})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as n}from"../../../shared/lib/utils";import{transformWordFillParagraph as o}from"../../../components/exams/take/exam-taking.utils";export function EcWordFillParagraph({part:
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as n}from"../../../shared/lib/utils";import{transformWordFillParagraph as o}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as l}from"./english-cert-scroll";export function EcWordFillParagraph({part:s,answers:i,onAnswerChange:d,isReviewMode:c=!1}){const m=r(()=>o(s.questions),[s.questions]),{questionId:p,paragraph:x,title:b,imageUrl:f,wordBank:h,viewMode:u,instruction:g}=m,w=i[p]||[],N=r(()=>x.split(/(\{\d+\})/),[x]),v="WITH_WORD_BANK"===u,y=new Set(w.filter(Boolean)),_=(e,t)=>{if(c)return;const r=[...w];r[e]=t,d(p,r)};return t("div",{id:l(p),className:"scroll-mt-24 flex flex-col gap-4",children:[g&&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:g}),f&&e("div",{className:"flex items-center justify-center",children:e(a,{src:f,alt:b||"Illustration",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),v&&h.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Word bank"}),e("div",{className:"mt-2 flex flex-wrap gap-2",children:h.map((t,r)=>{const a=y.has(t.word);return e("span",{className:n("rounded-full border px-3 py-1 text-sm font-semibold transition-all",t.isExample?"border-[#b9edc8] bg-[#ddf8e7] text-[#15803d]":a?"border-[#d9e4f2] bg-[#f4f9ff] text-[#94a3b8] line-through":"border-[#9cc4f5] bg-white text-[#0b57d0]"),children:t.word},`${t.word}-${r}`)})})]}),e("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-5 text-base leading-loose text-[#0f1730] shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:N.map((r,a)=>{const o=r.match(/^\{(\d+)\}$/);if(!o)return e("span",{children:r},a);const l=parseInt(o[1],10),s=w[l]||"";return t("span",v?{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",l+1,")"]}),t("select",{value:s,disabled:c,onChange:e=>_(l,e.target.value),className:n("rounded-lg border-2 px-2 py-1 text-sm font-semibold outline-none transition-all",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",c&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"———"}),h.filter(e=>!e.isExample).map((t,r)=>e("option",{value:t.word,children:t.word},`${l}-${r}`))]})]}:{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",l+1,")"]}),e("input",{type:"text",value:s,disabled:c,placeholder:"···",onChange:e=>_(l,e.target.value),style:{width:`${Math.max(4,s.length+1)}ch`},className:n("inline-block min-w-[4ch] max-w-[16ch] border-b-2 bg-transparent px-1 text-center text-sm font-semibold outline-none transition-colors",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",c&&"cursor-not-allowed opacity-70")})]},a)})})]})}
|
|
@@ -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
|
|
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 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ListChecks as s,PenLine as l,CheckCircle2 as a,AlertCircle as d}from"lucide-react";import{ResolvedImage as i}from"../../../components/common/ResolvedImage";import{HtmlOrText as o}from"../../../shared/lib/html-content";import{cn as n}from"../../../shared/lib/utils";import{transformWriteShortLetter as c}from"../../../components/exams/take/utils/question-transformers";import{englishCertQuestionDomId as m}from"./english-cert-scroll";export function EcWritingTask({part:f,answers:x,onAnswerChange:p,isReviewMode:u=!1}){const b=f.questions[0],h=r(()=>b?c(b):null,[b]),g=h?.minWords,w=h?.maxWords,v=b&&x[b.id]||"",N=function(e){const t=e.trim();return t?t.split(/\s+/).length:0}(v),y=r(()=>{if(g&&N<g){const e=g-N;return{text:`Add ${e} more word${1===e?"":"s"} to reach the minimum`,ok:!1}}if(w&&N>w){const e=N-w;return{text:`${e} word${1===e?"":"s"} over the maximum limit`,ok:!1}}return g||w?{text:"Word count requirement met",ok:!0}:null},[N,g,w]);if(!b||!h)return null;const{prompt:k,requirements:$,guideImages:j}=h,W=(!g||N>=g)&&(!w||N<=w),_=w||g||0,q=_?Math.min(100,Math.round(N/_*100)):0;return t("div",{id:m(b.id),className:"scroll-mt-24 flex flex-col gap-5",children:[t("div",{className:"flex flex-col gap-5",children:[t("div",{className:"overflow-hidden rounded-2xl border border-[#cfe0f7] bg-white shadow-[0_18px_40px_rgba(13,71,161,0.10)]",children:[k&&e(o,{value:k,as:"div",className:"whitespace-pre-line px-5 pb-4 pt-5 text-base leading-relaxed text-[#0f1730]"}),$&&$.length>0&&e("div",{className:n("px-5 pb-4",!k&&"pt-5"),children:t("div",{className:"rounded-xl border border-[#e3edfb] bg-[#f6faff] p-4",children:[t("div",{className:"flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-wider text-[#0b57d0]",children:[e(s,{className:"h-3.5 w-3.5"}),"Requirements"]}),e("ul",{className:"mt-2 list-inside list-disc space-y-1.5 text-sm text-[#0f1730]",children:$.map((t,r)=>e("li",{children:e(o,{value:t,as:"span"})},r))})]})}),g&&t("div",{className:"border-t border-[#e3edfb] bg-[#f9fbfe] px-5 py-3 text-sm font-semibold text-[#0f1730]",children:["Write at least ",g," words."]})]}),j&&j.length>0&&e("div",{className:"flex flex-col items-center justify-center gap-4 rounded-2xl border border-[#d9e4f2] bg-white/60 p-4",children:j.map((t,r)=>e(i,{src:t,alt:`Guide ${r+1}`,className:"w-full max-w-3xl rounded-xl bg-white object-contain shadow-sm"},r))})]}),t("div",{className:"overflow-hidden rounded-2xl border border-[#cfe0f7] bg-white shadow-[0_18px_40px_rgba(13,71,161,0.10)]",children:[t("div",{className:"flex items-center gap-1.5 border-b border-[#e3edfb] bg-[#f6faff] px-4 py-2.5 text-xs font-bold uppercase tracking-wider text-[#0b57d0]",children:[e(l,{className:"h-3.5 w-3.5"}),"Your answer"]}),e("textarea",{value:v,disabled:u,placeholder:"Write your essay here…",onChange:e=>p(b.id,e.target.value),rows:14,className:n("w-full resize-y border-0 bg-white px-5 py-4 text-sm leading-relaxed text-[#0f1730] outline-none transition-all placeholder:text-[#9aa9c2] focus:bg-[#fbfdff]",u&&"cursor-not-allowed opacity-80")}),t("div",{className:"flex flex-col gap-2 border-t border-[#e3edfb] bg-[#f9fbfe] px-4 py-3",children:[t("div",{className:"flex items-center justify-between text-xs",children:[t("span",{className:n("inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 font-semibold",W?"bg-[#ddf8e7] text-[#15803d]":"bg-[#fde8e8] text-[#ef4444]"),children:[N," words"]}),(g||w)&&t("span",{className:"font-medium text-[#64748b]",children:[g?`Min ${g}`:"",g&&w?" · ":"",w?`Max ${w}`:""]})]}),_>0&&e("div",{className:"h-1.5 w-full overflow-hidden rounded-full bg-[#e3edfb]",children:e("div",{className:n("h-full rounded-full transition-all",W?"bg-[#15803d]":"bg-[#1167e8]"),style:{width:`${q}%`}})}),y&&t("div",{className:n("flex items-center gap-1.5 text-xs font-medium",y.ok?"text-[#15803d]":"text-[#64748b]"),children:[y.ok?e(a,{className:"h-3.5 w-3.5 shrink-0"}):e(d,{className:"h-3.5 w-3.5 shrink-0"}),y.text]})]})]})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as i}from"react";import{List as r}from"lucide-react";import{Sheet as o,SheetContent as l,SheetHeader as n,SheetTitle as a}from"../../../components/ui/sheet";import{EnglishCertificationHeader as s}from"./EnglishCertificationHeader";import{EnglishCertificationNavigationPanel as
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useState as i}from"react";import{List as r}from"lucide-react";import{Sheet as o,SheetContent as l,SheetHeader as n,SheetTitle as a}from"../../../components/ui/sheet";import{EnglishCertificationHeader as s}from"./EnglishCertificationHeader";import{EnglishCertificationNavigationPanel as c}from"./EnglishCertificationNavigationPanel";import{EnglishCertificationFooterBar as d}from"./EnglishCertificationFooterBar";import{ENGLISH_CERT_APP_BACKGROUND as h,ENGLISH_CERT_PRIMARY_GRADIENT as m}from"./english-certification-theme";export function EnglishCertificationExamLayout({children:f,headerProps:x,navigationProps:p,footerProps:b}){const[g,u]=i(!0),[w,k]=i(!1),v={...p,onQuestionClick:e=>{p.onQuestionClick(e),k(!1)},onPartClick:e=>{p.onPartClick(e),k(!1)}};return t("div",{className:"flex h-screen flex-col overflow-hidden text-[#0f1730]",style:{background:h},children:[e(s,{...x}),t("div",{className:"flex flex-1 gap-4 overflow-hidden px-4 py-4 lg:px-6",children:[e("main",{id:"exam-main-scroll-area",className:"min-w-0 flex-1 overflow-y-auto",children:f}),g&&t("aside",{className:"hidden w-[360px] shrink-0 flex-col overflow-hidden rounded-xl border border-[#d9e4f2] bg-white/90 shadow-[0_14px_35px_rgba(13,71,161,0.12)] backdrop-blur-md lg:flex","aria-label":"Answer sheet navigation",children:[t("div",{className:"flex h-14 items-center justify-between px-5 text-white",style:{background:m},children:[e("h3",{className:"text-[18px] font-black tracking-[0.1em]",children:"ANSWER SHEET"}),e("button",{type:"button",onClick:()=>u(!1),className:"text-sm font-bold text-white/90 hover:text-white",children:"Hide ≪"})]}),e("div",{className:"flex-1 overflow-hidden",children:e(c,{...v})})]}),!g&&e("button",{type:"button",onClick:()=>u(!0),className:"fixed right-0 top-24 z-30 hidden rounded-l-lg border border-r-0 border-[#d9e4f2] bg-white px-2 py-3 text-sm font-bold text-[#0b57d0] shadow-sm hover:bg-blue-50 lg:block","aria-label":"Show answer sheet",children:"≫"})]}),b&&e(d,{...b}),e("button",{type:"button",onClick:()=>k(!0),className:"fixed bottom-24 right-4 z-30 flex h-12 w-12 items-center justify-center rounded-full text-white shadow-lg lg:hidden",style:{background:m},"aria-label":"Open answer sheet",children:e(r,{className:"h-5 w-5"})}),e(o,{open:w,onOpenChange:k,children:t(l,{side:"bottom",className:"h-[78vh] p-0",children:[e(n,{className:"flex h-14 flex-row items-center px-5 text-white",style:{background:m},children:e(a,{className:"text-[18px] font-black tracking-[0.1em] text-white",children:"ANSWER SHEET"})}),e("div",{className:"h-[calc(78vh-3.5rem)] overflow-hidden",children:e(c,{...v})})]})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{FileText as a,Headphones as t,Info as r}from"lucide-react";import{EnglishCertificationQuestionCard as i}from"./EnglishCertificationQuestionCard";import{EnglishCertificationPassagePanel as n}from"./EnglishCertificationPassagePanel";import{EnglishCertificationReadingSection as l}from"./EnglishCertificationReadingSection";import{EnglishCertificationAudioPlayer as o}from"./EnglishCertificationAudioPlayer";import{ENGLISH_CERT_CONTENT_WIDTH_CLASS as d}from"./english-certification-theme";import{
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{FileText as a,Headphones as t,Info as r}from"lucide-react";import{EnglishCertificationQuestionCard as i}from"./EnglishCertificationQuestionCard";import{EnglishCertificationPassagePanel as n}from"./EnglishCertificationPassagePanel";import{EnglishCertificationReadingSection as l}from"./EnglishCertificationReadingSection";import{EnglishCertificationAudioPlayer as o}from"./EnglishCertificationAudioPlayer";import{ENGLISH_CERT_CONTENT_WIDTH_CLASS as d}from"./english-certification-theme";import{ENGLISH_CERT_STICKY_AUDIO_ATTR as c,englishCertQuestionDomId as p}from"./english-cert-scroll";import{isHtmlContent as g,stripInstruction as m}from"./grouped-question-utils";export function EnglishCertificationGroupedQuestion({part:u,partConfig:f,answers:h,flaggedQuestions:x,onAnswerChange:b,onToggleFlag:w,isReviewMode:N=!1,isListeningPart:v=!1,partAudioUrl:q}){const I=f.startIndex??0,y=function(e,s){const a=e.questions[0];return(a?.questionGroup?.payload?.instructions??(s?.trim()||void 0)??a?.content?.question??"").trim()}(u,u.instructions??f.instructions),_=u.sections?.length?[(()=>{const e=u.questions[0]?.questionGroup?.payload??{},s=e.content??e.passage??"",a=m(s,y),t=e.imageUrl??e.passageImageUrl??"";return{groupId:u.partId,questions:u.questions,passage:a,passageTitle:e.passageTitle??e.title??"",passageSubtitle:e.subtitle??"",passageImageUrl:t,hasPassageContent:Boolean(a.trim())||Boolean(t)}})()]:function(e,s){const a=[],t=new Map;return e.questions.forEach(e=>{const s=e.group_id??e.id;t.has(s)||(t.set(s,[]),a.push(s)),t.get(s).push(e)}),a.map(e=>{const a=t.get(e),r=a[0]?.questionGroup?.payload??{},i=r.content??r.passage??"",n=m(i,s),l=r.imageUrl??r.passageImageUrl??"";return{groupId:e,questions:a,passage:n,passageTitle:r.passageTitle??r.title??"",passageSubtitle:r.subtitle??"",passageImageUrl:l,hasPassageContent:Boolean(n.trim())||Boolean(l)}})}(u,y);if(!_.length)return e("div",{className:"flex h-full items-center justify-center rounded-xl border border-red-200 bg-red-50 p-8 text-red-600",children:"No questions found for this part"});const C=v&&Boolean(q),T=s=>u.sections?.length?e("div",{className:"flex-1 space-y-6 px-4 py-4",children:u.sections.map((a,t)=>{const r=s.questions.filter(e=>{const s=u.questions.indexOf(e);return s>=a.startIndex-I&&s<=a.endIndex-I});return r.length?e(l,{part:u,section:a,questions:r,startIndex:I,answers:h,flaggedQuestions:x,onAnswerChange:b,onToggleFlag:w,isReviewMode:N},`${s.groupId}-section-${t}`):null})}):e("div",{className:"flex-1 space-y-3 px-4 py-4",children:s.questions.map(s=>{const a=u.questions.indexOf(s)+1;return e(i,{question:s,globalQuestionNumber:I+a,answer:h[s.id],isFlagged:x.has(s.id),sharedInstruction:y,onAnswerChange:b,onToggleFlag:w,isReviewMode:N,domId:p(s.id)},s.id)})});return s("div",{className:"flex h-full flex-col gap-6 overflow-y-auto pb-4",children:[C&&e("div",{[c]:"",className:`sticky top-0 z-20 ${d} w-full self-center`,children:e(o,{audioUrl:q,partNumber:u.partNo})}),y&&e("div",{className:`${d} w-full self-center`,children:s("div",{className:"flex items-start gap-3 rounded-xl border border-[#bfd8f8] bg-gradient-to-r from-[#eef5ff] to-[#f7fbff] px-5 py-4 shadow-[0_5px_16px_rgba(13,71,161,0.08)] backdrop-blur-md",children:[e("span",{className:"mt-0.5 grid h-6 w-6 shrink-0 place-items-center rounded-full bg-[#1167e8] text-white",children:e(v?t:r,{className:"h-3.5 w-3.5"})}),s("div",{className:"min-w-0",children:[u.name&&e("div",{className:"mb-1 text-xs font-black uppercase tracking-wide text-[#0b57d0]",children:u.name}),e("p",{className:"text-base font-semibold leading-relaxed text-[#0f1730]",children:y})]})]})}),_.map(t=>{const i=u.questions.indexOf(t.questions[0])+I+1,l=u.questions.indexOf(t.questions[t.questions.length-1])+I+1,o=g(t.passage);return t.hasPassageContent?s("div",{className:"flex flex-col gap-3",children:[e("div",{className:"flex flex-wrap items-center gap-3 rounded-xl border border-[#d9e4f2] bg-white/85 px-4 py-3 shadow-[0_5px_16px_rgba(13,71,161,0.08)] backdrop-blur-md",children:s("div",{className:"flex items-center gap-2.5 rounded-md border border-[#bfd8f8] bg-white/70 px-3 py-1.5 text-base font-bold text-[#0b57d0]",children:[e("span",{className:"grid h-[18px] w-[18px] place-items-center rounded-full bg-[#1167e8] text-white",children:e(r,{className:"h-3 w-3"})}),"Questions ",i,"–",l," refer to the following passage."]})}),s("div",{className:"grid gap-4",style:{gridTemplateColumns:"minmax(0, 1fr) minmax(0, 1fr)"},children:[e("div",{className:"max-h-[calc(100vh-220px)] min-h-0 overflow-y-auto",children:e(n,{passage:t.passage,passageTitle:t.passageTitle,passageSubtitle:t.passageSubtitle,passageImageUrl:t.passageImageUrl,passageIsHtml:o,partName:u.name??""})}),e("section",{className:"flex max-h-[calc(100vh-220px)] min-h-0 flex-col overflow-y-auto rounded-xl border border-[#d9e4f2] bg-white/90 shadow-[0_14px_35px_rgba(13,71,161,0.12)] backdrop-blur-md",children:T(t)})]})]},t.groupId):s("div",{className:`${d} flex w-full flex-col gap-3 self-center`,children:[s("div",{className:"flex items-center gap-4 rounded-xl border border-[#d9e4f2] bg-white/90 px-5 py-4 shadow-[0_5px_16px_rgba(13,71,161,0.08)] backdrop-blur-md",children:[e("span",{className:"grid h-12 w-12 shrink-0 place-items-center rounded-xl bg-[#eaf2ff] text-[#1167e8]",children:e(a,{className:"h-6 w-6"})}),s("div",{className:"min-w-0 flex-1",children:[s("span",{className:"inline-flex items-center gap-1.5 rounded-md border border-[#bfd8f8] bg-[#eaf2ff] px-2.5 py-1 text-xs font-bold text-[#0b57d0]",children:["Questions ",i,"–",l]}),t.passageTitle&&e("p",{className:"mt-2 text-lg font-bold leading-tight text-[#0f1730]",children:t.passageTitle}),t.passageSubtitle&&e("p",{className:"mt-1 text-[15px] font-medium text-[#475569]",children:t.passageSubtitle})]}),t.passageImageUrl&&e("img",{src:t.passageImageUrl,alt:t.passageTitle||"Illustration",className:"h-20 w-32 shrink-0 rounded-lg object-contain"})]}),e("section",{className:"flex flex-col overflow-hidden rounded-xl border border-[#d9e4f2] bg-white/90 shadow-[0_14px_35px_rgba(13,71,161,0.12)] backdrop-blur-md",children:T(t)})]},t.groupId)})]})}
|
package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface EnglishCertificationInstructionBannerProps {
|
|
2
|
+
instruction: string;
|
|
3
|
+
isListeningPart?: boolean;
|
|
4
|
+
isFullWidth?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Premium branded "Directions" callout block.
|
|
8
|
+
*
|
|
9
|
+
* Design:
|
|
10
|
+
* - Gradient header strip with icon + "DIRECTIONS" label — clear visual anchor.
|
|
11
|
+
* - Cream-white body with generous padding for readability.
|
|
12
|
+
* - HTML instructions rendered as rich prose with "Example:" sections styled
|
|
13
|
+
* as an inset callout for TOEIC-style worked examples.
|
|
14
|
+
* - Plain-text instructions get the same header but a simple prose paragraph.
|
|
15
|
+
*/
|
|
16
|
+
export declare function EnglishCertificationInstructionBanner({ instruction, isListeningPart, isFullWidth, }: EnglishCertificationInstructionBannerProps): import("react").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{Headphones as t,Info as i}from"lucide-react";import{ENGLISH_CERT_COLORS as r,ENGLISH_CERT_CONTENT_WIDTH_CLASS as l,ENGLISH_CERT_PRIMARY_GRADIENT as s}from"./english-certification-theme";import{isHtmlContent as a}from"./grouped-question-utils";export function EnglishCertificationInstructionBanner({instruction:o,isListeningPart:c=!1,isFullWidth:d=!1}){if(!o)return null;const p=c?t:i,m=a(o),h=m?o:(f=o).replace(/^\s*directions\s*[:.\\-–]?\s*/i,"").trim()||f;var f;return n("div",{className:d?"w-full":`${l} w-full self-center`,children:[n("div",{className:"overflow-hidden rounded-2xl",style:{boxShadow:"0 4px 6px -1px rgba(11,87,208,0.08), 0 12px_28px rgba(11,87,208,0.10)",border:`1px solid ${r.blue600}26`},children:[n("div",{className:"flex items-center gap-3 px-5 py-3",style:{background:s},children:[e("span",{className:"grid h-8 w-8 shrink-0 place-items-center rounded-lg",style:{background:"rgba(255,255,255,0.18)"},children:e(p,{className:"h-4 w-4 text-white",strokeWidth:2.5})}),e("span",{className:"text-[11px] font-black uppercase tracking-[0.22em] text-white/90",children:"Directions"}),e("div",{className:"ml-auto flex items-center gap-1","aria-hidden":!0,children:[.5,.35,.2].map((n,t)=>e("span",{className:"h-1.5 w-1.5 rounded-full bg-white",style:{opacity:n}},t))})]}),e("div",{className:"px-6 py-5",style:{background:"linear-gradient(160deg, #f8fbff 0%, #eef5ff 100%)"},children:m?e("div",{className:"ec-instruction-html text-[15px] leading-[1.8] text-[#0f1730]",dangerouslySetInnerHTML:{__html:h}}):e("p",{className:"text-[15px] font-semibold leading-[1.8] text-[#0f1730]",children:h})})]}),e("style",{children:`\n /* Base paragraphs */\n .ec-instruction-html p {\n margin-bottom: 0.5rem;\n font-size: 15px;\n font-weight: 600;\n color: #0f1730;\n }\n .ec-instruction-html p:last-child {\n margin-bottom: 0;\n }\n\n /* Bold labels ("Directions:", "Example:") */\n .ec-instruction-html strong {\n font-weight: 700;\n color: ${r.blue700};\n }\n\n /* "Example:" paragraph — inset callout block */\n .ec-instruction-html p:has(> strong:first-child):not(:first-child) {\n margin-top: 1rem;\n padding: 0.7rem 1rem;\n background: rgba(11, 87, 208, 0.06);\n border-left: 3px solid ${r.blue600};\n border-radius: 0 8px 8px 0;\n }\n\n /* Lines that follow inside an inset callout */\n .ec-instruction-html p:has(> strong:first-child) ~ p {\n padding-left: 1rem;\n font-size: 14.5px;\n font-weight: 500;\n color: #1e2d4d;\n }\n `})]})}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface EnglishCertificationPartHeaderProps {
|
|
2
|
+
/** e.g. "Part 2" or "PART 2" — displayed as the primary label. */
|
|
3
|
+
partName?: string;
|
|
4
|
+
/** e.g. 2 — used to render the large decorative number. */
|
|
5
|
+
partNo?: number;
|
|
6
|
+
/** Skill category to pick the right icon and accent colour. */
|
|
7
|
+
skill?: 'LISTENING' | 'READING' | 'WRITING' | 'SPEAKING' | string;
|
|
8
|
+
/** Optional subtitle, e.g. "Question Responses" */
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
/** Whether to span the full width of the container (used for split views). */
|
|
11
|
+
isFullWidth?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Premium standalone Part title header for English Certification exams.
|
|
15
|
+
*
|
|
16
|
+
* Design decisions:
|
|
17
|
+
* - Full-bleed gradient card matching the brand palette (never plain text).
|
|
18
|
+
* - Large ghost number in the background gives spatial identity.
|
|
19
|
+
* - Skill badge + icon communicate exam section at a glance.
|
|
20
|
+
* - Decorative wave SVG and a thin accent bar at the bottom tie it
|
|
21
|
+
* to the footer / audio-player language.
|
|
22
|
+
*/
|
|
23
|
+
export declare function EnglishCertificationPartHeader({ partName, partNo, skill, subtitle, isFullWidth, }: EnglishCertificationPartHeaderProps): import("react").JSX.Element;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{BookOpen as l,Headphones as t,Pencil as r,Mic as n}from"lucide-react";import{ENGLISH_CERT_COLORS as i,ENGLISH_CERT_CONTENT_WIDTH_CLASS as c,ENGLISH_CERT_PRIMARY_GRADIENT as s}from"./english-certification-theme";export function EnglishCertificationPartHeader({partName:o,partNo:d,skill:p,subtitle:h,isFullWidth:u=!1}){if(!o&&void 0===d)return null;const{Icon:b,label:x}=function(e){switch((e??"").toUpperCase()){case"LISTENING":return{Icon:t,label:"Listening",color:"#0b57d0"};case"READING":return{Icon:l,label:"Reading",color:"#0f6cbf"};case"WRITING":return{Icon:r,label:"Writing",color:"#1255a0"};case"SPEAKING":return{Icon:n,label:"Speaking",color:"#0d4fa3"};default:return{Icon:l,label:null,color:i.blue700}}}(p),g=o?o.replace(/^part\s*/i,"").toUpperCase():String(d??""),m=d??o?.match(/\d+/)?.[0]??"";return e("div",{className:u?"w-full":`${c} w-full self-center`,children:a("div",{className:"relative overflow-hidden rounded-2xl",style:{background:s,boxShadow:"0 8px 32px rgba(11,87,208,0.28), 0 2px 8px rgba(11,87,208,0.16)"},children:[e("span",{"aria-hidden":!0,className:"pointer-events-none absolute -right-4 -top-3 select-none font-black leading-none text-white/10",style:{fontSize:"clamp(80px, 12vw, 110px)"},children:m}),e("div",{"aria-hidden":!0,className:"pointer-events-none absolute -left-12 -top-12 h-48 w-48 rounded-full",style:{background:"radial-gradient(circle, rgba(255,255,255,0.12) 0%, transparent 70%)"}}),a("div",{className:"relative flex items-center gap-5 px-7 py-5",children:[e("div",{className:"grid h-14 w-14 shrink-0 place-items-center rounded-2xl shadow-[0_4px_16px_rgba(0,0,0,0.20)]",style:{background:"rgba(255,255,255,0.18)",backdropFilter:"blur(8px)"},children:e(b,{className:"h-6 w-6 text-white",strokeWidth:2})}),a("div",{className:"min-w-0 flex-1",children:[x&&e("span",{className:"mb-1.5 inline-flex items-center gap-1.5 rounded-full px-3 py-0.5 text-[10px] font-black uppercase tracking-[0.2em]",style:{background:"rgba(255,255,255,0.20)",color:"rgba(255,255,255,0.90)"},children:x}),a("p",{className:"text-2xl font-black leading-none tracking-tight text-white drop-shadow-sm",children:["Part"," ",e("span",{className:"rounded-lg px-2.5 py-0.5 text-[22px] font-black",style:{background:"rgba(255,255,255,0.22)"},children:g})]}),h&&e("p",{className:"mt-1 text-[13px] font-medium text-white/75",children:h})]})]}),e("svg",{"aria-hidden":!0,className:"block w-full",height:"18",viewBox:"0 0 940 18",preserveAspectRatio:"none",fill:"none",children:e("path",{d:"M0 8C160 0 300 16 470 8C640 0 780 16 940 8V18H0V8Z",fill:"rgba(255,255,255,0.10)"})})]})})}
|
|
@@ -9,6 +9,8 @@ interface EnglishCertificationQuestionCardProps {
|
|
|
9
9
|
onAnswerChange: (questionId: string, answer: any) => void;
|
|
10
10
|
onToggleFlag: (questionId: string) => void;
|
|
11
11
|
isReviewMode?: boolean;
|
|
12
|
+
/** Optional DOM id used by the Answer Sheet to scroll the card into view. */
|
|
13
|
+
domId?: string;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Single MCQ rendered as a standalone Ocean Edu white card.
|
|
@@ -16,5 +18,5 @@ interface EnglishCertificationQuestionCardProps {
|
|
|
16
18
|
* Replaces the former shared-section/divider layout so each question matches the
|
|
17
19
|
* target mockup (own card, number chip, flag button, compact options).
|
|
18
20
|
*/
|
|
19
|
-
export declare function EnglishCertificationQuestionCard({ question, globalQuestionNumber, answer, isFlagged, sharedInstruction, onAnswerChange, onToggleFlag, isReviewMode, }: EnglishCertificationQuestionCardProps): import("react").JSX.Element;
|
|
21
|
+
export declare function EnglishCertificationQuestionCard({ question, globalQuestionNumber, answer, isFlagged, sharedInstruction, onAnswerChange, onToggleFlag, isReviewMode, domId, }: EnglishCertificationQuestionCardProps): import("react").JSX.Element;
|
|
20
22
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{EnglishCertificationOptionSelector as t}from"./EnglishCertificationOptionSelector";import{EnglishCertificationFlagButton as n}from"./EnglishCertificationFlagButton";export function EnglishCertificationQuestionCard({question:o,globalQuestionNumber:r,answer:s,isFlagged:a,sharedInstruction:
|
|
1
|
+
"use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{EnglishCertificationOptionSelector as t}from"./EnglishCertificationOptionSelector";import{EnglishCertificationFlagButton as n}from"./EnglishCertificationFlagButton";export function EnglishCertificationQuestionCard({question:o,globalQuestionNumber:r,answer:s,isFlagged:a,sharedInstruction:d,onAnswerChange:l,onToggleFlag:c,isReviewMode:g=!1,domId:m}){const f=o.content||{},p=f.options||[],u=f.question?.trim()??"",b=u.length>0&&u!==d;return e("article",{id:m,className:"scroll-mt-24 rounded-xl border border-[#d9e4f2] bg-white/90 px-4 py-4 shadow-[0_5px_16px_rgba(13,71,161,0.08)] backdrop-blur-md transition-colors",children:i("div",{className:"grid grid-cols-[44px_1fr_32px] gap-1",children:[e("div",{className:"grid h-9 w-9 place-items-center rounded-full bg-[#eef5ff] text-base font-black leading-none text-[#0b57d0]",children:r}),i("div",{className:"min-w-0",children:[b&&e("div",{className:"mb-2 text-base font-black leading-snug text-[#10172f]",children:u}),e(t,{options:p.map((e,i)=>({id:e?.id||String.fromCharCode(65+i),label:e?.id||String.fromCharCode(65+i),text:e?.text||String(e??"")})),selectedOptionId:s?.optionId??null,onSelect:e=>l(o.id,{optionId:e}),isReviewMode:g,disabled:g,variant:"compact"})]}),e(n,{isFlagged:a,onToggle:()=>c(o.id),size:"sm",className:"self-start justify-self-end"})]})})}
|
package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{SkillEnum as i}from"../../../shared/types/common.types";import{EnglishCertificationSingleQuestionList as
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{SkillEnum as i}from"../../../shared/types/common.types";import{EnglishCertificationSingleQuestionList as t}from"./EnglishCertificationSingleQuestionList";import{EnglishCertificationGroupedQuestion as n}from"./EnglishCertificationGroupedQuestion";import{EnglishCertificationAudioPlayer as o}from"./EnglishCertificationAudioPlayer";import{EnglishCertificationPartHeader as s}from"./EnglishCertificationPartHeader";import{EnglishCertificationInstructionBanner as a}from"./EnglishCertificationInstructionBanner";import{ENGLISH_CERT_CONTENT_WIDTH_CLASS as l}from"./english-certification-theme";import{ENGLISH_CERT_STICKY_AUDIO_ATTR as c}from"./english-cert-scroll";import{EcWordFillStructuredForm as d}from"./EcWordFillStructuredForm";import{EcMatchByWritingAnswer as u}from"./EcMatchByWritingAnswer";import{EcAnswerTheQuestion as g}from"./EcAnswerTheQuestion";import{EcWordFillParagraph as m}from"./EcWordFillParagraph";import{EcWritingTask as p}from"./EcWritingTask";const f=new Set(["CHOOSE_THE_CORRECT_ANSWER"]);export function EnglishCertificationQuestionRenderer({part:h,partConfig:w,answers:E,flaggedQuestions:R,onAnswerChange:A,onToggleFlag:C,isReviewMode:N=!1,isAudioPlayed:T=!1,onAudioFirstPlay:_}){if(!h.questions.length)return e("div",{className:"flex h-full items-center justify-center rounded-xl border border-red-200 bg-red-50 p-8 text-red-600",children:"No questions found for this part"});const v=w.category===i.LISTENING,y=v?h.audioUrl??w.audioUrl??"":void 0,x=h.questionType,L=Boolean(h.isGroup)&&"DOCUMENT"===h.group?.type,M=w.isGroup&&f.has(x),b=Boolean(h.sections?.length);if(L||M||b)return e("div",{className:"h-full",children:e(n,{part:h,partConfig:w,answers:E,flaggedQuestions:R,onAnswerChange:A,onToggleFlag:C,isReviewMode:N,isListeningPart:v,partAudioUrl:y})});if(f.has(x))return e(t,{part:h,partConfig:w,answers:E,flaggedQuestions:R,onAnswerChange:A,onToggleFlag:C,isReviewMode:N,isListeningPart:v,partAudioUrl:y});const F=(h.questions[0]?.questionGroup?.payload?.instructions??h.instructions??w.instructions??"").trim(),P=!N&&T;return r("div",{className:"flex flex-col items-center gap-6 pb-4",children:[e(s,{partName:h.name??w.name,partNo:h.partNo,skill:w.category}),e(a,{instruction:F,isListeningPart:v}),v&&e("div",{[c]:"",className:`sticky top-0 z-20 ${l}`,children:e(o,{audioUrl:y??"",partNumber:h.partNo,isLocked:P,onFirstPlay:_})}),e("div",{className:`${l} w-full`,children:(()=>{switch(x){case"WORD_FILL_STRUCTURED_FORM":return e(d,{part:h,answers:E,onAnswerChange:A,isReviewMode:N});case"MATCH_BY_WRITING_ANSWER":return e(u,{part:h,answers:E,onAnswerChange:A,isReviewMode:N});case"ANSWER_THE_QUESTION":return e(g,{part:h,answers:E,onAnswerChange:A,isReviewMode:N});case"WORD_FILL_PARAGRAPH":return e(m,{part:h,answers:E,onAnswerChange:A,isReviewMode:N});case"WRITE_A_SHORT_LETTER":return e(p,{part:h,answers:E,onAnswerChange:A,isReviewMode:N});default:return r("div",{className:"rounded-xl border border-amber-200 bg-amber-50 p-6 text-sm text-amber-700",children:['Loại câu hỏi "',x,'" chưa được hỗ trợ trong giao diện này.']})}})()})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{EnglishCertificationOptionSelector as t}from"./EnglishCertificationOptionSelector";import{EnglishCertificationFlagButton as n}from"./EnglishCertificationFlagButton";import{EcWordFillStructuredForm as r}from"./EcWordFillStructuredForm";import{EcMatchByWritingAnswer as s}from"./EcMatchByWritingAnswer";import{EcAnswerTheQuestion as o}from"./EcAnswerTheQuestion";import{EcWordFillParagraph as a}from"./EcWordFillParagraph";import{EcWritingTask as d}from"./EcWritingTask";function
|
|
1
|
+
"use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{EnglishCertificationOptionSelector as t}from"./EnglishCertificationOptionSelector";import{EnglishCertificationFlagButton as n}from"./EnglishCertificationFlagButton";import{EcWordFillStructuredForm as r}from"./EcWordFillStructuredForm";import{EcMatchByWritingAnswer as s}from"./EcMatchByWritingAnswer";import{EcAnswerTheQuestion as o}from"./EcAnswerTheQuestion";import{EcWordFillParagraph as a}from"./EcWordFillParagraph";import{EcWritingTask as d}from"./EcWritingTask";import{englishCertQuestionDomId as l}from"./english-cert-scroll";function c(e){return e.map((e,i)=>{const t=String.fromCharCode(65+i);return"string"==typeof e?{id:e,label:t,text:e}:{id:String(e?.id||t),label:String(e?.id||t),text:String(e?.text??e?.value??e??"")}})}export function EnglishCertificationReadingSection({part:m,section:p,questions:u,startIndex:g,answers:f,flaggedQuestions:x,onAnswerChange:h,onToggleFlag:w,isReviewMode:R=!1}){if(!u.length)return null;const v=(p.instructions||p.name||"").trim();if("CHOOSE_THE_CORRECT_ANSWER"===p.questionType)return i("div",{className:"flex flex-col gap-3",children:[v&&e("p",{className:"text-sm font-semibold leading-relaxed text-[#0b57d0]",children:v}),e("div",{className:"divide-y divide-[#e8eef7]",children:u.map(r=>{const s=m.questions.indexOf(r)+g+1,o=r.content||{},a=Array.isArray(o.options)?o.options:p.defaultValue??[],d=o.question?.trim()??"",u=f[r.id];return i("article",{id:l(r.id),className:"scroll-mt-24 grid grid-cols-[44px_1fr_32px] gap-1 py-4",children:[i("div",{className:"text-[18px] font-black leading-snug text-[#0b57d0]",children:[s,"."]}),i("div",{className:"min-w-0",children:[d&&e("div",{className:"mb-2 text-[15px] font-black leading-snug text-[#10172f]",children:d}),e(t,{options:c(a),selectedOptionId:u?.optionId??null,onSelect:e=>h(r.id,{optionId:e}),isReviewMode:R,disabled:R,variant:"compact"})]}),e(n,{isFlagged:x.has(r.id),onToggle:()=>w(r.id),size:"sm",className:"self-start justify-self-end"})]},r.id)})})]});const T={...m,questionType:p.questionType,questions:u,instructions:v||m.instructions,isGroup:!1,group:void 0,sections:void 0,viewMode:p.viewMode,wordBankConfig:p.wordBankConfig,startIndex:p.startIndex,endIndex:p.endIndex};return i("div",{className:"flex flex-col gap-3",children:[v&&e("p",{className:"text-sm font-semibold leading-relaxed text-[#0b57d0]",children:v}),(()=>{switch(p.questionType){case"WORD_FILL_STRUCTURED_FORM":return e(r,{part:T,answers:f,onAnswerChange:h,isReviewMode:R});case"MATCH_BY_WRITING_ANSWER":return e(s,{part:T,answers:f,onAnswerChange:h,isReviewMode:R});case"ANSWER_THE_QUESTION":return e(o,{part:T,answers:f,onAnswerChange:h,isReviewMode:R});case"WORD_FILL_PARAGRAPH":return e(a,{part:T,answers:f,onAnswerChange:h,isReviewMode:R});case"WRITE_A_SHORT_LETTER":return e(d,{part:T,answers:f,onAnswerChange:h,isReviewMode:R});default:return i("div",{className:"rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-700",children:['Loại câu hỏi "',p.questionType,'" chưa được hỗ trợ.']})}})()]})}
|
package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.d.ts
CHANGED
|
@@ -13,8 +13,6 @@ interface EnglishCertificationSingleQuestionListProps {
|
|
|
13
13
|
/** Part-level audio URL (shown once at the top for listening parts). */
|
|
14
14
|
partAudioUrl?: string;
|
|
15
15
|
}
|
|
16
|
-
/** Stable DOM id for a question card, used for Answer-Sheet scroll-to. */
|
|
17
|
-
export declare function englishCertQuestionDomId(questionId: string): string;
|
|
18
16
|
/**
|
|
19
17
|
* Renders every question of a single-question part (or section) on one screen.
|
|
20
18
|
*
|
package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as i,jsxs as e}from"react/jsx-runtime";import{EnglishCertificationAudioPlayer as t}from"./EnglishCertificationAudioPlayer";import{EnglishCertificationQuestionItem as o}from"./EnglishCertificationQuestionItem";import{ENGLISH_CERT_CONTENT_WIDTH_CLASS as n}from"./english-certification-theme";import{ENGLISH_CERT_STICKY_AUDIO_ATTR as r,englishCertQuestionDomId as s}from"./english-cert-scroll";export function EnglishCertificationSingleQuestionList({part:a,partConfig:l,answers:u,flaggedQuestions:g,onAnswerChange:d,onToggleFlag:m,isReviewMode:f=!1,isListeningPart:c=!1,partAudioUrl:p}){const h=l.startIndex??0,C=Array.isArray(l.questionConfig)?l.questionConfig:[],w=l.defaultQuestion,x=c&&Boolean(p);return e("div",{className:"flex flex-col items-center gap-5 pb-4",children:[x&&i("div",{[r]:"",className:`sticky top-0 z-20 ${n}`,children:i(t,{audioUrl:p,partNumber:a.partNo})}),a.questions.map((e,t)=>{const n=e.audio_url?Array.from(new Set([...C,"audioUrl"])):C;return i(o,{domId:s(e.id),question:e,questionNumber:h+t+1,questionConfig:n,defaultQuestion:w,isListeningPart:c,answer:u[e.id],isFlagged:g.has(e.id),onAnswerChange:d,onToggleFlag:m,isReviewMode:f},e.id)})]})}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scroll helpers for English Certification Answer Sheet navigation.
|
|
3
|
+
*
|
|
4
|
+
* Question cards use a stable DOM id (`ec-question-{id}`) so the sidebar can
|
|
5
|
+
* jump to the chosen question after `goToQuestion` re-renders the active part.
|
|
6
|
+
*
|
|
7
|
+
* Listening parts pin the audio bar with `position: sticky`. Manual scroll must
|
|
8
|
+
* subtract that bar's height so the target card is not hidden underneath it.
|
|
9
|
+
*/
|
|
10
|
+
/** Stable DOM id for a question card / row, used for Answer-Sheet scroll-to. */
|
|
11
|
+
export declare function englishCertQuestionDomId(questionId: string): string;
|
|
12
|
+
/** Marker on sticky audio wrappers so scroll offset can be measured at runtime. */
|
|
13
|
+
export declare const ENGLISH_CERT_STICKY_AUDIO_ATTR = "data-ec-sticky-audio";
|
|
14
|
+
/** Nearest ancestor that actually scrolls (falls back to document scrolling element). */
|
|
15
|
+
export declare function findScrollableParent(el: HTMLElement): HTMLElement;
|
|
16
|
+
/**
|
|
17
|
+
* Scroll `el` into view inside its nearest scrollable ancestor.
|
|
18
|
+
* Prefer parent-relative scroll so nested columns (Reading split-view) work.
|
|
19
|
+
* When a sticky Listening audio bar is present, leave room under it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function scrollElementIntoView(el: HTMLElement, options?: {
|
|
22
|
+
behavior?: ScrollBehavior;
|
|
23
|
+
block?: ScrollLogicalPosition;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Find the question anchor by id and scroll it into view.
|
|
27
|
+
* Retries briefly so cross-part navigation can wait for React to mount the card.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scrollToEnglishCertQuestion(questionId: string, options?: {
|
|
30
|
+
behavior?: ScrollBehavior;
|
|
31
|
+
block?: ScrollLogicalPosition;
|
|
32
|
+
}): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function englishCertQuestionDomId(t){return`ec-question-${t}`}export const ENGLISH_CERT_STICKY_AUDIO_ATTR="data-ec-sticky-audio";const t=[0,50,120,250,400];function e(t){const e=window.getComputedStyle(t).overflowY;return("auto"===e||"scroll"===e||"overlay"===e)&&t.scrollHeight>t.clientHeight+1}export function findScrollableParent(t){let n=t.parentElement;for(;n;){if(e(n))return n;n=n.parentElement}return document.scrollingElement??document.documentElement}export function scrollElementIntoView(t,e){const n=e?.behavior??"smooth",o=e?.block??"start",i=findScrollableParent(t),l=function(t,e){const n=t.querySelectorAll("[data-ec-sticky-audio]");if(!n.length)return 0;let o=0;return n.forEach(n=>{if(n===e||n.contains(e))return;if(!t.contains(n))return;const i=n.getBoundingClientRect().height;i>o&&(o=i)}),o>0?o+12:0}(i,t),r=i.getBoundingClientRect(),c=t.getBoundingClientRect(),s=i.scrollTop,u=c.top-r.top+s;let a=u;if("center"===o)a=u-i.clientHeight/2+c.height/2;else if("end"===o)a=u-i.clientHeight+c.height;else if("nearest"===o){const t=s+l,e=s+i.clientHeight,n=u+c.height;if(u>=t&&n<=e)return;a=u<t?u-l:n-i.clientHeight}else a=u-l;"start"===o&&0===l&&(a=Math.max(0,a-12)),i.scrollTo({top:Math.max(0,a),behavior:n})}export function scrollToEnglishCertQuestion(e,n){if("undefined"==typeof document||!e)return;const o=englishCertQuestionDomId(e);let i=0;const l=()=>{const e=document.getElementById(o);e?scrollElementIntoView(e,n):(i+=1,i<t.length&&window.setTimeout(l,t[i]))};window.setTimeout(l,t[0])}
|
|
@@ -6,11 +6,14 @@ export { EnglishCertificationFooterBar } from './EnglishCertificationFooterBar';
|
|
|
6
6
|
export { EnglishCertificationOptionSelector } from './EnglishCertificationOptionSelector';
|
|
7
7
|
export { EnglishCertificationAudioPlayer } from './EnglishCertificationAudioPlayer';
|
|
8
8
|
export { EnglishCertificationSingleQuestion } from './EnglishCertificationSingleQuestion';
|
|
9
|
-
export { EnglishCertificationSingleQuestionList,
|
|
9
|
+
export { EnglishCertificationSingleQuestionList, } from './EnglishCertificationSingleQuestionList';
|
|
10
|
+
export { ENGLISH_CERT_STICKY_AUDIO_ATTR, englishCertQuestionDomId, scrollToEnglishCertQuestion, } from './english-cert-scroll';
|
|
10
11
|
export { EnglishCertificationGroupedQuestion } from './EnglishCertificationGroupedQuestion';
|
|
11
12
|
export { EnglishCertificationReadingSection } from './EnglishCertificationReadingSection';
|
|
12
13
|
export { EnglishCertificationFlagButton } from './EnglishCertificationFlagButton';
|
|
13
14
|
export { EnglishCertificationBrand } from './EnglishCertificationBrand';
|
|
15
|
+
export { EnglishCertificationPartHeader } from './EnglishCertificationPartHeader';
|
|
16
|
+
export { EnglishCertificationInstructionBanner } from './EnglishCertificationInstructionBanner';
|
|
14
17
|
export { EcWordFillStructuredForm } from './EcWordFillStructuredForm';
|
|
15
18
|
export { EcMatchByWritingAnswer } from './EcMatchByWritingAnswer';
|
|
16
19
|
export { EcAnswerTheQuestion } from './EcAnswerTheQuestion';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{EnglishCertificationExamLayout}from"./EnglishCertificationExamLayout";export{EnglishCertificationQuestionRenderer}from"./EnglishCertificationQuestionRenderer";export{EnglishCertificationHeader}from"./EnglishCertificationHeader";export{EnglishCertificationNavigationPanel}from"./EnglishCertificationNavigationPanel";export{EnglishCertificationFooterBar}from"./EnglishCertificationFooterBar";export{EnglishCertificationOptionSelector}from"./EnglishCertificationOptionSelector";export{EnglishCertificationAudioPlayer}from"./EnglishCertificationAudioPlayer";export{EnglishCertificationSingleQuestion}from"./EnglishCertificationSingleQuestion";export{EnglishCertificationSingleQuestionList,englishCertQuestionDomId}from"./
|
|
1
|
+
export{EnglishCertificationExamLayout}from"./EnglishCertificationExamLayout";export{EnglishCertificationQuestionRenderer}from"./EnglishCertificationQuestionRenderer";export{EnglishCertificationHeader}from"./EnglishCertificationHeader";export{EnglishCertificationNavigationPanel}from"./EnglishCertificationNavigationPanel";export{EnglishCertificationFooterBar}from"./EnglishCertificationFooterBar";export{EnglishCertificationOptionSelector}from"./EnglishCertificationOptionSelector";export{EnglishCertificationAudioPlayer}from"./EnglishCertificationAudioPlayer";export{EnglishCertificationSingleQuestion}from"./EnglishCertificationSingleQuestion";export{EnglishCertificationSingleQuestionList}from"./EnglishCertificationSingleQuestionList";export{ENGLISH_CERT_STICKY_AUDIO_ATTR,englishCertQuestionDomId,scrollToEnglishCertQuestion}from"./english-cert-scroll";export{EnglishCertificationGroupedQuestion}from"./EnglishCertificationGroupedQuestion";export{EnglishCertificationReadingSection}from"./EnglishCertificationReadingSection";export{EnglishCertificationFlagButton}from"./EnglishCertificationFlagButton";export{EnglishCertificationBrand}from"./EnglishCertificationBrand";export{EnglishCertificationPartHeader}from"./EnglishCertificationPartHeader";export{EnglishCertificationInstructionBanner}from"./EnglishCertificationInstructionBanner";export{EcWordFillStructuredForm}from"./EcWordFillStructuredForm";export{EcMatchByWritingAnswer}from"./EcMatchByWritingAnswer";export{EcAnswerTheQuestion}from"./EcAnswerTheQuestion";export{EcWordFillParagraph}from"./EcWordFillParagraph";export{EcWritingTask}from"./EcWritingTask";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Detects whether a CMS string carries HTML markup vs plain text. */
|
|
2
|
+
export declare function isHtmlContent(value: string): boolean;
|
|
3
|
+
interface HtmlOrTextProps {
|
|
4
|
+
value: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
/** Element used for plain-text fallback. Default: `p`. */
|
|
7
|
+
as?: 'p' | 'div' | 'span';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Renders CMS-authored content as HTML when it contains tags, otherwise as
|
|
11
|
+
* plain text. Content comes from the exam CMS (not end-user input).
|
|
12
|
+
*/
|
|
13
|
+
export declare function HtmlOrText({ value, className, as }: HtmlOrTextProps): import("react").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as t}from"react/jsx-runtime";import{cn as l}from"../lib/utils";export function isHtmlContent(t){return/<[a-z][\s\S]*>/i.test(t)}export function HtmlOrText({value:e,className:s,as:i="p"}){if(!e)return null;if(isHtmlContent(e))return t("div",{className:l("[&_p]:mb-2 [&_p:last-child]:mb-0 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_strong]:font-semibold",s),dangerouslySetInnerHTML:{__html:e}});return t(i,{className:s,children:e})}
|
|
@@ -102,6 +102,17 @@ export interface AttemptQuestionsResponse {
|
|
|
102
102
|
} | null;
|
|
103
103
|
questions: any[];
|
|
104
104
|
}
|
|
105
|
+
/** Summary of one exam part for student waiting room / room detail */
|
|
106
|
+
export interface StudentExamPartSummary {
|
|
107
|
+
id: string;
|
|
108
|
+
name: string;
|
|
109
|
+
skill?: string;
|
|
110
|
+
category?: string;
|
|
111
|
+
points: number;
|
|
112
|
+
questionCount: number;
|
|
113
|
+
instructions?: string;
|
|
114
|
+
questionType?: string;
|
|
115
|
+
}
|
|
105
116
|
export interface StudentRoom {
|
|
106
117
|
id: string;
|
|
107
118
|
name: string;
|
|
@@ -127,9 +138,12 @@ export interface StudentRoom {
|
|
|
127
138
|
passScore: number;
|
|
128
139
|
numberOfParts: number | null;
|
|
129
140
|
level?: string;
|
|
141
|
+
theme?: string;
|
|
130
142
|
template?: {
|
|
131
143
|
theme?: string;
|
|
132
144
|
};
|
|
145
|
+
/** Summary parts from exams.template.parts */
|
|
146
|
+
parts?: StudentExamPartSummary[];
|
|
133
147
|
};
|
|
134
148
|
contest?: {
|
|
135
149
|
id: string;
|