openlearn-next 0.4.2 → 0.6.0

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 (74) hide show
  1. package/README.md +21 -20
  2. package/dist/assets/ActivityWorkspaceWidget-_6XMBAcc.js +1 -0
  3. package/dist/assets/AdminDirectoryView-BufUF-sk.js +5 -0
  4. package/dist/assets/{BatchPickerModal-BpWu0Lil.js → BatchPickerModal-CES2DlPx.js} +1 -1
  5. package/dist/assets/ClassesView-BLvRJKcc.js +24 -0
  6. package/dist/assets/ClassroomCountdownWidget-DfKotHP8.js +2 -0
  7. package/dist/assets/{CloudDriveModal-DEQ1nkNk.js → CloudDriveModal-CLe4I18S.js} +1 -1
  8. package/dist/assets/ComputerLabView-CPnWWguS.js +1 -0
  9. package/dist/assets/CourseManagement-BSR61ggI.js +1 -0
  10. package/dist/assets/CourseWizardModal-D2m3PG7k.js +3 -0
  11. package/dist/assets/CoursewareHubPanel-gqjte-Pv.js +1 -0
  12. package/dist/assets/Dashboard-BPBJd0QR.js +8 -0
  13. package/dist/assets/ExportWeightModal-C3gIzDaP.js +1 -0
  14. package/dist/assets/HelpTour-B-RKDb1-.js +1 -0
  15. package/dist/assets/{HelpView-CtzdqhBq.js → HelpView-Bk64VK-J.js} +12 -12
  16. package/dist/assets/ImportLessonsModal-DUGpcZV3.js +1 -0
  17. package/dist/assets/ImportModal-ChY_Y5DZ.js +1 -0
  18. package/dist/assets/InteractiveCoursewareViewer-B9wvha7w.js +1 -0
  19. package/dist/assets/InteractiveWhiteboard-FPrze5CJ.js +78 -0
  20. package/dist/assets/LazyCourseware-BV5nOs5y.js +2 -0
  21. package/dist/assets/LazyWhiteboard-Cy5DdYnO.js +2 -0
  22. package/dist/assets/LessonEditorView-3SyplRhr.js +1 -0
  23. package/dist/assets/LiveClassroomView-CX7SUnmx.js +61 -0
  24. package/dist/assets/{NotificationDetailModal-Baqnc5pU.js → NotificationDetailModal-BBATA8Lh.js} +1 -1
  25. package/dist/assets/{PluginView-CCbIuZ24.js → PluginView-D5jMNscn.js} +5 -5
  26. package/dist/assets/ProcessLogsModal-DfKPVIYe.js +1 -0
  27. package/dist/assets/{QuizGeneratorModal-BBEDssp7.js → QuizGeneratorModal-CbRirQId.js} +1 -1
  28. package/dist/assets/StudentAssignmentView-ucXAOac9.js +1 -0
  29. package/dist/assets/StudentLessonView-CW6FYMtd.js +13 -0
  30. package/dist/assets/StudentView-Bxrut8tS.js +2 -0
  31. package/dist/assets/SystemResourceLibraryModal-CXdrWHDL.js +1 -0
  32. package/dist/assets/TeacherView-DXg0boJH.js +2 -0
  33. package/dist/assets/TimetableView-DPABkaFX.js +6 -0
  34. package/dist/assets/index-B3W5zons.css +1 -0
  35. package/dist/assets/index-B6wtREUD.js +221 -0
  36. package/dist/assets/{index.es-C5eWEO4o.js → index.es-DvJa33KC.js} +1 -1
  37. package/dist/assets/{vendor-charts-qLbgF1eL.js → vendor-charts-DGsG2RUv.js} +1 -1
  38. package/dist/assets/{vendor-icons-BRmhY6fg.js → vendor-icons-CyfamhaC.js} +2 -2
  39. package/dist/assets/{vendor-konva-CEOq4dcl.js → vendor-konva-DBWwlLTb.js} +1 -1
  40. package/dist/assets/{vendor-pdf-D7rGevI1.js → vendor-pdf-D0UGJOgo.js} +49 -49
  41. package/dist/assets/{vendor-pptx-C5-U7ieS.js → vendor-pptx-D4btWy5L.js} +8 -8
  42. package/dist/assets/{vendor-react-B0t7H3hh.js → vendor-react-CZ1I7IcM.js} +1 -1
  43. package/dist/assets/{vendor-utils-m0Urvtws.js → vendor-utils-B6R8dnOe.js} +1 -1
  44. package/dist/index.html +13 -10
  45. package/dist/server.cjs +19224 -11247
  46. package/package.json +11 -4
  47. package/dist/assets/AdminDirectoryView-DY--WM5Z.js +0 -1
  48. package/dist/assets/ClassesView-KbHEqJto.js +0 -22
  49. package/dist/assets/ClassroomCountdownWidget-96WFRO9A.js +0 -2
  50. package/dist/assets/ComputerLabView-1qWDNRQ2.js +0 -1
  51. package/dist/assets/CourseManagement-D3ZpxY0l.js +0 -1
  52. package/dist/assets/CourseWizardModal-Ck_-M8pk.js +0 -3
  53. package/dist/assets/CoursewareHubPanel-CaEizhxl.js +0 -1
  54. package/dist/assets/Dashboard-CYbpbofV.js +0 -8
  55. package/dist/assets/ExportWeightModal-DW2bu9Zz.js +0 -1
  56. package/dist/assets/HelpTour-CMJbbGne.js +0 -1
  57. package/dist/assets/ImportLessonsModal-jBuIK453.js +0 -1
  58. package/dist/assets/ImportModal-D7L-KNhZ.js +0 -1
  59. package/dist/assets/InteractiveCoursewareViewer-Bj7ahXMs.js +0 -1
  60. package/dist/assets/InteractiveWhiteboard-B7JcJvDu.js +0 -77
  61. package/dist/assets/LazyCourseware-CuiPxhDg.js +0 -2
  62. package/dist/assets/LazyWhiteboard-BJwCEZAU.js +0 -2
  63. package/dist/assets/LessonEditorView-DFrOp2qp.js +0 -1
  64. package/dist/assets/LiveClassroomView-BZ5nGee3.js +0 -59
  65. package/dist/assets/ProcessLogsModal-DmFXg9mG.js +0 -1
  66. package/dist/assets/StudentAssignmentView-DgIjUsXz.js +0 -1
  67. package/dist/assets/StudentLessonView-CBJbI5x6.js +0 -1
  68. package/dist/assets/StudentPreviewModal-Bh8OZs0t.js +0 -1
  69. package/dist/assets/StudentView--uGxc5TJ.js +0 -2
  70. package/dist/assets/SystemResourceLibraryModal-BVCclcqA.js +0 -1
  71. package/dist/assets/TeacherView-D4Zsc0eZ.js +0 -2
  72. package/dist/assets/TimetableView-BQG-rEb5.js +0 -6
  73. package/dist/assets/index-BKBCBKvy.js +0 -217
  74. package/dist/assets/index-CvGu7LSj.css +0 -1
