@tinyweb_dev/oe-exam-sdk 0.1.19 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +5 -4
  2. package/dist/api/result-review.types.d.ts +1 -0
  3. package/dist/components/exams/ExamPreviewDialog.d.ts +6 -7
  4. package/dist/components/exams/ExamPreviewDialog.js +1 -1
  5. package/dist/components/exams/ExamPreviewPartContent.d.ts +18 -0
  6. package/dist/components/exams/ExamPreviewPartContent.js +1 -0
  7. package/dist/components/exams/ExamPreviewSidebar.d.ts +17 -0
  8. package/dist/components/exams/ExamPreviewSidebar.js +1 -0
  9. package/dist/components/exams/exam-preview.types.d.ts +34 -0
  10. package/dist/components/exams/exam-preview.types.js +1 -0
  11. package/dist/components/exams/index.d.ts +1 -0
  12. package/dist/components/exams/take/components/question-renderers/MoversChooseBestAnswerRenderer.js +1 -1
  13. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +1 -1
  14. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -1
  15. package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.js +1 -1
  16. package/dist/components/exams/take/exam-taking.utils.d.ts +13 -0
  17. package/dist/components/exams/take/exam-taking.utils.js +1 -1
  18. package/dist/components/exams/take/types.d.ts +3 -0
  19. package/dist/components/exams/take/utils/question-transformers.d.ts +13 -0
  20. package/dist/components/exams/take/utils/question-transformers.js +1 -1
  21. package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +25 -0
  22. package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +30 -0
  23. package/dist/components/questions/_shared/utils/parseFillBlankStem.js +1 -0
  24. package/dist/components/questions/index.d.ts +1 -0
  25. package/dist/components/questions/index.js +1 -1
  26. package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +2 -0
  27. package/dist/components/questions/question-bank/EditQuestionBankDialog.js +1 -0
  28. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +23 -0
  29. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +1 -0
  30. package/dist/components/questions/question-bank/difficulty.d.ts +15 -0
  31. package/dist/components/questions/question-bank/difficulty.js +1 -0
  32. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +5 -0
  33. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +1 -0
  34. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +5 -0
  35. package/dist/components/questions/question-bank/editor-adapters/index.js +1 -0
  36. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +6 -0
  37. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +1 -0
  38. package/dist/components/questions/question-bank/editor-adapters/types.d.ts +1 -0
  39. package/dist/components/questions/question-bank/editor-adapters/types.js +1 -0
  40. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +8 -0
  41. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +1 -0
  42. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +5 -0
  43. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +1 -0
  44. package/dist/components/questions/question-bank/index.d.ts +4 -0
  45. package/dist/components/questions/question-bank/index.js +1 -0
  46. package/dist/components/questions/question-bank/types.d.ts +59 -0
  47. package/dist/components/questions/question-bank/types.js +1 -0
  48. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +1 -1
  49. package/dist/components/questions/types/choose-the-correct-answer/index.d.ts +1 -0
  50. package/dist/components/questions/types/choose-the-correct-answer/index.js +1 -1
  51. package/dist/components/questions/types/choose-the-correct-answer/normalize.d.ts +27 -0
  52. package/dist/components/questions/types/choose-the-correct-answer/normalize.js +1 -0
  53. package/dist/components/questions/types/choose-the-correct-answer/register.js +1 -1
  54. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +1 -1
  55. package/dist/components/questions/types/fill-in-blank/register.js +1 -1
  56. package/dist/components/questions/types/fill-in-blank/transform.js +1 -1
  57. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.d.ts +1 -1
  58. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
  59. package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -1
  60. package/dist/components/questions/viewer/QuestionViewer.js +1 -1
  61. package/dist/components/results/review-data.js +1 -1
  62. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.d.ts +2 -1
  63. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +1 -1
  64. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
  65. package/dist/index.d.ts +3 -0
  66. package/dist/index.js +1 -1
  67. package/dist/mcp/config.d.ts +12 -0
  68. package/dist/mcp/config.js +1 -0
  69. package/dist/mcp/http-client.d.ts +6 -0
  70. package/dist/mcp/http-client.js +1 -0
  71. package/dist/mcp/index.d.ts +6 -0
  72. package/dist/mcp/index.js +2 -0
  73. package/dist/mcp/tools/_helpers.d.ts +4 -0
  74. package/dist/mcp/tools/_helpers.js +1 -0
  75. package/dist/mcp/tools/exams.d.ts +2 -0
  76. package/dist/mcp/tools/exams.js +1 -0
  77. package/dist/mcp/tools/index.d.ts +2 -0
  78. package/dist/mcp/tools/index.js +1 -0
  79. package/dist/mcp/tools/results.d.ts +2 -0
  80. package/dist/mcp/tools/results.js +1 -0
  81. package/dist/shared/lib/i18n/messages/en/admin.d.ts +11 -1
  82. package/dist/shared/lib/i18n/messages/en/admin.js +1 -1
  83. package/dist/shared/lib/i18n/messages/en.d.ts +11 -1
  84. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +11 -1
  85. package/dist/shared/lib/i18n/messages/vi/admin.js +1 -1
  86. package/dist/shared/lib/i18n/messages/vi.d.ts +11 -1
  87. package/package.json +163 -155