@@ -1 +1 @@
1
- import{j as e}from"./vendor-react-B0t7H3hh.js";import{m as O}from"./index-BKBCBKvy.js";import{a5 as w,z as C,r as k}from"./vendor-icons-BRmhY6fg.js";import"./vendor-utils-m0Urvtws.js";import"./vendor-pdf-D7rGevI1.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-pptx-C5-U7ieS.js";import"./vendor-charts-qLbgF1eL.js";function _(z){const{isQuizGeneratorOpen:S,setIsQuizGeneratorOpen:x,lessons:g,quizGenMode:n,setQuizGenMode:u,quizGenSelectedLessonId:l,setQuizGenSelectedLessonId:Q,quizGenTopic:d,setQuizGenTopic:M,isGeneratingSuggestions:p,setIsGeneratingSuggestions:h,suggestedObjectives:b,setSuggestedObjectives:f,suggestedQuestions:r,setSuggestedQuestions:m,quizGenTimeLimit:j,setQuizGenTimeLimit:G,savingQuiz:y,setSavingQuiz:v,quizGeneratorClassId:o,fetchClassDashboard:N}=z;return e.jsx(e.Fragment,{children:S&&e.jsx("div",{className:"fixed inset-0 bg-gray-900/40 backdrop-blur-sm flex items-center justify-center p-6 z-50 overflow-y-auto text-gray-850",children:e.jsxs(O.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:"bg-white border text-gray-900 border-gray-200 rounded-2xl shadow-2xl w-full max-w-3xl flex flex-col overflow-hidden max-h-[90vh]",children:[e.jsxs("div",{className:"p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/80 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(w,{className:"text-indigo-600 animate-pulse",size:20}),e.jsx("h2",{className:"font-bold text-gray-800 text-lg",children:"AI-Objective Quiz Generator"})]}),e.jsx("button",{onClick:()=>x(!1),className:"text-gray-400 hover:text-gray-600 font-bold p-1 hover:bg-gray-200 rounded transition-colors",children:"×"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-6",children:[r.length===0&&e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"bg-indigo-50/80 p-4 rounded-xl border border-indigo-100 text-xs text-indigo-800 leading-relaxed font-sans",children:"Choose a lesson to scan. Our advanced AI model will run a deep semantic scan across the entire lesson curriculum content, discover your core learning objectives, and construct interactive multiple-choice questions aligning precisely with each of them."}),e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2",children:"Scan Core Selection Mode"}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("button",{onClick:()=>u("scan_lesson"),className:`p-3 rounded-lg border text-left flex flex-col transition-all ${n==="scan_lesson"?"border-indigo-600 bg-indigo-50/40 ring-2 ring-indigo-100":"border-gray-200 hover:border-gray-300"}`,children:[e.jsx("span",{className:"font-semibold text-sm text-indigo-900",children:"Curriculum Lesson Scanning"}),e.jsx("span",{className:"text-xs text-gray-500 mt-1",children:"Examines real Markdown content inside virtual lesson modules."})]}),e.jsxs("button",{onClick:()=>u("topic"),className:`p-3 rounded-lg border text-left flex flex-col transition-all ${n==="topic"?"border-indigo-600 bg-indigo-50/40 ring-2 ring-indigo-100":"border-gray-200 hover:border-gray-300"}`,children:[e.jsx("span",{className:"font-semibold text-sm text-indigo-900",children:"Custom Keyword / Topic"}),e.jsx("span",{className:"text-xs text-gray-500 mt-1",children:"Provide a custom prompt keyword or objective manually."})]})]})]}),n==="scan_lesson"?e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2",children:"Select Lesson to Scan"}),g.length===0?e.jsx("div",{className:"text-gray-500 text-xs py-3 border rounded border-dashed text-center",children:"No lessons available. Please create a lesson first."}):e.jsxs("select",{value:l,onChange:s=>Q(s.target.value),className:"w-full p-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:border-indigo-500 focus:outline-none shadow-sm",children:[e.jsx("option",{value:"",children:"-- Choose a lesson --"}),g.map(s=>e.jsx("option",{value:s.id,children:s.title},s.id))]})]}):e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-505 uppercase tracking-wider mb-2",children:"Custom Topic Prompt"}),e.jsx("input",{type:"text",placeholder:"e.g. Introduction to React state, Cloud SQL setup...",value:d,onChange:s=>M(s.target.value),className:"w-full p-2.5 bg-white border border-gray-200 rounded-lg text-sm focus:border-indigo-500 focus:outline-none shadow-sm text-gray-800"})]}),e.jsx("div",{className:"pt-4 flex justify-end font-sans",children:e.jsx("button",{disabled:p||n==="scan_lesson"&&!l||n==="topic"&&!d.trim(),onClick:async()=>{h(!0);try{if(n==="scan_lesson"){const s=await fetch(`/api/classes/${o}/assignments/suggest`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:l})});if(s.ok){const t=await s.json();f(t.learningObjectives||[]),m((t.questions||[]).map(a=>({...a,selected:!0})))}else alert("Error generating suggestions. Please make sure the selected lesson has content.")}else(await fetch(`/api/classes/${o}/assignments/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({topic:d})})).ok?(await N(o),x(!1)):alert("Error generating topic quiz.")}catch(s){console.error(s),alert(s.message)}finally{h(!1)}},className:"px-5 py-2.5 bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 text-white rounded-lg font-medium text-xs shadow transition flex items-center gap-2",children:p?e.jsxs(e.Fragment,{children:[e.jsx(C,{size:16,className:"animate-spin"}),e.jsx("span",{children:"AI Scanning Content..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(w,{size:16}),e.jsx("span",{children:"Generate Key MCQ Quiz"})]})})})]}),r.length>0&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"font-sans",children:[e.jsx("div",{className:"text-xs font-bold text-gray-500 uppercase tracking-wider mb-2",children:"Identified Core Objectives"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:b.map((s,t)=>e.jsxs("span",{className:"px-2.5 py-1 bg-teal-50 text-teal-800 border border-teal-200 rounded-full text-xs font-semibold",children:["🎯 ",s]},t))})]}),e.jsxs("div",{className:"space-y-4 font-sans",children:[e.jsx("div",{className:"text-xs font-bold text-gray-500 uppercase tracking-wider font-semibold",children:"Suggested MCQ Questions"}),e.jsx("div",{className:"space-y-3",children:r.map((s,t)=>e.jsxs("div",{className:"p-4 rounded-xl border border-gray-150 bg-gray-50/50 hover:bg-gray-50 transition space-y-3 text-gray-800 text-gray-850",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-5 h-5 rounded-full bg-indigo-150 text-indigo-700 flex items-center justify-center text-xs font-bold shrink-0",children:t+1}),e.jsxs("span",{className:"text-xs font-semibold text-teal-700 bg-teal-50 px-2.5 py-0.5 rounded border border-teal-100",children:["objective: ",s.objective]})]}),e.jsx("input",{type:"checkbox",checked:!!s.selected,onChange:a=>{const i=[...r];i[t].selected=a.target.checked,m(i)},className:"w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"})]}),e.jsx("p",{className:"font-semibold text-gray-800 text-sm leading-relaxed",children:s.question}),e.jsx("div",{className:"grid grid-cols-2 gap-2 text-xs",children:s.options.map((a,i)=>{const c=a===s.correctAnswer;return e.jsxs("div",{className:`p-2 rounded border flex items-center justify-between ${c?"bg-green-50 border-green-200 text-green-955 font-semibold":"bg-white border-gray-100 text-gray-700"}`,children:[e.jsx("span",{children:a}),c&&e.jsx(k,{size:12,className:"text-green-600 shrink-0"})]},i)})})]},t))})]}),e.jsxs("div",{className:"pt-4 border-t border-gray-100 flex justify-between items-center font-sans",children:[e.jsx("button",{onClick:()=>{f([]),m([])},className:"px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg text-xs font-semibold transition",children:"Back / Scan New"}),e.jsxs("div",{className:"flex items-center gap-2 border border-indigo-150 bg-indigo-50/50 px-3 py-1.5 rounded-lg text-xs font-semibold text-indigo-900",children:[e.jsx("span",{children:"⏱️ Quiz Time Limit:"}),e.jsxs("select",{value:j,onChange:s=>G(Number(s.target.value)),className:"bg-transparent text-xs text-indigo-950 font-bold focus:outline-none cursor-pointer",children:[e.jsx("option",{className:"text-gray-800",value:0,children:"No Limit"}),e.jsx("option",{className:"text-gray-800",value:1,children:"1 Min"}),e.jsx("option",{className:"text-gray-800",value:2,children:"2 Mins"}),e.jsx("option",{className:"text-gray-800",value:5,children:"5 Mins"}),e.jsx("option",{className:"text-gray-800",value:10,children:"10 Mins"}),e.jsx("option",{className:"text-gray-800",value:15,children:"15 Mins"}),e.jsx("option",{className:"text-gray-800",value:20,children:"20 Mins"}),e.jsx("option",{className:"text-gray-800",value:30,children:"30 Mins"}),e.jsx("option",{className:"text-gray-800",value:45,children:"45 Mins"}),e.jsx("option",{className:"text-gray-800",value:60,children:"60 Mins"})]})]}),e.jsxs("button",{disabled:y||r.filter(s=>s.selected).length===0,onClick:async()=>{v(!0);try{const s=g.find(i=>i.id===l),t=s?s.title:d||"Custom Objective";(await fetch(`/api/classes/${o}/assignments/create-suggested-quiz`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:`MCQ Evaluation: ${t}`,description:"Automatic evaluation based on core learning objectives.",questions:r.filter(i=>i.selected).map(({selected:i,...c})=>c),learningObjectives:b,timeLimit:j})})).ok?(await N(o),x(!1)):alert("Failed to save suggested quiz.")}catch(s){console.error(s),alert(s.message)}finally{v(!1)}},className:"px-5 py-2.5 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg font-medium text-xs shadow hover:shadow-md transition flex items-center gap-2",children:[y?e.jsx(C,{size:16,className:"animate-spin"}):e.jsx(k,{size:16}),e.jsx("span",{children:"Create Assessment Quiz"})]})]})]})]})]})})})}export{_ as QuizGeneratorModal};
1
+ import{j as e}from"./vendor-react-CZ1I7IcM.js";import{m as O}from"./index-B6wtREUD.js";import{an as w,c as C,o as k}from"./vendor-icons-CyfamhaC.js";import"./vendor-utils-B6R8dnOe.js";import"./vendor-pptx-D4btWy5L.js";import"./vendor-pdf-D0UGJOgo.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-DGsG2RUv.js";function _(z){const{isQuizGeneratorOpen:S,setIsQuizGeneratorOpen:x,lessons:g,quizGenMode:n,setQuizGenMode:u,quizGenSelectedLessonId:l,setQuizGenSelectedLessonId:Q,quizGenTopic:c,setQuizGenTopic:M,isGeneratingSuggestions:p,setIsGeneratingSuggestions:h,suggestedObjectives:b,setSuggestedObjectives:f,suggestedQuestions:r,setSuggestedQuestions:m,quizGenTimeLimit:j,setQuizGenTimeLimit:G,savingQuiz:y,setSavingQuiz:v,quizGeneratorClassId:o,fetchClassDashboard:N}=z;return e.jsx(e.Fragment,{children:S&&e.jsx("div",{className:"fixed inset-0 bg-gray-900/40 backdrop-blur-sm flex items-center justify-center p-6 z-50 overflow-y-auto text-gray-850",children:e.jsxs(O.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:"bg-white border text-gray-900 border-gray-200 rounded-2xl shadow-2xl w-full max-w-3xl flex flex-col overflow-hidden max-h-[90vh]",children:[e.jsxs("div",{className:"p-4 border-b border-gray-100 flex items-center justify-between bg-gray-50/80 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(w,{className:"text-indigo-600 animate-pulse",size:20}),e.jsx("h2",{className:"font-bold text-gray-800 text-lg",children:"AI-Objective Quiz Generator"})]}),e.jsx("button",{onClick:()=>x(!1),className:"text-gray-400 hover:text-gray-600 font-bold p-1 hover:bg-gray-200 rounded transition-colors",children:"×"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-6 space-y-6",children:[r.length===0&&e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"bg-indigo-50/80 p-4 rounded-xl border border-indigo-100 text-xs text-indigo-800 leading-relaxed font-sans",children:"Choose a lesson to scan. Our advanced AI model will run a deep semantic scan across the entire lesson curriculum content, discover your core learning objectives, and construct interactive multiple-choice questions aligning precisely with each of them."}),e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2",children:"Scan Core Selection Mode"}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("button",{onClick:()=>u("scan_lesson"),className:`p-3 rounded-lg border text-left flex flex-col transition-all ${n==="scan_lesson"?"border-indigo-600 bg-indigo-50/40 ring-2 ring-indigo-100":"border-gray-200 hover:border-gray-300"}`,children:[e.jsx("span",{className:"font-semibold text-sm text-indigo-900",children:"Curriculum Lesson Scanning"}),e.jsx("span",{className:"text-xs text-gray-500 mt-1",children:"Examines real Markdown content inside virtual lesson modules."})]}),e.jsxs("button",{onClick:()=>u("topic"),className:`p-3 rounded-lg border text-left flex flex-col transition-all ${n==="topic"?"border-indigo-600 bg-indigo-50/40 ring-2 ring-indigo-100":"border-gray-200 hover:border-gray-300"}`,children:[e.jsx("span",{className:"font-semibold text-sm text-indigo-900",children:"Custom Keyword / Topic"}),e.jsx("span",{className:"text-xs text-gray-500 mt-1",children:"Provide a custom prompt keyword or objective manually."})]})]})]}),n==="scan_lesson"?e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2",children:"Select Lesson to Scan"}),g.length===0?e.jsx("div",{className:"text-gray-500 text-xs py-3 border rounded border-dashed text-center",children:"No lessons available. Please create a lesson first."}):e.jsxs("select",{value:l,onChange:s=>Q(s.target.value),className:"w-full p-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:border-indigo-500 focus:outline-none shadow-sm",children:[e.jsx("option",{value:"",children:"-- Choose a lesson --"}),g.map(s=>e.jsx("option",{value:s.id,children:s.title},s.id))]})]}):e.jsxs("div",{className:"font-sans",children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-505 uppercase tracking-wider mb-2",children:"Custom Topic Prompt"}),e.jsx("input",{type:"text",placeholder:"e.g. Introduction to React state, Cloud SQL setup...",value:c,onChange:s=>M(s.target.value),className:"w-full p-2.5 bg-white border border-gray-200 rounded-lg text-sm focus:border-indigo-500 focus:outline-none shadow-sm text-gray-800"})]}),e.jsx("div",{className:"pt-4 flex justify-end font-sans",children:e.jsx("button",{disabled:p||n==="scan_lesson"&&!l||n==="topic"&&!c.trim(),onClick:async()=>{h(!0);try{if(n==="scan_lesson"){const s=await fetch(`/api/classes/${o}/assignments/suggest`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:l})});if(s.ok){const t=await s.json();f(t.learningObjectives||[]),m((t.questions||[]).map(a=>({...a,selected:!0})))}else alert("Error generating suggestions. Please make sure the selected lesson has content.")}else(await fetch(`/api/classes/${o}/assignments/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({topic:c})})).ok?(await N(o),x(!1)):alert("Error generating topic quiz.")}catch(s){console.error(s),alert(s.message)}finally{h(!1)}},className:"px-5 py-2.5 bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 text-white rounded-lg font-medium text-xs shadow transition flex items-center gap-2",children:p?e.jsxs(e.Fragment,{children:[e.jsx(C,{size:16,className:"animate-spin"}),e.jsx("span",{children:"AI Scanning Content..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(w,{size:16}),e.jsx("span",{children:"Generate Key MCQ Quiz"})]})})})]}),r.length>0&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"font-sans",children:[e.jsx("div",{className:"text-xs font-bold text-gray-500 uppercase tracking-wider mb-2",children:"Identified Core Objectives"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:b.map((s,t)=>e.jsxs("span",{className:"px-2.5 py-1 bg-teal-50 text-teal-800 border border-teal-200 rounded-full text-xs font-semibold",children:["🎯 ",s]},t))})]}),e.jsxs("div",{className:"space-y-4 font-sans",children:[e.jsx("div",{className:"text-xs font-bold text-gray-500 uppercase tracking-wider font-semibold",children:"Suggested MCQ Questions"}),e.jsx("div",{className:"space-y-3",children:r.map((s,t)=>e.jsxs("div",{className:"p-4 rounded-xl border border-gray-150 bg-gray-50/50 hover:bg-gray-50 transition space-y-3 text-gray-800 text-gray-850",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-5 h-5 rounded-full bg-indigo-150 text-indigo-700 flex items-center justify-center text-xs font-bold shrink-0",children:t+1}),e.jsxs("span",{className:"text-xs font-semibold text-teal-700 bg-teal-50 px-2.5 py-0.5 rounded border border-teal-100",children:["objective: ",s.objective]})]}),e.jsx("input",{type:"checkbox",checked:!!s.selected,onChange:a=>{const i=[...r];i[t].selected=a.target.checked,m(i)},className:"w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"})]}),e.jsx("p",{className:"font-semibold text-gray-800 text-sm leading-relaxed",children:s.question}),e.jsx("div",{className:"grid grid-cols-2 gap-2 text-xs",children:s.options.map((a,i)=>{const d=a===s.correctAnswer;return e.jsxs("div",{className:`p-2 rounded border flex items-center justify-between ${d?"bg-green-50 border-green-200 text-green-955 font-semibold":"bg-white border-gray-100 text-gray-700"}`,children:[e.jsx("span",{children:a}),d&&e.jsx(k,{size:12,className:"text-green-600 shrink-0"})]},i)})})]},t))})]}),e.jsxs("div",{className:"pt-4 border-t border-gray-100 flex justify-between items-center font-sans",children:[e.jsx("button",{onClick:()=>{f([]),m([])},className:"px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg text-xs font-semibold transition",children:"Back / Scan New"}),e.jsxs("div",{className:"flex items-center gap-2 border border-indigo-150 bg-indigo-50/50 px-3 py-1.5 rounded-lg text-xs font-semibold text-indigo-900",children:[e.jsx("span",{children:"⏱️ Quiz Time Limit:"}),e.jsxs("select",{value:j,onChange:s=>G(Number(s.target.value)),className:"bg-transparent text-xs text-indigo-950 font-bold focus:outline-none cursor-pointer",children:[e.jsx("option",{className:"text-gray-800",value:0,children:"No Limit"}),e.jsx("option",{className:"text-gray-800",value:1,children:"1 Min"}),e.jsx("option",{className:"text-gray-800",value:2,children:"2 Mins"}),e.jsx("option",{className:"text-gray-800",value:5,children:"5 Mins"}),e.jsx("option",{className:"text-gray-800",value:10,children:"10 Mins"}),e.jsx("option",{className:"text-gray-800",value:15,children:"15 Mins"}),e.jsx("option",{className:"text-gray-800",value:20,children:"20 Mins"}),e.jsx("option",{className:"text-gray-800",value:30,children:"30 Mins"}),e.jsx("option",{className:"text-gray-800",value:45,children:"45 Mins"}),e.jsx("option",{className:"text-gray-800",value:60,children:"60 Mins"})]})]}),e.jsxs("button",{disabled:y||r.filter(s=>s.selected).length===0,onClick:async()=>{v(!0);try{const s=g.find(i=>i.id===l),t=s?s.title:c||"Custom Objective";(await fetch(`/api/classes/${o}/assignments/create-suggested-quiz`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:`MCQ Evaluation: ${t}`,description:"Automatic evaluation based on core learning objectives.",questions:r.filter(i=>i.selected).map(({selected:i,...d})=>d),learningObjectives:b,timeLimit:j})})).ok?(await N(o),x(!1)):alert("Failed to save suggested quiz.")}catch(s){console.error(s),alert(s.message)}finally{v(!1)}},className:"px-5 py-2.5 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg font-medium text-xs shadow hover:shadow-md transition flex items-center gap-2",children:[y?e.jsx(C,{size:16,className:"animate-spin"}):e.jsx(k,{size:16}),e.jsx("span",{children:"Create Assessment Quiz"})]})]})]})]})]})})})}export{_ as QuizGeneratorModal};
@@ -0,0 +1 @@
1
+ import{j as e,r as N}from"./vendor-react-CZ1I7IcM.js";import{E as z,e as T,M as q}from"./index-B6wtREUD.js";import{f as _,an as C,o as A,h as S,T as E,X as R}from"./vendor-icons-CyfamhaC.js";import{L as O}from"./LazyWhiteboard-Cy5DdYnO.js";import"./vendor-utils-B6R8dnOe.js";import"./vendor-pptx-D4btWy5L.js";import"./vendor-pdf-D0UGJOgo.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-DGsG2RUv.js";function I(x){const{setStudentViewStatus:s,setSelectedAssignment:i,selectedAssignment:o}=x;return e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsxs("button",{onClick:()=>{s("dashboard"),i(null)},className:"flex items-center gap-2 text-indigo-600 hover:text-indigo-800 transition-colors font-medium text-sm",children:[e.jsx(_,{className:"rotate-180",size:16})," Back to Dashboard"]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("h2",{className:"text-xl font-bold text-gray-800",children:["Assignment: ",o.title]}),e.jsx(z,{slot:"student.assignment.toolbar.action",slotProps:{assignment:o}})]})]})}function Q(x){const{selectedAssignment:s,quizStudentAnswers:i,setQuizStudentAnswers:o,submitQuizAssignment:d}=x,m=T.match(s?.content);if(m){const n=m.config,r={assignment:s,answers:i,setAnswers:t=>o?.(t),lang:"zh"};return e.jsxs("div",{className:"w-1/3 border-r border-gray-100 pr-4 overflow-y-auto hidden md:block",children:[e.jsx("div",{className:"flex justify-between items-center mb-4",children:e.jsx("div",{className:"text-xs font-semibold uppercase tracking-wider text-indigo-500 bg-indigo-50 border border-indigo-100 p-2.5 rounded-lg flex items-center gap-1.5 w-full",children:n.label})}),n.render(r),!s.submission_status&&e.jsx("div",{className:"mt-6 border-t border-gray-100 pt-4",children:e.jsx("button",{onClick:async()=>{if(n.validate){const t=n.validate(r);if(t){window.alert(t);return}}n.buildSubmission&&o?.(n.buildSubmission(r)),await d(!1)},className:"w-full py-2 bg-indigo-600 text-white rounded-lg shadow font-medium hover:bg-indigo-700 transition",children:"Submit"})})]})}return e.jsxs("div",{className:"w-1/3 border-r border-gray-100 pr-4 overflow-y-auto hidden md:block",children:[e.jsx("div",{className:"flex justify-between items-center mb-4",children:e.jsx("div",{className:"text-xs font-semibold uppercase tracking-wider text-gray-400",children:s?.content&&s.content.startsWith('{"quizType":"mcq_learning_objectives"')?"Assessment":"Question"})}),s?.content&&s.content.startsWith('{"quizType":"mcq_learning_objectives"')?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"text-xs font-semibold uppercase tracking-wider text-teal-700 bg-teal-50 border border-teal-100 p-2.5 rounded-lg flex items-center gap-1.5 font-sans",children:[e.jsx(C,{size:12,className:"text-teal-600 animate-pulse"})," AI Interactive Evaluation"]}),e.jsx("p",{className:"text-xs text-gray-500 leading-relaxed font-sans",children:"This assessment was automatically mapped to the core learning objectives of your lesson by our tutoring assistant compiler."}),(()=>{try{const n=JSON.parse(s.content);return e.jsxs("div",{className:"space-y-2 font-sans",children:[e.jsx("div",{className:"text-xs font-bold text-gray-400 uppercase tracking-wider",children:"Lesson Learning Objectives:"}),e.jsx("ul",{className:"space-y-1.5",children:(n.learningObjectives||[]).map((r,t)=>e.jsxs("li",{className:"text-xs text-gray-755 flex items-start gap-1.5 font-medium leading-normal",children:[e.jsx("span",{className:"text-indigo-500 shrink-0 select-none",children:"🎯"}),e.jsx("span",{children:r})]},t))})]})}catch{return null}})()]}):e.jsx("div",{className:"prose prose-sm prose-indigo max-w-none mb-6",children:e.jsx(q,{children:s.content||""})}),!s.submission_status&&e.jsxs("div",{className:"mt-8 border-t border-gray-100 pt-6",children:[e.jsx("div",{className:"text-xs font-semibold uppercase tracking-wider text-gray-400 mb-2",children:"Ready to submit?"}),e.jsx("p",{className:"text-xs text-gray-500 mb-4",children:s?.content&&s.content.startsWith('{"quizType":"mcq_learning_objectives"')?"Please answer all the interactive questions on the evaluation sheet, then click Submit.":"You can use the whiteboard to draw or answer, then click submit when finished."}),e.jsx("button",{onClick:async()=>{const n=s?.content&&s.content.startsWith('{"quizType":"mcq_learning_objectives"');if(n&&JSON.stringify(i),n)try{const r=JSON.parse(s.content),t=Object.keys(i).length;if(t<r.questions.length&&!window.confirm(`You have only answered ${t}/${r.questions.length} questions. Are you sure you want to submit your answers?`))return}catch{}await d(!1)},className:"w-full py-2 bg-indigo-600 text-white rounded-lg shadow font-medium hover:bg-indigo-700 transition",children:"Submit"})]}),s.submission_status==="graded"&&s.feedback&&e.jsxs("div",{className:"mt-6 bg-green-50 p-4 rounded-xl border border-green-100",children:[e.jsxs("div",{className:"font-semibold text-green-800 text-sm mb-1 flex items-center gap-1",children:[e.jsx(A,{size:16})," Grade: ",s.score,"%"]}),e.jsx("div",{className:"text-xs text-green-700 whitespace-pre-wrap leading-relaxed font-sans",children:s.feedback})]})]})}function W({assignmentId:x,timeLimitMinutes:s,onTimeUp:i,isSubmitted:o}){const[d,m]=N.useState(null);if(N.useEffect(()=>{if(o||!s||s<=0){m(null);return}const a=`quiz_timer_start_${x}`;let u=sessionStorage.getItem(a),g=u?parseInt(u,10):null;g||(g=Date.now(),sessionStorage.setItem(a,g.toString()));const l=s*60,c=()=>{const j=Math.floor((Date.now()-g)/1e3),h=l-j;h<=0?(m(0),i()):m(h)};c();const b=setInterval(c,1e3);return()=>clearInterval(b)},[x,s,o,i]),!s||s<=0)return null;if(o)return e.jsxs("div",{className:"flex items-center gap-2 font-sans text-xs bg-gray-100 text-gray-600 px-3 py-1.5 rounded-lg border border-gray-200",children:[e.jsx(S,{size:14}),e.jsxs("span",{children:["Time Limit: ",s," mins (Completed)"]})]});if(d===null)return null;const n=Math.floor(d/60),r=d%60,t=d<60;return e.jsxs("div",{className:`flex items-center gap-3 font-sans px-4 py-2.5 rounded-xl border transition-all ${t?"bg-red-50 text-red-700 border-red-200 animate-pulse font-bold":d<180?"bg-amber-50 text-amber-700 border-amber-200 font-semibold":"bg-indigo-50 text-indigo-700 border-indigo-100"}`,children:[e.jsx(S,{size:16,className:t?"text-red-600 animate-pulse":"text-indigo-600"}),e.jsxs("div",{className:"flex-1 flex justify-between items-center text-xs gap-4",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Time Remaining:"}),e.jsxs("span",{className:"font-mono ml-1 text-sm bg-black/5 text-slate-800 px-1.5 py-0.5 rounded font-bold",children:[n.toString().padStart(2,"0"),":",r.toString().padStart(2,"0")]})]}),t&&e.jsxs("span",{className:"flex items-center gap-1 text-xs uppercase tracking-wider text-red-600 font-bold animate-pulse",children:[e.jsx(E,{size:12})," Time is almost up!"]})]})]})}function P(x){const{selectedAssignment:s,subAssignmentTab:i,setSubAssignmentTab:o,quizStudentAnswers:d,setQuizStudentAnswers:m,submitQuizAssignment:n,elements:r,activeRole:t,activeStudentId:a,fetchElements:u}=x;return e.jsx("div",{className:"flex-1 relative flex flex-col min-h-0",children:(()=>{const g=s?.content&&s.content.startsWith('{"quizType":"mcq_learning_objectives"');return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs font-semibold uppercase tracking-wider text-gray-500 pointer-events-none",children:g&&i==="quiz"?"Evaluation Sheet":"Live Canvas"}),g&&e.jsxs("div",{className:"flex bg-gray-100 p-0.5 rounded-lg border border-gray-200 text-xs",children:[e.jsx("button",{onClick:()=>o("quiz"),className:`px-2.5 py-0.5 rounded text-xs font-bold transition-all ${i==="quiz"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-900"}`,children:"Interactive Test"}),e.jsx("button",{onClick:()=>o("whiteboard"),className:`px-2.5 py-0.5 rounded text-xs font-bold transition-all ${i==="whiteboard"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-900"}`,children:"Sketch Whiteboard"})]})]}),s.submission_status&&e.jsx("div",{className:"text-xs uppercase font-bold text-gray-400 bg-gray-100 px-2 py-0.5 rounded",children:"Read Only"})]}),g&&i==="quiz"?e.jsx("div",{className:"flex-1 bg-gray-50/50 rounded-xl border border-gray-200 p-6 overflow-y-auto space-y-6",children:(()=>{try{const l=JSON.parse(s.content);return e.jsxs(e.Fragment,{children:[l.timeLimit>0&&e.jsx(W,{assignmentId:s.id,timeLimitMinutes:l.timeLimit,onTimeUp:()=>n(!0),isSubmitted:!!s.submission_status}),l.questions.map((c,b)=>{const j=d[b],h=!!s.submission_status,v=d[b]===c.correctAnswer;return e.jsxs("div",{className:"bg-white p-5 rounded-xl border border-gray-100 shadow-sm space-y-3 font-sans",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-6 h-6 rounded-full bg-indigo-50 text-indigo-700 flex items-center justify-center text-xs font-bold ring-1 ring-indigo-100",children:b+1}),e.jsxs("span",{className:"text-xs font-semibold text-teal-700 bg-teal-50 px-2.5 py-0.5 rounded-full border border-teal-100",children:["evaluates: ",c.objective]})]}),h&&e.jsx("span",{className:`text-xs font-bold px-2.5 py-0.5 rounded-full ${v?"bg-green-100 text-green-800":"bg-red-100 text-red-800"}`,children:v?"Correct ✓":`Incorrect (Correct Option: ${c.correctAnswer})`})]}),e.jsx("div",{className:"font-semibold text-gray-800 text-sm",children:c.question}),e.jsx("div",{className:"grid grid-cols-2 gap-3 text-xs pt-1",children:c.options.map((f,$)=>{const y=j===f,w=f===c.correctAnswer;let p="border-gray-200 hover:border-gray-300 bg-white text-gray-700 hover:bg-gray-50/50 cursor-pointer";return h?y?p=w?"border-green-600 bg-green-50 text-green-900 ring-2 ring-green-100":"border-red-600 bg-red-50 text-red-900 ring-2 ring-red-100":w?p="border-green-400 bg-green-50/20 text-green-900":p="border-gray-200 opacity-60 text-gray-400":y&&(p="border-indigo-600 bg-indigo-50/30 text-indigo-900 ring-2 ring-indigo-100 font-medium cursor-pointer"),e.jsxs("div",{onClick:()=>{h||m(k=>({...k,[b]:f}))},className:`p-3 rounded-xl border transition-all duration-150 flex items-center justify-between ${p}`,children:[e.jsx("span",{children:f}),y&&(h?w?e.jsx(A,{size:14,className:"text-green-600 shrink-0"}):e.jsx(R,{size:14,className:"text-red-600 shrink-0"}):e.jsx("div",{className:"w-2 h-2 rounded-full bg-indigo-600 shadow-sm shrink-0"}))]},$)})})]},b)})]})}catch{return e.jsx("div",{className:"text-xs text-red-500 font-sans",children:"Error parsing quiz structure."})}})()}):e.jsx("div",{className:`flex-1 min-h-0 flex flex-col ${s.submission_status?"opacity-90 pointer-events-none filter grayscale-[0.2]":""}`,children:e.jsx(O,{lessonId:`assignment-${s.id}-student-${a}`,elements:r,userRole:t,enableAutoAI:t==="student"&&!s.submission_status,onElementAdd:async(l,c)=>{await fetch(`/api/lessons/assignment-${s.id}-student-${a}/whiteboard`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:l,data:c})}),u(`assignment-${s.id}-student-${a}`)},onElementUpdate:async(l,c)=>{await fetch(`/api/lessons/assignment-${s.id}-student-${a}/whiteboard/${l}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({data:c})}),u(`assignment-${s.id}-student-${a}`)},onElementDelete:async l=>{await fetch(`/api/lessons/assignment-${s.id}-student-${a}/whiteboard/${l}`,{method:"DELETE"}),u(`assignment-${s.id}-student-${a}`)},onClearBoard:async()=>{await fetch(`/api/lessons/assignment-${s.id}-student-${a}/whiteboard`,{method:"DELETE"}),u(`assignment-${s.id}-student-${a}`)},onRefresh:()=>u(`assignment-${s.id}-student-${a}`)})})]})})()})}function K(x){const{selectedAssignment:s,setStudentViewStatus:i,setSelectedAssignment:o,quizStudentAnswers:d,submitQuizAssignment:m,subAssignmentTab:n,setSubAssignmentTab:r,setQuizStudentAnswers:t,elements:a,activeRole:u,activeStudentId:g,fetchElements:l}=x;return e.jsxs("div",{className:"flex flex-col h-full space-y-4",children:[e.jsx(I,{setStudentViewStatus:i,setSelectedAssignment:o,selectedAssignment:s}),e.jsxs("div",{className:"flex-1 flex gap-6 min-h-0 bg-white border border-gray-200 rounded-xl p-4 shadow-sm",children:[e.jsx(Q,{selectedAssignment:s,quizStudentAnswers:d,setQuizStudentAnswers:t,submitQuizAssignment:m}),e.jsx(P,{selectedAssignment:s,subAssignmentTab:n,setSubAssignmentTab:r,quizStudentAnswers:d,setQuizStudentAnswers:t,submitQuizAssignment:m,elements:a,activeRole:u,activeStudentId:g,fetchElements:l})]})]})}export{K as StudentAssignmentView};
@@ -0,0 +1,13 @@
1
+ import{r as v,j as s}from"./vendor-react-CZ1I7IcM.js";import{L as Z,f as ee,B as te,l as se,m as ie,q as Q,b as ne,ah as B,a3 as K,b0 as ae,O as re,C as oe,k as le,z as ce,a as de,aq as ue,Z as he,p as me,aV as ge,al as fe}from"./vendor-icons-CyfamhaC.js";import{f as J,M as xe,E as G}from"./index-B6wtREUD.js";import{h as pe}from"./vendor-utils-B6R8dnOe.js";import{L as we}from"./LazyWhiteboard-Cy5DdYnO.js";import{L as ve}from"./LazyCourseware-BV5nOs5y.js";import"./vendor-pptx-D4btWy5L.js";import"./vendor-pdf-D0UGJOgo.js";import"./vendor-motion-BFAPOs-b.js";import"./vendor-charts-DGsG2RUv.js";function ye({lessonId:c,lang:e,addToast:t}){const[i,n]=v.useState(""),[a,l]=v.useState("idle"),[o,m]=v.useState("");if(v.useEffect(()=>{n(""),l("idle"),m("")},[c]),!c)return null;const f=async()=>{const p=i.trim();if(!p){l("error"),m(e==="zh"?"请先输入签到码":"Enter the check-in code first");return}l("submitting"),m("");try{const S=await fetch(`/api/classroom/sessions/${encodeURIComponent(c)}/checkin`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:p})}),y=await S.json().catch(()=>({}));if(!S.ok||!y.success){l("error");const P=y.error==="Invalid checkin code"?e==="zh"?"签到码不正确,请核对大屏后重试":"Wrong code, check the stage display and retry":y.error||(e==="zh"?"签到失败,请稍后重试":"Check-in failed, retry later");m(P);return}l("done"),m(e==="zh"?"签到成功,出勤已记录":"Checked in, attendance recorded"),t(e==="zh"?"签到成功":"Checked in",e==="zh"?"出勤已记录":"Attendance recorded","success")}catch{l("error"),m(e==="zh"?"网络异常,请稍后重试":"Network error, retry later")}};return s.jsxs("div",{className:"flex flex-wrap items-center gap-2 bg-surface border border-theme rounded-xl px-3 py-2 shadow-sm text-main",children:[s.jsx("span",{className:"text-xs font-bold",children:e==="zh"?"课堂签到":"Check-in"}),a==="done"?s.jsxs("span",{className:"text-xs font-bold text-emerald-600",children:["✓ ",o]}):s.jsxs(s.Fragment,{children:[s.jsx("input",{value:i,onChange:p=>n(p.target.value.replace(/\s/g,"").slice(0,12)),onKeyDown:p=>{p.key==="Enter"&&f()},placeholder:e==="zh"?"输入大屏 4 位签到码":"4-digit code on stage display",inputMode:"numeric","aria-label":e==="zh"?"课堂签到码":"Class check-in code",className:"w-44 px-2 py-1 text-sm font-mono tracking-widest border border-theme rounded-lg bg-transparent"}),s.jsx("button",{type:"button",onClick:()=>void f(),disabled:a==="submitting",className:"px-3 py-1 text-xs font-bold rounded-lg bg-indigo-600 text-white hover:bg-indigo-700 disabled:opacity-50 cursor-pointer",children:a==="submitting"?e==="zh"?"提交中…":"Submitting…":e==="zh"?"签到":"Check in"})]}),a==="error"&&o&&s.jsx("span",{className:"text-xs text-rose-600",children:o})]})}function be(c){const{students:e,activeStudentId:t,isStudentLocked:i=!1,setStudentViewStatus:n,setSelectedLesson:a,lessons:l,selectedLesson:o,lang:m="zh"}=c,f=i||!!e.find(p=>p.id===t)?.locked_lesson_id;return s.jsxs("div",{className:"flex items-center justify-between gap-4",children:[f?s.jsxs("div",{className:"text-indigo-700 font-semibold text-sm flex items-center gap-2 px-3 py-1.5 rounded-lg bg-indigo-50 border border-indigo-200 shadow-3xs select-none",role:"status",title:m==="zh"?"老师已开启全班专注锁定,您暂时无法切换页面":"The teacher locked the class focus. Navigating away is disabled.",children:[s.jsx(Z,{size:15,className:"text-indigo-600 shrink-0"}),m==="zh"?"全班专注锁定 · 跟随教师授课":"Class Focus Locked · Following Teacher"]}):s.jsxs("button",{onClick:()=>{n("dashboard"),a(null)},className:"flex items-center gap-2 text-indigo-600 hover:text-indigo-800 transition-colors font-medium text-sm cursor-pointer",children:[s.jsx(ee,{className:"rotate-180",size:16})," Back to Dashboard"]}),s.jsx("h2",{className:"text-xl font-bold text-gray-800",children:l.find(p=>p.id===o)?.title})]})}class Se{constructor(){this.activities=new Map,this.registerBuiltins()}registerActivity(e){if(!e.type)throw new Error('[ActivityRegistry] Activity definition must specify a "type" property.');this.activities.set(e.type,e)}unregisterActivity(e){return this.activities.delete(e)}getActivity(e){return this.activities.get(e)}hasActivity(e){return this.activities.has(e)}listActivities(){return Array.from(this.activities.values())}registerBuiltins(){const e=[{type:"video",name:"播放视频",description:"支持MP4/HLS及网页视频流",category:"media"},{type:"image",name:"展示图片",description:"高质量图像及图表展示",category:"media"},{type:"python",name:"运行Python",description:"代码编辑器与Pyodide在线运行",category:"coding"},{type:"quiz",name:"开始Quiz",description:"单选、多选、填空即时测验",category:"assessment"},{type:"discussion",name:"开始讨论",description:"分组与全班实时互动研讨",category:"collaboration"},{type:"ai_question",name:"AI生成问题",description:"AI智能提问与实时反馈",category:"ai"},{type:"web_browse",name:"网页浏览",description:"内置浏览器嵌入外部网页资源",category:"custom"},{type:"geogebra",name:"GeoGebra演示",description:"动态数学与几何三维建模",category:"simulation"},{type:"mindmap",name:"思维导图",description:"协作式思维导图绘制",category:"collaboration"},{type:"simulation",name:"科学实验模拟",description:"物理化学交互式仿真",category:"simulation"},{type:"vr",name:"VR沉浸式体验",description:"WebXR 3D虚拟现实场景",category:"simulation"}];for(const t of e)this.registerActivity(t)}}class je{constructor(e){this.flow=null,this.stageIndex=0,this.activityIndex=0,this.stageElapsedSeconds=0,this.totalElapsedSeconds=0,this.isPreviewMode=!1,this.listeners=new Set,this.timer=null,e&&this.loadFlow(e)}loadFlow(e){this.flow=e,this.stageIndex=0,this.activityIndex=0,this.stageElapsedSeconds=0,this.notify()}getFlow(){return this.flow}subscribe(e){return this.listeners.add(e),e(this.getState()),()=>{this.listeners.delete(e)}}getState(){if(!this.flow||this.flow.stages.length===0)return{currentStageIndex:-1,currentActivityIndex:-1,stageElapsedSeconds:0,totalElapsedSeconds:this.totalElapsedSeconds,isPreview:this.isPreviewMode,canNext:!1,canPrevious:!1};const e=this.flow.stages[this.stageIndex],t=e?.activities?.[this.activityIndex],i=this.stageIndex>=this.flow.stages.length-1,n=e?.activities?this.activityIndex>=e.activities.length-1:!0,a=!i||!n,l=this.stageIndex>0||this.activityIndex>0;return{currentStageIndex:this.stageIndex,currentActivityIndex:this.activityIndex,currentStage:e,currentActivity:t,stageElapsedSeconds:this.stageElapsedSeconds,totalElapsedSeconds:this.totalElapsedSeconds,isPreview:this.isPreviewMode,canNext:a,canPrevious:l}}startTimer(){this.timer||(this.timer=setInterval(()=>{this.stageElapsedSeconds+=1,this.totalElapsedSeconds+=1,this.notify()},1e3))}stopTimer(){this.timer&&(clearInterval(this.timer),this.timer=null)}resetTimer(){this.stageElapsedSeconds=0,this.notify()}next(){if(!this.flow||this.flow.stages.length===0)return!1;const e=this.flow.stages[this.stageIndex];if(e?.activities&&this.activityIndex<e.activities.length-1)this.activityIndex+=1;else if(this.stageIndex<this.flow.stages.length-1)this.stageIndex+=1,this.activityIndex=0,this.stageElapsedSeconds=0;else return!1;return this.notify(),!0}previous(){if(!this.flow||this.flow.stages.length===0)return!1;if(this.activityIndex>0)this.activityIndex-=1;else if(this.stageIndex>0){this.stageIndex-=1;const e=this.flow.stages[this.stageIndex];this.activityIndex=e.activities&&e.activities.length>0?e.activities.length-1:0,this.stageElapsedSeconds=0}else return!1;return this.notify(),!0}jump(e,t){if(!this.flow||this.flow.stages.length===0)return!1;let i=-1;if(typeof e=="number"?i=e:i=this.flow.stages.findIndex(a=>a.id===e),i<0||i>=this.flow.stages.length)return!1;this.stageIndex=i;const n=this.flow.stages[i];if(t!==void 0){let a=-1;typeof t=="number"?a=t:a=n.activities.findIndex(l=>l.id===t),a>=0&&a<n.activities.length?this.activityIndex=a:this.activityIndex=0}else this.activityIndex=0;return this.stageElapsedSeconds=0,this.notify(),!0}restart(){this.stageIndex=0,this.activityIndex=0,this.stageElapsedSeconds=0,this.notify()}setPreview(e){this.isPreviewMode=e,this.notify()}notify(){const e=this.getState();for(const t of this.listeners)try{t(e)}catch(i){console.error("[TeachingTimeline] Listener error:",i)}}}class Ne{constructor(e){this.currentStage=null,this.isPaused=!1,this.startTime=0,this.elapsedTime=0,this.studentActions=[],this.timer=null,this.eventBus=e?.eventBus,this.onTimeoutWarning=e?.onTimeoutWarning}async enterStage(e,t,i,n){this.currentStage&&await this.exitStage(t,i),this.currentStage={...e,completionStatus:"in_progress"},this.isPaused=!1,this.startTime=Date.now(),this.elapsedTime=0,this.studentActions=[],this.currentStage.analytics||(this.currentStage.analytics={completionRate:0,participantCount:0,elapsedTimeSeconds:0,interactionCount:0,quizScores:[],discussionHeat:0}),this.startTimer(t),this.eventBus&&await this.eventBus.publish({id:globalThis.crypto.randomUUID(),type:"stage.entered",source:"stage.runtime",payload:{lessonId:t,flowId:i,stageId:e.id,stageIndex:n,timestamp:Date.now()},timestamp:Date.now()})}async exitStage(e,t){if(!this.currentStage)return null;this.stopTimer(),this.currentStage.completionStatus="completed";const i=this.calculateAnalytics();this.currentStage.analytics=i,this.eventBus&&await this.eventBus.publish({id:globalThis.crypto.randomUUID(),type:"stage.finished",source:"stage.runtime",payload:{lessonId:e,flowId:t,stageId:this.currentStage.id,analytics:i,timestamp:Date.now()},timestamp:Date.now()});const n={...i};return this.currentStage=null,n}pauseStage(){!this.currentStage||this.isPaused||(this.isPaused=!0)}resumeStage(){!this.currentStage||!this.isPaused||(this.isPaused=!1)}autoFinishStage(e,t){return this.exitStage(e,t)}recordStudentAction(e){this.currentStage&&(this.studentActions.push(e),this.updateAnalyticsLive())}updateActivityStatus(e,t){if(!this.currentStage)return;const i=this.currentStage.activities.find(n=>n.id===e);i&&(i.status=t)}getCurrentStage(){return this.currentStage}getElapsedTimeSeconds(){return this.elapsedTime}isStagePaused(){return this.isPaused}startTimer(e){this.stopTimer(),this.timer=setInterval(()=>{!this.isPaused&&this.currentStage&&(this.elapsedTime+=1,this.checkTimeout(e))},1e3)}stopTimer(){this.timer&&(clearInterval(this.timer),this.timer=null)}checkTimeout(e){if(!this.currentStage)return;const t=this.currentStage.estimatedDurationSeconds;if(t&&t>0){const i=t-this.elapsedTime;(i===60||i===30)&&this.onTimeoutWarning&&this.onTimeoutWarning(this.currentStage.id,i)}}updateAnalyticsLive(){if(!this.currentStage||!this.currentStage.analytics)return;const e=new Set(this.studentActions.map(i=>i.studentId));this.currentStage.analytics.participantCount=e.size,this.currentStage.analytics.interactionCount=this.studentActions.length,this.currentStage.analytics.elapsedTimeSeconds=this.elapsedTime;const t=this.studentActions.filter(i=>Date.now()-i.timestamp<3e5);this.currentStage.analytics.discussionHeat=Math.min(100,Math.round(t.length*10))}calculateAnalytics(){const e=new Set(this.studentActions.map(o=>o.studentId)),i=this.studentActions.filter(o=>o.actionType==="quiz_submit").map(o=>({studentId:o.studentId,score:o.payload.score||0,maxScore:o.payload.maxScore||100})),n=this.currentStage?.activities.filter(o=>o.status==="completed").length||0,a=this.currentStage?.activities.length||1;return{completionRate:Math.round(n/a*100),participantCount:e.size,elapsedTimeSeconds:this.elapsedTime,interactionCount:this.studentActions.length,quizScores:i,discussionHeat:Math.min(100,Math.round(this.studentActions.length*8))}}}class Le{constructor(){this.data={role:"teacher",isPresentationMode:!1},this.listeners=new Set}getContext(){return{...this.data}}updateContext(e){this.data={...this.data,...e},this.notify()}setCurrentLesson(e){this.data.currentLesson=e,e&&(this.data.teacher=e.teacher),this.notify()}setCurrentFlow(e){this.data.currentFlow=e,this.notify()}setCurrentStage(e){this.data.currentStage=e,this.notify()}setCurrentActivity(e){this.data.currentActivity=e,this.notify()}setUser(e){this.data.currentUser=e,this.data.role=e.role,this.notify()}setPresentationMode(e){this.data.isPresentationMode=e,this.notify()}subscribe(e){return this.listeners.add(e),e(this.getContext()),()=>{this.listeners.delete(e)}}notify(){const e=this.getContext();for(const t of this.listeners)try{t(e)}catch(i){console.error("[TeachingContextManager] Listener error:",i)}}}class Ie{constructor(){this.stageViews=new Map,this.sharedObjects=new Map}getStageView(e,t="Stage View"){let i=this.stageViews.get(e);return i||(i={stageId:e,stageTitle:t,elements:[],backgroundColor:"#ffffff",viewport:{x:0,y:0,zoom:1},updatedAt:Date.now()},this.stageViews.set(e,i)),this.resolveSharedElements(i)}updateStageView(e,t){const i=this.getStageView(e),n={...i,...t,elements:t.elements?[...t.elements]:i.elements,updatedAt:Date.now()};return this.stageViews.set(e,n),n}shareObjectAcrossStages(e,t){const i={...e,isShared:!0,sharedStageIds:t};this.sharedObjects.set(e.id,i);for(const n of t){const a=this.getStageView(n);a.elements.some(o=>o.id===e.id)||(a.elements.push(i),a.updatedAt=Date.now(),this.stageViews.set(n,a))}}unshareObject(e,t){if(t){const i=this.stageViews.get(t);i&&(i.elements=i.elements.filter(n=>n.id!==e),this.stageViews.set(t,i))}else{this.sharedObjects.delete(e);for(const[i,n]of this.stageViews.entries())n.elements=n.elements.filter(a=>a.id!==e),this.stageViews.set(i,n)}}copyStageView(e,t,i){const n=this.getStageView(e),a=n.elements.map(o=>({...o,id:o.isShared?o.id:`elem_${globalThis.crypto.randomUUID()}`,sourceStageId:t})),l={stageId:t,stageTitle:i,elements:a,backgroundColor:n.backgroundColor,viewport:n.viewport?{...n.viewport}:void 0,updatedAt:Date.now()};return this.stageViews.set(t,l),l}clearStageView(e){const t=this.stageViews.get(e);t&&(t.elements=t.elements.filter(i=>i.isShared),t.updatedAt=Date.now(),this.stageViews.set(e,t))}resolveSharedElements(e){const t=new Map;for(const i of e.elements)t.set(i.id,i);for(const[i,n]of this.sharedObjects.entries())n.sharedStageIds?.includes(e.stageId)&&t.set(i,n);return{...e,elements:Array.from(t.values())}}}class ke{constructor(){this.frames=[],this.isReplaying=!1,this.isPaused=!1,this.currentFrameIndex=0,this.startTime=0,this.timer=null}recordEvent(e,t){const i=Math.max(0,e.timestamp-t);this.frames.push({timestamp:e.timestamp,relativeTimeMs:i,event:e}),this.sortFrames()}recordSnapshot(e,t){const i=Math.max(0,e.timestamp-t);this.frames.push({timestamp:e.timestamp,relativeTimeMs:i,snapshot:e}),this.sortFrames()}loadFrames(e){this.frames=[...e],this.sortFrames(),this.currentFrameIndex=0}getFrames(){return[...this.frames]}startReplay(e,t=1){if(this.frames.length===0)return;this.frameHandler=e,this.isReplaying=!0,this.isPaused=!1,this.startTime=Date.now();const i=Math.max(50,Math.floor(100/t));this.stopTimer(),this.timer=setInterval(()=>{if(this.isPaused)return;if(this.currentFrameIndex>=this.frames.length){this.stopReplay();return}const n=this.frames[this.currentFrameIndex];this.frameHandler&&this.frameHandler(n),this.currentFrameIndex+=1},i)}pauseReplay(){this.isPaused=!0}resumeReplay(){this.isPaused=!1}seek(e){if(e<0||e>=this.frames.length)return null;this.currentFrameIndex=e;const t=this.frames[this.currentFrameIndex];return this.frameHandler&&this.frameHandler(t),t}stopReplay(){this.stopTimer(),this.isReplaying=!1,this.isPaused=!1,this.currentFrameIndex=0}isReplayingActive(){return this.isReplaying}stopTimer(){this.timer&&(clearInterval(this.timer),this.timer=null)}sortFrames(){this.frames.sort((e,t)=>e.relativeTimeMs-t.relativeTimeMs)}}class Ae{constructor(e){this.aiService=e}setAIService(e){this.aiService=e}getStageContextForAI(e){return`[Stage Context]
2
+ Title: ${e.title}
3
+ Goals: ${e.teachingGoals.join(", ")||"N/A"}
4
+ Knowledge Points: ${e.knowledgePoints.join(", ")||"N/A"}
5
+ Assignee: ${e.assignee}
6
+ Activities Count: ${e.activities.length}
7
+ Activities: ${e.activities.map(t=>`${t.title} (${t.type})`).join(" -> ")}`}getLessonContextForAI(e,t){return`[Lesson Context]
8
+ Title: ${e.title}
9
+ Subject: ${e.subject}
10
+ Grade: ${e.grade}
11
+ Teacher: ${e.teacher.name}
12
+ Active Flow: ${t?.name||"Default Flow"}
13
+ Stages Count: ${t?.stages.length||0}`}async generateQuizForStage(e,t=3){const i=`Based on the teaching stage "${e.title}" with knowledge points [${e.knowledgePoints.join(", ")}] and goals [${e.teachingGoals.join(", ")}], generate ${t} multiple choice questions in JSON array format with fields: question, options (array of 4 strings), answerIndex (0-3), explanation. Return ONLY JSON.`;if(this.aiService)try{const n=await this.aiService.generateText(i,{temperature:.3}),a=JSON.parse(n.replace(/```json|```/g,"").trim());if(Array.isArray(a))return a}catch(n){console.warn("[LessonAIInterface] Fallback to synthetic quiz generation due to AI call error:",n)}return e.knowledgePoints.map((n,a)=>({question:`关于 ${n},下列哪项说法是正确的?`,options:[`${n} 是本阶段核心学习要点A`,`${n} 的定义与逻辑推导B`,`${n} 的实际应用场景C`,"以上说法均正确"],answerIndex:3,explanation:`本题考查${e.title}中关于${n}的基础理解。`}))}async generateSummaryForActivity(e){const t=`Summarize the educational activity "${e.title}" (Type: ${e.type}) for teacher recap. Keep it under 100 words.`;if(this.aiService)try{return await this.aiService.generateText(t,{temperature:.4})}catch(i){console.warn("[LessonAIInterface] AI service failed, returning fallback summary:",i)}return`环节 [${e.title}] (类型: ${e.type}) 已顺利完成。学生积极参与了互动与思考,达成了该环节的预定教学指标。`}async generateLessonPlan(e,t,i){const n=`Generate a structured lesson flow for ${t} ${e} topic "${i}". Include 5 stages: 导入, 新知学习, 课堂演示, 课堂练习, 课堂总结. Return standard JSON.`;if(this.aiService)try{const a=await this.aiService.generateText(n,{temperature:.5}),l=JSON.parse(a.replace(/```json|```/g,"").trim());if(l&&Array.isArray(l.stages))return l}catch(a){console.warn("[LessonAIInterface] AI lesson plan generation failed, using standard template:",a)}return{name:`${i} 教学流程`,description:`${t}${e}《${i}》标准教学流程`,version:1,stages:[{id:`stg_import_${Date.now()}`,title:"一、导入",estimatedDurationSeconds:300,teachingGoals:["激发学习兴趣","引入课题背景"],knowledgePoints:[i],completionStatus:"pending",assignee:"teacher",activities:[{id:`act_img_${Date.now()}`,type:"image",title:"情境图片展示",config:{},status:"idle",teachingObjects:[]},{id:`act_vid_${Date.now()}`,type:"video",title:"导入短视频",config:{},status:"idle",teachingObjects:[]}]},{id:`stg_learn_${Date.now()}`,title:"二、新知学习",estimatedDurationSeconds:900,teachingGoals:["讲解核心概念","剖析要点推导"],knowledgePoints:[`${i}基础概念`,`${i}主要定理`],completionStatus:"pending",assignee:"teacher",activities:[{id:`act_ppt_${Date.now()}`,type:"image",title:"知识点课件讲解",config:{},status:"idle",teachingObjects:[]}]},{id:`stg_demo_${Date.now()}`,title:"三、课堂演示",estimatedDurationSeconds:600,teachingGoals:["示例演示","直观模型说明"],knowledgePoints:[`${i}应用示例`],completionStatus:"pending",assignee:"teacher",activities:[{id:`act_geo_${Date.now()}`,type:"geogebra",title:"动态模型演示",config:{},status:"idle",teachingObjects:[]},{id:`act_py_${Date.now()}`,type:"python",title:"Python代码验证",config:{},status:"idle",teachingObjects:[]}]},{id:`stg_practice_${Date.now()}`,title:"四、课堂练习",estimatedDurationSeconds:600,teachingGoals:["巩固练习","查漏补缺"],knowledgePoints:[`${i}习题训练`],completionStatus:"pending",assignee:"student",activities:[{id:`act_quiz_${Date.now()}`,type:"quiz",title:"随堂测验Quiz",config:{},status:"idle",teachingObjects:[]}]},{id:`stg_summary_${Date.now()}`,title:"五、课堂总结",estimatedDurationSeconds:300,teachingGoals:["梳理知识脉络","总结注意事项"],knowledgePoints:[`${i}知识小结`],completionStatus:"pending",assignee:"teacher",activities:[{id:`act_mind_${Date.now()}`,type:"mindmap",title:"思维导图总结",config:{},status:"idle",teachingObjects:[]}]}]}}}const W={idle:["draft","ready","active"],draft:["ready","active","idle"],ready:["active","idle"],active:["paused","completed"],paused:["active","completed"],completed:["idle"]};class H extends Error{constructor(e,t,i,n){super(`[LessonEngine] Invalid state transition for lesson "${e}": cannot transition from "${t}" to "${i}". Allowed transitions: [${n.join(", ")}]`),this.lessonId=e,this.fromStatus=t,this.toStatus=i,this.allowedTransitions=n,this.name="InvalidLessonStateTransitionError"}}class Ce{constructor(e="idle",t=""){this._listeners=new Set,this._status=e,this._lessonId=t}get status(){return this._status}get lessonId(){return this._lessonId}setLessonId(e){this._lessonId=e}canTransitionTo(e){return(W[this._status]||[]).includes(e)}transitionTo(e){if(this._status===e){if(e==="active")throw new H(this._lessonId,this._status,e,W[this._status]);return this._status}if(!this.canTransitionTo(e))throw new H(this._lessonId,this._status,e,W[this._status]||[]);const t=this._status;this._status=e;for(const i of this._listeners)try{i(t,e,this._lessonId)}catch(n){console.error("[LessonStateMachine] Listener callback failed:",n)}return this._status}onTransition(e){return this._listeners.add(e),()=>{this._listeners.delete(e)}}reset(e=""){this._status="idle",this._lessonId=e}}class Pe{constructor(e){this.guards=new Map,this.timeoutMs=e?.timeoutMs??1500,this.totalTimeoutMs=e?.totalTimeoutMs??Math.max(this.timeoutMs*3,3e3),this.failurePolicy=e?.onGuardFailure??"fail-close",this.onFailure=e?.onFailure}registerGuard(e,t){if(!e||!e.id)throw new Error("[StageGuardPipeline] Invalid guard: must have a non-empty id");const i=t??"";t||console.warn(`[StageGuardPipeline] Guard "${e.id}" registered without owner. Guards are keyed by id only — another plugin registering the same id will silently override it. Pass owner (pluginId) to registerGuard().`);const n=this.keyOf(i,e.id),a=this.guards.get(n);return a&&a!==e&&i&&console.warn(`[StageGuardPipeline] Guard "${e.id}" replaced for owner "${i}" (previous: "${a.name}"). This is normal for hot reload.`),this.guards.set(n,{...e,owner:i}),()=>{this.unregisterGuard(e.id,i)}}unregisterGuard(e,t){this.guards.delete(this.keyOf(t??"",e))}unregisterByOwner(e){let t=0;for(const[i,n]of this.guards)n.owner===e&&(this.guards.delete(i),t++);return t}listGuardsByOwner(e){return this.listGuards().filter(t=>t.owner===e)}keyOf(e,t){return`${e}\0${t}`}listGuards(){return Array.from(this.guards.values()).sort((e,t)=>(e.priority??100)-(t.priority??100))}async checkAccess(e){const t=this.listGuards();if(t.length===0)return{allowed:!0};const i=await Promise.all(t.map(o=>this.executeGuardWithResilience(o,e,this.totalTimeoutMs))),n=[],a=[];let l;for(let o=0;o<t.length;o++){const m=i[o];m.allowed||(n.push(t[o].id),m.reason&&a.push(m.reason),m.progress&&!l&&(l=m.progress))}return n.length>0?{allowed:!1,reason:a.join(";")||"未满足进入下一环节的前置条件",guardIds:n,progress:l}:{allowed:!0}}async executeGuardWithResilience(e,t,i){let n,a=!1;const l=i===void 0?this.timeoutMs:Math.min(this.timeoutMs,Math.max(i,1)),o=new Promise(f=>{n=setTimeout(()=>{a=!0,f(this.onGuardFailure(e,"timeout",void 0))},l)}),m=(async()=>{try{return await e.canEnterStage(t)}catch(f){return this.onGuardFailure(e,"threw",f)}})();try{return await Promise.race([m,o])}finally{n&&clearTimeout(n),a&&m.catch(()=>{})}}onGuardFailure(e,t,i){const n=this.failurePolicy==="fail-open";t==="threw"?console.error(`[StageGuardPipeline] Guard "${e.id}" (${e.name}) threw an exception. Policy=${this.failurePolicy}.`,i):console.warn(`[StageGuardPipeline] Guard "${e.id}" (${e.name}) timed out after ${Math.min(this.timeoutMs,this.totalTimeoutMs)}ms. Policy=${this.failurePolicy}.`);try{this.onFailure?.({guardId:e.id,guardName:e.name,reason:t,error:i})}catch(a){console.error("[StageGuardPipeline] onFailure hook threw:",a)}return n?{allowed:!0}:{allowed:!1,reason:t==="timeout"?`门禁插件「${e.name||e.id}」响应超时,本环节暂不可进入`:`门禁插件「${e.name||e.id}」执行出错,本环节暂不可进入`}}clear(){this.guards.clear()}}const Te=new Pe({onFailure:({guardId:c,reason:e,error:t})=>{e==="timeout"?console.error(`[StageGuard] 门禁插件超时,已按 fail-close 拒绝进入: guardId=${c}`):console.error(`[StageGuard] 门禁插件抛错,已按 fail-close 拒绝进入: guardId=${c}`,t)}});class $e{constructor(e){this.currentLesson=null,this.activeFlow=null,this.snapshots=[],this.startTime=0,this.isLive=!1,this.eventBus=e?.eventBus,this.stageGuard=e?.stageGuard??Te,this.activityRegistry=new Se,this.timeline=new je,this.stageRuntime=new Ne({eventBus:this.eventBus}),this.contextManager=new Le,this.whiteboardAdapter=new Ie,this.replayer=new ke,this.aiInterface=new Ae,this.stateMachine=new Ce("idle"),this.stateMachine.onTransition((t,i,n)=>{this.publishEvent("LessonStateChanged",{lessonId:n,previousStatus:t,currentStatus:i,timestamp:Date.now()})}),this.timeline.subscribe(async t=>{!this.currentLesson||!this.activeFlow||(this.contextManager.setCurrentStage(t.currentStage),this.contextManager.setCurrentActivity(t.currentActivity),t.currentStage&&t.currentStage.id!==this.stageRuntime.getCurrentStage()?.id&&await this.stageRuntime.enterStage(t.currentStage,this.currentLesson.id,this.activeFlow.id,t.currentStageIndex),this.isLive&&this.publishEvent("StudentSynced",{lessonId:this.currentLesson.id,studentId:"*",stageId:t.currentStage?.id||"",activityId:t.currentActivity?.id,timestamp:Date.now()}))})}getStatus(){return this.stateMachine.status}async startLesson(e,t){if(this.currentLesson&&this.currentLesson.id===e.id&&this.stateMachine.status==="active")throw new H(e.id,this.stateMachine.status,"active",["paused","completed"]);this.stateMachine.setLessonId(e.id),this.stateMachine.transitionTo("active"),this.currentLesson={...e,status:"active",updatedAt:Date.now()};const i=t?e.flows.find(n=>n.id===t)||e.flows[0]:e.flows.find(n=>n.isCurrent)||e.flows[0];if(!i)throw new Error(`[LessonRuntime] No flow found in lesson ${e.id}`);this.activeFlow=i,this.currentLesson.activeFlowId=i.id,this.startTime=Date.now(),this.isLive=!0,this.timeline.loadFlow(i),this.timeline.startTimer(),this.contextManager.setCurrentLesson(this.currentLesson),this.contextManager.setCurrentFlow(i),await this.publishEvent("LessonStarted",{lessonId:e.id,flowId:i.id,timestamp:this.startTime}),this.takeSnapshot()}async pauseLesson(){if(!this.currentLesson)throw new Error("[LessonRuntime] Cannot pause without an active lesson.");this.stateMachine.transitionTo("paused"),this.currentLesson.status="paused",this.currentLesson.updatedAt=Date.now(),this.timeline.stopTimer(),this.stageRuntime.pauseStage(),await this.publishEvent("LessonPaused",{lessonId:this.currentLesson.id,elapsedSeconds:this.timeline.getState().totalElapsedSeconds,timestamp:Date.now()})}async resumeLesson(){if(!this.currentLesson)throw new Error("[LessonRuntime] Cannot resume without a lesson.");this.stateMachine.transitionTo("active"),this.currentLesson.status="active",this.currentLesson.updatedAt=Date.now(),this.timeline.startTimer(),this.stageRuntime.resumeStage(),await this.publishEvent("LessonStarted",{lessonId:this.currentLesson.id,flowId:this.activeFlow?.id||"",timestamp:Date.now()})}async stopLesson(){if(!this.currentLesson)return null;this.stateMachine.transitionTo("completed"),this.currentLesson.status="completed",this.currentLesson.updatedAt=Date.now(),this.isLive=!1,this.timeline.stopTimer();const e=await this.stageRuntime.exitStage(this.currentLesson.id,this.activeFlow?.id||"");return await this.publishEvent("LessonEnded",{lessonId:this.currentLesson.id,totalDurationSeconds:this.timeline.getState().totalElapsedSeconds,timestamp:Date.now()}),this.takeSnapshot(),e}reset(){this.stateMachine.reset(),this.currentLesson=null,this.activeFlow=null,this.isLive=!1,this.startTime=0,this.timeline.stopTimer()}takeSnapshot(){if(!this.currentLesson||!this.activeFlow)throw new Error("[LessonRuntime] Cannot take snapshot without active lesson.");const e=this.timeline.getState(),t={id:`snap_${globalThis.crypto.randomUUID()}`,lessonId:this.currentLesson.id,timestamp:Date.now(),lessonState:JSON.parse(JSON.stringify(this.currentLesson)),activeFlowId:this.activeFlow.id,activeStageId:e.currentStage?.id||"",activeActivityId:e.currentActivity?.id,elapsedSeconds:e.totalElapsedSeconds,whiteboardData:e.currentStage?this.whiteboardAdapter.getStageView(e.currentStage.id):void 0};return this.snapshots.push(t),this.startTime>0&&this.replayer.recordSnapshot(t,this.startTime),t}getSnapshots(){return[...this.snapshots]}nextStage(){return this.timeline.next()}backStage(){return this.timeline.previous()}lockStage(e,t=!0){if(!this.activeFlow)return!1;const i=this.activeFlow.stages.find(n=>n.id===e);return i?(i.locked=t,this.contextManager.setCurrentStage(this.timeline.getState().currentStage),!0):!1}skipStage(e){if(!this.activeFlow||!this.currentLesson)return!1;const t=this.activeFlow.stages.findIndex(i=>i.id===e);if(t>=0){const i=this.activeFlow.stages[t];return i.completionStatus="skipped",this.publishEvent("ActivitySkipped",{lessonId:this.currentLesson.id,stageId:e,activityId:"*",timestamp:Date.now()}),this.jumpStage(t+1)}return!1}jumpStage(e,t){const i=this.timeline.jump(e,t);if(i&&this.currentLesson){const n=this.timeline.getState();this.publishEvent("TeacherJump",{lessonId:this.currentLesson.id,targetStageId:n.currentStage?.id||"",targetActivityId:n.currentActivity?.id,timestamp:Date.now()})}return i}repeatStage(e){return this.jumpStage(e,0)}setPresentationMode(e){this.contextManager.setPresentationMode(e)}addFlow(e){this.currentLesson&&(this.currentLesson.flows.push(e),this.currentLesson.updatedAt=Date.now())}removeFlow(e){if(!this.currentLesson)return!1;const t=this.currentLesson.flows.findIndex(i=>i.id===e);return t>=0?(this.currentLesson.flows.splice(t,1),this.currentLesson.updatedAt=Date.now(),!0):!1}copyFlow(e,t){if(!this.currentLesson)return null;const i=this.currentLesson.flows.find(a=>a.id===e);if(!i)return null;const n={...JSON.parse(JSON.stringify(i)),id:`flw_${globalThis.crypto.randomUUID()}`,name:t||`${i.name} (副本)`,version:1,createdAt:Date.now(),updatedAt:Date.now()};return this.currentLesson.flows.push(n),n}addStageToFlow(e,t){if(!this.currentLesson)return!1;const i=this.currentLesson.flows.find(n=>n.id===e);return i?(i.stages.push(t),i.updatedAt=Date.now(),this.activeFlow?.id===e&&this.timeline.loadFlow(i),!0):!1}removeStageFromFlow(e,t){if(!this.currentLesson)return!1;const i=this.currentLesson.flows.find(a=>a.id===e);if(!i)return!1;const n=i.stages.findIndex(a=>a.id===t);return n>=0?(i.stages.splice(n,1),i.updatedAt=Date.now(),this.activeFlow?.id===e&&this.timeline.loadFlow(i),!0):!1}copyStageInFlow(e,t){if(!this.currentLesson)return null;const i=this.currentLesson.flows.find(o=>o.id===e);if(!i)return null;const n=i.stages.findIndex(o=>o.id===t);if(n<0)return null;const a=i.stages[n],l={...JSON.parse(JSON.stringify(a)),id:`stg_${globalThis.crypto.randomUUID()}`,title:`${a.title} (副本)`,completionStatus:"pending"};return i.stages.splice(n+1,0,l),i.updatedAt=Date.now(),this.activeFlow?.id===e&&this.timeline.loadFlow(i),l}reorderStagesInFlow(e,t,i){if(!this.currentLesson)return!1;const n=this.currentLesson.flows.find(l=>l.id===e);if(!n||t<0||t>=n.stages.length||i<0||i>=n.stages.length)return!1;const[a]=n.stages.splice(t,1);return n.stages.splice(i,0,a),n.updatedAt=Date.now(),this.activeFlow?.id===e&&this.timeline.loadFlow(n),!0}getCurrentLesson(){return this.currentLesson}getActiveFlow(){return this.activeFlow}async publishEvent(e,t){const i={id:globalThis.crypto.randomUUID(),type:e,source:"lesson.runtime",payload:t,timestamp:Date.now()};this.eventBus&&await this.eventBus.publish(i),this.startTime>0&&this.replayer.recordEvent(i,this.startTime)}}const Fe={id:"usr_teacher_demo",name:"演示教师",role:"teacher"},h=new $e({eventBus:J}),Me=pe((c,e)=>(h.timeline.subscribe(t=>{c({currentStageIndex:t.currentStageIndex,currentActivityIndex:t.currentActivityIndex,currentStage:t.currentStage||null,currentActivity:t.currentActivity||null,stageElapsedSeconds:t.stageElapsedSeconds,totalElapsedSeconds:t.totalElapsedSeconds,isPreviewMode:t.isPreview})}),h.stateMachine.onTransition((t,i)=>{c({status:i})}),h.contextManager.subscribe(t=>{c({isPresentationMode:t.isPresentationMode})}),{runtime:h,status:h.getStatus(),currentLesson:null,activeFlow:null,currentStage:null,currentActivity:null,currentStageIndex:0,currentActivityIndex:0,stageElapsedSeconds:0,totalElapsedSeconds:0,isPresentationMode:!1,isPreviewMode:!1,currentUser:Fe,initializeLesson:async(t,i)=>{h.getStatus()==="completed"&&h.reset(),await h.startLesson(t,i),c({status:h.getStatus(),currentLesson:h.getCurrentLesson(),activeFlow:h.getActiveFlow()})},startLesson:async()=>{const t=e().currentLesson;t&&(h.getStatus()==="completed"&&h.reset(),await h.startLesson(t),c({status:h.getStatus(),currentLesson:h.getCurrentLesson()}))},pauseLesson:async()=>{await h.pauseLesson(),c({status:h.getStatus(),currentLesson:h.getCurrentLesson()})},resumeLesson:async()=>{await h.resumeLesson(),c({status:h.getStatus(),currentLesson:h.getCurrentLesson()})},stopLesson:async()=>{const t=await h.stopLesson();return c({status:h.getStatus(),currentLesson:h.getCurrentLesson()}),t},resetLesson:()=>{h.reset(),c({status:"idle",currentLesson:null,activeFlow:null,currentStage:null,currentActivity:null,currentStageIndex:0,currentActivityIndex:0,stageElapsedSeconds:0,totalElapsedSeconds:0})},nextStage:()=>h.nextStage(),backStage:()=>h.backStage(),jumpStage:(t,i)=>h.jumpStage(t,i),skipStage:t=>h.skipStage(t),lockStage:(t,i=!0)=>h.lockStage(t,i),setPresentationMode:t=>{h.setPresentationMode(t)},setUser:t=>{h.contextManager.setUser(t),c({currentUser:t})},takeSnapshot:()=>h.takeSnapshot(),stageGuardPipeline:h.stageGuard,checkStageAccess:async(t,i)=>{const n=e(),a=i||n.currentUser?.id||"anonymous",l=n.currentLesson?.id||"",o=n.currentStage?.id||null;if(!l)return{allowed:!1,reason:"缺少 lessonId,无法校验环节门禁"};try{const m=await fetch(`/api/lessons/${encodeURIComponent(l)}/stage-access`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"same-origin",body:JSON.stringify({currentStageId:o,targetStageId:t,metadata:{studentId:a}})});if(!m.ok)return{allowed:!1,reason:`门禁服务不可用(HTTP ${m.status})`};const f=await m.json();return typeof f?.allowed!="boolean"?{allowed:!1,reason:"门禁服务返回了无法识别的结果"}:f}catch{return{allowed:!1,reason:"门禁服务不可达,已拒绝进入该环节"}}},checkStageAccessLocally:async(t,i)=>{const n=e(),a=i||n.currentUser?.id||"anonymous",l=n.currentLesson?.id||"",o=n.currentStage?.id||null;return h.stageGuard.checkAccess({studentId:a,lessonId:l,currentStageId:o,targetStageId:t})}}));function _e(c){const{students:e,activeStudentId:t,isStudentLocked:i=!1,studentFullscreenPanel:n,setStudentFullscreenPanel:a,timelineSegments:l,lang:o,activeSegmentId:m,setActiveSegmentId:f,localProgressPercent:p,setLocalProgressPercent:S,updateStudentProgress:y,selectedLesson:P,lessons:T,isStudentLessonContentCollapsed:M,addToast:k}=c,N=Me(r=>r.checkStageAccess),[L,A]=v.useState(null),[$,F]=v.useState({}),d=v.useCallback(async()=>{if(!l||l.length===0)return;const r=t||void 0,j={};for(const g of l){if(!g.id)continue;const x=await N(g.id,r);j[g.id]={allowed:x.allowed,reason:x.reason}}F(j)},[l,t,N]);v.useEffect(()=>{d()},[d]),v.useEffect(()=>{const r=()=>{d()},j=J.subscribe("QuizSubmitted",r),g=J.subscribe("assignment.submitted",r);return()=>{j(),g()}},[d]);const I=async r=>{if(m===r.id)return;const j=t||void 0,g=await N(r.id,j);if(!g.allowed){const x=g.reason||(o==="zh"?"尚未满足进入该环节的前置条件":"Prerequisite conditions not met");A({segmentId:r.id,segmentTitle:r.title||r.id,reason:x}),k&&k(o==="zh"?"暂未解锁该教学环节":"Stage Locked",x,"warning");return}A(null),f(r.id)};return s.jsxs("div",{className:`${M?"hidden":n==="left"?"w-full":"w-1/3 md:block hidden"} border-gray-100 pr-4 overflow-y-auto ${n==="right"?"hidden":""} ${n==="left"?"":"border-r"} transition-all duration-300`,children:[s.jsxs("div",{className:"text-xs font-semibold uppercase tracking-wider text-gray-400 mb-4 flex items-center justify-between pointer-events-auto shrink-0 select-none border-b border-gray-100 pb-2",children:[s.jsxs("span",{className:"flex items-center gap-1",children:[s.jsx(te,{size:14,className:"text-indigo-500"})," Lesson Content (课程内容)"]}),s.jsx("button",{onClick:()=>a(r=>r==="left"?"none":"left"),className:"p-1 hover:bg-gray-100 text-gray-400 hover:text-gray-700 rounded transition-colors cursor-pointer flex items-center gap-1",title:n==="left"?"退出全屏":"全屏",children:n==="left"?s.jsxs(s.Fragment,{children:[s.jsx(se,{size:13}),s.jsx("span",{className:"text-xs font-medium",children:"退出全屏"})]}):s.jsxs(s.Fragment,{children:[s.jsx(ie,{size:13}),s.jsx("span",{className:"text-xs font-medium",children:"全屏"})]})})]}),s.jsxs("div",{className:"prose prose-sm prose-indigo max-w-none",children:[!i&&!e.find(r=>r.id===t)?.locked_lesson_id&&l.length>0&&s.jsxs("div",{className:"mb-4 flex flex-col gap-2 p-3 bg-slate-50/70 border border-slate-200/50 rounded-xl shadow-3xs text-left",onClick:r=>r.stopPropagation(),children:[s.jsxs("div",{className:"text-xs font-bold text-gray-500 uppercase tracking-wider flex items-center gap-1.5 mb-1 select-none",children:[s.jsx(Q,{size:12,className:"text-indigo-500"}),o==="zh"?"教学环节 (点击切换)":"Timeline Segments"]}),s.jsx("div",{className:"flex flex-wrap gap-1.5",children:l.map((r,j)=>{const g=$[r.id],x=g?.allowed===!1,z=m===r.id;return s.jsxs("button",{onClick:()=>I(r),title:x?`未解锁: ${g.reason||"未满足前置条件"}`:void 0,className:`px-2.5 py-1 text-xs font-semibold rounded-lg border transition-all cursor-pointer shadow-3xs flex items-center gap-1.5 ${r.color} ${z?"ring-2 ring-indigo-500 scale-[1.02] shadow-sm border-indigo-400 font-bold":x?"opacity-70 hover:opacity-90 border-dashed border-amber-300":"opacity-85 hover:opacity-100"}`,children:[x&&s.jsx(Z,{size:11,className:"text-amber-600 shrink-0"}),s.jsxs("span",{children:[r.title," (",r.duration,")"]})]},r.id||j)})}),L&&s.jsxs("div",{className:"mt-2.5 p-2.5 bg-amber-50/90 border border-amber-200 rounded-lg flex items-start gap-2 text-xs text-amber-800 animate-in fade-in slide-in-from-top-1 duration-200",children:[s.jsx(ne,{size:14,className:"text-amber-600 shrink-0 mt-0.5"}),s.jsxs("div",{className:"flex-1 leading-snug",children:[s.jsxs("span",{className:"font-bold",children:["【",L.segmentTitle,"】暂未解锁:"]}),s.jsx("span",{children:L.reason})]}),s.jsx("button",{onClick:()=>A(null),className:"text-amber-500 hover:text-amber-700 font-bold text-xs cursor-pointer ml-1 px-1 rounded hover:bg-amber-100",title:o==="zh"?"关闭":"Dismiss",children:"×"})]})]}),s.jsxs("div",{className:"mb-4 bg-slate-50 p-2.5 rounded-xl border border-slate-200/60 shadow-3xs flex flex-col gap-1.5 text-left select-none",children:[s.jsxs("div",{className:"flex justify-between items-center text-xs font-bold text-gray-500",children:[s.jsxs("span",{className:"flex items-center gap-1",children:[s.jsx(Q,{size:12,className:"text-indigo-500 animate-pulse"}),o==="zh"?"自主学习进度反馈":"Learning Progress"]}),s.jsxs("span",{className:"font-mono text-indigo-600 font-extrabold",children:[p,"%"]})]}),s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx("input",{type:"range",min:"0",max:"100",value:p,onChange:r=>{const j=parseInt(r.target.value);S(j)},onMouseUp:()=>y(p),onTouchEnd:()=>y(p),className:"flex-grow h-1.5 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-indigo-600"}),s.jsx("button",{onClick:()=>{S(100),y(100)},className:`text-xs font-bold rounded-lg px-2 py-1 transition-all ${p===100?"bg-emerald-100 text-emerald-700 border border-emerald-200":"bg-white hover:bg-slate-50 text-slate-650 border border-slate-200 hover:border-indigo-200 shadow-3xs cursor-pointer"}`,children:o==="zh"?"已完成":"Done"})]})]}),s.jsx(xe,{children:T.find(r=>r.id===P)?.content||""})]})]})}function Ee(c){if(!c)return"";const e=c.split("/");return e[e.length-1]||c}function Y(c){const e=Ee(c?.file_path);if(e)return e;const t=Array.isArray(c?.files)?c.files:[];return t.length===1?t[0]?.name||"附件":t.length>1?`${t.length} 个附件`:c?.textContent?"文字作答":c?.linkUrl?"链接作答":"已提交(无附件)"}function X(c,e){return!e?.fileId||!c?.assignment_id?null:`/api/assignments/${c.assignment_id}/files/${e.fileId}`}function ze({lessonId:c,studentId:e,lang:t,addToast:i}){const[n,a]=v.useState(!1),[l,o]=v.useState(!1),[m,f]=v.useState(null),[p,S]=v.useState([]),[y,P]=v.useState("/files/my-homework.pdf"),[T,M]=v.useState(!1),[k,N]=v.useState({}),[L,A]=v.useState({}),[$,F]=v.useState({}),d=t==="zh",I=async(u=!1)=>{u?o(!0):a(!0);try{const b=await(await fetch(`/api/lessons/${c}/students/${e}/eval-status`)).json();f(b);const C=await(await fetch(`/api/lessons/${c}/eval-submissions`)).json();S(C)}catch(w){console.error("Error fetching eval data:",w),i(d?"数据加载失败":"Failed to Load Data",d?"请检查网络连接或刷新页面。":"Please check your connection and try again.","warning")}finally{a(!1),o(!1)}};v.useEffect(()=>{c&&e&&I()},[c,e]);const r=async u=>{if(u.preventDefault(),!!y.trim()){M(!0);try{const b=await(await fetch("/api/commands",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commandType:"assignment.submit",payload:{lessonId:c,studentId:e,filePath:y.trim()}})})).json();if(b.success)i(d?"作业提交成功":"Assignment Submitted",d?`成功提交版本 ${b.result.version}!`:`Successfully submitted version ${b.result.version}!`,"success"),I(!0);else throw new Error(b.error||"Failed to submit assignment")}catch(w){i(d?"提交失败":"Submission Failed",w.message,"warning")}finally{M(!1)}}},j=async(u,w)=>{const b=k[u],O=L[u]||"";if(b===void 0||isNaN(b)||b<0||b>100){i(d?"评分无效":"Invalid Score",d?"分数必须在 0 到 100 之间!":"Score must be between 0 and 100!","warning");return}F(C=>({...C,[u]:!0}));try{const U=await(await fetch("/api/commands",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commandType:"assignment.peer_review",payload:{submissionId:u,reviewerId:e,score:Number(b),comment:O}})})).json();if(U.success)i(d?"互评提交成功":"Review Submitted",d?"成功对同学的作品完成了评价!":"Successfully completed review for classmate!","success"),A(V=>{const D={...V};return delete D[u],D}),I(!0);else throw new Error(U.error||"Failed to submit review")}catch(C){i(d?"评价提交失败":"Review Failed",C.message,"warning")}finally{F(C=>({...C,[u]:!1}))}};if(n)return s.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center py-12 text-gray-500",children:[s.jsx(B,{className:"animate-spin text-indigo-500 mb-2",size:32}),s.jsx("p",{children:d?"正在读取作业互评状态...":"Loading assignment status..."})]});const g=m?.submission,x=m?.grade,z=m?.reviewsWritten||[],E=p.filter(u=>u.student_id!==e);return s.jsxs("div",{className:"flex-1 flex flex-col lg:flex-row gap-6 overflow-y-auto pr-2",children:[s.jsxs("div",{className:"w-full lg:w-5/12 flex flex-col gap-6",children:[s.jsxs("div",{className:"bg-slate-50 border border-slate-200/80 rounded-2xl p-5 shadow-3xs text-left",children:[s.jsxs("div",{className:"flex justify-between items-center mb-4",children:[s.jsxs("h3",{className:"text-sm font-bold text-slate-800 flex items-center gap-1.5 select-none",children:[s.jsx(K,{size:16,className:"text-indigo-650"}),d?"我的作业提交":"My Assignment Submission"]}),s.jsx("button",{onClick:()=>I(!0),className:"p-1 hover:bg-slate-200/50 rounded transition-colors text-slate-550",title:d?"刷新数据":"Refresh Data",children:s.jsx(B,{size:14,className:l?"animate-spin":""})})]}),g?s.jsxs("div",{className:"bg-white border border-slate-200 p-4 rounded-xl space-y-3 mb-4",children:[s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx("div",{className:"bg-emerald-50 text-emerald-600 p-2.5 rounded-lg border border-emerald-100",children:s.jsx(ae,{size:20})}),s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("p",{className:"text-xs text-slate-400 font-medium",children:d?"当前已提交版本":"Currently Submitted Version"}),s.jsx("p",{className:"text-sm font-semibold text-slate-700 truncate",children:Y(g)})]}),s.jsxs("span",{className:"bg-indigo-100 text-indigo-700 text-xs font-bold px-2 py-0.5 rounded-full border border-indigo-200",children:["V",g.version]})]}),s.jsxs("div",{className:"border-t border-slate-100 pt-2.5 flex justify-between items-center text-xs text-slate-400",children:[s.jsxs("span",{className:"flex items-center gap-1",children:[s.jsx(re,{size:11}),d?"更新时间:":"Updated At:"," ",new Date(g.updated_at).toLocaleString()]}),s.jsx("span",{className:"font-mono text-slate-350 select-all truncate max-w-[120px]",title:g.file_path||void 0,children:g.file_path||"—"})]}),(g.textContent||g.linkUrl||Array.isArray(g.files)&&g.files.length>0)&&s.jsxs("div",{className:"border-t border-slate-100 pt-2.5 space-y-1 text-xs text-slate-600",children:[g.textContent&&s.jsx("p",{className:"whitespace-pre-wrap break-all max-h-20 overflow-hidden",children:g.textContent}),g.linkUrl&&s.jsx("a",{href:g.linkUrl,target:"_blank",rel:"noopener noreferrer",className:"block truncate text-indigo-650 hover:underline",children:g.linkUrl}),Array.isArray(g.files)&&g.files.map((u,w)=>{const b=X(g,u);return b?s.jsx("a",{href:b,target:"_blank",rel:"noopener noreferrer",className:"block truncate text-indigo-650 hover:underline",children:u.name},u.fileId??w):s.jsx("span",{className:"block truncate",children:u.name},u.name??w)})]}),s.jsx(G,{slot:"assignment.submission.preview",slotProps:{submission:g,studentId:e,lessonId:c,isSelf:!0,lang:t}})]}):s.jsxs("div",{className:"bg-amber-50/50 border border-amber-100 p-4 rounded-xl flex items-start gap-3 mb-4 text-left",children:[s.jsx(oe,{className:"text-amber-500 shrink-0 mt-0.5",size:16}),s.jsxs("div",{className:"text-xs text-amber-700",children:[s.jsx("p",{className:"font-bold",children:d?"未提交作业":"No Submission Yet"}),s.jsx("p",{className:"mt-1",children:d?"在此上传提交后,其他同学将可以对您的作业进行评分互评。":"Once submitted, other students can view and peer-review your work."})]})]}),s.jsx("form",{onSubmit:r,className:"space-y-3",children:s.jsxs("div",{children:[s.jsx("label",{className:"block text-xs font-bold text-slate-500 uppercase tracking-wider mb-1",children:d?"输入作品文件路径 / 虚拟路径":"Simulated File Path"}),s.jsxs("div",{className:"flex gap-2",children:[s.jsx("input",{type:"text",value:y,onChange:u=>P(u.target.value),placeholder:"/files/homework.pdf",required:!0,className:"flex-1 bg-white border border-slate-200 px-3 py-2 text-xs rounded-lg text-slate-700 focus:outline-none focus:border-indigo-400 font-mono transition-colors"}),s.jsxs("button",{type:"submit",disabled:T,className:"bg-indigo-650 hover:bg-indigo-700 text-white font-bold text-xs px-4 py-2 rounded-lg transition-colors cursor-pointer disabled:opacity-50 flex items-center gap-1.5 shadow-3xs",children:[T?s.jsx(B,{className:"animate-spin",size:13}):s.jsx(K,{size:13}),g?d?"重新提交":"Re-submit":d?"上传作品":"Submit"]})]})]})})]}),g&&s.jsxs("div",{className:"bg-slate-50 border border-slate-200/80 rounded-2xl p-5 shadow-3xs text-left",children:[s.jsxs("h3",{className:"text-sm font-bold text-slate-800 flex items-center gap-1.5 mb-4 select-none",children:[s.jsx(le,{size:16,className:"text-pink-650"}),d?"我的平时学习得分":"My Score & Feedback"]}),x?s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"bg-white border border-slate-200 p-4 rounded-xl flex items-center justify-between shadow-3xs",children:[s.jsxs("div",{children:[s.jsx("span",{className:"text-xs text-slate-400 font-bold uppercase tracking-wider",children:d?"学期对接总分":"Weighted Final Grade"}),s.jsxs("h2",{className:"text-3xl font-extrabold text-indigo-700 font-mono mt-1",children:[x.calculated_final_score," ",s.jsx("span",{className:"text-xs text-slate-455 font-normal",children:"/ 100"})]})]}),s.jsxs("div",{className:"text-right",children:[s.jsx("span",{className:`inline-block px-2.5 py-1 text-xs font-bold rounded-lg border ${x.status==="confirmed"?"bg-emerald-50 text-emerald-700 border-emerald-100":"bg-amber-50 text-amber-700 border-amber-100"}`,children:x.status==="confirmed"?d?"已确认同步":"Synced":d?"教师评分草稿":"Draft"}),s.jsx("p",{className:"text-xs text-slate-400 mt-1.5 font-medium",children:d?`教师分 ${x.teacher_score} (占 ${(x.teacher_weight*100).toFixed(0)}%)`:`Teacher ${x.teacher_score} (${(x.teacher_weight*100).toFixed(0)}%)`}),s.jsx("p",{className:"text-xs text-slate-400 mt-0.5 font-medium",children:d?`学生互评 (占 ${(x.peer_weight*100).toFixed(0)}%)`:`Peer Review (${(x.peer_weight*100).toFixed(0)}%)`})]})]}),x.teacher_comment&&s.jsxs("div",{className:"bg-slate-100/60 p-3 rounded-lg border border-slate-200 flex gap-2",children:[s.jsx(ce,{size:14,className:"text-slate-400 shrink-0 mt-0.5"}),s.jsxs("div",{children:[s.jsx("p",{className:"text-xs font-bold text-slate-500",children:d?"教师寄语":"Teacher Comments"}),s.jsx("p",{className:"text-xs text-slate-650 mt-0.5",children:x.teacher_comment})]})]})]}):s.jsx("div",{className:"bg-white border border-slate-150 p-4 rounded-xl flex items-center justify-center text-slate-400 italic text-xs py-8",children:d?"教师尚未确认最终成绩与权重折算。":"Teacher grading is in progress."})]})]}),s.jsxs("div",{className:"flex-grow bg-slate-50 border border-slate-200/80 rounded-2xl p-5 shadow-3xs flex flex-col min-h-[400px] text-left",children:[s.jsxs("h3",{className:"text-sm font-bold text-slate-800 flex items-center gap-1.5 mb-4 shrink-0 select-none",children:[s.jsx(de,{size:16,className:"text-teal-650"}),d?"同学作业互评公开板":"Classmate Submissions for Peer Review"]}),E.length===0?s.jsx("div",{className:"flex-grow flex items-center justify-center text-slate-400 italic text-xs py-12 border border-dashed border-slate-200 rounded-xl bg-white",children:d?"当前暂无同学提交作业作品。":"No classmate submissions available yet."}):s.jsx("div",{className:"flex-grow overflow-y-auto space-y-4 pr-1",children:E.map(u=>{const w=z.find(_=>_.submission_id===u.id),b=k[u.id]!==void 0?k[u.id]:w?w.score:85,O=L[u.id]!==void 0?L[u.id]:w?w.comment:"",C=$[u.id]||!1,U=Array.isArray(u.files)?u.files:[],V=u.file_path||X(u,U[0])||null,D=V||u.linkUrl||null;return s.jsxs("div",{className:"bg-white border border-slate-200 rounded-xl p-4 shadow-3xs flex flex-col gap-3",children:[s.jsxs("div",{className:"flex justify-between items-start border-b border-slate-100 pb-2",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("div",{className:"w-8 h-8 rounded-full bg-indigo-50 text-indigo-700 flex items-center justify-center font-bold text-xs select-none",children:u.student_name?u.student_name[0]:"?"}),s.jsxs("div",{children:[s.jsx("h4",{className:"text-xs font-bold text-slate-700",children:u.student_name||u.student_id}),s.jsxs("p",{className:"text-xs text-slate-400 font-mono flex items-center gap-1 mt-0.5 truncate max-w-[200px]",title:u.file_path||void 0,children:[s.jsx(ue,{size:11,className:"text-slate-350"}),Y(u)," (V",u.version,")"]})]})]}),D?s.jsx("a",{href:D,target:"_blank",rel:"noopener noreferrer",className:"text-xs font-bold text-indigo-650 hover:text-indigo-800 transition-colors border border-indigo-100 px-2 py-1 rounded bg-indigo-50/50 hover:bg-indigo-50 shrink-0",children:V?d?"下载查阅":"Download File":d?"打开链接":"Open Link"}):s.jsx("span",{className:"text-xs text-slate-400 px-2 py-1 border border-slate-200 rounded bg-white shrink-0",children:d?"无附件":"No File"})]}),u.textContent&&s.jsx("p",{className:"text-xs text-slate-600 whitespace-pre-wrap break-all max-h-24 overflow-auto bg-slate-50 border border-slate-100 rounded-lg p-2",children:u.textContent}),s.jsx(G,{slot:"assignment.submission.preview",slotProps:{submission:u,studentId:u.student_id,lessonId:c,isSelf:!1,lang:t}}),w&&s.jsxs("div",{className:"bg-emerald-50/50 border border-emerald-100 p-2.5 rounded-lg flex items-start gap-2 text-xs text-emerald-800",children:[s.jsx(he,{className:"text-emerald-500 shrink-0 mt-0.5",size:14}),s.jsxs("div",{className:"flex-1",children:[s.jsx("p",{className:"font-bold flex items-center gap-1",children:d?`我已评分:${w.score} 分`:`My Score: ${w.score} pts`}),w.comment&&s.jsxs("p",{className:"text-xs text-emerald-700/80 mt-0.5 italic",children:['"',w.comment,'"']})]})]}),s.jsxs("div",{className:"bg-slate-50/60 border border-slate-100 rounded-lg p-3 space-y-3",children:[s.jsxs("div",{className:"flex justify-between items-center",children:[s.jsx("span",{className:"text-xs font-bold text-slate-500 uppercase tracking-wider",children:d?"滑动或输入互评分数":"Peer Rating"}),s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx("input",{type:"number",min:"0",max:"100",value:b,onChange:_=>{const R=Math.min(100,Math.max(0,parseInt(_.target.value)||0));N(q=>({...q,[u.id]:R}))},className:"w-12 text-center text-xs font-bold font-mono border border-slate-200 rounded px-1 py-0.5 bg-white text-indigo-750"}),s.jsx("span",{className:"text-xs text-slate-400 font-bold",children:d?"分":"pts"})]})]}),s.jsx("input",{type:"range",min:"0",max:"100",value:b,onChange:_=>{const R=parseInt(_.target.value);N(q=>({...q,[u.id]:R}))},className:"w-full h-1.5 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-indigo-650"}),s.jsxs("div",{className:"flex gap-2",children:[s.jsx("textarea",{rows:1,value:O,onChange:_=>{A(R=>({...R,[u.id]:_.target.value}))},placeholder:d?"简要评语反馈...":"Brief feedback comment...",className:"flex-1 bg-white border border-slate-200 px-2 py-1 text-xs rounded-lg text-slate-700 focus:outline-none focus:border-indigo-400 resize-none transition-colors"}),s.jsxs("button",{onClick:()=>j(u.id,u.student_id),disabled:C,className:"bg-indigo-650 hover:bg-indigo-700 text-white font-bold text-xs px-3 rounded-lg transition-colors cursor-pointer disabled:opacity-50 flex items-center justify-center",children:[C?s.jsx(B,{className:"animate-spin",size:13}):s.jsx(me,{size:13}),s.jsx("span",{className:"ml-1 shrink-0",children:w?d?"修改评分":"Update":d?"确认提交":"Submit"})]})]})]})]},u.id)})})]})]})}function De(c){const{isStudentLocked:e=!1,studentLessonTab:t,setStudentLessonTab:i,isStudentLessonContentCollapsed:n,setIsStudentLessonContentCollapsed:a,lang:l,studentFullscreenPanel:o,setStudentFullscreenPanel:m,selectedLesson:f,elements:p,activeRole:S,activeSegmentId:y,setActiveSegmentId:P,fetchElements:T,currentVfsParent:M,setCurrentVfsParent:k,vfsNodes:N,studentSelectedCourseware:L,setStudentSelectedCourseware:A,activeStudentId:$,addToast:F}=c,d=r=>{if(e){r!==t&&F(l==="zh"?"🔒 全班专注锁定":"🔒 Class Focus Locked",l==="zh"?"锁定期间无法切换标签页,请跟随教师当前授课内容。":"Switching tabs is disabled while the class is locked.","warning");return}i(r)},I=r=>`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${t===r?"bg-primary-theme/10 text-primary-theme shadow-sm font-bold":"text-muted hover:bg-surface-secondary"} ${e&&t!==r?"opacity-50 cursor-not-allowed":"cursor-pointer"}`;return s.jsxs("div",{className:`${n||o==="right"?"w-full flex-grow":"flex-grow flex-1"} relative flex flex-col min-h-0 ${o==="left"?"hidden":""} transition-all duration-300`,children:[s.jsxs("div",{className:"flex items-center justify-between mb-2",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsxs("button",{onClick:()=>a(!n),className:"flex items-center gap-1.5 px-3 py-1.5 text-xs font-bold bg-primary-theme/10 text-primary-theme rounded-lg hover:bg-primary-theme/20 transition-colors border border-primary-theme/20 cursor-pointer shadow-3xs",title:n?"展开课程内容":"折叠课程内容",children:[s.jsx(te,{size:13,className:"text-primary-theme"}),s.jsx("span",{children:n?l==="zh"?"展开课程内容":"Expand Content":l==="zh"?"折叠课程内容":"Collapse Content"})]}),s.jsxs("button",{onClick:()=>d("whiteboard"),className:I("whiteboard"),title:e&&l==="zh"?"锁定中:白板为只读跟随模式":void 0,children:["Interactive Whiteboard",e&&t==="whiteboard"&&s.jsxs("span",{className:"ml-1.5 text-xs font-bold text-indigo-500",children:["🔒 ",l==="zh"?"只读":"RO"]})]}),s.jsx("button",{onClick:()=>d("courseware"),className:I("courseware"),children:"Interactive Courseware Viewer"}),s.jsx("button",{onClick:()=>d("assignment"),className:I("assignment"),children:l==="zh"?"作业提交与互评":"Assignments & Peer Reviews"})]}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(G,{slot:"student.lesson.tool",slotProps:{lessonId:f,studentId:$,activeSegmentId:y,lang:l}}),s.jsx("button",{onClick:()=>m(r=>r==="right"?"none":"right"),className:"p-1 hover:bg-gray-100 text-gray-400 hover:text-gray-700 rounded transition-colors cursor-pointer flex items-center gap-1",title:o==="right"?"退出全屏":"全屏",children:o==="right"?s.jsxs(s.Fragment,{children:[s.jsx(se,{size:13}),s.jsx("span",{className:"text-xs font-medium",children:"退出全屏"})]}):s.jsxs(s.Fragment,{children:[s.jsx(ie,{size:13}),s.jsx("span",{className:"text-xs font-medium",children:"全屏"})]})})]})]}),t==="whiteboard"&&s.jsx(we,{lessonId:f,elements:p,userRole:S,readOnly:e,followRemoteFullscreen:!0,activeSegmentId:y,onSegmentSync:r=>P(r),onElementUpdate:async()=>{},onElementDelete:async r=>{e||f&&(await fetch(`/api/lessons/${f}/whiteboard/${r}`,{method:"DELETE"}),T(f))},onClearBoard:async()=>{e||f&&(await fetch(`/api/lessons/${f}/whiteboard`,{method:"DELETE"}),T(f))},onElementAdd:async()=>{},onRefresh:()=>{f&&T(f)}}),t==="courseware"&&s.jsxs("div",{className:"flex-1 flex gap-4 min-h-0",children:[s.jsxs("div",{className:"w-48 flex-shrink-0 bg-gray-50 border border-gray-200 rounded-lg p-3 flex flex-col min-h-0",children:[s.jsx("h4",{className:"text-xs font-semibold uppercase tracking-wider text-gray-500 mb-2 border-b border-gray-200 pb-2",children:"Cloud Apps"}),s.jsxs("div",{className:"flex-1 overflow-y-auto space-y-1",children:[M!==null&&s.jsxs("button",{onClick:()=>k(null),className:"flex items-center gap-2 p-1.5 text-xs text-indigo-600 w-full hover:bg-gray-200 rounded mb-1 font-medium",children:[s.jsx(ee,{className:"rotate-180",size:14})," Back to Root"]}),N.filter(r=>r.type==="dir").map(r=>s.jsxs("button",{onClick:()=>k(r.id),className:"w-full text-left p-1.5 rounded text-xs text-gray-700 hover:bg-gray-200 flex items-center gap-2 group truncate",title:r.name,children:[s.jsx(ge,{size:14,className:"text-indigo-400 shrink-0 group-hover:text-indigo-600"}),s.jsx("span",{className:"truncate",children:r.name})]},r.id)),N.filter(r=>r.type==="file"&&(r.name.endsWith(".html")||r.name.endsWith(".htm")||r.content?.includes("<html"))).length===0?s.jsx("div",{className:"text-xs text-center text-gray-400 italic py-4",children:"No interactive HTML apps found."}):N.filter(r=>r.type==="file"&&(r.name.endsWith(".html")||r.name.endsWith(".htm")||r.content?.includes("<html"))).map(r=>s.jsxs("button",{onClick:()=>A(r.id),className:`w-full text-left p-2 rounded text-xs flex items-center gap-2 truncate transition-colors ${L===r.id?"bg-indigo-100 text-indigo-700 font-medium":"text-gray-600 hover:bg-gray-100"}`,title:r.name,children:[s.jsx(fe,{size:14,className:"shrink-0"}),s.jsx("span",{className:"truncate",children:r.name})]},r.id))]}),s.jsx("div",{className:"mt-2 text-xs text-gray-400 leading-tight",children:"Note: Showing HTML courseware from current OS drive directory. Ask agent to generate courseware."})]}),s.jsx("div",{className:"flex-1 relative bg-white min-h-0",children:s.jsx(ve,{coursewareId:L,onClose:()=>A(null)})})]}),t==="assignment"&&f&&$&&s.jsx(ze,{lessonId:f,studentId:$,lang:l,addToast:F})]})}function Qe(c){const{students:e,activeStudentId:t,isStudentLocked:i=!1,setStudentViewStatus:n,setSelectedLesson:a,lessons:l,selectedLesson:o,studentFullscreenPanel:m,setStudentFullscreenPanel:f,timelineSegments:p,lang:S,activeSegmentId:y,setActiveSegmentId:P,localProgressPercent:T,setLocalProgressPercent:M,updateStudentProgress:k,isStudentLessonContentCollapsed:N,setIsStudentLessonContentCollapsed:L,studentLessonTab:A,setStudentLessonTab:$,elements:F,activeRole:d,fetchElements:I,currentVfsParent:r,setCurrentVfsParent:j,vfsNodes:g,studentSelectedCourseware:x,setStudentSelectedCourseware:z,addToast:E}=c;return s.jsxs("div",{className:"flex flex-col h-full space-y-4",children:[s.jsx(be,{students:e,activeStudentId:t,isStudentLocked:i,setStudentViewStatus:n,setSelectedLesson:a,lessons:l,selectedLesson:o}),s.jsx(ye,{lessonId:o,lang:S,addToast:E}),s.jsxs("div",{className:"flex-1 flex gap-6 min-h-0 bg-surface border border-theme rounded-xl p-4 shadow-sm text-main",children:[s.jsx(_e,{students:e,activeStudentId:t,isStudentLocked:i,studentFullscreenPanel:m,setStudentFullscreenPanel:f,timelineSegments:p,lang:S,activeSegmentId:y,setActiveSegmentId:P,localProgressPercent:T,setLocalProgressPercent:M,updateStudentProgress:k,selectedLesson:o,lessons:l,isStudentLessonContentCollapsed:N,addToast:E}),s.jsx(De,{isStudentLocked:i,studentLessonTab:A,setStudentLessonTab:$,isStudentLessonContentCollapsed:N,setIsStudentLessonContentCollapsed:L,lang:S,studentFullscreenPanel:m,setStudentFullscreenPanel:f,selectedLesson:o,elements:F,activeRole:d,activeSegmentId:y,setActiveSegmentId:P,fetchElements:I,currentVfsParent:r,setCurrentVfsParent:j,vfsNodes:g,studentSelectedCourseware:x,setStudentSelectedCourseware:z,activeStudentId:t,addToast:E})]}),s.jsx(G,{slot:"student.lesson.notes_addon",slotProps:{lessonId:o,studentId:t,activeSegmentId:y,lang:S}}),s.jsx(G,{slot:"student.lesson.toolbox",slotProps:{lessonId:o,studentId:t,lang:S}})]})}export{Qe as StudentLessonView};