@@ -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,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
+ export function groupQuestionsByPart(t,e){const n=new Map,o=new Map;for(const e of t){const t=o.get(e.part_id)||[];t.push(e),o.set(e.part_id,t)}for(const[t,r]of o.entries()){const o=[...r].sort((t,e)=>t.question_number-e.question_number),i=o[0];if(!i)continue;const s=e?.find(e=>String(e.id)===String(t)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),l=u?parseInt(u[0],10):i.part_no,c=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===c?.type,p=s?.sections??[],d=new Set(p.map(t=>t.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:c,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[e,r]of s.sections.entries()){const i=o.filter(t=>{const e=t.question_number-1;return e>=r.startIndex&&e<=r.endIndex});if(!i.length)continue;const u=`${t}_section_${e}`,c=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:t,partNo:l,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:c,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((t,e)=>{const n=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder,o=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder;return n!==o?n-o:(t.questions[0]?.question_number||0)-(e.questions[0]?.question_number||0)})}export function transformFillInBlank(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload,r=[],i=t=>t.replace(/\*\*/g,"");for(const e of t){const t=e.content,n=e.is_example||!1,o=t.question||t.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const s=o.split("\n").filter(t=>t.trim());for(const o of s){const s=o.match(/\{(\d+)\}/);if(!s)continue;const a=parseInt(s[1],10),u=o.split(/\{\d+\}/),l=i(u[0]?.trim()||""),c=i(u[1]?.trim()||"");r.push({id:`${e.id}-blank-${a}`,questionNumber:e.question_number,textBefore:l,textAfter:c,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[a]:void 0})}}else{const s=o.match(/^(.*?)\{0\}(.*)$/),a=i(s?s[1].trim():o),u=i(s?s[2].trim():"");r.push({id:e.id,questionNumber:e.question_number,textBefore:a,textAfter:u,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"",imageUrl:o?n?.imageUrl:void 0,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(t){const e=t[0],n=e?.content;return{questions:t.map(t=>{const e=t.content,n=e.sentence||"",o=n.match(/^(.*?)\{0\}(.*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:t.id,questionNumber:t.question_number,textBefore:r,textAfter:i,verbHint:e.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}const t=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(e){const n=e[0]?.content,o=e[0]?.questionGroup?.payload,r=e.find(t=>t.is_example),i=e.filter(t=>!t.is_example);let s;if(r){const e=r.content,n=(e.options||[]).map((e,n)=>{const o="object"==typeof e&&null!==e,i=o&&e.id?String(e.id):`${r.id}-opt-${n}`,s=o?e.text??e.content??"":String(e),a=o?e.imageUrl:void 0;return{id:i,label:t[n]||String(n+1),text:s,...a?{imageUrl:a}:{}}}),o=r.correct_answer?.answer??r.correct_answer?.optionId;let i="";if("string"==typeof o&&o){const t=n.find(t=>t.id===o);i=t?t.id:o}else"number"==typeof o&&o>=0&&o<n.length&&(i=n[o]?.id||"");s={questionNumber:r.question_number,questionText:e.question||"",options:n,correctOptionId:i||n[0]?.id||"",optionType:e.optionType||"text",imageUrl:e.imageUrl,audioUrl:e.audioUrl}}const a=i.map(e=>{const n=e.content,o=n.optionType||"text",r=(n.options||[]).map((n,o)=>{const r="object"==typeof n&&null!==n,i=r&&n.id?String(n.id):`${e.id}-opt-${o}`,s=r?n.text??n.content??"":String(n),a=r?n.imageUrl:void 0;return{id:i,label:t[o]||String(o+1),text:s,...a?{imageUrl:a}:{}}}),i=e.correct_answer?.answer??e.correct_answer?.optionId??e.correct_answer?.optionIds,s=t=>{if(null==t)return;const e=String(t),n=r.find(t=>t.id===e);if(n)return n.id;const o=e.match(/-opt-(\d+)$/);if(o){const t=parseInt(o[1],10);if(t>=0&&t<r.length)return r[t]?.id}if("number"==typeof t&&t>=0&&t<r.length)return r[t]?.id;const i=parseInt(e,10);return!isNaN(i)&&i>=0&&i<r.length&&!e.startsWith("opt-")?r[i]?.id:e};let a=[];if(Array.isArray(i))a=i.map(s).filter(t=>Boolean(t));else{const t=s(i);t&&(a=[t])}return{id:e.id,questionNumber:e.question_number,questionText:n.question||"",options:r,correctOptionId:a[0],correctOptionIds:a,imageUrl:n.imageUrl,audioUrl:n.audioUrl,optionType:o,multipleAnswers:Boolean(n.multipleAnswers||Array.isArray(i)),explanation:e.explanation}}),u=a.some(t=>!!t.audioUrl?.trim())||!!s?.audioUrl?.trim();return{questions:a,example:s,imageUrl:n?.imageUrl,groupImageUrl:o?.mainImageUrl||o?.imageUrl,groupTitle:o?.title,groupContent:o?.content,articles:o?.articles,audioUrl:u?void 0:n?.audioUrl,instruction:n?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseCorrectAdjective(e){return{questions:e.map(e=>{const n=e.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:e.id,questionNumber:e.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(t){const e=t.content;if(e.instructions?.mainInstruction||e.informations?.length)return{prompt:e.instructions?.mainInstruction||"",requirements:e.informations,minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages};return{prompt:e.contexts?.filter(t=>"text"===t.type).map(t=>t.text).join("\n")||"",minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages}}export function transformColorObjects(t){const e=t[0],n=e?.content,o=n?.colorNodes?.map(t=>({id:t.id,color:t.color,label:t.label}))||n?.hintItems||[],r=n?.regionNodes?.map(t=>({id:t.id,x:t.x,y:t.y,width:t.width,height:t.height,correctHintId:t.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(e){if(function(t){const e=t[0];if(!e)return!1;const n=e.content;return void 0!==n?.question&&!n?.questions&&void 0!==e.questionGroup?.payload?.passage}(e)){const n=e[0],o=n.questionGroup?.payload||{},r=e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=e[0],o=n?.content,r=o?.questions?.map((e,o)=>({id:e.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:e.question,options:(e.options||[]).map((o,r)=>({id:`${e.id||n.id}-opt-${r}`,label:t[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(t){const e=t[0],n=e?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(t=>({id:t.id,number:t.number,isPreFilled:t.isPreFilled||!1,correctAnswer:t.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function e(t){return t&&"string"==typeof t.word&&!t.subQuestions}export function transformFillWordHint(t){const n=t[0],o=n?.content;if(t.length>1&&t.every(t=>e(t.content))){const e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:t.map(t=>{const e=t.content,n=e.word.replace(/\{\d+\}/,"_");return{id:t.id,questionNumber:t.question_number,imageUrl:e.imageUrl||"",word:n}}),hintLetters:e,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(e(o)){const t=o,e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(t){const e=[],n=t.split(",").map(t=>t.trim());for(const t of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(t));){const o=parseInt(n[1],10),r=t.replace(n[0],"_");e.push({index:o,displayWord:r})}}return e.sort((t,e)=>t.index-e.index),e}(t.word).map(e=>({id:`${n.id}-blank-${e.index}`,questionNumber:n.question_number,imageUrl:t.imageUrl||"",word:e.displayWord,blankIndex:e.index})),hintLetters:e,instruction:t.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((t,e)=>({id:t.id,questionNumber:n.question_number+e,imageUrl:t.imageUrl||"",word:t.word||""}))||[],hintLetters:r?.hintLetters||n.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(t){const e=t[0],n=e?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:(e.question||"").replace(/\{\d+\}/g,"______"),imageUrl:e.imageUrl,prefixText:e.prefixText,suffixText:e.suffixText,suggestedAnswers:e.suggestedAnswers,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(t){const e=t[0]?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=n&&"boolean"==typeof t.correct_answer?.answer?t.correct_answer.answer:void 0;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:e?.mainImageUrl||e?.imageUrl,groupContent:e?.content||e?.groupContent}}export function transformWordOrdering(t){return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=Array.isArray(t.correct_answer?.answer)?t.correct_answer.answer:Array.isArray(e.answer)?e.answer:void 0;return{id:t.id,questionNumber:t.question_number,words:e.words||[],imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content,r=o?.title||n?.title||t.find(t=>t.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(t=>"string"==typeof t?{word:t}:t),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let l;l="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const c=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:e?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:l,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:c,emailTo:m}}export function transformMatchByWritingAnswer(t){const e=t[0]?.questionGroup?.payload,n=t.some(t=>!!t.content?.askerName),o=t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0,askerName:e.askerName,answererName:e.answererName}}),r=e?.options?.map(t=>({answer:t.answer,imageUrl:t.imageUrl||"",content:t.content||""}))||[],i=n?t[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:e?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload;return{questions:t.map(t=>({id:t.id,questionNumber:t.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}function n(t){const e=String(t||"").toLowerCase();return"letter"===e||"box"===e?"letter":"phrase"===e||"sentence"===e?"phrase":"word"}export function transformWordFillStructuredForm(t){const e=t[0],o=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,o=t.correct_answer||{};let r=e?.content||"";const i=e?.blocks;!r&&i?.length&&(r=i.map(t=>(t.heading?`<h3>${t.heading}</h3>`:"")+(t.content||"")).join(""));const s=function(t){if(!Array.isArray(t)||0===t.length)return;const e=t.map(t=>{if(null==t)return null;if("object"!=typeof t||Array.isArray(t))return null;const e=t;if(Array.isArray(e.options)){const t=e.options.map(t=>String(t??"").trim()).filter(t=>t.length>0);return t.length>=2?{options:t}:null}const n=String(e.word??"").trim();return n?e.isExample?{word:n,isExample:!0}:{word:n}:null});return e.some(t=>null!=t)?e:void 0}(e?.wordBank),a=Boolean(s?.some(t=>null!=t&&"options"in t&&Array.isArray(t.options))),u=Boolean(s?.some(t=>null!=t&&"word"in t&&t.word)),l=e?.viewMode||(a?"WITH_OPTIONS":u?"WITH_WORD_BANK":void 0);return{id:t.id,questionNumber:t.question_number,title:e?.title||"",imageUrl:e?.imageUrl,content:r,answers:o?.answers||{},caseSensitive:o?.caseSensitive??e?.caseSensitive??!1,blankStyle:n(e?.blankStyle),...l?{viewMode:l}:{},...s?{wordBank:s}:{}}}),instruction:o?.instructions||"COMPLETE THE FORM BELOW",groupTitle:o?.title,groupContent:o?.content,groupImageUrl:o?.imageUrl,audioUrl:e?.audio_url||o?.audioUrl}}export function transformListenChooseObjects(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:e?.correctAnswer?.objectId||e?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(t){return{questions:t.map(t=>{const e=t.content,n=t.questionGroup?.payload||{};return{id:t.id,questionNumber:t.question_number,audioUrl:e?.audioUrl||"",arrowNode:e?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:e?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
@@ -1,8 +1,30 @@
1
+ /** WFSF blank input width/shape (content.blankStyle). */
2
+ export type WfsfBlankStyle = 'letter' | 'word' | 'phrase';
3
+ /** Plan 0024 WITH_OPTIONS: { options }. Plan 0025 WITH_WORD_BANK: { word }. null = free-type slot (OPTIONS only). */
4
+ export type WfsfWordBankEntry = {
5
+ options: string[];
6
+ } | {
7
+ word: string;
8
+ isExample?: boolean;
9
+ } | null;
1
10
  export interface WordFillStructuredFormData {
2
11
  title?: string;
3
12
  imageUrl?: string;
4
13
  content: string;
5
14
  answers: Record<string, string>;
15
+ /**
16
+ * letter = square 1-char box; word = single-word underline; phrase = multi-word.
17
+ * Default when omitted: word.
18
+ */
19
+ blankStyle?: WfsfBlankStyle;
20
+ /**
21
+ * WITH_OPTIONS (0024): per-blank options.
22
+ * WITH_WORD_BANK (0025): shared chip box { word }[] (not 1:1 blanks).
23
+ * Pure free-type pages omit these fields.
24
+ */
25
+ viewMode?: 'WITH_OPTIONS' | 'WITH_WORD_BANK' | 'DEFAULT' | string;
26
+ /** OPTIONS: index i ↔ {i}; WORD_BANK: shared list of { word }. */
27
+ wordBank?: WfsfWordBankEntry[];
6
28
  points?: number;
7
29
  explanation?: string;
8
30
  caseSensitive?: boolean;
@@ -42,5 +64,8 @@ export interface WordFillStructuredFormClientProps {
42
64
  userAnswer?: Record<string, string>;
43
65
  onAnswerChange?: (questionNumber: string, value: string) => void;
44
66
  autoFillCorrectAnswers?: boolean;
67
+ /** Student-facing rubric (Pearson instruction maps here). */
45
68
  explanation?: string;
69
+ /** Exercise / question number shown above instruction (e.g. Bài 1). */
70
+ questionNumber?: number;
46
71
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Parse FILL_IN_BLANK stem text into display tokens.
3
+ *
4
+ * Contract (workbook / Pearson map):
5
+ * - Bold: lightweight markdown `**text**` (toggle, non-nested)
6
+ * - Blanks: `{0}`, `{1}`, … left-to-right
7
+ * - Multi-line: `\n`
8
+ *
9
+ * Blank may sit *inside* a bold span (e.g. `**1. {0}:**`). Older viewers
10
+ * split blanks first then bold, which left orphan `**` in the UI.
11
+ */
12
+ export type FillBlankStemTextToken = {
13
+ kind: 'text';
14
+ text: string;
15
+ bold: boolean;
16
+ };
17
+ export type FillBlankStemBlankToken = {
18
+ kind: 'blank';
19
+ index: number;
20
+ /** True when blank is inside an open `**…**` span (label bold only; input stays normal weight). */
21
+ bold: boolean;
22
+ };
23
+ export type FillBlankStemToken = FillBlankStemTextToken | FillBlankStemBlankToken;
24
+ /**
25
+ * Tokenize one line. Unclosed bold at EOL → remaining text is plain and
26
+ * dangling `**` markers are dropped so they never show in the UI.
27
+ */
28
+ export declare function parseFillBlankStemLine(line: string): FillBlankStemToken[];
29
+ /** Split stem on newlines and parse each line. */
30
+ export declare function parseFillBlankStem(stem: string): FillBlankStemToken[][];
@@ -0,0 +1 @@
1
+ export function parseFillBlankStemLine(t){const e=[];let n=!1,l="",i=0;const o=()=>{l&&(e.push({kind:"text",text:l,bold:n}),l="")};for(;i<t.length;)if("*"!==t[i]||"*"!==t[i+1]){if("{"===t[i]){const l=/^\{(\d+)\}/.exec(t.slice(i));if(l){o(),e.push({kind:"blank",index:Number(l[1]),bold:n}),i+=l[0].length;continue}}l+=t[i],i+=1}else o(),n=!n,i+=2;return n&&l?(e.push({kind:"text",text:l,bold:!1}),l=""):o(),0===e.length?[{kind:"text",text:t,bold:!1}]:e}export function parseFillBlankStem(t){if(!t)return[[{kind:"text",text:"",bold:!1}]];return(t.includes("\n")?t.split("\n"):[t]).map(t=>parseFillBlankStemLine(t))}
@@ -8,3 +8,4 @@ export * from './groups/DocumentGroupCard';
8
8
  export * from './groups/MatchAnswerGroupCard';
9
9
  export * from './viewer';
10
10
  export * from './_shared';
11
+ export * from './question-bank';
@@ -1 +1 @@
1
- export*from"./creator";export*from"./creator/dedicated-component-router";export*from"./creator/question-type-registry";export*from"./components";export*from"./groups/ArticlesGroupCard";export*from"./groups/BasicQuestionGroupCard";export*from"./groups/DocumentGroupCard";export*from"./groups/MatchAnswerGroupCard";export*from"./viewer";export*from"./_shared";
1
+ export*from"./creator";export*from"./creator/dedicated-component-router";export*from"./creator/question-type-registry";export*from"./components";export*from"./groups/ArticlesGroupCard";export*from"./groups/BasicQuestionGroupCard";export*from"./groups/DocumentGroupCard";export*from"./groups/MatchAnswerGroupCard";export*from"./viewer";export*from"./_shared";export*from"./question-bank";
@@ -0,0 +1,2 @@
1
+ import type { EditQuestionBankDialogProps } from './types';
2
+ export declare function EditQuestionBankDialog({ open, onOpenChange, question, onSave, saving, }: EditQuestionBankDialogProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as t,Fragment as i}from"react/jsx-runtime";import{useEffect as a,useRef as n,useState as s}from"react";import{FileQuestion as l,Loader2 as o,Lock as d,Pencil as r,Save as c}from"lucide-react";import{Button as m}from"../../../components/ui/button";import{Dialog as h,DialogContent as p,DialogFooter as u,DialogHeader as x,DialogTitle as N}from"../../../components/ui/dialog";import{Input as g}from"../../../components/ui/input";import{Label as f}from"../../../components/ui/label";import{Select as b,SelectContent as v,SelectItem as y,SelectTrigger as w,SelectValue as I}from"../../../components/ui/select";import{getQuestionTypeLabel as k,SKILL_METADATA as q}from"../../../shared/constants/question-skills";import{t as E}from"../../../shared/lib/i18n";import{cn as G}from"../../../shared/lib/utils";import{SkillEnum as B}from"../../../shared/types/common.types";import{DIFFICULTY_LEVELS as j,DifficultyLevel as A,parseDifficultyLevel as S}from"./difficulty";import{QuestionEditorRenderer as T}from"./QuestionEditorRenderer";const R=[{value:B.READING,label:q[B.READING].name,emoji:q[B.READING].emoji},{value:B.WRITING,label:q[B.WRITING].name,emoji:q[B.WRITING].emoji},{value:B.LISTENING,label:q[B.LISTENING].name,emoji:q[B.LISTENING].emoji},{value:B.SPEAKING,label:q[B.SPEAKING].name,emoji:q[B.SPEAKING].emoji}];export function EditQuestionBankDialog({open:q,onOpenChange:C,question:P,onSave:D,saving:K}){const L=n(null),[W,F]=s(""),[O,Q]=s(""),[V,Y]=s(A.EASY),[z,H]=s(B.READING),[J,M]=s({}),[U,X]=s({});a(()=>{var e;P&&(F(P.code||""),Q(P.title||""),Y(S(String(P.difficulty||""))),H((e=P.skill?String(P.skill):null)===B.WRITING?B.WRITING:e===B.LISTENING?B.LISTENING:e===B.SPEAKING?B.SPEAKING:B.READING),M({content:P.content,answer:P.correctAnswer,explanation:P.explanation||"",points:Number(P.points)}),X({}))},[P]);const Z=R.find(e=>e.value===z);return e(h,{open:q,onOpenChange:C,children:t(p,{className:"max-w-4xl max-h-[90vh] flex flex-col p-0",children:[e(x,{className:"px-6 py-4 border-b bg-slate-50",children:t(N,{className:"flex items-center gap-3 text-lg",children:[e("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-amber-100",children:e(r,{className:"h-5 w-5 text-amber-600"})}),t("div",{children:[e("span",{className:"font-semibold",children:E("admin.questionBank.dialog.edit.title")}),P&&t("span",{className:"ml-2 text-sm font-normal text-slate-500",children:["• ",P.code]})]})]})}),e("div",{className:"flex-1 overflow-y-auto px-6 py-5",children:P&&t("div",{className:"space-y-6",children:[t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"1"}),E("admin.questionBank.dialog.edit.section1")]}),t("div",{className:"grid grid-cols-2 gap-4",children:[t("div",{className:"space-y-1.5",children:[t(f,{htmlFor:"edit-code",className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.code")," ",e("span",{className:"text-rose-500",children:"*"})]}),e(g,{id:"edit-code",value:W,onChange:e=>{F(e.target.value),U.code&&X(e=>({...e,code:void 0}))},placeholder:E("admin.questionBank.dialog.edit.codePlaceholder"),className:G("h-10",U.code&&"border-rose-500 focus-visible:ring-rose-500")}),U.code&&e("p",{className:"text-xs text-rose-500",children:U.code})]}),t("div",{className:"space-y-1.5",children:[t(f,{htmlFor:"edit-title",className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.titleLabel")," ",e("span",{className:"text-rose-500",children:"*"})]}),e(g,{id:"edit-title",value:O,onChange:e=>{Q(e.target.value),U.title&&X(e=>({...e,title:void 0}))},placeholder:E("admin.questionBank.dialog.edit.titlePlaceholder"),className:G("h-10",U.title&&"border-rose-500 focus-visible:ring-rose-500")}),U.title&&e("p",{className:"text-xs text-rose-500",children:U.title})]})]}),t("div",{className:"grid grid-cols-2 gap-4",children:[t("div",{className:"space-y-1.5",children:[t(f,{className:"text-sm text-slate-600",children:[E("admin.questionBank.dialog.edit.difficulty")," ",e("span",{className:"text-rose-500",children:"*"})]}),t(b,{value:V,onValueChange:e=>Y(S(e)),children:[e(w,{className:"h-10 bg-white w-full",children:e(I,{})}),e(v,{children:j.map(i=>e(y,{value:i.value,children:t("div",{className:"flex items-center gap-2",children:[i.icon,e("span",{children:E(i.labelKey)})]})},i.value))})]})]}),t("div",{className:"space-y-1.5",children:[t(f,{className:"text-sm text-slate-600 flex items-center gap-1",children:[E("admin.questionBank.dialog.edit.skill"),e(d,{className:"h-3 w-3 text-slate-400"})]}),t("div",{className:"flex items-center gap-2 px-4 py-2 bg-slate-100 rounded-lg border border-slate-200 h-10",children:[e("span",{children:Z?.emoji}),e("span",{className:"text-sm text-slate-600 font-medium",children:Z?.label||z}),e("span",{className:"text-xs text-slate-400 ml-auto",children:E("admin.questionBank.dialog.edit.unchangeable")})]})]})]})]}),t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"2"}),E("admin.questionBank.dialog.edit.section2"),e(d,{className:"h-3.5 w-3.5 text-slate-400"})]}),e("div",{className:"w-1/2",children:t("div",{className:"flex items-center gap-2 px-4 py-2.5 bg-slate-100 rounded-lg border border-slate-200 h-10",children:[e(l,{className:"h-4 w-4 text-slate-500"}),e("span",{className:"text-sm text-slate-600 font-medium",children:k(P.questionType)}),e("span",{className:"text-xs text-slate-400 ml-auto",children:E("admin.questionBank.dialog.edit.unchangeable")})]})})]}),t("div",{className:"space-y-4",children:[t("h3",{className:"text-base font-semibold text-slate-800 flex items-center gap-2",children:[e("span",{className:"flex h-6 w-6 items-center justify-center rounded bg-indigo-600 text-white text-xs font-bold",children:"3"}),E("admin.questionBank.dialog.edit.section3")]}),e("div",{className:"border rounded-lg p-4 bg-white",children:e(T,{questionType:P.questionType,content:P.content,correctAnswer:P.correctAnswer,explanation:P.explanation,points:Number(P.points),onChange:e=>{M({content:e.content,answer:e.answer,explanation:e.explanation,points:e.points})},validationRef:L})})]})]})}),e(u,{className:"px-6 py-4 border-t bg-slate-50",children:t("div",{className:"flex items-center justify-between w-full",children:[t("p",{className:"text-xs text-slate-500",children:[e("span",{className:"text-rose-500",children:"*"})," ",E("admin.questionBank.dialog.edit.required")]}),t("div",{className:"flex gap-2",children:[e(m,{type:"button",variant:"outline",onClick:()=>C(!1),disabled:K,children:E("admin.questionBank.dialog.edit.cancel")}),e(m,{type:"button",onClick:async()=>{const e={};if(W.trim()||(e.code=E("admin.questionBank.dialog.edit.codeError")),O.trim()||(e.title=E("admin.questionBank.dialog.edit.titleError")),Object.keys(e).length>0)return void X(e);if(L.current){if(!await L.current.triggerValidation())return}const t={code:W.trim(),title:O.trim(),difficulty:V,skill:z,content:J.content,correctAnswer:J.answer??void 0,explanation:J.explanation,points:J.points};D(t)},disabled:K,className:"bg-indigo-600 hover:bg-indigo-700",children:t(i,K?{children:[e(o,{className:"mr-2 h-4 w-4 animate-spin"}),E("admin.questionBank.dialog.edit.saving")]}:{children:[e(c,{className:"mr-2 h-4 w-4"}),E("admin.questionBank.dialog.edit.save")]})})]})]})})]})})}
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { QuestionEditorRendererProps } from './types';
3
+ /** Marketing question types supported by the question-bank editor. */
4
+ export declare enum QuestionBankEditorType {
5
+ CHOOSE_THE_CORRECT_ANSWER = "CHOOSE_THE_CORRECT_ANSWER",
6
+ LOOK_PICTURE_CHOOSE_CORRECT_ANSWER = "LOOK_PICTURE_CHOOSE_CORRECT_ANSWER",
7
+ LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER = "LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER",
8
+ FILL_MISSING_WORDS_IN_GRID = "FILL_MISSING_WORDS_IN_GRID",
9
+ LABEL_THE_PICTURE = "LABEL_THE_PICTURE",
10
+ LOOK_PICTURE_FILL_WORD_HINT = "LOOK_PICTURE_FILL_WORD_HINT",
11
+ READ_AND_COLOR_OBJECTS = "READ_AND_COLOR_OBJECTS",
12
+ IMAGE_OBJECT_MATCHING = "IMAGE_OBJECT_MATCHING",
13
+ READ_PASSAGE_AND_ANSWER_QUESTIONS = "READ_PASSAGE_AND_ANSWER_QUESTIONS",
14
+ WRITE_A_SHORT_LETTER = "WRITE_A_SHORT_LETTER",
15
+ WRITE_CORRECT_VERB_FORM = "WRITE_CORRECT_VERB_FORM",
16
+ FILL_IN_BLANK = "FILL_IN_BLANK",
17
+ CHOOSE_CORRECT_ADJECTIVE = "CHOOSE_CORRECT_ADJECTIVE"
18
+ }
19
+ /**
20
+ * Renders the appropriate Creator for a question-bank item.
21
+ * Maps API content/correctAnswer into Creator initialData and back via onChange.
22
+ */
23
+ export declare function QuestionEditorRenderer({ questionType, content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorRendererProps): ReactNode;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as _}from"react/jsx-runtime";import{useEffect as E,useRef as e,useState as t}from"react";import{t as n}from"../../../shared/lib/i18n";import{renderChooseCorrectAdjectiveEditor as R,renderChooseTheCorrectAnswerEditor as O,renderFillInBlankEditor as T,renderFillMissingWordsInGridEditor as r,renderImageObjectMatchingEditor as o,renderLabelThePictureEditor as i,renderLookPictureChooseCorrectAnswerEditor as C,renderLookPictureFillBlankChooseAnswerEditor as I,renderLookPictureFillWordHintEditor as a,renderReadAndColorObjectsEditor as A,renderReadPassageAndAnswerQuestionsEditor as L,renderWriteAShortLetterEditor as S,renderWriteCorrectVerbFormEditor as s,UnsupportedEditorFallback as N}from"./editor-adapters";export var QuestionBankEditorType;!function(_){_.CHOOSE_THE_CORRECT_ANSWER="CHOOSE_THE_CORRECT_ANSWER",_.LOOK_PICTURE_CHOOSE_CORRECT_ANSWER="LOOK_PICTURE_CHOOSE_CORRECT_ANSWER",_.LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER="LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER",_.FILL_MISSING_WORDS_IN_GRID="FILL_MISSING_WORDS_IN_GRID",_.LABEL_THE_PICTURE="LABEL_THE_PICTURE",_.LOOK_PICTURE_FILL_WORD_HINT="LOOK_PICTURE_FILL_WORD_HINT",_.READ_AND_COLOR_OBJECTS="READ_AND_COLOR_OBJECTS",_.IMAGE_OBJECT_MATCHING="IMAGE_OBJECT_MATCHING",_.READ_PASSAGE_AND_ANSWER_QUESTIONS="READ_PASSAGE_AND_ANSWER_QUESTIONS",_.WRITE_A_SHORT_LETTER="WRITE_A_SHORT_LETTER",_.WRITE_CORRECT_VERB_FORM="WRITE_CORRECT_VERB_FORM",_.FILL_IN_BLANK="FILL_IN_BLANK",_.CHOOSE_CORRECT_ADJECTIVE="CHOOSE_CORRECT_ADJECTIVE"}(QuestionBankEditorType||(QuestionBankEditorType={}));export function QuestionEditorRenderer({questionType:u,content:B,correctAnswer:c,explanation:p,points:d,onChange:H,validationRef:D}){const W=e(null),[y,Q]=t(!1);E(()=>{Q(!0)},[]);const k=D||W;if(!y)return _("div",{className:"text-center py-8 text-gray-500",children:n("admin.questionBank.dialog.edit.loading")});const F={content:B,correctAnswer:c,explanation:p,points:d,onChange:H,validationRef:k};switch(u){case QuestionBankEditorType.CHOOSE_THE_CORRECT_ANSWER:return O(F);case QuestionBankEditorType.LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:return C(F);case QuestionBankEditorType.LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:return I(F);case QuestionBankEditorType.FILL_MISSING_WORDS_IN_GRID:return r(F);case QuestionBankEditorType.LABEL_THE_PICTURE:return i(F);case QuestionBankEditorType.LOOK_PICTURE_FILL_WORD_HINT:return a(F);case QuestionBankEditorType.READ_AND_COLOR_OBJECTS:return A(F);case QuestionBankEditorType.IMAGE_OBJECT_MATCHING:return o(F);case QuestionBankEditorType.READ_PASSAGE_AND_ANSWER_QUESTIONS:return L(F);case QuestionBankEditorType.WRITE_A_SHORT_LETTER:return S(F);case QuestionBankEditorType.WRITE_CORRECT_VERB_FORM:return s(F);case QuestionBankEditorType.FILL_IN_BLANK:return T(F);case QuestionBankEditorType.CHOOSE_CORRECT_ADJECTIVE:return R(F);default:return _(N,{questionType:u,content:B,correctAnswer:c,explanation:p})}}
@@ -0,0 +1,15 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { MessageKey } from '../../../shared/lib/i18n';
3
+ /** Question-bank difficulty values (API wire format). */
4
+ export declare enum DifficultyLevel {
5
+ EASY = "easy",
6
+ MEDIUM = "medium",
7
+ HARD = "hard"
8
+ }
9
+ export interface DifficultyLevelOption {
10
+ value: DifficultyLevel;
11
+ labelKey: MessageKey;
12
+ icon: ReactNode;
13
+ }
14
+ export declare const DIFFICULTY_LEVELS: DifficultyLevelOption[];
15
+ export declare function parseDifficultyLevel(value: string | null | undefined): DifficultyLevel;
@@ -0,0 +1 @@
1
+ import{Sparkles as e,Target as i,Zap as l}from"lucide-react";import{createElement as f}from"react";export var DifficultyLevel;!function(e){e.EASY="easy",e.MEDIUM="medium",e.HARD="hard"}(DifficultyLevel||(DifficultyLevel={}));export const DIFFICULTY_LEVELS=[{value:DifficultyLevel.EASY,labelKey:"admin.questionBank.difficulty.easy",icon:f(l,{className:"h-3.5 w-3.5"})},{value:DifficultyLevel.MEDIUM,labelKey:"admin.questionBank.difficulty.medium",icon:f(i,{className:"h-3.5 w-3.5"})},{value:DifficultyLevel.HARD,labelKey:"admin.questionBank.difficulty.hard",icon:f(e,{className:"h-3.5 w-3.5"})}];export function parseDifficultyLevel(e){return e===DifficultyLevel.MEDIUM?DifficultyLevel.MEDIUM:e===DifficultyLevel.HARD?DifficultyLevel.HARD:DifficultyLevel.EASY}
@@ -0,0 +1,5 @@
1
+ import type { QuestionEditorAdapterProps } from './types';
2
+ export declare function renderChooseTheCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
3
+ export declare function renderLookPictureChooseCorrectAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
4
+ export declare function renderLookPictureFillBlankChooseAnswerEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
5
+ export declare function renderChooseCorrectAdjectiveEditor({ content, correctAnswer, explanation, points, onChange, }: QuestionEditorAdapterProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{ChooseTheCorrectAnswerCreator as n}from"../../types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator";import{normalizeChooseAnswerCorrectAnswer as o,normalizeChooseAnswerOptions as t,pickRawChooseAnswer as r}from"../../types/choose-the-correct-answer/normalize";import{LookPictureChooseCorrectAnswer as i}from"../../types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator";import{LookPictureFillBlankChooseAnswer as s}from"../../types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator";import{ChooseCorrectAdjectiveCreator as a}from"../../types/choose-correct-adjective/ChooseCorrectAdjectiveCreator";export function renderChooseTheCorrectAnswerEditor({content:i,correctAnswer:s,explanation:a,points:c,onChange:p,validationRef:l}){const w=i.options,m={question:i.question||"",options:t(w,4),correctAnswer:o(r(s),w),multipleAnswers:Boolean(i.multipleAnswers??s?.multipleAnswers),imageUrl:i.imageUrl||"",audioUrl:i.audioUrl||"",askerName:i.askerName||"",answererName:i.answererName||"",explanation:a||"",points:c||1};return e(n,{initialData:m,validationRef:l,onChange:e=>{p?.({content:{question:e?.question,options:e?.options,imageUrl:e?.imageUrl,audioUrl:e?.audioUrl,askerName:e?.askerName,answererName:e?.answererName,...e?.multipleAnswers?{multipleAnswers:!0}:{}},answer:{answer:e?.correctAnswer,...e?.multipleAnswers?{multipleAnswers:!0}:{}},explanation:e?.explanation,points:e?.points})}})}export function renderLookPictureChooseCorrectAnswerEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:s,validationRef:a}){const c={imageUrl:n.imageUrl||"",options:n.options||["",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(i,{initialData:c,validationRef:a,onChange:e=>{s?.({content:{imageUrl:e?.imageUrl,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}export function renderLookPictureFillBlankChooseAnswerEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:i,validationRef:a}){const c={imageUrl:n.imageUrl||"",question:n.question||"",options:n.options||["","","",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(s,{initialData:c,validationRef:a,onChange:e=>{i?.({content:{imageUrl:e?.imageUrl,question:e?.question,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}export function renderChooseCorrectAdjectiveEditor({content:n,correctAnswer:o,explanation:t,points:r,onChange:i}){const s={sentence:n.sentence||"",options:n.options||["","",""],correctAnswer:o?.answer??-1,explanation:t||"",points:r||1};return e(a,{initialData:s,onChange:e=>{i?.({content:{sentence:e?.sentence,options:e?.options},answer:{answer:e?.correctAnswer},explanation:e?.explanation,points:e?.points})}})}
@@ -0,0 +1,5 @@
1
+ export { renderChooseTheCorrectAnswerEditor, renderLookPictureChooseCorrectAnswerEditor, renderLookPictureFillBlankChooseAnswerEditor, renderChooseCorrectAdjectiveEditor, } from './choice-adapters';
2
+ export { renderFillMissingWordsInGridEditor, renderLabelThePictureEditor, renderLookPictureFillWordHintEditor, renderReadAndColorObjectsEditor, renderImageObjectMatchingEditor, } from './media-adapters';
3
+ export { renderReadPassageAndAnswerQuestionsEditor, renderWriteAShortLetterEditor, renderWriteCorrectVerbFormEditor, renderFillInBlankEditor, } from './writing-adapters';
4
+ export { UnsupportedEditorFallback } from './unsupported-fallback';
5
+ export type { QuestionEditorAdapterProps, QuestionEditorChangeData } from './types';
@@ -0,0 +1 @@
1
+ export{renderChooseTheCorrectAnswerEditor,renderLookPictureChooseCorrectAnswerEditor,renderLookPictureFillBlankChooseAnswerEditor,renderChooseCorrectAdjectiveEditor}from"./choice-adapters";export{renderFillMissingWordsInGridEditor,renderLabelThePictureEditor,renderLookPictureFillWordHintEditor,renderReadAndColorObjectsEditor,renderImageObjectMatchingEditor}from"./media-adapters";export{renderReadPassageAndAnswerQuestionsEditor,renderWriteAShortLetterEditor,renderWriteCorrectVerbFormEditor,renderFillInBlankEditor}from"./writing-adapters";export{UnsupportedEditorFallback}from"./unsupported-fallback";
@@ -0,0 +1,6 @@
1
+ import type { QuestionEditorAdapterProps } from './types';
2
+ export declare function renderFillMissingWordsInGridEditor({ content, correctAnswer, onChange, }: QuestionEditorAdapterProps): import("react").JSX.Element;
3
+ export declare function renderLabelThePictureEditor({ content, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
4
+ export declare function renderLookPictureFillWordHintEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
5
+ export declare function renderReadAndColorObjectsEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
6
+ export declare function renderImageObjectMatchingEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as n}from"react/jsx-runtime";import{FillMissingWordsInGridCreator as e}from"../../types/fill-missing-words-in-grid/FillMissingWordsInGridCreator";import{LabelThePictureCreator as o}from"../../types/label-the-picture/LabelThePictureCreator";import{LookPictureFillWordHintCreator as r}from"../../types/look-picture-fill-word-hint/LookPictureFillWordHintCreator";import{ReadAndColorObjectsCreator as t}from"../../types/read-and-color-objects/ReadAndColorObjectsCreator";import{ImageObjectMatchingCreator as i}from"../../types/image-object-matching/ImageObjectMatchingCreator";export function renderFillMissingWordsInGridEditor({content:o,correctAnswer:r,onChange:t}){const i={content:{grid:o.grid||[],rows:o.rows||5,columns:o.columns||5,disabledCells:o.disabledCells||[]},answer:{answers:r?.answers||{},caseSensitive:r?.caseSensitive??!1}};return n(e,{initialData:i,onChange:n=>{t?.({content:{grid:n?.content?.grid,rows:n?.content?.rows,columns:n?.content?.columns,disabledCells:n?.content?.disabledCells},answer:{answers:n?.answer?.answers,caseSensitive:n?.answer?.caseSensitive},explanation:n?.explanation,points:n?.points})}})}export function renderLabelThePictureEditor({content:e,explanation:r,points:t,onChange:i,validationRef:a}){const s={imageUrl:e.imageUrl||"",wordBank:e.wordBank||[],labels:e.labels||[],explanation:r||"",points:t||1};return n(o,{initialData:s,validationRef:a,onChange:n=>{const e={};(n?.labels||[]).forEach(n=>{!n.isPreFilled&&n.correctAnswer&&(e[n.id]=n.correctAnswer)}),i?.({content:{imageUrl:n?.imageUrl,wordBank:n?.wordBank,labels:n?.labels},answer:{labels:e},explanation:n?.explanation,points:n?.points})}})}export function renderLookPictureFillWordHintEditor({content:e,correctAnswer:o,explanation:t,points:i,onChange:a,validationRef:s}){const l={subQuestions:[{id:"edit-1",imageUrl:e.imageUrl||"",word:e.word||"",correctAnswer:o?.correctAnswer||""}],hintLetters:[],explanation:t||"",points:i||1};return n(r,{initialData:l,validationRef:s,onChange:n=>{const e=n?.subQuestions?.[0]||{};a?.({content:{imageUrl:e.imageUrl,word:e.word},answer:{correctAnswer:e.correctAnswer},explanation:n?.explanation,points:n?.points})}})}export function renderReadAndColorObjectsEditor({content:e,correctAnswer:o,explanation:r,points:i,onChange:a,validationRef:s}){const l={backgroundImageUrl:e.backgroundImageUrl||"",colorNodes:e.colorNodes||[],regionNodes:e.regionNodes||[],instructions:e.instructions||[],regions:o?.regions||{},explanation:r||"",points:i||1};return n(t,{initialData:l,validationRef:s,onChange:n=>{a?.({content:{backgroundImageUrl:n?.backgroundImageUrl,colorNodes:n?.colorNodes,regionNodes:n?.regionNodes,instructions:n?.instructions},answer:{regions:n?.regions},explanation:n?.explanation,points:n?.points})}})}export function renderImageObjectMatchingEditor({content:e,correctAnswer:o,explanation:r,points:t,onChange:a,validationRef:s}){const l={backgroundImageUrl:e.backgroundImageUrl||"",colorNodes:e.colorNodes||[],regionNodes:e.regionNodes||[],instructions:e.instructions||[],regions:o?.regions||{},explanation:r||"",points:t||1};return n(i,{initialData:l,validationRef:s,onChange:n=>{a?.({content:{backgroundImageUrl:n?.backgroundImageUrl,colorNodes:n?.colorNodes,regionNodes:n?.regionNodes,instructions:n?.instructions},answer:{regions:n?.regions},explanation:n?.explanation,points:n?.points})}})}
@@ -0,0 +1 @@
1
+ export type { QuestionEditorAdapterProps, QuestionEditorChangeData } from '../types';
@@ -0,0 +1,8 @@
1
+ interface UnsupportedEditorFallbackProps {
2
+ questionType: string;
3
+ content: Record<string, unknown>;
4
+ correctAnswer: Record<string, unknown> | null;
5
+ explanation?: string | null;
6
+ }
7
+ export declare function UnsupportedEditorFallback({ questionType, content, correctAnswer, explanation, }: UnsupportedEditorFallbackProps): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{t}from"../../../../shared/lib/i18n";export function UnsupportedEditorFallback({questionType:a,content:d,correctAnswer:i,explanation:n}){return r("div",{className:"space-y-6",children:[e("div",{className:"bg-yellow-50 border border-yellow-200 rounded-lg p-4",children:r("p",{className:"text-yellow-800 text-sm",children:[e("strong",{children:t("admin.questionBank.dialog.edit.unsupportedNote")})," ",t("admin.questionBank.dialog.edit.unsupportedType",{type:a})]})}),r("div",{className:"grid gap-4 md:grid-cols-2",children:[r("div",{children:[e("p",{className:"text-sm font-medium text-gray-700 mb-2",children:t("admin.questionBank.dialog.edit.contentLabel")}),e("pre",{className:"max-h-60 overflow-auto rounded-lg bg-gray-50 p-3 text-xs text-gray-900 border border-gray-200",children:JSON.stringify(d,null,2)})]}),i&&r("div",{children:[e("p",{className:"text-sm font-medium text-gray-700 mb-2",children:t("admin.questionBank.dialog.edit.answerLabel")}),e("pre",{className:"max-h-60 overflow-auto rounded-lg bg-gray-50 p-3 text-xs text-gray-900 border border-gray-200",children:JSON.stringify(i,null,2)})]})]}),n&&r("div",{children:[e("p",{className:"text-sm font-medium text-gray-700 mb-2",children:t("admin.questionBank.dialog.edit.explanationLabel")}),e("div",{className:"bg-blue-50 border border-blue-200 rounded-lg p-3 text-sm text-gray-900",children:n})]})]})}
@@ -0,0 +1,5 @@
1
+ import type { QuestionEditorAdapterProps } from './types';
2
+ export declare function renderReadPassageAndAnswerQuestionsEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
3
+ export declare function renderWriteAShortLetterEditor({ content, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
4
+ export declare function renderWriteCorrectVerbFormEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
5
+ export declare function renderFillInBlankEditor({ content, correctAnswer, explanation, points, onChange, validationRef, }: QuestionEditorAdapterProps): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as n}from"react/jsx-runtime";import{ReadPassageAndAnswerQuestionsCreator as t}from"../../types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator";import{WriteAShortLetterCreator as e}from"../../types/write-a-short-letter/WriteAShortLetterCreator";import{WriteCorrectVerbFormCreator as i}from"../../types/write-correct-verb-form/WriteCorrectVerbFormCreator";import{FillInBlankCreator as o}from"../../types/fill-in-blank/FillInBlankCreator";export function renderReadPassageAndAnswerQuestionsEditor({content:e,correctAnswer:i,explanation:o,points:s,onChange:r,validationRef:a}){const c={passageTitle:"",passage:"",instructions:"",singleQuestion:{id:"edit-1",question:e.question||"",options:e.options||["","","",""],correctAnswer:i?.correctAnswer??-1,points:s||1},explanation:o||"",points:s||1};return n(t,{initialData:c,validationRef:a,onChange:n=>{const t=n?.singleQuestion||{};r?.({content:{question:t.question,options:t.options},answer:{correctAnswer:t.correctAnswer},explanation:n?.explanation,points:n?.points||t.points})}})}export function renderWriteAShortLetterEditor({content:t,explanation:i,points:o,onChange:s,validationRef:r}){const a={informations:t.informations||[],minWords:t.minWords||25,maxWords:t.maxWords||50,instruction:t.instructions?.mainInstruction||"",explanation:i||"",points:o||1};return n(e,{initialData:a,validationRef:r,onChange:n=>{s?.({content:{informations:n?.informations,minWords:n?.minWords,maxWords:n?.maxWords,instructions:{mainInstruction:n?.instruction}},answer:null,explanation:n?.explanation,points:n?.points})}})}export function renderWriteCorrectVerbFormEditor({content:t,correctAnswer:e,explanation:o,points:s,onChange:r,validationRef:a}){const c={sentence:t.sentence||"",verbHint:t.verbHint||"",correctAnswer:e?.correctAnswer||"",caseSensitive:e?.caseSensitive??!1,instruction:t.instruction||"Write the correct form of the verb in parentheses to complete each sentence. Pay attention to the tense.",explanation:o||"",points:s||1};return n(i,{initialData:c,validationRef:a,onChange:n=>{r?.({content:{sentence:n?.sentence,verbHint:n?.verbHint},answer:{correctAnswer:n?.correctAnswer,caseSensitive:n?.caseSensitive},explanation:n?.explanation,points:n?.points})}})}export function renderFillInBlankEditor({content:t,correctAnswer:e,explanation:i,points:s,onChange:r,validationRef:a}){const c={question:t.question||"",answers:e?.answers||[],caseSensitive:e?.caseSensitive??!1,showHints:t.showHints??!1,hints:t.hints||[],audioUrl:t.audioUrl||"",explanation:i||"",points:s||1};return n(o,{initialData:c,validationRef:a,onChange:n=>{r?.({content:{question:n?.question,showHints:n?.showHints??!1,hints:n?.showHints&&n?.hints||[],audioUrl:n?.audioUrl||""},answer:{answers:n?.answers,caseSensitive:n?.caseSensitive},explanation:n?.explanation,points:n?.points})}})}
@@ -0,0 +1,4 @@
1
+ export { EditQuestionBankDialog } from './EditQuestionBankDialog';
2
+ export { QuestionEditorRenderer, QuestionBankEditorType } from './QuestionEditorRenderer';
3
+ export { DifficultyLevel, DIFFICULTY_LEVELS, parseDifficultyLevel } from './difficulty';
4
+ export type { EditQuestionBankDialogProps, QuestionBankEditItem, QuestionEditorChangeData, QuestionEditorRendererProps, SkillType, UpdateQuestionBankDto, } from './types';
@@ -0,0 +1 @@
1
+ export{EditQuestionBankDialog}from"./EditQuestionBankDialog";export{QuestionEditorRenderer,QuestionBankEditorType}from"./QuestionEditorRenderer";export{DifficultyLevel,DIFFICULTY_LEVELS,parseDifficultyLevel}from"./difficulty";
@@ -0,0 +1,59 @@
1
+ import type { MutableRefObject } from 'react';
2
+ import type { ValidationRef } from '../creator/dedicated-component-router';
3
+ import type { DifficultyLevel } from './difficulty';
4
+ export type SkillType = 'READING' | 'WRITING' | 'LISTENING' | 'SPEAKING';
5
+ /** Minimal question bank item required by the edit dialog. */
6
+ export interface QuestionBankEditItem {
7
+ id: string;
8
+ code: string;
9
+ title: string | null;
10
+ content: Record<string, unknown>;
11
+ correctAnswer: Record<string, unknown> | null;
12
+ questionType: string;
13
+ difficulty: DifficultyLevel | string;
14
+ skill: SkillType | string | null;
15
+ points: string | number;
16
+ explanation: string | null;
17
+ }
18
+ /** Payload host apps pass to their update API. */
19
+ export interface UpdateQuestionBankDto {
20
+ code?: string;
21
+ title?: string;
22
+ content?: Record<string, unknown>;
23
+ correctAnswer?: Record<string, unknown>;
24
+ difficulty?: DifficultyLevel;
25
+ skill?: SkillType;
26
+ points?: number;
27
+ explanation?: string;
28
+ }
29
+ export interface EditQuestionBankDialogProps {
30
+ open: boolean;
31
+ onOpenChange: (open: boolean) => void;
32
+ question: QuestionBankEditItem | null;
33
+ onSave: (data: UpdateQuestionBankDto) => void;
34
+ saving: boolean;
35
+ }
36
+ export interface QuestionEditorChangeData {
37
+ content: Record<string, unknown>;
38
+ answer: Record<string, unknown> | null;
39
+ explanation?: string;
40
+ points?: number;
41
+ }
42
+ export interface QuestionEditorRendererProps {
43
+ questionType: string;
44
+ content: Record<string, unknown>;
45
+ correctAnswer: Record<string, unknown> | null;
46
+ explanation?: string | null;
47
+ points?: number;
48
+ onChange?: (data: QuestionEditorChangeData) => void;
49
+ onSave?: (data: unknown) => void;
50
+ validationRef?: MutableRefObject<ValidationRef | null>;
51
+ }
52
+ export interface QuestionEditorAdapterProps {
53
+ content: Record<string, unknown>;
54
+ correctAnswer: Record<string, unknown> | null;
55
+ explanation?: string | null;
56
+ points?: number;
57
+ onChange?: (data: QuestionEditorChangeData) => void;
58
+ validationRef: MutableRefObject<ValidationRef | null>;
59
+ }
@@ -0,0 +1 @@
1
+ export{};
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{ImagePreview as t}from"../../../../components/ui/image-preview";import{useState as n,useRef as s,useEffect as o,useMemo as a}from"react";import{Button as i}from"../../../../components/ui/button";import{Label as l}from"../../../../components/ui/label";import{Input as c}from"../../../../components/ui/input";import{Textarea as d}from"../../../../components/ui/textarea";import{PointsInput as m}from"../../../../components/ui/points-input";import{Card as g,CardContent as p,CardHeader as u,CardTitle as h}from"../../../../components/ui/card";import{RadioGroup as x}from"../../../../components/ui/radio-group";import{Switch as f}from"../../../../components/ui/switch";import{usePresignedFileUrl as b,useDebouncedCallback as w}from"../../../../shared/lib/hooks";import{useReactHookForm as N}from"../../../../shared/lib/hooks/useReactHookForm";import{Pencil as y,Eye as v,Plus as A,Trash2 as C,HelpCircle as V,CheckCircle2 as U,Lightbulb as k,MessageSquare as T,ImageIcon as S,Type as E,Users as q,BookOpen as I,Star as G,ListChecks as O}from"lucide-react";import{FileUpload as j}from"../../../../components/ui/file-upload";import{ChooseTheCorrectAnswerClient as $}from"./ChooseTheCorrectAnswerClient";import{chooseCorrectAnswerFormSchema as R}from"../../../../shared/lib/validation/choose-correct-answer.validation";import{BasicQuestionGroupCard as z}from"../../groups/BasicQuestionGroupCard";import{ArticlesGroupCard as B}from"../../groups/ArticlesGroupCard";import{DocumentGroupCard as F}from"../../groups/DocumentGroupCard";import{useBasicQuestionGroup as J}from"../../_shared/hooks/useBasicQuestionGroup";import{z as P}from"zod";function D({src:r,alt:t}){const{previewUrl:n,isLoading:s}=b(r);return e("div",s?{className:"flex h-24 w-full max-w-[200px] items-center justify-center rounded-lg border border-gray-200 bg-gray-50",children:e("div",{className:"h-5 w-5 animate-spin rounded-full border-2 border-gray-200 border-t-blue-500"})}:{className:"relative h-24 w-full max-w-[200px] overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:e("img",{src:n||r,alt:t,className:"h-full w-full object-contain",onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})})}function L({initialData:L,onSave:M,onCancel:H,onChange:Q,externalErrors:Z,optionCount:K=4,optionMode:X,defaultValue:_,defaultQuestion:W,viewMode:Y,onUnsavedChangesChange:ee,validationRef:re,groups:te,questionIndexInPart:ne=0,partId:se="",questionConfig:oe,groupType:ae,groupConfig:ie,articleCount:le=0,multipleAnswers:ce,headerExtra:de}){console.log("=== viewMode ===",Y);const me=L,ge=a(()=>R.superRefine((e,r)=>{"CONVERSATION"===Y&&(e.askerName?.trim()||r.addIssue({code:P.ZodIssueCode.custom,message:"Vui lòng nhập tên người hỏi!",path:["askerName"]}),e.answererName?.trim()||r.addIssue({code:P.ZodIssueCode.custom,message:"Vui lòng nhập tên người trả lời!",path:["answererName"]}))}),[Y]),pe=me?.correctAnswer,ue=Array.isArray(pe)?pe:"object"==typeof pe&&null!==pe?pe?.answer??-1:pe??-1,he=Boolean(me?.multipleAnswers??me?.content?.multipleAnswers??me?.questionGroup?.payload?.multipleAnswers??Array.isArray(ue)),xe=N({defaultValues:{question:me?.content?.question||me?.question||W||"",optionType:me?.content?.optionType||me?.optionType||"text",options:(me?.content?.options||me?.options)?.length>0?me?.content?.options||me?.options:_&&_.length>0?_:Array.from({length:K},()=>""),correctAnswer:he?Array.isArray(ue)?ue:-1===ue?[]:[ue]:Array.isArray(ue)?ue[0]??-1:ue,multipleAnswers:he||Boolean(ce),imageUrl:me?.content?.imageUrl||me?.imageUrl||"",explanation:me?.explanation||"",askerName:me?.content?.askerName||me?.askerName||"",answererName:me?.content?.answererName||me?.answererName||"",isExample:me?.isExample||!1,points:me?.points??1},zodSchema:ge,mode:"onBlur"}),[fe,be]=n(!1),[we,Ne]=n(""),[ye,ve]=n({}),{isGrouped:Ae,currentGroupNumber:Ce,isFirstInGroup:Ve,groupTitle:Ue,groupSubtitle:ke,groupContent:Te,imageUrl:Se,articles:Ee,setGroupTitle:qe,setGroupSubtitle:Ie,setGroupContent:Ge,setImageUrl:Oe,setArticles:je}=J({partId:se,groups:te,questionIndexInPart:ne,initialData:{title:L?.groupTitle||L?.questionGroup?.payload?.title||L?.title||"",subtitle:L?.groupSubtitle||L?.questionGroup?.payload?.subtitle||"",content:L?.groupContent||L?.questionGroup?.payload?.content||"",imageUrl:L?.groupImageUrl||L?.questionGroup?.payload?.imageUrl||"",articles:L?.articles||L?.questionGroup?.payload?.articles||void 0},articleCount:le}),$e=s(null),Re=s(null),ze=s(L),Be=s(!1),Fe=s(Q),Je=s("");o(()=>{Fe.current=Q},[Q]);const Pe=w(e=>{Fe.current?.(e)},300),De=xe.watch("question"),Le=xe.watch("optionType"),Me=xe.watch("options"),He=xe.watch("correctAnswer"),Qe=xe.watch("multipleAnswers"),Ze=xe.watch("imageUrl"),Ke=xe.watch("explanation"),Xe=xe.watch("askerName"),_e=xe.watch("answererName"),We=xe.watch("isExample"),Ye=xe.watch("points"),er="image"===X?.toLowerCase()?"image":"text",rr=(ae||"BASIC").toUpperCase(),tr=!oe||0===oe.length||oe.includes("imageUrl"),nr=!ie||0===ie.length||ie.includes("imageUrl");o(()=>{er&&Le!==er&&xe.setValue("optionType",er)},[er,Le,xe]);const{previewUrl:sr}=b(Ze),or=we||sr||"";o(()=>{re&&(re.current={triggerValidation:async()=>await xe.trigger(),getFormData:()=>({question:De,optionType:Le,options:Me,correctAnswer:He,multipleAnswers:Qe,imageUrl:tr?Ze:"",explanation:Ke,askerName:Xe,answererName:_e,isExample:We,points:Ye,groupTitle:Ue,groupSubtitle:ke,groupContent:Te,groupImageUrl:nr?Se:"",groupNumber:Ce,..."ARTICLES"===rr?{articles:Ee}:{}})})},[re,xe,He,Qe,De,Le,Me,Ze,Ke,Xe,_e,We,Ye,Ue,ke,Te,Se,Ce,ae,Ee]),o(()=>{const e=L,r={question:e?.content?.question||e?.question||W||"",optionType:e?.content?.optionType||e?.optionType||"text",options:(e?.content?.options||e?.options)?.length>0?e?.content?.options||e?.options:_&&_.length>0?_:Array.from({length:K},()=>""),correctAnswer:he?Array.isArray(ue)?ue:-1===ue?[]:[ue]:Array.isArray(ue)?ue[0]??-1:ue,multipleAnswers:he||Boolean(ce),imageUrl:e?.content?.imageUrl||e?.imageUrl||"",explanation:e?.explanation||"",askerName:e?.content?.askerName||e?.askerName||"",answererName:e?.content?.answererName||e?.answererName||"",isExample:e?.isExample||!1,points:e?.points??1,groupTitle:e?.groupTitle||e?.questionGroup?.payload?.title||"",groupContent:e?.groupContent||e?.questionGroup?.payload?.content||"",groupImageUrl:e?.groupImageUrl||e?.questionGroup?.payload?.imageUrl||""};if(!(JSON.stringify(ze.current)!==JSON.stringify(L)))return;ze.current=L;const t={question:De,optionType:Le,options:Me,correctAnswer:He,multipleAnswers:Qe,imageUrl:Ze,explanation:Ke,askerName:Xe,answererName:_e,isExample:We,points:Ye},n=t.question===r.question&&t.optionType===r.optionType&&JSON.stringify(t.correctAnswer)===JSON.stringify(r.correctAnswer)&&t.multipleAnswers===r.multipleAnswers&&t.points===r.points&&t.explanation===r.explanation&&t.imageUrl===r.imageUrl&&JSON.stringify(t.options)===JSON.stringify(r.options);if(n&&!0===L?.isCompleted)return;const s=!n&&(JSON.stringify(r.correctAnswer)!==JSON.stringify(t.correctAnswer)||r.multipleAnswers!==t.multipleAnswers||r.question!==t.question||r.imageUrl!==t.imageUrl),o=Array.isArray(r.correctAnswer)?r.correctAnswer.length>0:-1!==r.correctAnswer;s&&o&&(Be.current=!0,xe.reset(r),setTimeout(()=>{Be.current=!1},150))},[L,K,ce,xe,De,Le,Me,He,Qe,Ze,Ke,Xe,_e,We,Ye]);const ar=JSON.stringify(Me);o(()=>{if(Be.current){const e=JSON.stringify({question:De,optionType:Le,options:Me,correctAnswer:He,multipleAnswers:Qe,imageUrl:Ze,explanation:Ke,askerName:Xe,answererName:_e,isExample:We,points:Ye,groupTitle:Ue,groupSubtitle:ke,groupContent:Te,groupImageUrl:Se,groupNumber:Ce,..."ARTICLES"===rr?{articles:Ee}:{}});return void(Je.current=e)}const e={question:De,optionType:Le,options:Me,correctAnswer:He,multipleAnswers:Qe,imageUrl:tr?Ze:"",explanation:Ke,askerName:Xe,answererName:_e,isExample:We,points:Ye,groupTitle:Ue,groupSubtitle:ke,groupContent:Te,groupImageUrl:nr?Se:"",groupNumber:Ce,..."ARTICLES"===rr?{articles:Ee}:{}},r=JSON.stringify(e);Je.current!==r&&(Je.current=r,Pe(e))},[De,Le,ar,He,Qe,Ze,Ke,Xe,_e,We,Ye,Ue,ke,Te,Se,Ce,ae,Ee]);xe.handleSubmit(e=>{if(e.multipleAnswers){if((Array.isArray(e.correctAnswer)?e.correctAnswer:-1===e.correctAnswer?[]:[e.correctAnswer]).some(r=>r<0||r>=e.options.length))return void xe.setError("correctAnswer",{message:"Đáp án đúng không hợp lệ!"})}else{const r="number"==typeof e.correctAnswer?e.correctAnswer:-1;if(-1!==r&&r>=e.options.length)return void xe.setError("correctAnswer",{message:"Đáp án đúng không hợp lệ!"})}$e.current=null,Re.current=null,M?.(e)});if(fe){const t={question:De||"",optionType:Le,options:Me,correctAnswer:He,multipleAnswers:Qe,imageUrl:or||Ze,explanation:Ke,askerName:Xe,answererName:_e,isExample:We,isGroup:Ae,groupTitle:Ue,groupSubtitle:ke,groupContent:Te,groupImageUrl:Se,groupNumber:Ce,..."ARTICLES"===rr?{articles:Ee}:{}};return r("div",{className:"space-y-4",children:[e(g,{children:e(u,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(h,{children:"Choose the correct answer (Preview)"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Chế độ xem trước - Hiển thị đáp án đúng"})]}),r(i,{variant:"outline",size:"sm",onClick:()=>be(!1),children:[e(y,{className:"mr-2 h-4 w-4"}),"Quay lại Edit Mode"]})]})})}),e($,{questionData:t,questionConfig:oe,isReviewMode:!0,userAnswer:Qe||-1!==He?He:void 0})]})}return r("div",{className:"space-y-4",children:[Ae&&"ARTICLES"===rr&&e(B,{groupNumber:Ce,articleCount:le,articles:Ee,onArticlesChange:je,title:Ue,onTitleChange:qe,isReadOnly:!Ve,uploadIdPrefix:`choose-correct-answer-${se??"articles"}`}),Ae&&"BASIC"===rr&&e(z,{groupNumber:Ce,title:Ue,subtitle:ke,content:Te,imageUrl:Se,onTitleChange:qe,onSubtitleChange:Ie,onContentChange:Ge,onImageChange:Oe,groupConfig:ae?ie:void 0,isReadOnly:!Ve,uploadIdPrefix:`choose-correct-answer-${se??"group"}`}),Ae&&"DOCUMENT"===rr&&e(F,{groupNumber:Ce,title:Ue,subtitle:ke,content:Te,imageUrl:Se,onTitleChange:qe,onSubtitleChange:Ie,onContentChange:Ge,onImageChange:Oe,groupConfig:ae?ie:void 0,isReadOnly:!Ve,uploadIdPrefix:`choose-correct-answer-${se??"document"}`}),r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-blue-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100",children:e(V,{className:"h-4 w-4 text-gray-600"})}),r("div",{children:[e(h,{className:"text-base font-bold text-gray-900",children:"Chọn đáp án đúng"}),e("p",{className:"text-xs text-gray-500",children:"Tạo câu hỏi trắc nghiệm với nhiều lựa chọn"})]})]}),r("div",{className:"flex items-center gap-2",children:[de,r(i,{variant:"outline",size:"sm",onClick:()=>be(!0),disabled:Me.filter(e=>e.trim()).length<2,className:"gap-2 border-indigo-200 text-indigo-600 hover:bg-indigo-50 hover:text-indigo-700",children:[e(v,{className:"h-4 w-4"}),"Xem trước"]})]})]})}),r(p,{className:"space-y-3 px-4 pb-4",children:[r("div",{className:"flex flex-wrap items-center justify-between gap-y-2",children:[e(m,{...xe.register("points",{valueAsNumber:!0}),error:xe.hasError("points")?xe.getFieldError("points"):void 0}),r("div",{className:"flex items-center gap-2",children:[r("button",{type:"button",style:{paddingBlock:"calc(var(--spacing) * 1)"},onClick:()=>xe.setValue("isExample",!We),className:"inline-flex items-center gap-2 rounded-md border px-3.5 text-sm font-medium transition-colors select-none "+(We?"border-amber-300 bg-amber-50 text-amber-700":"border-gray-200 bg-white text-gray-400 hover:text-gray-600"),children:[e(G,{className:"h-4 w-4 "+(We?"fill-amber-400 text-amber-400":"")}),"Example"]}),r("button",{type:"button",style:{paddingBlock:"calc(var(--spacing) * 1)"},disabled:Boolean(ce),onClick:()=>{const e=!Qe,r=xe.getValues("correctAnswer"),t=Array.isArray(r)?r:-1===r?[]:[r];xe.setValue("multipleAnswers",e,{shouldValidate:!0}),xe.setValue("correctAnswer",e?t:t[0]??-1,{shouldValidate:!0})},className:`inline-flex items-center gap-2 rounded-md border px-3.5 text-sm font-medium transition-colors select-none ${Qe?"border-violet-300 bg-violet-50 text-violet-700":"border-gray-200 bg-white text-gray-400 hover:text-gray-600"} ${Boolean(ce)?"cursor-not-allowed opacity-50":""}`,children:[e(O,{className:"h-4 w-4"}),"Nhiều đáp án"]})]})]}),"CONVERSATION"===Y&&r("div",{className:"space-y-3",children:[r(l,{className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(q,{className:"h-4 w-4 text-indigo-500"}),"Hội thoại ",e("span",{className:"text-sm font-normal text-gray-500",children:"(tuỳ chọn - dùng cho câu hỏi dạng hội thoại)"})]}),r("div",{className:"grid grid-cols-2 gap-4 rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4",children:[r("div",{className:"space-y-1.5",children:[r(l,{htmlFor:"askerName",className:"flex items-center gap-1 text-sm font-medium text-gray-600",children:["Tên người hỏi ",e("span",{className:"text-red-500",children:"*"})]}),e(c,{id:"askerName",...xe.register("askerName"),placeholder:"VD: John, Mary, Teacher...",className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(xe.hasError("askerName")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),xe.hasError("askerName")&&e("p",{className:"text-sm text-red-600",children:xe.getFieldError("askerName")})]}),r("div",{className:"space-y-1.5",children:[r(l,{htmlFor:"answererName",className:"flex items-center gap-1 text-sm font-medium text-gray-600",children:["Tên người trả lời ",e("span",{className:"text-red-500",children:"*"})]}),e(c,{id:"answererName",...xe.register("answererName"),placeholder:"VD: Tom, Anna, Student...",className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(xe.hasError("answererName")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),xe.hasError("answererName")&&e("p",{className:"text-sm text-red-600",children:xe.getFieldError("answererName")})]})]})]}),(!oe||0===oe.length||oe.includes("question"))&&r("div",{className:"space-y-2",children:[r(l,{htmlFor:"question",className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(T,{className:"h-4 w-4 text-indigo-500"}),e("span",{className:"flex items-center gap-1",children:"Câu hỏi"}),e("span",{className:"text-sm font-normal text-gray-500",children:"(tuỳ chọn)"})]}),e(d,{id:"question",...xe.register("question"),placeholder:"Nhập câu hỏi...",className:"min-h-[100px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(xe.hasError("question")?"border-red-400 focus:border-red-500 focus:ring-red-200":""),rows:3}),xe.hasError("question")&&e("p",{className:"text-sm text-red-600",children:xe.getFieldError("question")})]}),(!oe||0===oe.length||oe.includes("imageUrl")||oe.includes("imageUrl "))&&r("div",{className:"space-y-2",children:[r(l,{className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(S,{className:"h-4 w-4 text-indigo-500"}),"Hình ảnh ",e("span",{className:"text-sm font-normal text-gray-500"})]}),e(j,{id:"question-image",label:"",accept:"image/*",value:Ze||"",onChange:e=>{xe.setValue("imageUrl",e,{shouldValidate:!0})},onPresignedUrlChange:Ne,maxSize:5,placeholder:"Upload ảnh hoặc paste URL",autoUpload:!0,prefix:"questions"}),xe.hasError("imageUrl")&&e("p",{className:"mt-1 text-sm text-red-600",children:xe.getFieldError("imageUrl")}),or&&e(t,{src:or,alt:"Preview",className:"mt-2 h-48 w-full max-w-md rounded-lg border border-gray-200"})]}),Z&&Z.length>0&&r("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100",children:e("span",{className:"text-lg",children:"❌"})}),r("div",{className:"text-sm",children:[e("p",{className:"font-semibold text-red-800",children:"Lỗi:"}),e("ul",{className:"mt-1 list-inside list-disc text-red-700",children:Z.map((r,t)=>e("li",{children:r},t))})]})]}),xe.formState.errors.options?.message&&e("div",{className:"rounded-xl border border-red-200 bg-red-50 p-4",children:e("p",{className:"text-sm text-red-600",children:xe.formState.errors.options.message})})]})]}),(!oe||0===oe.length||oe.includes("options"))&&r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-indigo-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-md bg-indigo-100",children:e(k,{className:"h-3.5 w-3.5 text-indigo-600"})}),r(h,{className:"text-base font-semibold text-gray-800",children:["Các lựa chọn ",r("span",{className:"text-xs font-normal text-gray-500",children:["(",Me.length," đáp án)"]})]})]}),r("div",{className:"flex items-center gap-3",children:[r("div",{className:"flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-1.5",children:[e(E,{className:"h-3.5 w-3.5 "+("text"===Le?"text-indigo-600":"text-gray-400")}),e("span",{className:"text-xs font-medium "+("text"===Le?"text-indigo-600":"text-gray-400"),children:"Text"}),e(f,{checked:"image"===Le,disabled:!0,className:"!bg-indigo-600 !opacity-100",onCheckedChange:e=>{const r=e?"image":"text",t=xe.getValues("options"),n=xe.getValues("correctAnswer");"text"===Le?$e.current={options:t,correctAnswer:n}:Re.current={options:t,correctAnswer:n};const s="text"===r?$e.current:Re.current;if(s)xe.setValue("options",s.options),xe.setValue("correctAnswer",s.correctAnswer);else{const e=Array.from({length:t.length},()=>"");xe.setValue("options",e),xe.setValue("correctAnswer",-1)}xe.setValue("optionType",r),xe.clearErrors(),ve({})}}),e(S,{className:"h-3.5 w-3.5 "+("image"===Le?"text-indigo-600":"text-gray-400")}),e("span",{className:"text-xs font-medium "+("image"===Le?"text-indigo-600":"text-gray-400"),children:"Ảnh"})]}),r(i,{variant:"outline",size:"sm",onClick:()=>{const e=xe.getValues("options");xe.setValue("options",[...e,""])},className:"gap-2 border-green-200 text-green-600 hover:bg-green-50 hover:text-green-700",children:[e(A,{className:"h-4 w-4"}),"Thêm đáp án"]})]})]})}),r(p,{className:"space-y-3 px-4 pb-4",children:[Qe?e("div",{className:"space-y-3",children:Me.map((t,n)=>{const s=xe.formState.errors.options?.[n],o=(Array.isArray(He)?He:-1===He?[]:[He]).includes(n),a=String.fromCharCode(65+n);return e("div",{className:"group relative rounded-xl border-2 p-4 transition-all duration-200 "+(o?"border-green-300 bg-gradient-to-r from-green-50 to-emerald-50 shadow-md shadow-green-100":"border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm"),children:r("div",{className:"flex items-start gap-4",children:[e("div",{className:"flex h-10 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-xl font-bold transition-all "+(o?"bg-gradient-to-br from-green-500 to-emerald-600 text-white shadow-md":"bg-gray-100 text-gray-600 hover:bg-indigo-100 hover:text-indigo-600"),onClick:()=>{if(Qe){const e=Array.isArray(xe.getValues("correctAnswer"))?xe.getValues("correctAnswer"):[],r=e.includes(n)?e.filter(e=>e!==n):[...e,n].sort((e,r)=>e-r);return void xe.setValue("correctAnswer",r,{shouldValidate:!0})}xe.setValue("correctAnswer",n,{shouldValidate:!0})},children:a}),r("div",{className:"flex-1 space-y-2",children:["image"===Le?r("div",{className:"space-y-2",children:[e(j,{id:`option-image-${n}`,label:"",accept:"image/*",value:t||"",onChange:e=>{const r=[...Me];r[n]=e,xe.setValue("options",r,{shouldValidate:!0})},onPresignedUrlChange:e=>{ve(r=>({...r,[n]:e}))},maxSize:5,placeholder:`Upload ảnh đáp án ${a}...`,autoUpload:!0,prefix:"questions/options"}),(ye[n]||t)&&e(D,{src:ye[n]||t,alt:`Đáp án ${a}`})]}):e(c,{id:`option-input-${n}`,...xe.register(`options.${n}`),placeholder:`Nhập đáp án ${a}...`,className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(s?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),s&&e("p",{className:"text-sm text-red-600",children:s.message}),o&&r("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-700",children:[e(U,{className:"h-3.5 w-3.5"}),Qe?"Đáp án đúng đã chọn":"Đáp án đúng"]})]}),r("div",{className:"flex items-center gap-2",children:[e(i,{type:"button",variant:"ghost",size:"sm",onClick:()=>{if(Qe){const e=Array.isArray(xe.getValues("correctAnswer"))?xe.getValues("correctAnswer"):[],r=e.includes(n)?e.filter(e=>e!==n):[...e,n].sort((e,r)=>e-r);return void xe.setValue("correctAnswer",r,{shouldValidate:!0})}xe.setValue("correctAnswer",n,{shouldValidate:!0})},className:o?"text-green-600 hover:text-green-700":"text-gray-400 hover:text-green-600",title:Qe?o?"Bỏ chọn đáp án đúng":"Chọn thêm đáp án đúng":"Chọn làm đáp án đúng",children:e(U,{className:"h-4 w-4"})}),Me.length>2&&e(i,{variant:"ghost",size:"sm",onClick:()=>{const e=xe.getValues("options").filter((e,r)=>r!==n);xe.setValue("options",e);const r=xe.getValues("correctAnswer");if(Array.isArray(r)){const e=r.filter(e=>e!==n).map(e=>e>n?e-1:e);xe.setValue("correctAnswer",e,{shouldValidate:!0})}else r===n?xe.setValue("correctAnswer",-1,{shouldValidate:!0}):"number"==typeof r&&r>n&&xe.setValue("correctAnswer",r-1,{shouldValidate:!0})},className:"text-red-500 hover:bg-red-50 hover:text-red-600",children:e(C,{className:"h-4 w-4"})})]})]})},n)})}):e(x,{value:-1===He?"":He.toString(),onValueChange:e=>{xe.setValue("correctAnswer",Number(e),{shouldValidate:!0})},children:Me.map((t,n)=>{const s=xe.formState.errors.options?.[n],o=He===n,a=String.fromCharCode(65+n);return e("div",{className:"group relative rounded-xl border-2 p-4 transition-all duration-200 "+(o?"border-green-300 bg-gradient-to-r from-green-50 to-emerald-50 shadow-md shadow-green-100":"border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm"),children:r("div",{className:"flex items-start gap-4",children:[e("div",{className:"flex h-10 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-xl font-bold transition-all "+(o?"bg-gradient-to-br from-green-500 to-emerald-600 text-white shadow-md":"bg-gray-100 text-gray-600 hover:bg-indigo-100 hover:text-indigo-600"),onClick:()=>{xe.setValue("correctAnswer",n,{shouldValidate:!0})},children:a}),r("div",{className:"flex-1 space-y-2",children:["image"===Le?r("div",{className:"space-y-2",children:[e(j,{id:`option-image-${n}`,label:"",accept:"image/*",value:t||"",onChange:e=>{const r=[...Me];r[n]=e,xe.setValue("options",r,{shouldValidate:!0})},onPresignedUrlChange:e=>{ve(r=>({...r,[n]:e}))},maxSize:5,placeholder:`Upload ảnh đáp án ${a}...`,autoUpload:!0,prefix:"questions/options"}),(ye[n]||t)&&e(D,{src:ye[n]||t,alt:`Đáp án ${a}`})]}):e(c,{id:`option-input-${n}`,...xe.register(`options.${n}`),placeholder:`Nhập đáp án ${a}...`,className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(s?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),s&&e("p",{className:"text-sm text-red-600",children:s.message}),o&&r("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-700",children:[e(U,{className:"h-3.5 w-3.5"}),"Đáp án đúng"]})]}),r("div",{className:"flex items-center gap-2",children:[e(i,{type:"button",variant:"ghost",size:"sm",onClick:()=>{xe.setValue("correctAnswer",n,{shouldValidate:!0})},className:o?"text-green-600 hover:text-green-700":"text-gray-400 hover:text-green-600",title:"Chọn làm đáp án đúng",children:e(U,{className:"h-4 w-4"})}),Me.length>2&&e(i,{variant:"ghost",size:"sm",onClick:()=>{const e=xe.getValues("options").filter((e,r)=>r!==n);xe.setValue("options",e);const r=xe.getValues("correctAnswer");"number"==typeof r&&r===n?xe.setValue("correctAnswer",-1,{shouldValidate:!0}):"number"==typeof r&&r>n&&xe.setValue("correctAnswer",r-1,{shouldValidate:!0})},className:"text-red-500 hover:bg-red-50 hover:text-red-600",children:e(C,{className:"h-4 w-4"})})]})]})},n)})}),(Array.isArray(He)&&0===He.length||!Array.isArray(He)&&-1===He)&&r("div",{className:"flex items-start gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-amber-100",children:e("span",{className:"text-lg",children:"⚠️"})}),r("div",{className:"text-sm text-amber-800",children:[e("p",{className:"font-semibold",children:"Chưa chọn đáp án đúng"}),e("p",{className:"mt-0.5 text-amber-700",children:Qe?"Click vào ô chữ cái hoặc icon ✓ để chọn một hoặc nhiều đáp án đúng":"Click vào ô chữ cái hoặc icon ✓ để chọn đáp án đúng"})]})]}),xe.hasError("correctAnswer")&&e("div",{className:"rounded-xl border border-red-200 bg-red-50 p-4",children:e("p",{className:"text-sm text-red-600",children:xe.getFieldError("correctAnswer")})})]})]}),r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm",children:e(I,{className:"h-3.5 w-3.5 text-white"})}),r("div",{children:[r("div",{className:"flex items-center gap-2",children:[e(h,{className:"text-base font-semibold text-gray-800",children:"Giải thích"}),e("span",{className:"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600",children:"Không bắt buộc"})]}),e("p",{className:"text-xs text-gray-500 mt-0.5",children:"Giải thích cho đáp án đúng — hiển thị sau khi học sinh hoàn thành câu hỏi"})]})]})}),e(p,{className:"px-4 pb-4",children:e(d,{...xe.register("explanation"),placeholder:"VD: Câu trả lời đúng là... vì...",rows:3,className:"min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none"})})]})]})}export function ChooseTheCorrectAnswerCreator(r){return e(L,{...r})}
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{ImagePreview as t}from"../../../../components/ui/image-preview";import{useState as s,useRef as n,useEffect as a,useMemo as o}from"react";import{Button as i}from"../../../../components/ui/button";import{Label as l}from"../../../../components/ui/label";import{Input as c}from"../../../../components/ui/input";import{Textarea as d}from"../../../../components/ui/textarea";import{PointsInput as m}from"../../../../components/ui/points-input";import{Card as g,CardContent as p,CardHeader as u,CardTitle as h}from"../../../../components/ui/card";import{RadioGroup as x}from"../../../../components/ui/radio-group";import{Switch as f}from"../../../../components/ui/switch";import{usePresignedFileUrl as b,useDebouncedCallback as w}from"../../../../shared/lib/hooks";import{useReactHookForm as N}from"../../../../shared/lib/hooks/useReactHookForm";import{Pencil as y,Eye as v,Plus as A,Trash2 as C,HelpCircle as V,CheckCircle2 as U,Lightbulb as k,MessageSquare as T,ImageIcon as S,Type as E,Users as q,BookOpen as I,Star as G,ListChecks as O}from"lucide-react";import{FileUpload as $}from"../../../../components/ui/file-upload";import{ChooseTheCorrectAnswerClient as j}from"./ChooseTheCorrectAnswerClient";import{normalizeChooseAnswerCorrectAnswer as R,normalizeChooseAnswerOptions as z,pickRawChooseAnswer as B}from"./normalize";import{chooseCorrectAnswerFormSchema as F}from"../../../../shared/lib/validation/choose-correct-answer.validation";import{BasicQuestionGroupCard as J}from"../../groups/BasicQuestionGroupCard";import{ArticlesGroupCard as P}from"../../groups/ArticlesGroupCard";import{DocumentGroupCard as D}from"../../groups/DocumentGroupCard";import{useBasicQuestionGroup as L}from"../../_shared/hooks/useBasicQuestionGroup";import{z as M}from"zod";function Q({src:r,alt:t}){const{previewUrl:s,isLoading:n}=b(r);return e("div",n?{className:"flex h-24 w-full max-w-[200px] items-center justify-center rounded-lg border border-gray-200 bg-gray-50",children:e("div",{className:"h-5 w-5 animate-spin rounded-full border-2 border-gray-200 border-t-blue-500"})}:{className:"relative h-24 w-full max-w-[200px] overflow-hidden rounded-lg border border-gray-200 bg-gray-50",children:e("img",{src:s||r,alt:t,className:"h-full w-full object-contain",onError:e=>{const r=e.target;r.onerror=null,r.src="/images/placeholder-image.svg"}})})}function H(e,r){const{optionCount:t,defaultValue:s,defaultQuestion:n,multipleAnswers:a}=r,o=e?.content?.options||e?.options,i=o?.length>0?z(o):s&&s.length>0?s:Array.from({length:t},()=>""),l=R(B(e?.correctAnswer),o),c=Boolean(e?.multipleAnswers??e?.content?.multipleAnswers??e?.questionGroup?.payload?.multipleAnswers??Array.isArray(l))||Boolean(a);return{question:e?.content?.question||e?.question||n||"",optionType:e?.content?.optionType||e?.optionType||"text",options:i,correctAnswer:c?Array.isArray(l)?l:-1===l?[]:[l]:Array.isArray(l)?l[0]??-1:l,multipleAnswers:c,imageUrl:e?.content?.imageUrl||e?.imageUrl||"",explanation:e?.explanation||"",askerName:e?.content?.askerName||e?.askerName||"",answererName:e?.content?.answererName||e?.answererName||"",isExample:e?.isExample||!1,points:e?.points??1}}function Z({initialData:R,onSave:z,onCancel:B,onChange:Z,externalErrors:K,optionCount:X=4,optionMode:_,defaultValue:W,defaultQuestion:Y,viewMode:ee,onUnsavedChangesChange:re,validationRef:te,groups:se,questionIndexInPart:ne=0,partId:ae="",questionConfig:oe,groupType:ie,groupConfig:le,articleCount:ce=0,multipleAnswers:de,headerExtra:me}){const ge=R,pe=o(()=>F.superRefine((e,r)=>{"CONVERSATION"===ee&&(e.askerName?.trim()||r.addIssue({code:M.ZodIssueCode.custom,message:"Vui lòng nhập tên người hỏi!",path:["askerName"]}),e.answererName?.trim()||r.addIssue({code:M.ZodIssueCode.custom,message:"Vui lòng nhập tên người trả lời!",path:["answererName"]}))}),[ee]),ue=o(()=>({optionCount:X,defaultValue:W,defaultQuestion:Y,multipleAnswers:de}),[X,W,Y,de]),he=N({defaultValues:H(ge,ue),zodSchema:pe,mode:"onBlur"}),[xe,fe]=s(!1),[be,we]=s(""),[Ne,ye]=s({}),{isGrouped:ve,currentGroupNumber:Ae,isFirstInGroup:Ce,groupTitle:Ve,groupSubtitle:Ue,groupContent:ke,imageUrl:Te,articles:Se,setGroupTitle:Ee,setGroupSubtitle:qe,setGroupContent:Ie,setImageUrl:Ge,setArticles:Oe}=L({partId:ae,groups:se,questionIndexInPart:ne,initialData:{title:R?.groupTitle||R?.questionGroup?.payload?.title||R?.title||"",subtitle:R?.groupSubtitle||R?.questionGroup?.payload?.subtitle||"",content:R?.groupContent||R?.questionGroup?.payload?.content||"",imageUrl:R?.groupImageUrl||R?.questionGroup?.payload?.imageUrl||"",articles:R?.articles||R?.questionGroup?.payload?.articles||void 0},articleCount:ce}),$e=n(null),je=n(null),Re=n(R),ze=n(!1),Be=n(Z),Fe=n("");a(()=>{Be.current=Z},[Z]);const Je=w(e=>{Be.current?.(e)},300),Pe=he.watch("question"),De=he.watch("optionType"),Le=he.watch("options"),Me=he.watch("correctAnswer"),Qe=he.watch("multipleAnswers"),He=he.watch("imageUrl"),Ze=he.watch("explanation"),Ke=he.watch("askerName"),Xe=he.watch("answererName"),_e=he.watch("isExample"),We=he.watch("points"),Ye="image"===_?.toLowerCase()?"image":"text",er=(ie||"BASIC").toUpperCase(),rr=!oe||0===oe.length||oe.includes("imageUrl"),tr=!le||0===le.length||le.includes("imageUrl");a(()=>{Ye&&De!==Ye&&he.setValue("optionType",Ye)},[Ye,De,he]);const{previewUrl:sr}=b(He),nr=be||sr||"";a(()=>{te&&(te.current={triggerValidation:async()=>await he.trigger(),getFormData:()=>({question:Pe,optionType:De,options:Le,correctAnswer:Me,multipleAnswers:Qe,imageUrl:rr?He:"",explanation:Ze,askerName:Ke,answererName:Xe,isExample:_e,points:We,groupTitle:Ve,groupSubtitle:Ue,groupContent:ke,groupImageUrl:tr?Te:"",groupNumber:Ae,..."ARTICLES"===er?{articles:Se}:{}})})},[te,he,Me,Qe,Pe,De,Le,He,Ze,Ke,Xe,_e,We,Ve,Ue,ke,Te,Ae,ie,Se]),a(()=>{const e=R,r={...H(e,ue),groupTitle:e?.groupTitle||e?.questionGroup?.payload?.title||"",groupContent:e?.groupContent||e?.questionGroup?.payload?.content||"",groupImageUrl:e?.groupImageUrl||e?.questionGroup?.payload?.imageUrl||""};if(!(JSON.stringify(Re.current)!==JSON.stringify(R)))return;Re.current=R;const t={question:Pe,optionType:De,options:Le,correctAnswer:Me,multipleAnswers:Qe,imageUrl:He,explanation:Ze,askerName:Ke,answererName:Xe,isExample:_e,points:We},s=t.question===r.question&&t.optionType===r.optionType&&JSON.stringify(t.correctAnswer)===JSON.stringify(r.correctAnswer)&&t.multipleAnswers===r.multipleAnswers&&t.points===r.points&&t.explanation===r.explanation&&t.imageUrl===r.imageUrl&&JSON.stringify(t.options)===JSON.stringify(r.options);if(s&&!0===R?.isCompleted)return;const n=!s&&(JSON.stringify(r.correctAnswer)!==JSON.stringify(t.correctAnswer)||r.multipleAnswers!==t.multipleAnswers||r.question!==t.question||r.imageUrl!==t.imageUrl),a=Array.isArray(r.correctAnswer)?r.correctAnswer.length>0:-1!==r.correctAnswer;n&&a&&(ze.current=!0,he.reset(r),setTimeout(()=>{ze.current=!1},150))},[R,X,de,he,Pe,De,Le,Me,Qe,He,Ze,Ke,Xe,_e,We,ue]);const ar=JSON.stringify(Le);a(()=>{if(ze.current){const e=JSON.stringify({question:Pe,optionType:De,options:Le,correctAnswer:Me,multipleAnswers:Qe,imageUrl:He,explanation:Ze,askerName:Ke,answererName:Xe,isExample:_e,points:We,groupTitle:Ve,groupSubtitle:Ue,groupContent:ke,groupImageUrl:Te,groupNumber:Ae,..."ARTICLES"===er?{articles:Se}:{}});return void(Fe.current=e)}const e={question:Pe,optionType:De,options:Le,correctAnswer:Me,multipleAnswers:Qe,imageUrl:rr?He:"",explanation:Ze,askerName:Ke,answererName:Xe,isExample:_e,points:We,groupTitle:Ve,groupSubtitle:Ue,groupContent:ke,groupImageUrl:tr?Te:"",groupNumber:Ae,..."ARTICLES"===er?{articles:Se}:{}},r=JSON.stringify(e);Fe.current!==r&&(Fe.current=r,Je(e))},[Pe,De,ar,Me,Qe,He,Ze,Ke,Xe,_e,We,Ve,Ue,ke,Te,Ae,ie,Se]);he.handleSubmit(e=>{if(e.multipleAnswers){if((Array.isArray(e.correctAnswer)?e.correctAnswer:-1===e.correctAnswer?[]:[e.correctAnswer]).some(r=>r<0||r>=e.options.length))return void he.setError("correctAnswer",{message:"Đáp án đúng không hợp lệ!"})}else{const r="number"==typeof e.correctAnswer?e.correctAnswer:-1;if(-1!==r&&r>=e.options.length)return void he.setError("correctAnswer",{message:"Đáp án đúng không hợp lệ!"})}$e.current=null,je.current=null,z?.(e)});if(xe){const t={question:Pe||"",optionType:De,options:Le,correctAnswer:Me,multipleAnswers:Qe,imageUrl:nr||He,explanation:Ze,askerName:Ke,answererName:Xe,isExample:_e,isGroup:ve,groupTitle:Ve,groupSubtitle:Ue,groupContent:ke,groupImageUrl:Te,groupNumber:Ae,..."ARTICLES"===er?{articles:Se}:{}};return r("div",{className:"space-y-4",children:[e(g,{children:e(u,{children:r("div",{className:"flex items-center justify-between",children:[r("div",{children:[e(h,{children:"Choose the correct answer (Preview)"}),e("p",{className:"mt-1 text-sm text-gray-500",children:"Chế độ xem trước - Hiển thị đáp án đúng"})]}),r(i,{variant:"outline",size:"sm",onClick:()=>fe(!1),children:[e(y,{className:"mr-2 h-4 w-4"}),"Quay lại Edit Mode"]})]})})}),e(j,{questionData:t,questionConfig:oe,isReviewMode:!0,userAnswer:Qe||-1!==Me?Me:void 0})]})}return r("div",{className:"space-y-4",children:[ve&&"ARTICLES"===er&&e(P,{groupNumber:Ae,articleCount:ce,articles:Se,onArticlesChange:Oe,title:Ve,onTitleChange:Ee,isReadOnly:!Ce,uploadIdPrefix:`choose-correct-answer-${ae??"articles"}`}),ve&&"BASIC"===er&&e(J,{groupNumber:Ae,title:Ve,subtitle:Ue,content:ke,imageUrl:Te,onTitleChange:Ee,onSubtitleChange:qe,onContentChange:Ie,onImageChange:Ge,groupConfig:ie?le:void 0,isReadOnly:!Ce,uploadIdPrefix:`choose-correct-answer-${ae??"group"}`}),ve&&"DOCUMENT"===er&&e(D,{groupNumber:Ae,title:Ve,subtitle:Ue,content:ke,imageUrl:Te,onTitleChange:Ee,onSubtitleChange:qe,onContentChange:Ie,onImageChange:Ge,groupConfig:ie?le:void 0,isReadOnly:!Ce,uploadIdPrefix:`choose-correct-answer-${ae??"document"}`}),r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-blue-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gray-100",children:e(V,{className:"h-4 w-4 text-gray-600"})}),r("div",{children:[e(h,{className:"text-base font-bold text-gray-900",children:"Chọn đáp án đúng"}),e("p",{className:"text-xs text-gray-500",children:"Tạo câu hỏi trắc nghiệm với nhiều lựa chọn"})]})]}),r("div",{className:"flex items-center gap-2",children:[me,r(i,{variant:"outline",size:"sm",onClick:()=>fe(!0),disabled:Le.filter(e=>"string"==typeof e&&e.trim()).length<2,className:"gap-2 border-indigo-200 text-indigo-600 hover:bg-indigo-50 hover:text-indigo-700",children:[e(v,{className:"h-4 w-4"}),"Xem trước"]})]})]})}),r(p,{className:"space-y-3 px-4 pb-4",children:[r("div",{className:"flex flex-wrap items-center justify-between gap-y-2",children:[e(m,{...he.register("points",{valueAsNumber:!0}),error:he.hasError("points")?he.getFieldError("points"):void 0}),r("div",{className:"flex items-center gap-2",children:[r("button",{type:"button",style:{paddingBlock:"calc(var(--spacing) * 1)"},onClick:()=>he.setValue("isExample",!_e),className:"inline-flex items-center gap-2 rounded-md border px-3.5 text-sm font-medium transition-colors select-none "+(_e?"border-amber-300 bg-amber-50 text-amber-700":"border-gray-200 bg-white text-gray-400 hover:text-gray-600"),children:[e(G,{className:"h-4 w-4 "+(_e?"fill-amber-400 text-amber-400":"")}),"Example"]}),r("button",{type:"button",style:{paddingBlock:"calc(var(--spacing) * 1)"},disabled:Boolean(de),onClick:()=>{const e=!Qe,r=he.getValues("correctAnswer"),t=Array.isArray(r)?r:-1===r?[]:[r];he.setValue("multipleAnswers",e,{shouldValidate:!0}),he.setValue("correctAnswer",e?t:t[0]??-1,{shouldValidate:!0})},className:`inline-flex items-center gap-2 rounded-md border px-3.5 text-sm font-medium transition-colors select-none ${Qe?"border-violet-300 bg-violet-50 text-violet-700":"border-gray-200 bg-white text-gray-400 hover:text-gray-600"} ${Boolean(de)?"cursor-not-allowed opacity-50":""}`,children:[e(O,{className:"h-4 w-4"}),"Nhiều đáp án"]})]})]}),"CONVERSATION"===ee&&r("div",{className:"space-y-3",children:[r(l,{className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(q,{className:"h-4 w-4 text-indigo-500"}),"Hội thoại ",e("span",{className:"text-sm font-normal text-gray-500",children:"(tuỳ chọn - dùng cho câu hỏi dạng hội thoại)"})]}),r("div",{className:"grid grid-cols-2 gap-4 rounded-xl border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4",children:[r("div",{className:"space-y-1.5",children:[r(l,{htmlFor:"askerName",className:"flex items-center gap-1 text-sm font-medium text-gray-600",children:["Tên người hỏi ",e("span",{className:"text-red-500",children:"*"})]}),e(c,{id:"askerName",...he.register("askerName"),placeholder:"VD: John, Mary, Teacher...",className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(he.hasError("askerName")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),he.hasError("askerName")&&e("p",{className:"text-sm text-red-600",children:he.getFieldError("askerName")})]}),r("div",{className:"space-y-1.5",children:[r(l,{htmlFor:"answererName",className:"flex items-center gap-1 text-sm font-medium text-gray-600",children:["Tên người trả lời ",e("span",{className:"text-red-500",children:"*"})]}),e(c,{id:"answererName",...he.register("answererName"),placeholder:"VD: Tom, Anna, Student...",className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(he.hasError("answererName")?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),he.hasError("answererName")&&e("p",{className:"text-sm text-red-600",children:he.getFieldError("answererName")})]})]})]}),(!oe||0===oe.length||oe.includes("question"))&&r("div",{className:"space-y-2",children:[r(l,{htmlFor:"question",className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(T,{className:"h-4 w-4 text-indigo-500"}),e("span",{className:"flex items-center gap-1",children:"Câu hỏi"}),e("span",{className:"text-sm font-normal text-gray-500",children:"(tuỳ chọn)"})]}),e(d,{id:"question",...he.register("question"),placeholder:"Nhập câu hỏi...",className:"min-h-[100px] border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(he.hasError("question")?"border-red-400 focus:border-red-500 focus:ring-red-200":""),rows:3}),he.hasError("question")&&e("p",{className:"text-sm text-red-600",children:he.getFieldError("question")})]}),(!oe||0===oe.length||oe.includes("imageUrl")||oe.includes("imageUrl "))&&r("div",{className:"space-y-2",children:[r(l,{className:"flex items-center gap-2 text-base font-semibold text-gray-800",children:[e(S,{className:"h-4 w-4 text-indigo-500"}),"Hình ảnh ",e("span",{className:"text-sm font-normal text-gray-500"})]}),e($,{id:"question-image",label:"",accept:"image/*",value:He||"",onChange:e=>{he.setValue("imageUrl",e,{shouldValidate:!0})},onPresignedUrlChange:we,maxSize:5,placeholder:"Upload ảnh hoặc paste URL",autoUpload:!0,prefix:"questions"}),he.hasError("imageUrl")&&e("p",{className:"mt-1 text-sm text-red-600",children:he.getFieldError("imageUrl")}),nr&&e(t,{src:nr,alt:"Preview",className:"mt-2 h-48 w-full max-w-md rounded-lg border border-gray-200"})]}),K&&K.length>0&&r("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-gradient-to-r from-red-50 to-rose-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-red-100",children:e("span",{className:"text-lg",children:"❌"})}),r("div",{className:"text-sm",children:[e("p",{className:"font-semibold text-red-800",children:"Lỗi:"}),e("ul",{className:"mt-1 list-inside list-disc text-red-700",children:K.map((r,t)=>e("li",{children:r},t))})]})]}),he.formState.errors.options?.message&&e("div",{className:"rounded-xl border border-red-200 bg-red-50 p-4",children:e("p",{className:"text-sm text-red-600",children:he.formState.errors.options.message})})]})]}),(!oe||0===oe.length||oe.includes("options"))&&r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-indigo-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center justify-between",children:[r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-6 w-6 items-center justify-center rounded-md bg-indigo-100",children:e(k,{className:"h-3.5 w-3.5 text-indigo-600"})}),r(h,{className:"text-base font-semibold text-gray-800",children:["Các lựa chọn ",r("span",{className:"text-xs font-normal text-gray-500",children:["(",Le.length," đáp án)"]})]})]}),r("div",{className:"flex items-center gap-3",children:[r("div",{className:"flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-1.5",children:[e(E,{className:"h-3.5 w-3.5 "+("text"===De?"text-indigo-600":"text-gray-400")}),e("span",{className:"text-xs font-medium "+("text"===De?"text-indigo-600":"text-gray-400"),children:"Text"}),e(f,{checked:"image"===De,disabled:!0,className:"!bg-indigo-600 !opacity-100",onCheckedChange:e=>{const r=e?"image":"text",t=he.getValues("options"),s=he.getValues("correctAnswer");"text"===De?$e.current={options:t,correctAnswer:s}:je.current={options:t,correctAnswer:s};const n="text"===r?$e.current:je.current;if(n)he.setValue("options",n.options),he.setValue("correctAnswer",n.correctAnswer);else{const e=Array.from({length:t.length},()=>"");he.setValue("options",e),he.setValue("correctAnswer",-1)}he.setValue("optionType",r),he.clearErrors(),ye({})}}),e(S,{className:"h-3.5 w-3.5 "+("image"===De?"text-indigo-600":"text-gray-400")}),e("span",{className:"text-xs font-medium "+("image"===De?"text-indigo-600":"text-gray-400"),children:"Ảnh"})]}),r(i,{variant:"outline",size:"sm",onClick:()=>{const e=he.getValues("options");he.setValue("options",[...e,""])},className:"gap-2 border-green-200 text-green-600 hover:bg-green-50 hover:text-green-700",children:[e(A,{className:"h-4 w-4"}),"Thêm đáp án"]})]})]})}),r(p,{className:"space-y-3 px-4 pb-4",children:[Qe?e("div",{className:"space-y-3",children:Le.map((t,s)=>{const n=he.formState.errors.options?.[s],a=(Array.isArray(Me)?Me:-1===Me?[]:[Me]).includes(s),o=String.fromCharCode(65+s);return e("div",{className:"group relative rounded-xl border-2 p-4 transition-all duration-200 "+(a?"border-green-300 bg-gradient-to-r from-green-50 to-emerald-50 shadow-md shadow-green-100":"border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm"),children:r("div",{className:"flex items-start gap-4",children:[e("div",{className:"flex h-10 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-xl font-bold transition-all "+(a?"bg-gradient-to-br from-green-500 to-emerald-600 text-white shadow-md":"bg-gray-100 text-gray-600 hover:bg-indigo-100 hover:text-indigo-600"),onClick:()=>{if(Qe){const e=Array.isArray(he.getValues("correctAnswer"))?he.getValues("correctAnswer"):[],r=e.includes(s)?e.filter(e=>e!==s):[...e,s].sort((e,r)=>e-r);return void he.setValue("correctAnswer",r,{shouldValidate:!0})}he.setValue("correctAnswer",s,{shouldValidate:!0})},children:o}),r("div",{className:"flex-1 space-y-2",children:["image"===De?r("div",{className:"space-y-2",children:[e($,{id:`option-image-${s}`,label:"",accept:"image/*",value:t||"",onChange:e=>{const r=[...Le];r[s]=e,he.setValue("options",r,{shouldValidate:!0})},onPresignedUrlChange:e=>{ye(r=>({...r,[s]:e}))},maxSize:5,placeholder:`Upload ảnh đáp án ${o}...`,autoUpload:!0,prefix:"questions/options"}),(Ne[s]||t)&&e(Q,{src:Ne[s]||t,alt:`Đáp án ${o}`})]}):e(c,{id:`option-input-${s}`,...he.register(`options.${s}`),placeholder:`Nhập đáp án ${o}...`,className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(n?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),n&&e("p",{className:"text-sm text-red-600",children:n.message}),a&&r("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-700",children:[e(U,{className:"h-3.5 w-3.5"}),Qe?"Đáp án đúng đã chọn":"Đáp án đúng"]})]}),r("div",{className:"flex items-center gap-2",children:[e(i,{type:"button",variant:"ghost",size:"sm",onClick:()=>{if(Qe){const e=Array.isArray(he.getValues("correctAnswer"))?he.getValues("correctAnswer"):[],r=e.includes(s)?e.filter(e=>e!==s):[...e,s].sort((e,r)=>e-r);return void he.setValue("correctAnswer",r,{shouldValidate:!0})}he.setValue("correctAnswer",s,{shouldValidate:!0})},className:a?"text-green-600 hover:text-green-700":"text-gray-400 hover:text-green-600",title:Qe?a?"Bỏ chọn đáp án đúng":"Chọn thêm đáp án đúng":"Chọn làm đáp án đúng",children:e(U,{className:"h-4 w-4"})}),Le.length>2&&e(i,{variant:"ghost",size:"sm",onClick:()=>{const e=he.getValues("options").filter((e,r)=>r!==s);he.setValue("options",e);const r=he.getValues("correctAnswer");if(Array.isArray(r)){const e=r.filter(e=>e!==s).map(e=>e>s?e-1:e);he.setValue("correctAnswer",e,{shouldValidate:!0})}else r===s?he.setValue("correctAnswer",-1,{shouldValidate:!0}):"number"==typeof r&&r>s&&he.setValue("correctAnswer",r-1,{shouldValidate:!0})},className:"text-red-500 hover:bg-red-50 hover:text-red-600",children:e(C,{className:"h-4 w-4"})})]})]})},s)})}):e(x,{value:-1===Me?"":Me.toString(),onValueChange:e=>{he.setValue("correctAnswer",Number(e),{shouldValidate:!0})},children:Le.map((t,s)=>{const n=he.formState.errors.options?.[s],a=Me===s,o=String.fromCharCode(65+s);return e("div",{className:"group relative rounded-xl border-2 p-4 transition-all duration-200 "+(a?"border-green-300 bg-gradient-to-r from-green-50 to-emerald-50 shadow-md shadow-green-100":"border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm"),children:r("div",{className:"flex items-start gap-4",children:[e("div",{className:"flex h-10 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-xl font-bold transition-all "+(a?"bg-gradient-to-br from-green-500 to-emerald-600 text-white shadow-md":"bg-gray-100 text-gray-600 hover:bg-indigo-100 hover:text-indigo-600"),onClick:()=>{he.setValue("correctAnswer",s,{shouldValidate:!0})},children:o}),r("div",{className:"flex-1 space-y-2",children:["image"===De?r("div",{className:"space-y-2",children:[e($,{id:`option-image-${s}`,label:"",accept:"image/*",value:t||"",onChange:e=>{const r=[...Le];r[s]=e,he.setValue("options",r,{shouldValidate:!0})},onPresignedUrlChange:e=>{ye(r=>({...r,[s]:e}))},maxSize:5,placeholder:`Upload ảnh đáp án ${o}...`,autoUpload:!0,prefix:"questions/options"}),(Ne[s]||t)&&e(Q,{src:Ne[s]||t,alt:`Đáp án ${o}`})]}):e(c,{id:`option-input-${s}`,...he.register(`options.${s}`),placeholder:`Nhập đáp án ${o}...`,className:"border-gray-200 bg-white transition-all focus:border-indigo-300 focus:ring-indigo-200 "+(n?"border-red-400 focus:border-red-500 focus:ring-red-200":"")}),n&&e("p",{className:"text-sm text-red-600",children:n.message}),a&&r("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-700",children:[e(U,{className:"h-3.5 w-3.5"}),"Đáp án đúng"]})]}),r("div",{className:"flex items-center gap-2",children:[e(i,{type:"button",variant:"ghost",size:"sm",onClick:()=>{he.setValue("correctAnswer",s,{shouldValidate:!0})},className:a?"text-green-600 hover:text-green-700":"text-gray-400 hover:text-green-600",title:"Chọn làm đáp án đúng",children:e(U,{className:"h-4 w-4"})}),Le.length>2&&e(i,{variant:"ghost",size:"sm",onClick:()=>{const e=he.getValues("options").filter((e,r)=>r!==s);he.setValue("options",e);const r=he.getValues("correctAnswer");"number"==typeof r&&r===s?he.setValue("correctAnswer",-1,{shouldValidate:!0}):"number"==typeof r&&r>s&&he.setValue("correctAnswer",r-1,{shouldValidate:!0})},className:"text-red-500 hover:bg-red-50 hover:text-red-600",children:e(C,{className:"h-4 w-4"})})]})]})},s)})}),(Array.isArray(Me)&&0===Me.length||!Array.isArray(Me)&&-1===Me)&&r("div",{className:"flex items-start gap-3 rounded-xl border border-amber-200 bg-gradient-to-r from-amber-50 to-yellow-50 p-4",children:[e("div",{className:"flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-amber-100",children:e("span",{className:"text-lg",children:"⚠️"})}),r("div",{className:"text-sm text-amber-800",children:[e("p",{className:"font-semibold",children:"Chưa chọn đáp án đúng"}),e("p",{className:"mt-0.5 text-amber-700",children:Qe?"Click vào ô chữ cái hoặc icon ✓ để chọn một hoặc nhiều đáp án đúng":"Click vào ô chữ cái hoặc icon ✓ để chọn đáp án đúng"})]})]}),he.hasError("correctAnswer")&&e("div",{className:"rounded-xl border border-red-200 bg-red-50 p-4",children:e("p",{className:"text-sm text-red-600",children:he.getFieldError("correctAnswer")})})]})]}),r(g,{className:"overflow-hidden border-0 bg-white shadow-lg shadow-amber-100/50",children:[e(u,{className:"px-4 py-3",children:r("div",{className:"flex items-center gap-2",children:[e("div",{className:"flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br from-amber-500 to-orange-500 shadow-sm",children:e(I,{className:"h-3.5 w-3.5 text-white"})}),r("div",{children:[r("div",{className:"flex items-center gap-2",children:[e(h,{className:"text-base font-semibold text-gray-800",children:"Giải thích"}),e("span",{className:"inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600",children:"Không bắt buộc"})]}),e("p",{className:"text-xs text-gray-500 mt-0.5",children:"Giải thích cho đáp án đúng — hiển thị sau khi học sinh hoàn thành câu hỏi"})]})]})}),e(p,{className:"px-4 pb-4",children:e(d,{...he.register("explanation"),placeholder:"VD: Câu trả lời đúng là... vì...",rows:3,className:"min-h-[80px] border-gray-200 bg-white transition-all focus:border-amber-300 focus:ring-amber-200 resize-none"})})]})]})}export function ChooseTheCorrectAnswerCreator(r){return e(Z,{...r})}
@@ -1,2 +1,3 @@
1
1
  export * from './ChooseTheCorrectAnswerCreator';
2
2
  export * from './ChooseTheCorrectAnswerClient';
3
+ export * from './normalize';
@@ -1 +1 @@
1
- export*from"./ChooseTheCorrectAnswerCreator";export*from"./ChooseTheCorrectAnswerClient";
1
+ export*from"./ChooseTheCorrectAnswerCreator";export*from"./ChooseTheCorrectAnswerClient";export*from"./normalize";