openlearn-next 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/assets/{AdminDirectoryView-Cai0cQqi.js → AdminDirectoryView-CD7tW4mc.js} +1 -1
  2. package/dist/assets/BatchPickerModal-Bt8Qx0Av.js +1 -0
  3. package/dist/assets/{ClassesView-Cxgfcrx1.js → ClassesView-B1B3wlkx.js} +2 -2
  4. package/dist/assets/CloudDriveModal-BSZaWIex.js +1 -0
  5. package/dist/assets/{ComputerLabView-CUCO2VIV.js → ComputerLabView-B6-twB0u.js} +1 -1
  6. package/dist/assets/CourseManagement-Bnezm9Vv.js +1 -0
  7. package/dist/assets/CourseWizardModal-BvfTvcQT.js +3 -0
  8. package/dist/assets/{CoursewareHubPanel-CAaf22Qm.js → CoursewareHubPanel-Cb1mAqHS.js} +1 -1
  9. package/dist/assets/{Dashboard-vSYAYoji.js → Dashboard-DQ91dQio.js} +2 -2
  10. package/dist/assets/ExportWeightModal-al1iIVxb.js +1 -0
  11. package/dist/assets/{HelpTour-ZgEkRnin.js → HelpTour-DwM9UBiA.js} +1 -1
  12. package/dist/assets/{HelpView-D3WIxMoB.js → HelpView-DLAKVpwf.js} +5 -5
  13. package/dist/assets/ImportLessonsModal-DwhvqzY_.js +1 -0
  14. package/dist/assets/{ImportModal-mkWuDoAN.js → ImportModal-CmUt1YeX.js} +1 -1
  15. package/dist/assets/InteractiveCoursewareViewer-DWnzq20c.js +1 -0
  16. package/dist/assets/{InteractiveWhiteboard-bmT1LKD6.js → InteractiveWhiteboard-CQ-4meYj.js} +12 -12
  17. package/dist/assets/{LazyCourseware-Bcxn_20f.js → LazyCourseware-g7b8EXR_.js} +1 -1
  18. package/dist/assets/{LazyWhiteboard-CJA7aRIM.js → LazyWhiteboard-B6rDWBFb.js} +1 -1
  19. package/dist/assets/{LessonEditorView-hdJblhmb.js → LessonEditorView-DixwX1Kw.js} +1 -1
  20. package/dist/assets/{LiveClassroomView-ByyIOLJC.js → LiveClassroomView-j93YOxSh.js} +1 -1
  21. package/dist/assets/NotificationDetailModal-CQ9PIqkD.js +1 -0
  22. package/dist/assets/{PluginView-B3ZolNGQ.js → PluginView-DCY4yi2h.js} +1 -1
  23. package/dist/assets/{ProcessLogsModal-8mVp07ic.js → ProcessLogsModal-B-PY780w.js} +1 -1
  24. package/dist/assets/QuizGeneratorModal-BvTcmD68.js +1 -0
  25. package/dist/assets/StudentAssignmentView-4R0WxStx.js +1 -0
  26. package/dist/assets/StudentLessonView-DZ0i9-tX.js +1 -0
  27. package/dist/assets/StudentPreviewModal-CfsB1dPY.js +1 -0
  28. package/dist/assets/StudentView-D7GtUiYR.js +2 -0
  29. package/dist/assets/SystemResourceLibraryModal-Ilnthwpw.js +1 -0
  30. package/dist/assets/TeacherView-DjnjsQ_3.js +2 -0
  31. package/dist/assets/{TimetableView-zce3okQn.js → TimetableView-BMsjwi-s.js} +3 -3
  32. package/dist/assets/index-D8x6bUeG.js +150 -0
  33. package/dist/assets/{index-CDTw8wSY.js → index-wdWIWwbg.js} +1 -1
  34. package/dist/assets/{vendor-icons-BvCtGbt1.js → vendor-icons-_c3xpwjZ.js} +1 -1
  35. package/dist/assets/vendor-motion-DjY2czvL.js +1 -0
  36. package/dist/index.html +1 -1
  37. package/dist/server.cjs +72 -20
  38. package/package.json +1 -1
  39. package/dist/assets/BatchPickerModal-CKQyeY6R.js +0 -1
  40. package/dist/assets/CloudDriveModal-TFWlPh8x.js +0 -1
  41. package/dist/assets/CourseManagement-DSCOjuIC.js +0 -1
  42. package/dist/assets/CourseWizardModal-B3QnFxvj.js +0 -3
  43. package/dist/assets/ExportWeightModal-BlS2auLs.js +0 -1
  44. package/dist/assets/ImportLessonsModal-BZZRDBRU.js +0 -1
  45. package/dist/assets/InteractiveCoursewareViewer-01PS40_x.js +0 -1
  46. package/dist/assets/NotificationDetailModal-dndFrE7p.js +0 -1
  47. package/dist/assets/QuizGeneratorModal-DpTFYbVJ.js +0 -1
  48. package/dist/assets/StudentAssignmentView-DDY7C092.js +0 -1
  49. package/dist/assets/StudentLessonView-BcQ7q4QF.js +0 -1
  50. package/dist/assets/StudentPreviewModal-ETJBF1Vc.js +0 -1
  51. package/dist/assets/StudentView-BOqPntx-.js +0 -1
  52. package/dist/assets/SystemResourceLibraryModal-tg8xnblT.js +0 -1
  53. package/dist/assets/TeacherView-CrbllHIm.js +0 -2
  54. package/dist/assets/index-BrEBeWAQ.js +0 -14
  55. package/dist/assets/index-eXp-qZdm.js +0 -129
  56. package/dist/assets/vendor-motion-Dz5URUo4.js +0 -9
@@ -1,6 +1,6 @@
1
- import{j as e,r as c}from"./vendor-react-0Lg0vA-4.js";import{E as qt,aT as Zt,aU as Ue,aL as Xt,ad as Qt,X as be,a6 as mt,l as Ie,aV as De,aW as Te,aa as dt,a2 as es,Z as ts,f as Ae,m as ct,a4 as ss,aX as xt,a3 as ls,C as rs,aY as as,aZ as os,J as is,a_ as ht,af as ns,g as Be,x as ds,O as cs}from"./vendor-icons-BvCtGbt1.js";const xs=l=>{const b=[];for(let r=0;r<7;r++){const N=new Date(l.getTime()+r*24*60*60*1e3),T=N.getFullYear(),v=String(N.getMonth()+1).padStart(2,"0"),I=String(N.getDate()).padStart(2,"0");b.push(`${T}-${v}-${I}`)}return b},ut=l=>{if(!l)return!1;const b=l.match(/^(\d{1,2}):(\d{2})/);return b?parseInt(b[1],10)>=12:!1},hs=({lang:l,viewMode:b,setViewMode:r,selectedClassId:N,setSelectedClassId:T,statusFilter:v,setStatusFilter:I,searchQuery:G,setSearchQuery:B,classes:P,getClassDisplayName:U,loading:C,filteredSchedules:E,currentWeekMonday:X,setCurrentWeekMonday:O,showWeekend:ae,setShowWeekend:Q,dateOverrides:L,setDateOverrides:J,setOverridingDateKey:F,setOverrideMode:k,setOverrideTargetDow:ie,setOverrideTargetDate:ee,openEditModal:xe,handleDeleteSchedule:he,getDayOfWeekIndex:$,getMonday:ne,getWeekRangeString:p,setFormClassId:W,setFormLessonId:te,setFormDate:ve,setFormStatus:Y,setFormNotes:de,setIsAddOpen:se})=>{const M=[{key:1,label:l==="zh"?"周一 (Mon)":"Mon"},{key:2,label:l==="zh"?"周二 (Tue)":"Tue"},{key:3,label:l==="zh"?"周三 (Wed)":"Wed"},{key:4,label:l==="zh"?"周四 (Thu)":"Thu"},{key:5,label:l==="zh"?"周五 (Fri)":"Fri"},{key:6,label:l==="zh"?"周六 (Sat)":"Sat"},{key:7,label:l==="zh"?"周日 (Sun)":"Sun"}],le=xs(X),K=a=>{const x=a.status==="cancelled"||a.status==="holiday";let h="border-l-green-500 bg-green-50/5 hover:bg-green-50/10 hover:border-l-green-600";return a.status==="cancelled"?h="border-l-red-500 bg-red-50/5 hover:bg-red-50/10 hover:border-l-red-600":a.status==="holiday"?h="border-l-amber-500 bg-amber-50/5 hover:bg-amber-50/10 hover:border-l-amber-600":a.status==="swap"&&(h="border-l-blue-500 bg-blue-50/5 hover:bg-blue-50/10 hover:border-l-blue-600"),e.jsxs("div",{className:`p-2.5 rounded-xl border border-slate-150 border-l-4 ${h} transition-all hover:shadow-xs relative group flex flex-col justify-between min-h-[85px]`,children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-[9px] font-mono text-slate-500 mb-1 font-bold flex justify-between items-center",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ct,{size:11,className:"text-slate-400"}),a.time_slot||(l==="zh"?"全天":"All-day")]}),b==="cycle"&&e.jsx("span",{className:"text-[8px] text-slate-400 font-sans font-normal bg-slate-100 px-1 py-0.5 rounded-sm",children:a.scheduled_date})]}),e.jsx("div",{className:`font-extrabold text-sm text-slate-805 tracking-tight leading-snug mt-1 ${x?"line-through opacity-60 text-slate-400":""}`,title:a.lesson_title||"",children:a.class_name}),a.notes&&e.jsxs("div",{className:"text-[9px] text-amber-600 font-medium mt-1 truncate",title:a.notes,children:["📌 ",a.notes]})]}),e.jsxs("div",{className:"flex items-center justify-between mt-2.5 pt-2 border-t border-slate-100/50",children:[e.jsx("span",{className:`inline-block text-[8px] px-1.5 py-0.5 rounded-full font-bold uppercase tracking-wide border ${a.status==="cancelled"?"bg-red-50 border-red-100 text-red-600":a.status==="holiday"?"bg-amber-50 border-amber-100 text-amber-600":a.status==="swap"?"bg-blue-50 border-blue-100 text-blue-600":"bg-green-50 border-green-100 text-green-600"}`,children:a.status==="cancelled"?l==="zh"?"停课":"Cancelled":a.status==="holiday"?l==="zh"?"假期":"Holiday":a.status==="swap"?l==="zh"?"代课":"Swapped":l==="zh"?"正常":"Active"}),e.jsxs("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{onClick:()=>xe(a),className:"text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 p-1 rounded-md transition-colors cursor-pointer",title:l==="zh"?"微调":"Edit",children:e.jsx(Te,{size:11})}),e.jsx("button",{onClick:()=>he(a.id,a.class_id,a.isRepeating,a.scheduled_date),className:"text-slate-400 hover:text-red-600 hover:bg-red-50 p-1 rounded-md transition-colors cursor-pointer",title:l==="zh"?"删除":"Delete",children:e.jsx(dt,{size:11})})]})]})]},a.id)},Pe=(a,x)=>{if(a===x){const f=E.filter(g=>g.scheduled_date===x);if(f.length>0)return f;const j=$(x),D=E.filter(g=>$(g.scheduled_date)===j&&g.scheduled_date<=x),y={};return D.forEach(g=>{const H=`${g.class_id}_${g.time_slot||"all-day"}`;y[H]||(y[H]={...g,scheduled_date:x,isRepeating:!0})}),Object.values(y)}let h=[];if(a.startsWith("dow-")){const f=parseInt(a.split("-")[1],10),j=E.filter(y=>$(y.scheduled_date)===f&&y.scheduled_date<=x),D={};j.forEach(y=>{const g=`${y.class_id}_${y.time_slot||"all-day"}`;D[g]||(D[g]={...y,scheduled_date:x,isRepeating:!0})}),h=Object.values(D)}else{const f=E.filter(j=>j.scheduled_date===a);if(f.length>0)h=f.map(j=>({...j,scheduled_date:x,isRepeating:!0}));else{const j=$(a),D=E.filter(g=>$(g.scheduled_date)===j&&g.scheduled_date<=a),y={};D.forEach(g=>{const H=`${g.class_id}_${g.time_slot||"all-day"}`;y[H]||(y[H]={...g,scheduled_date:x,isRepeating:!0})}),h=Object.values(y)}}const S=E.filter(f=>f.scheduled_date===x);if(S.length>0){const f=[...h];return S.forEach(j=>{const D=`${j.class_id}_${j.time_slot||"all-day"}`,y=f.findIndex(g=>`${g.class_id}_${g.time_slot||"all-day"}`===D);y!==-1?f[y]=j:j.status!=="cancelled"&&j.status!=="holiday"&&f.push(j)}),f}return h},ue=M.map((a,x)=>{const h=le[x],S=L[h]||h,f=Pe(S,h);return f.sort((j,D)=>(j.time_slot||"").localeCompare(D.time_slot||"")),{...a,dateStr:h,displayLabel:l==="zh"?`${a.label.split(" ")[0]} (${h.substring(5)})`:`${a.label} (${h.substring(5)})`,schedules:f}}),re=M.map(a=>{const x=le[a.key-1],h=E.filter(S=>$(S.scheduled_date)===a.key);return h.sort((S,f)=>(S.time_slot||"").localeCompare(f.time_slot||"")),{...a,dateStr:x,displayLabel:a.label,schedules:h}}),V=(b==="week"?ue:re).filter(a=>b==="week"&&!ae?a.key!==6&&a.key!==7:!0);return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 p-3 rounded-xl flex flex-wrap gap-3 items-center justify-between",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-bold text-gray-500 flex items-center gap-1",children:[e.jsx(qt,{size:13}),l==="zh"?"筛选:":"Filters:"]}),e.jsxs("div",{className:"flex bg-slate-200/70 p-0.5 rounded-lg border border-slate-300/30 shadow-xs mr-2 shrink-0",children:[e.jsxs("button",{onClick:()=>r("week"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="week"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Zt,{size:11}),l==="zh"?"周课表":"Week View"]}),e.jsxs("button",{onClick:()=>r("cycle"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="cycle"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Ue,{size:11}),l==="zh"?"星期总览":"Cycle View"]}),e.jsxs("button",{onClick:()=>r("list"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="list"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Xt,{size:11}),l==="zh"?"列表":"List View"]})]}),e.jsxs("select",{id:"timetable_class_select",title:"Select Class",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:N,onChange:a=>T(a.target.value),children:[e.jsx("option",{value:"all",children:l==="zh"?"所有班级 (All Classes)":"All Classes"}),P.map(a=>e.jsx("option",{value:a.id,children:U(a.name)},a.id))]}),e.jsxs("select",{id:"timetable_status_select",title:"Select Status",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:v,onChange:a=>I(a.target.value),children:[e.jsx("option",{value:"all",children:l==="zh"?"所有状态 (All Status)":"All Status"}),e.jsx("option",{value:"scheduled",children:l==="zh"?"正常上课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:l==="zh"?"停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:l==="zh"?"假期调休 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:l==="zh"?"代课换课 (Swapped)":"Swapped"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 max-w-xs min-w-[200px]",children:[e.jsxs("div",{className:"relative w-full",children:[e.jsx(Qt,{className:"absolute left-2.5 top-2 text-gray-400",size:14}),e.jsx("input",{type:"text",placeholder:l==="zh"?"检索课程标题, 班级, 备注...":"Search title, class, notes...",className:"w-full bg-white border border-gray-200 rounded-lg pl-8 pr-2.5 py-1.5 text-xs text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500",value:G,onChange:a=>B(a.target.value)}),G&&e.jsx("button",{onClick:()=>B(""),className:"absolute right-2.5 top-2 text-gray-400 hover:text-gray-600",children:e.jsx(be,{size:14})})]}),e.jsxs("button",{onClick:()=>{W(P[0]?.id||""),te(""),ve(new Date().toISOString().split("T")[0]),Y("scheduled"),de(""),se(!0)},className:"bg-indigo-600 hover:bg-indigo-700 text-white font-semibold text-xs py-1.5 px-3 rounded-lg flex items-center gap-1 shadow-sm shrink-0 cursor-pointer transition-all",children:[e.jsx(mt,{size:14}),l==="zh"?"排定课时":"Schedule Class"]})]})]}),C?e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-indigo-500",children:[e.jsx(Ie,{className:"animate-spin mb-2",size:32}),e.jsx("span",{className:"text-xs font-semibold",children:l==="zh"?"查询数据中...":"Accessing SQLite Database..."})]}):E.length===0?e.jsxs("div",{className:"text-center py-16 bg-slate-50/50 border border-dashed rounded-xl border-slate-200 flex flex-col items-center",children:[e.jsx(De,{className:"text-gray-300 mb-2",size:40}),e.jsx("p",{className:"text-gray-500 text-sm font-semibold",children:l==="zh"?"暂未匹配到对应的课次安排数据":"No schedules match your filters"}),e.jsx("p",{className:"text-gray-400 text-xs mt-1",children:l==="zh"?"您可以点击右上角“排定课时”为班级新增课程。":"Try adding a new entry using the schedule button above."})]}):b==="list"?e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-sm bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-xs",children:[e.jsx("th",{className:"p-3 w-[15%]",children:l==="zh"?"上课日期":"Date"}),e.jsx("th",{className:"p-3 w-[15%]",children:l==="zh"?"具体时间段":"Time Slot"}),e.jsx("th",{className:"p-3 w-[20%]",children:l==="zh"?"关联班级":"Class"}),e.jsx("th",{className:"p-3 w-[25%]",children:l==="zh"?"授课内容主题":"Lesson Topic"}),e.jsx("th",{className:"p-3 w-[10%] text-center",children:l==="zh"?"日常状态":"Status"}),e.jsx("th",{className:"p-3 w-[15%] text-right",children:l==="zh"?"教务微调":"Actions"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-150",children:E.map(a=>{const x=a.status==="cancelled"||a.status==="holiday";return e.jsxs("tr",{className:`hover:bg-slate-50/80 transition-colors ${x?"bg-red-50/10 text-gray-400":"text-gray-700"}`,children:[e.jsx("td",{className:"p-3 font-semibold text-xs",children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(De,{size:13,className:"text-slate-400"}),a.scheduled_date]})}),e.jsx("td",{className:"p-3 font-mono text-xs text-indigo-750",children:a.time_slot||e.jsx("span",{className:"text-[10px] text-gray-300 italic",children:l==="zh"?"全天":"All-day"})}),e.jsx("td",{className:"p-3 text-xs",children:e.jsx("span",{className:"bg-slate-100 text-slate-800 px-2 py-1 rounded-md border border-slate-250 font-medium",children:a.class_name})}),e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex flex-col leading-snug",children:[e.jsx("span",{className:`font-semibold ${x?"line-through opacity-70":""}`,children:a.lesson_title}),a.notes&&e.jsxs("span",{className:`text-[10px] italic mt-0.5 ${a.status==="holiday"?"text-amber-600 font-medium":a.status==="cancelled"?"text-red-500 font-medium":"text-slate-400"}`,children:["📌 ",a.notes]})]})}),e.jsx("td",{className:"p-3 text-center",children:e.jsx("span",{className:`inline-block text-[10px] px-2 py-0.5 rounded-full font-bold uppercase tracking-wide border ${a.status==="cancelled"?"bg-red-100 border-red-200 text-red-700":a.status==="holiday"?"bg-amber-100 border-amber-200 text-amber-700":a.status==="swap"?"bg-blue-100 border-blue-200 text-blue-700":"bg-green-100 border-green-200 text-green-700"}`,children:a.status==="cancelled"?l==="zh"?"停课":"Cancelled":a.status==="holiday"?l==="zh"?"假期调休":"Holiday":a.status==="swap"?l==="zh"?"换代课":"Swapped":l==="zh"?"正常上课":"Active"})}),e.jsx("td",{className:"p-3 text-right",children:e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx("button",{onClick:()=>xe(a),className:"text-slate-500 hover:text-indigo-600 hover:bg-indigo-50 p-1.5 rounded transition-colors cursor-pointer",title:l==="zh"?"调整此节课排课 (换课/换时间/写备注)":"Adjust this class (Swap/Edit)",children:e.jsx(Te,{size:13})}),e.jsx("button",{onClick:()=>he(a.id,a.class_id),className:"text-slate-500 hover:text-red-600 hover:bg-red-50 p-1.5 rounded transition-colors cursor-pointer",title:l==="zh"?"永久删除该课课表":"Delete schedule",children:e.jsx(dt,{size:13})})]})})]},a.id)})})]})}):e.jsxs("div",{className:"flex flex-col gap-4",children:[b==="week"&&e.jsxs("div",{className:"flex flex-col md:flex-row items-center justify-between bg-indigo-50/40 border border-indigo-100/60 p-3 rounded-xl gap-3 shadow-2xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>O(a=>new Date(a.getTime()-10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:l==="zh"?"上一周":"Previous Week",children:e.jsx(es,{size:16})}),e.jsx("button",{onClick:()=>O(ne(new Date)),className:"px-3 py-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer text-xs font-bold border border-indigo-200/50 bg-white shadow-2xs",children:l==="zh"?"本周":"This Week"}),e.jsx("button",{onClick:()=>O(a=>new Date(a.getTime()+10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:l==="zh"?"下一周":"Next Week",children:e.jsx(ts,{size:16})})]}),e.jsxs("div",{className:"text-sm font-bold text-indigo-900 flex items-center gap-2",children:[e.jsx(De,{size:16,className:"text-indigo-500"}),e.jsx("span",{children:p(X)})]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-indigo-700 font-semibold",children:l==="zh"?"跳转日期:":"Go to Date:"}),e.jsx("input",{type:"date",title:"Go to Date",className:"bg-white border border-indigo-200 rounded-lg text-xs py-1 px-2 text-indigo-950 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",onChange:a=>{a.target.value&&O(ne(new Date(a.target.value)))}})]}),e.jsx("div",{className:"flex items-center gap-2 border-l border-indigo-150 pl-3",children:e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-indigo-700 font-semibold cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:ae,onChange:a=>Q(a.target.checked),className:"w-3.5 h-3.5 text-indigo-600 border-indigo-300 rounded-sm focus:ring-indigo-500 focus:outline-hidden cursor-pointer"}),l==="zh"?"显示周末":"Show Weekend"]})})]})]}),e.jsx("div",{className:"w-full overflow-x-auto pb-2",children:e.jsxs("div",{className:"flex flex-col gap-4 min-w-[1050px]",children:[e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 rounded-xl p-3 text-center flex flex-col items-center justify-center gap-1 relative group/col",children:[e.jsxs("div",{className:"flex items-center justify-center gap-1.5 w-full",children:[e.jsx("span",{className:"font-extrabold text-xs text-indigo-700 uppercase tracking-wider",children:a.displayLabel}),b==="week"&&e.jsx("button",{onClick:()=>{const x=L[a.dateStr]||"";F(a.dateStr),x.startsWith("dow-")?(k("dow"),ie(x.split("-")[1]),ee("")):x?(k("date"),ee(x),ie("")):(k("dow"),ie(""),ee(""))},className:"text-slate-400 hover:text-indigo-600 p-0.5 rounded-md hover:bg-slate-200/50 transition-all opacity-0 group-hover/col:opacity-100 focus:opacity-100 cursor-pointer flex items-center justify-center",title:l==="zh"?"临时切换显示日期":"Temporarily switch date",children:e.jsx(Te,{size:10})})]}),b==="week"&&L[a.dateStr]&&(()=>{const x=L[a.dateStr];let h="";if(x.startsWith("dow-")){const S=parseInt(x.split("-")[1],10);h=l==="zh"?`常规${["","周一","周二","周三","周四","周五","周六","周日"][S]}`:`Regular ${["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"][S]}`}else h=x.substring(5);return e.jsxs("div",{className:"flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-700 text-[9px] px-1.5 py-0.5 rounded-md font-semibold select-none shadow-3xs animate-fade-in",children:[e.jsxs("span",{children:["🔄 ",h]}),e.jsx("button",{onClick:()=>{const S={...L};delete S[a.dateStr],J(S)},className:"hover:text-red-600 hover:bg-amber-100 rounded-sm p-px flex items-center justify-center cursor-pointer",title:l==="zh"?"恢复原日期课程":"Reset to original",children:e.jsx(be,{size:8})})]})})()]},`header-${a.key}`))}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[9px] font-bold text-sky-600 bg-sky-50 px-2 py-0.5 rounded-lg w-fit select-none border border-sky-100/60 shadow-3xs",children:[e.jsx(Ae,{size:10,className:"animate-pulse"}),l==="zh"?"上午课程 (AM)":"Morning (AM)"]}),e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>{const x=a.schedules.filter(h=>!ut(h.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-[10px] text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:l==="zh"?"无课":"Free"}):x.map(h=>K(h))},`morning-col-${a.key}`)})})]}),e.jsxs("div",{className:"relative my-2 flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 flex items-center","aria-hidden":"true",children:e.jsx("div",{className:"w-full border-t-2 border-dashed border-slate-200/80"})}),e.jsxs("div",{className:"relative flex justify-center text-[9px] font-extrabold uppercase tracking-wider text-slate-400 bg-white px-4 py-1.5 rounded-full border border-slate-200/60 shadow-3xs",children:["☕ ",l==="zh"?"午休时间 / Midday Break":"Lunch Break"]})]}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[9px] font-bold text-amber-600 bg-amber-50 px-2 py-0.5 rounded-lg w-fit select-none border border-amber-100/60 shadow-3xs",children:[e.jsx(ct,{size:10}),l==="zh"?"下午课程 (PM)":"Afternoon (PM)"]}),e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>{const x=a.schedules.filter(h=>ut(h.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-[10px] text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:l==="zh"?"无课":"Free"}):x.map(h=>K(h))},`afternoon-col-${a.key}`)})})]})]})})]})]})},us=({lang:l,holStartDate:b,setHolStartDate:r,holEndDate:N,setHolEndDate:T,holType:v,setHolType:I,holNotes:G,setHolNotes:B,handleBatchHolidayAdjustment:P,loading:U})=>e.jsxs("div",{className:"max-w-2xl mx-auto bg-slate-50/50 border border-slate-200 rounded-2xl p-6 shadow-3xs",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Ae,{className:"text-amber-500 shrink-0",size:18}),l==="zh"?"批量节假日调休排班":"Holiday / Cancellation Scheduler"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-5",children:l==="zh"?"此工具能快速把选定日期范围内的课程一键设为“假期调休”或“统一停课”,避免讲师依次手动调整,极大提高教务效率。":"Instantly cancel or exclude classes falling within a holiday or default break period."}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"开始日期 *":"Start Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:b,onChange:C=>r(C.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"结束日期 *":"End Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:N,onChange:C=>T(C.target.value)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"调整状态标签":"Target Status"}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:v==="holiday",onChange:()=>I("holiday"),className:"accent-indigo-600 cursor-pointer"}),"🏝️ ",l==="zh"?"假期调休 (Holiday)":"Holiday Exclusion"]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:v==="cancelled",onChange:()=>I("cancelled"),className:"accent-red-600 cursor-pointer"}),"🛑 ",l==="zh"?"异常停课 (Cancelled)":"Suspicious Cancellation"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"假日说明 / 停课备注":"Exclusion Note / Reason"}),e.jsx("input",{type:"text",placeholder:l==="zh"?"例: 国庆节假期停课调休 / 因极寒气象全市停课":"e.g., National Day break / weather closures",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all",value:G,onChange:C=>B(C.target.value)})]}),e.jsxs("button",{onClick:P,disabled:U,className:"w-full bg-slate-800 hover:bg-slate-900 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-1.5 shadow-sm disabled:opacity-50",children:[U?e.jsx(Ie,{className:"animate-spin",size:14}):e.jsx(Ue,{size:14}),l==="zh"?"一键更新该周期课表":"Execute Batch Holiday Updates"]})]})]}),ms=({lang:l,classes:b,getClassDisplayName:r,handleExportCSV:N,handleExportJSON:T,importClassId:v,setImportClassId:I,csvText:G,setCsvText:B,importMessage:P,handleImportData:U})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5 mb-3",children:[e.jsx(ss,{className:"text-green-600",size:16}),l==="zh"?"导出系统课表":"Export Timetables"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:l==="zh"?"把系统中当前排定的所有班级课表一键备份成标准 CSV 或 JSON 文件。您可以使用 Excel 便捷编辑修改后再导入回来。":"Download the compiled records from SQLite memory db into standard JSON or CSV sheet formats."})]}),e.jsxs("div",{className:"flex gap-2.5 mt-4",children:[e.jsxs("button",{onClick:N,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(xt,{className:"text-green-600",size:13}),l==="zh"?"导出为 Excel CSV":"Export CSV Sheet"]}),e.jsxs("button",{onClick:T,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(xt,{className:"text-amber-500",size:13}),l==="zh"?"导出为 JSON 树":"Export JSON Data"]})]})]}),e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col gap-3",children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5",children:[e.jsx(ls,{className:"text-indigo-600",size:16}),l==="zh"?"导入课表流程":"Import New Schedule"]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] uppercase font-bold text-gray-500 mb-1",children:l==="zh"?"分配排定给哪一个班级 *":"Target Class to load schedules *"}),e.jsxs("select",{id:"import_class_select",title:"Import Target Class",className:"w-full bg-white border border-gray-200 rounded-lg text-xs p-2 text-gray-750 cursor-pointer focus:outline-hidden",value:v,onChange:C=>I(C.target.value),children:[e.jsx("option",{value:"",children:l==="zh"?"选择班级...":"Select Class..."}),b.map(C=>e.jsx("option",{value:C.id,children:r(C.name)},C.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] uppercase font-bold text-gray-500 mb-1",children:l==="zh"?"粘贴 CSV 数据内容":"Paste CSV data rows"}),e.jsx("textarea",{rows:4,placeholder:l==="zh"?`date,lesson_id,time_slot,status,notes
1
+ import{j as e,r as c}from"./vendor-react-0Lg0vA-4.js";import{J as qt,aT as Zt,aU as Ue,aL as Qt,ad as Xt,X as be,a7 as mt,l as Ie,aV as De,aW as Te,aa as dt,a3 as es,_ as ts,f as Ae,m as ct,a5 as ss,aX as xt,a4 as ls,C as rs,aY as as,aZ as os,N as is,a_ as ht,af as ns,g as Be,y as ds,Q as cs}from"./vendor-icons-_c3xpwjZ.js";const xs=l=>{const b=[];for(let r=0;r<7;r++){const N=new Date(l.getTime()+r*24*60*60*1e3),T=N.getFullYear(),v=String(N.getMonth()+1).padStart(2,"0"),I=String(N.getDate()).padStart(2,"0");b.push(`${T}-${v}-${I}`)}return b},ut=l=>{if(!l)return!1;const b=l.match(/^(\d{1,2}):(\d{2})/);return b?parseInt(b[1],10)>=12:!1},hs=({lang:l,viewMode:b,setViewMode:r,selectedClassId:N,setSelectedClassId:T,statusFilter:v,setStatusFilter:I,searchQuery:G,setSearchQuery:B,classes:P,getClassDisplayName:U,loading:C,filteredSchedules:E,currentWeekMonday:Q,setCurrentWeekMonday:O,showWeekend:ae,setShowWeekend:X,dateOverrides:L,setDateOverrides:J,setOverridingDateKey:F,setOverrideMode:k,setOverrideTargetDow:ie,setOverrideTargetDate:ee,openEditModal:xe,handleDeleteSchedule:he,getDayOfWeekIndex:$,getMonday:ne,getWeekRangeString:p,setFormClassId:W,setFormLessonId:te,setFormDate:ve,setFormStatus:Y,setFormNotes:de,setIsAddOpen:se})=>{const M=[{key:1,label:l==="zh"?"周一 (Mon)":"Mon"},{key:2,label:l==="zh"?"周二 (Tue)":"Tue"},{key:3,label:l==="zh"?"周三 (Wed)":"Wed"},{key:4,label:l==="zh"?"周四 (Thu)":"Thu"},{key:5,label:l==="zh"?"周五 (Fri)":"Fri"},{key:6,label:l==="zh"?"周六 (Sat)":"Sat"},{key:7,label:l==="zh"?"周日 (Sun)":"Sun"}],le=xs(Q),K=a=>{const x=a.status==="cancelled"||a.status==="holiday";let h="border-l-green-500 bg-green-50/5 hover:bg-green-50/10 hover:border-l-green-600";return a.status==="cancelled"?h="border-l-red-500 bg-red-50/5 hover:bg-red-50/10 hover:border-l-red-600":a.status==="holiday"?h="border-l-amber-500 bg-amber-50/5 hover:bg-amber-50/10 hover:border-l-amber-600":a.status==="swap"&&(h="border-l-blue-500 bg-blue-50/5 hover:bg-blue-50/10 hover:border-l-blue-600"),e.jsxs("div",{className:`p-2.5 rounded-xl border border-slate-150 border-l-4 ${h} transition-all hover:shadow-xs relative group flex flex-col justify-between min-h-[85px]`,children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-[9px] font-mono text-slate-500 mb-1 font-bold flex justify-between items-center",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ct,{size:11,className:"text-slate-400"}),a.time_slot||(l==="zh"?"全天":"All-day")]}),b==="cycle"&&e.jsx("span",{className:"text-[8px] text-slate-400 font-sans font-normal bg-slate-100 px-1 py-0.5 rounded-sm",children:a.scheduled_date})]}),e.jsx("div",{className:`font-extrabold text-sm text-slate-805 tracking-tight leading-snug mt-1 ${x?"line-through opacity-60 text-slate-400":""}`,title:a.lesson_title||"",children:a.class_name}),a.notes&&e.jsxs("div",{className:"text-[9px] text-amber-600 font-medium mt-1 truncate",title:a.notes,children:["📌 ",a.notes]})]}),e.jsxs("div",{className:"flex items-center justify-between mt-2.5 pt-2 border-t border-slate-100/50",children:[e.jsx("span",{className:`inline-block text-[8px] px-1.5 py-0.5 rounded-full font-bold uppercase tracking-wide border ${a.status==="cancelled"?"bg-red-50 border-red-100 text-red-600":a.status==="holiday"?"bg-amber-50 border-amber-100 text-amber-600":a.status==="swap"?"bg-blue-50 border-blue-100 text-blue-600":"bg-green-50 border-green-100 text-green-600"}`,children:a.status==="cancelled"?l==="zh"?"停课":"Cancelled":a.status==="holiday"?l==="zh"?"假期":"Holiday":a.status==="swap"?l==="zh"?"代课":"Swapped":l==="zh"?"正常":"Active"}),e.jsxs("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{onClick:()=>xe(a),className:"text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 p-1 rounded-md transition-colors cursor-pointer",title:l==="zh"?"微调":"Edit",children:e.jsx(Te,{size:11})}),e.jsx("button",{onClick:()=>he(a.id,a.class_id,a.isRepeating,a.scheduled_date),className:"text-slate-400 hover:text-red-600 hover:bg-red-50 p-1 rounded-md transition-colors cursor-pointer",title:l==="zh"?"删除":"Delete",children:e.jsx(dt,{size:11})})]})]})]},a.id)},Pe=(a,x)=>{if(a===x){const f=E.filter(g=>g.scheduled_date===x);if(f.length>0)return f;const j=$(x),D=E.filter(g=>$(g.scheduled_date)===j&&g.scheduled_date<=x),y={};return D.forEach(g=>{const H=`${g.class_id}_${g.time_slot||"all-day"}`;y[H]||(y[H]={...g,scheduled_date:x,isRepeating:!0})}),Object.values(y)}let h=[];if(a.startsWith("dow-")){const f=parseInt(a.split("-")[1],10),j=E.filter(y=>$(y.scheduled_date)===f&&y.scheduled_date<=x),D={};j.forEach(y=>{const g=`${y.class_id}_${y.time_slot||"all-day"}`;D[g]||(D[g]={...y,scheduled_date:x,isRepeating:!0})}),h=Object.values(D)}else{const f=E.filter(j=>j.scheduled_date===a);if(f.length>0)h=f.map(j=>({...j,scheduled_date:x,isRepeating:!0}));else{const j=$(a),D=E.filter(g=>$(g.scheduled_date)===j&&g.scheduled_date<=a),y={};D.forEach(g=>{const H=`${g.class_id}_${g.time_slot||"all-day"}`;y[H]||(y[H]={...g,scheduled_date:x,isRepeating:!0})}),h=Object.values(y)}}const S=E.filter(f=>f.scheduled_date===x);if(S.length>0){const f=[...h];return S.forEach(j=>{const D=`${j.class_id}_${j.time_slot||"all-day"}`,y=f.findIndex(g=>`${g.class_id}_${g.time_slot||"all-day"}`===D);y!==-1?f[y]=j:j.status!=="cancelled"&&j.status!=="holiday"&&f.push(j)}),f}return h},ue=M.map((a,x)=>{const h=le[x],S=L[h]||h,f=Pe(S,h);return f.sort((j,D)=>(j.time_slot||"").localeCompare(D.time_slot||"")),{...a,dateStr:h,displayLabel:l==="zh"?`${a.label.split(" ")[0]} (${h.substring(5)})`:`${a.label} (${h.substring(5)})`,schedules:f}}),re=M.map(a=>{const x=le[a.key-1],h=E.filter(S=>$(S.scheduled_date)===a.key);return h.sort((S,f)=>(S.time_slot||"").localeCompare(f.time_slot||"")),{...a,dateStr:x,displayLabel:a.label,schedules:h}}),V=(b==="week"?ue:re).filter(a=>b==="week"&&!ae?a.key!==6&&a.key!==7:!0);return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 p-3 rounded-xl flex flex-wrap gap-3 items-center justify-between",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-xs font-bold text-gray-500 flex items-center gap-1",children:[e.jsx(qt,{size:13}),l==="zh"?"筛选:":"Filters:"]}),e.jsxs("div",{className:"flex bg-slate-200/70 p-0.5 rounded-lg border border-slate-300/30 shadow-xs mr-2 shrink-0",children:[e.jsxs("button",{onClick:()=>r("week"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="week"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Zt,{size:11}),l==="zh"?"周课表":"Week View"]}),e.jsxs("button",{onClick:()=>r("cycle"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="cycle"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Ue,{size:11}),l==="zh"?"星期总览":"Cycle View"]}),e.jsxs("button",{onClick:()=>r("list"),className:`px-2.5 py-1 rounded-lg text-[10px] font-bold transition-all flex items-center gap-1 ${b==="list"?"bg-white text-indigo-700 shadow-xs":"text-gray-500 hover:text-gray-800"}`,children:[e.jsx(Qt,{size:11}),l==="zh"?"列表":"List View"]})]}),e.jsxs("select",{id:"timetable_class_select",title:"Select Class",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:N,onChange:a=>T(a.target.value),children:[e.jsx("option",{value:"all",children:l==="zh"?"所有班级 (All Classes)":"All Classes"}),P.map(a=>e.jsx("option",{value:a.id,children:U(a.name)},a.id))]}),e.jsxs("select",{id:"timetable_status_select",title:"Select Status",className:"bg-white border border-gray-200 rounded-lg text-xs py-1.5 px-2 text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",value:v,onChange:a=>I(a.target.value),children:[e.jsx("option",{value:"all",children:l==="zh"?"所有状态 (All Status)":"All Status"}),e.jsx("option",{value:"scheduled",children:l==="zh"?"正常上课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:l==="zh"?"停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:l==="zh"?"假期调休 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:l==="zh"?"代课换课 (Swapped)":"Swapped"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 max-w-xs min-w-[200px]",children:[e.jsxs("div",{className:"relative w-full",children:[e.jsx(Xt,{className:"absolute left-2.5 top-2 text-gray-400",size:14}),e.jsx("input",{type:"text",placeholder:l==="zh"?"检索课程标题, 班级, 备注...":"Search title, class, notes...",className:"w-full bg-white border border-gray-200 rounded-lg pl-8 pr-2.5 py-1.5 text-xs text-gray-700 focus:outline-hidden focus:ring-1 focus:ring-indigo-500",value:G,onChange:a=>B(a.target.value)}),G&&e.jsx("button",{onClick:()=>B(""),className:"absolute right-2.5 top-2 text-gray-400 hover:text-gray-600",children:e.jsx(be,{size:14})})]}),e.jsxs("button",{onClick:()=>{W(P[0]?.id||""),te(""),ve(new Date().toISOString().split("T")[0]),Y("scheduled"),de(""),se(!0)},className:"bg-indigo-600 hover:bg-indigo-700 text-white font-semibold text-xs py-1.5 px-3 rounded-lg flex items-center gap-1 shadow-sm shrink-0 cursor-pointer transition-all",children:[e.jsx(mt,{size:14}),l==="zh"?"排定课时":"Schedule Class"]})]})]}),C?e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-indigo-500",children:[e.jsx(Ie,{className:"animate-spin mb-2",size:32}),e.jsx("span",{className:"text-xs font-semibold",children:l==="zh"?"查询数据中...":"Accessing SQLite Database..."})]}):E.length===0?e.jsxs("div",{className:"text-center py-16 bg-slate-50/50 border border-dashed rounded-xl border-slate-200 flex flex-col items-center",children:[e.jsx(De,{className:"text-gray-300 mb-2",size:40}),e.jsx("p",{className:"text-gray-500 text-sm font-semibold",children:l==="zh"?"暂未匹配到对应的课次安排数据":"No schedules match your filters"}),e.jsx("p",{className:"text-gray-400 text-xs mt-1",children:l==="zh"?"您可以点击右上角“排定课时”为班级新增课程。":"Try adding a new entry using the schedule button above."})]}):b==="list"?e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-sm bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-xs",children:[e.jsx("th",{className:"p-3 w-[15%]",children:l==="zh"?"上课日期":"Date"}),e.jsx("th",{className:"p-3 w-[15%]",children:l==="zh"?"具体时间段":"Time Slot"}),e.jsx("th",{className:"p-3 w-[20%]",children:l==="zh"?"关联班级":"Class"}),e.jsx("th",{className:"p-3 w-[25%]",children:l==="zh"?"授课内容主题":"Lesson Topic"}),e.jsx("th",{className:"p-3 w-[10%] text-center",children:l==="zh"?"日常状态":"Status"}),e.jsx("th",{className:"p-3 w-[15%] text-right",children:l==="zh"?"教务微调":"Actions"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-150",children:E.map(a=>{const x=a.status==="cancelled"||a.status==="holiday";return e.jsxs("tr",{className:`hover:bg-slate-50/80 transition-colors ${x?"bg-red-50/10 text-gray-400":"text-gray-700"}`,children:[e.jsx("td",{className:"p-3 font-semibold text-xs",children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(De,{size:13,className:"text-slate-400"}),a.scheduled_date]})}),e.jsx("td",{className:"p-3 font-mono text-xs text-indigo-750",children:a.time_slot||e.jsx("span",{className:"text-[10px] text-gray-300 italic",children:l==="zh"?"全天":"All-day"})}),e.jsx("td",{className:"p-3 text-xs",children:e.jsx("span",{className:"bg-slate-100 text-slate-800 px-2 py-1 rounded-md border border-slate-250 font-medium",children:a.class_name})}),e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex flex-col leading-snug",children:[e.jsx("span",{className:`font-semibold ${x?"line-through opacity-70":""}`,children:a.lesson_title}),a.notes&&e.jsxs("span",{className:`text-[10px] italic mt-0.5 ${a.status==="holiday"?"text-amber-600 font-medium":a.status==="cancelled"?"text-red-500 font-medium":"text-slate-400"}`,children:["📌 ",a.notes]})]})}),e.jsx("td",{className:"p-3 text-center",children:e.jsx("span",{className:`inline-block text-[10px] px-2 py-0.5 rounded-full font-bold uppercase tracking-wide border ${a.status==="cancelled"?"bg-red-100 border-red-200 text-red-700":a.status==="holiday"?"bg-amber-100 border-amber-200 text-amber-700":a.status==="swap"?"bg-blue-100 border-blue-200 text-blue-700":"bg-green-100 border-green-200 text-green-700"}`,children:a.status==="cancelled"?l==="zh"?"停课":"Cancelled":a.status==="holiday"?l==="zh"?"假期调休":"Holiday":a.status==="swap"?l==="zh"?"换代课":"Swapped":l==="zh"?"正常上课":"Active"})}),e.jsx("td",{className:"p-3 text-right",children:e.jsxs("div",{className:"flex items-center justify-end gap-1.5",children:[e.jsx("button",{onClick:()=>xe(a),className:"text-slate-500 hover:text-indigo-600 hover:bg-indigo-50 p-1.5 rounded transition-colors cursor-pointer",title:l==="zh"?"调整此节课排课 (换课/换时间/写备注)":"Adjust this class (Swap/Edit)",children:e.jsx(Te,{size:13})}),e.jsx("button",{onClick:()=>he(a.id,a.class_id),className:"text-slate-500 hover:text-red-600 hover:bg-red-50 p-1.5 rounded transition-colors cursor-pointer",title:l==="zh"?"永久删除该课课表":"Delete schedule",children:e.jsx(dt,{size:13})})]})})]},a.id)})})]})}):e.jsxs("div",{className:"flex flex-col gap-4",children:[b==="week"&&e.jsxs("div",{className:"flex flex-col md:flex-row items-center justify-between bg-indigo-50/40 border border-indigo-100/60 p-3 rounded-xl gap-3 shadow-2xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>O(a=>new Date(a.getTime()-10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:l==="zh"?"上一周":"Previous Week",children:e.jsx(es,{size:16})}),e.jsx("button",{onClick:()=>O(ne(new Date)),className:"px-3 py-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer text-xs font-bold border border-indigo-200/50 bg-white shadow-2xs",children:l==="zh"?"本周":"This Week"}),e.jsx("button",{onClick:()=>O(a=>new Date(a.getTime()+10080*60*1e3)),className:"p-1.5 rounded-lg hover:bg-indigo-100 hover:text-indigo-700 text-indigo-600 transition-all cursor-pointer border border-indigo-200/50 bg-white shadow-2xs flex items-center justify-center",title:l==="zh"?"下一周":"Next Week",children:e.jsx(ts,{size:16})})]}),e.jsxs("div",{className:"text-sm font-bold text-indigo-900 flex items-center gap-2",children:[e.jsx(De,{size:16,className:"text-indigo-500"}),e.jsx("span",{children:p(Q)})]}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-indigo-700 font-semibold",children:l==="zh"?"跳转日期:":"Go to Date:"}),e.jsx("input",{type:"date",title:"Go to Date",className:"bg-white border border-indigo-200 rounded-lg text-xs py-1 px-2 text-indigo-950 focus:outline-hidden focus:ring-1 focus:ring-indigo-500 font-sans cursor-pointer",onChange:a=>{a.target.value&&O(ne(new Date(a.target.value)))}})]}),e.jsx("div",{className:"flex items-center gap-2 border-l border-indigo-150 pl-3",children:e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-indigo-700 font-semibold cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:ae,onChange:a=>X(a.target.checked),className:"w-3.5 h-3.5 text-indigo-600 border-indigo-300 rounded-sm focus:ring-indigo-500 focus:outline-hidden cursor-pointer"}),l==="zh"?"显示周末":"Show Weekend"]})})]})]}),e.jsx("div",{className:"w-full overflow-x-auto pb-2",children:e.jsxs("div",{className:"flex flex-col gap-4 min-w-[1050px]",children:[e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>e.jsxs("div",{className:"bg-slate-50 border border-slate-200/50 rounded-xl p-3 text-center flex flex-col items-center justify-center gap-1 relative group/col",children:[e.jsxs("div",{className:"flex items-center justify-center gap-1.5 w-full",children:[e.jsx("span",{className:"font-extrabold text-xs text-indigo-700 uppercase tracking-wider",children:a.displayLabel}),b==="week"&&e.jsx("button",{onClick:()=>{const x=L[a.dateStr]||"";F(a.dateStr),x.startsWith("dow-")?(k("dow"),ie(x.split("-")[1]),ee("")):x?(k("date"),ee(x),ie("")):(k("dow"),ie(""),ee(""))},className:"text-slate-400 hover:text-indigo-600 p-0.5 rounded-md hover:bg-slate-200/50 transition-all opacity-0 group-hover/col:opacity-100 focus:opacity-100 cursor-pointer flex items-center justify-center",title:l==="zh"?"临时切换显示日期":"Temporarily switch date",children:e.jsx(Te,{size:10})})]}),b==="week"&&L[a.dateStr]&&(()=>{const x=L[a.dateStr];let h="";if(x.startsWith("dow-")){const S=parseInt(x.split("-")[1],10);h=l==="zh"?`常规${["","周一","周二","周三","周四","周五","周六","周日"][S]}`:`Regular ${["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"][S]}`}else h=x.substring(5);return e.jsxs("div",{className:"flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-700 text-[9px] px-1.5 py-0.5 rounded-md font-semibold select-none shadow-3xs animate-fade-in",children:[e.jsxs("span",{children:["🔄 ",h]}),e.jsx("button",{onClick:()=>{const S={...L};delete S[a.dateStr],J(S)},className:"hover:text-red-600 hover:bg-amber-100 rounded-sm p-px flex items-center justify-center cursor-pointer",title:l==="zh"?"恢复原日期课程":"Reset to original",children:e.jsx(be,{size:8})})]})})()]},`header-${a.key}`))}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[9px] font-bold text-sky-600 bg-sky-50 px-2 py-0.5 rounded-lg w-fit select-none border border-sky-100/60 shadow-3xs",children:[e.jsx(Ae,{size:10,className:"animate-pulse"}),l==="zh"?"上午课程 (AM)":"Morning (AM)"]}),e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>{const x=a.schedules.filter(h=>!ut(h.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-[10px] text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:l==="zh"?"无课":"Free"}):x.map(h=>K(h))},`morning-col-${a.key}`)})})]}),e.jsxs("div",{className:"relative my-2 flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 flex items-center","aria-hidden":"true",children:e.jsx("div",{className:"w-full border-t-2 border-dashed border-slate-200/80"})}),e.jsxs("div",{className:"relative flex justify-center text-[9px] font-extrabold uppercase tracking-wider text-slate-400 bg-white px-4 py-1.5 rounded-full border border-slate-200/60 shadow-3xs",children:["☕ ",l==="zh"?"午休时间 / Midday Break":"Lunch Break"]})]}),e.jsxs("div",{className:"bg-slate-50/30 border border-slate-200/50 rounded-2xl p-3 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-[9px] font-bold text-amber-600 bg-amber-50 px-2 py-0.5 rounded-lg w-fit select-none border border-amber-100/60 shadow-3xs",children:[e.jsx(ct,{size:10}),l==="zh"?"下午课程 (PM)":"Afternoon (PM)"]}),e.jsx("div",{className:`grid ${V.length===5?"grid-cols-5":"grid-cols-7"} gap-4`,children:V.map(a=>{const x=a.schedules.filter(h=>ut(h.time_slot));return e.jsx("div",{className:"flex flex-col gap-2 bg-white/40 p-2.5 rounded-xl border border-dashed border-slate-200/60 min-h-[160px] justify-start",children:x.length===0?e.jsx("div",{className:"flex-1 flex items-center justify-center text-[10px] text-slate-350 italic text-center p-3 border border-dashed border-slate-150 rounded-xl bg-white/30 select-none",children:l==="zh"?"无课":"Free"}):x.map(h=>K(h))},`afternoon-col-${a.key}`)})})]})]})})]})]})},us=({lang:l,holStartDate:b,setHolStartDate:r,holEndDate:N,setHolEndDate:T,holType:v,setHolType:I,holNotes:G,setHolNotes:B,handleBatchHolidayAdjustment:P,loading:U})=>e.jsxs("div",{className:"max-w-2xl mx-auto bg-slate-50/50 border border-slate-200 rounded-2xl p-6 shadow-3xs",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Ae,{className:"text-amber-500 shrink-0",size:18}),l==="zh"?"批量节假日调休排班":"Holiday / Cancellation Scheduler"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-5",children:l==="zh"?"此工具能快速把选定日期范围内的课程一键设为“假期调休”或“统一停课”,避免讲师依次手动调整,极大提高教务效率。":"Instantly cancel or exclude classes falling within a holiday or default break period."}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"开始日期 *":"Start Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:b,onChange:C=>r(C.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"结束日期 *":"End Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750",value:N,onChange:C=>T(C.target.value)})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"调整状态标签":"Target Status"}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:v==="holiday",onChange:()=>I("holiday"),className:"accent-indigo-600 cursor-pointer"}),"🏝️ ",l==="zh"?"假期调休 (Holiday)":"Holiday Exclusion"]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"holType",checked:v==="cancelled",onChange:()=>I("cancelled"),className:"accent-red-600 cursor-pointer"}),"🛑 ",l==="zh"?"异常停课 (Cancelled)":"Suspicious Cancellation"]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5",children:l==="zh"?"假日说明 / 停课备注":"Exclusion Note / Reason"}),e.jsx("input",{type:"text",placeholder:l==="zh"?"例: 国庆节假期停课调休 / 因极寒气象全市停课":"e.g., National Day break / weather closures",className:"w-full border border-gray-200 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all",value:G,onChange:C=>B(C.target.value)})]}),e.jsxs("button",{onClick:P,disabled:U,className:"w-full bg-slate-800 hover:bg-slate-900 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-1.5 shadow-sm disabled:opacity-50",children:[U?e.jsx(Ie,{className:"animate-spin",size:14}):e.jsx(Ue,{size:14}),l==="zh"?"一键更新该周期课表":"Execute Batch Holiday Updates"]})]})]}),ms=({lang:l,classes:b,getClassDisplayName:r,handleExportCSV:N,handleExportJSON:T,importClassId:v,setImportClassId:I,csvText:G,setCsvText:B,importMessage:P,handleImportData:U})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5 mb-3",children:[e.jsx(ss,{className:"text-green-600",size:16}),l==="zh"?"导出系统课表":"Export Timetables"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:l==="zh"?"把系统中当前排定的所有班级课表一键备份成标准 CSV 或 JSON 文件。您可以使用 Excel 便捷编辑修改后再导入回来。":"Download the compiled records from SQLite memory db into standard JSON or CSV sheet formats."})]}),e.jsxs("div",{className:"flex gap-2.5 mt-4",children:[e.jsxs("button",{onClick:N,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(xt,{className:"text-green-600",size:13}),l==="zh"?"导出为 Excel CSV":"Export CSV Sheet"]}),e.jsxs("button",{onClick:T,className:"flex-1 bg-white hover:bg-slate-50 text-slate-800 border border-slate-250 font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex justify-center items-center gap-1",children:[e.jsx(xt,{className:"text-amber-500",size:13}),l==="zh"?"导出为 JSON 树":"Export JSON Data"]})]})]}),e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-xl p-5 flex flex-col gap-3",children:[e.jsxs("h3",{className:"text-sm font-bold text-gray-800 flex items-center gap-2 border-b border-slate-100 pb-2.5",children:[e.jsx(ls,{className:"text-indigo-600",size:16}),l==="zh"?"导入课表流程":"Import New Schedule"]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] uppercase font-bold text-gray-500 mb-1",children:l==="zh"?"分配排定给哪一个班级 *":"Target Class to load schedules *"}),e.jsxs("select",{id:"import_class_select",title:"Import Target Class",className:"w-full bg-white border border-gray-200 rounded-lg text-xs p-2 text-gray-750 cursor-pointer focus:outline-hidden",value:v,onChange:C=>I(C.target.value),children:[e.jsx("option",{value:"",children:l==="zh"?"选择班级...":"Select Class..."}),b.map(C=>e.jsx("option",{value:C.id,children:r(C.name)},C.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] uppercase font-bold text-gray-500 mb-1",children:l==="zh"?"粘贴 CSV 数据内容":"Paste CSV data rows"}),e.jsx("textarea",{rows:4,placeholder:l==="zh"?`date,lesson_id,time_slot,status,notes
2
2
  2026-06-15,les-1,09:00 - 10:30,scheduled,首节授课
3
3
  2026-06-16,les-2,10:45 - 12:15,holiday,假期放假停课`:`date,lesson_id,time_slot,status,notes
4
- 2026-06-15,les-1,09:00 - 10:30,scheduled,First Class`,className:"w-full bg-white border border-gray-250 text-xs p-2 rounded-lg font-mono placeholder:text-gray-350 focus:outline-hidden",value:G,onChange:C=>B(C.target.value)}),e.jsx("span",{className:"text-[10px] text-gray-400 mt-1 block",children:l==="zh"?"首行必须为属性列(支持:date, lesson_id, time_slot, status, notes)。支持复制 JSON 树粘贴直接解析。":"Ensure first line consists of column keys (date, lesson_id, time_slots)."})]}),P&&e.jsxs("div",{className:`p-2.5 rounded-lg text-xs border flex items-center gap-1.5 ${P.type==="error"?"bg-red-50 border-red-200 text-red-700":"bg-green-50 border-green-200 text-green-700"}`,children:[e.jsx(rs,{size:14}),e.jsx("span",{children:P.text})]}),e.jsxs("button",{onClick:U,className:"w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex items-center justify-center gap-1 shadow-xs",children:[e.jsx(mt,{size:13}),l==="zh"?"开始解析并安全导入":"Execute Schema Check & Upload"]})]})]})]}),ps=({lang:l,ocrProviderId:b,setOcrProviderId:r,aiProviders:N,ocrFileInputRef:T,handleOcrDrop:v,handleOcrImageSelect:I,ocrImagePreview:G,setOcrImagePreview:B,setOcrImageBase64:P,setOcrEntries:U,setOcrMessage:C,setOcrSelectedEntries:E,ocrImageBase64:X,ocrLoading:O,handleOcrRecognize:ae,ocrProgressStatus:Q,ocrProgress:L,ocrMessage:J,ocrEntries:F,ocrSelectedEntries:k,toggleAllOcrEntries:ie,toggleOcrEntry:ee,dayNames:xe,findMatchedClass:he,handleOcrImport:$,ocrImporting:ne})=>e.jsxs("div",{className:"flex flex-col gap-5",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(as,{className:"text-violet-500 shrink-0",size:18}),l==="zh"?"第一步:上传课表图片":"Step 1: Upload Timetable Image"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:l==="zh"?"拍照或截图您的纸质/电子课表,AI 将自动识别课程信息并生成结构化数据。支持 PNG、JPG 格式,建议图片清晰、文字可辨。":"Upload a photo or screenshot of your timetable. AI will automatically recognize class information and generate structured data."}),e.jsxs("div",{className:"mb-4 p-3 bg-white rounded-xl border border-slate-200",children:[e.jsxs("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5 flex items-center gap-1.5",children:[e.jsx(Ae,{size:12,className:"text-violet-500"}),l==="zh"?"AI 识别引擎":"AI Recognition Engine"]}),e.jsxs("select",{title:"OCR AI Provider",className:"w-full bg-slate-50 border border-gray-200 rounded-lg text-xs p-2.5 text-gray-750 cursor-pointer focus:outline-hidden focus:ring-1 focus:ring-violet-500",value:b,onChange:p=>r(p.target.value),children:[e.jsx("option",{value:"",children:l==="zh"?"默认 (Gemini)":"Default (Gemini)"}),N.map(p=>e.jsxs("option",{value:p.id,children:[p.name," (",p.model_name,")"]},p.id))]}),e.jsx("span",{className:"text-[10px] text-gray-400 mt-1 block",children:l==="zh"?"选择用于识别课表图片的 AI 模型。需要支持图片输入的模型(如 GPT-4o、Gemini 等)。":"Choose the AI model for timetable recognition. Must support vision/image input."})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"flex-1 border-2 border-dashed border-slate-300 rounded-xl p-6 flex flex-col items-center justify-center gap-3 cursor-pointer hover:border-violet-400 hover:bg-violet-50/30 transition-all group",onClick:()=>T.current?.click(),onDragOver:p=>{p.preventDefault(),p.stopPropagation()},onDrop:v,children:[e.jsx("input",{ref:T,type:"file",accept:"image/png,image/jpeg,image/jpg,image/webp",className:"hidden",onChange:I}),e.jsx(os,{className:"text-slate-400 group-hover:text-violet-500 transition-colors",size:36}),e.jsx("span",{className:"text-xs font-semibold text-slate-500 group-hover:text-violet-600 transition-colors",children:l==="zh"?"点击选择、拖拽图片至此处 或 Ctrl+V 粘贴截图":"Click, drag & drop, or Ctrl+V to paste screenshot"}),e.jsx("span",{className:"text-[10px] text-slate-400",children:l==="zh"?"支持 PNG / JPG / JPEG / WebP,最大 20MB":"Supports PNG / JPG / JPEG / WebP, max 20MB"})]}),G&&e.jsxs("div",{className:"flex-1 relative rounded-xl overflow-hidden border border-slate-200 bg-white shadow-sm",children:[e.jsx("img",{src:G,alt:"Timetable preview",className:"w-full h-full object-contain max-h-[280px]"}),e.jsx("button",{onClick:p=>{p.stopPropagation(),B(null),P(null),U([]),C(null),E(new Set),T.current&&(T.current.value="")},className:"absolute top-2 right-2 bg-black/50 hover:bg-black/70 text-white p-1.5 rounded-lg transition-colors cursor-pointer",title:l==="zh"?"移除图片":"Remove image",children:e.jsx(be,{size:14})}),e.jsxs("div",{className:"absolute bottom-2 left-2 bg-black/50 text-white text-[10px] px-2 py-1 rounded-lg flex items-center gap-1",children:[e.jsx(is,{size:10}),l==="zh"?"课表预览":"Preview"]})]})]}),e.jsx("button",{onClick:ae,disabled:!X||O,className:"mt-4 w-full bg-violet-600 hover:bg-violet-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:O?e.jsxs(e.Fragment,{children:[e.jsx(Ie,{className:"animate-spin",size:14}),l==="zh"?"AI 识别中,请稍候...":"AI recognizing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ht,{size:14}),l==="zh"?"开始 AI 智能识别":"Start AI Recognition"]})})]}),O&&e.jsxs("div",{className:"bg-slate-50 border border-slate-200 rounded-xl p-3.5 space-y-2.5 animate-in fade-in duration-200 text-left",children:[e.jsxs("div",{className:"flex justify-between items-center text-xs",children:[e.jsx("span",{className:"font-semibold text-slate-700",children:Q}),e.jsxs("span",{className:"font-mono font-bold text-indigo-600",children:[L,"%"]})]}),e.jsx("div",{className:"w-full h-2 bg-slate-200 rounded-full overflow-hidden shrink-0",children:e.jsx("div",{className:"h-full bg-gradient-to-r from-violet-500 to-indigo-600 transition-all duration-300 rounded-full",style:{width:`${L}%`}})})]}),J&&e.jsxs("div",{className:`p-3 rounded-xl text-xs border flex items-start gap-2 ${J.type==="error"?"bg-red-50 border-red-200 text-red-700":J.type==="success"?"bg-green-50 border-green-200 text-green-700":"bg-blue-50 border-blue-200 text-blue-700"}`,children:[J.type==="error"?e.jsx(ns,{size:14,className:"shrink-0 mt-0.5"}):J.type==="success"?e.jsx(Be,{size:14,className:"shrink-0 mt-0.5"}):e.jsx(ht,{size:14,className:"shrink-0 mt-0.5 animate-pulse"}),e.jsx("span",{children:J.text})]}),F.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Be,{className:"text-emerald-500 shrink-0",size:18}),l==="zh"?"第二步:审核识别结果":"Step 2: Review Recognized Entries"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-3",children:l==="zh"?"以下是 AI 从课表图片中识别出的课程安排,请勾选需要导入的条目。":"Below are the class entries recognized by AI. Select the ones you want to import."}),e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:k.size===F.length,onChange:ie,className:"accent-violet-600 cursor-pointer rounded"}),l==="zh"?`全选 (${k.size}/${F.length})`:`Select All (${k.size}/${F.length})`]}),e.jsx("span",{className:"text-[10px] text-slate-400",children:l==="zh"?"取消勾选可排除不需要导入的条目":"Uncheck to exclude entries from import"})]}),e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-xs bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-[10px] uppercase tracking-wide",children:[e.jsx("th",{className:"p-2.5 w-[40px] text-center",children:"✓"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"星期":"Day"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"节次":"Period"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"班级":"Class"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"科目":"Subject"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"时间段":"Time"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"教室":"Room"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"教师":"Teacher"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:F.map((p,W)=>e.jsxs("tr",{className:`hover:bg-violet-50/30 transition-colors cursor-pointer ${k.has(W)?"bg-violet-50/20":"opacity-50"}`,onClick:()=>ee(W),children:[e.jsx("td",{className:"p-2.5 text-center",children:e.jsx("input",{type:"checkbox",checked:k.has(W),onChange:()=>ee(W),onClick:te=>te.stopPropagation(),className:"accent-violet-600 cursor-pointer"})}),e.jsx("td",{className:"p-2.5 font-medium",children:e.jsx("span",{className:"inline-block bg-indigo-100 text-indigo-700 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:xe[p.dayOfWeek]||`Day${p.dayOfWeek}`})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-slate-100 text-slate-700 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:l==="zh"?`第${p.periodNumber}节`:`P${p.periodNumber}`})}),e.jsx("td",{className:"p-2.5 font-semibold text-slate-800",children:p.className||"-"}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-amber-100 text-amber-800 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:p.subject||"-"})}),e.jsx("td",{className:"p-2.5 font-mono text-slate-600",children:p.timeSlot||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:p.location||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:p.teacherName||"-"})]},W))})]})})]}),F.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Be,{className:"text-emerald-500 shrink-0",size:18}),l==="zh"?"第三步:确认导入日程":"Step 3: Confirm Import"]}),(()=>{const p=new Date,W=p.getDay(),te=p.getDate()-W+(W===0?-6:1),Y=new Date(p.setDate(te)).toISOString().split("T")[0],de=F.filter((le,K)=>k.has(K)),se=new Set;let M=0;return de.forEach(le=>{he(le.className||"")?M++:le.className&&se.add(le.className.trim())}),e.jsxs("div",{className:"flex flex-col gap-4 mb-4",children:[e.jsxs("div",{className:"p-3.5 bg-indigo-50 border border-indigo-100 rounded-xl text-xs leading-relaxed",children:[e.jsxs("div",{className:"font-semibold text-indigo-900 flex items-center gap-1.5 mb-1.5",children:[e.jsx(Ae,{size:14,className:"text-indigo-600 animate-pulse"}),l==="zh"?"智能自动匹配规则":"Intelligent Auto-Mapping"]}),e.jsxs("div",{className:"text-gray-650 space-y-1",children:[e.jsxs("div",{children:["• ",l==="zh"?`本周起始日期(周一):${Y}`:`Week Start Date (Monday): ${Y}`]}),e.jsxs("div",{children:["• ",l==="zh"?"班级匹配:系统将根据识别到的班级名称自动导入至系统中对应班级。若班级不存在,将自动创建。":"Class Matching: System will automatically import entries into matched classes or create new classes on the fly."]})]})]}),e.jsxs("div",{className:"text-xs",children:[e.jsx("div",{className:"font-semibold text-gray-700",children:l==="zh"?`已选择 ${de.length} 条记录,其中 ${M} 条可直接匹配到系统班级。`:`${de.length} entries selected, ${M} matched existing classes.`}),se.size>0&&e.jsxs("div",{className:"mt-2 p-2.5 bg-violet-50 border border-violet-200 text-violet-800 rounded-lg leading-relaxed",children:["💡 ",l==="zh"?`以下识别出的班级在系统中暂不存在,导入时将自动创建:${Array.from(se).join(", ")}`:`The following recognized classes do not exist and will be automatically created on import: ${Array.from(se).join(", ")}.`]})]})]})})(),e.jsx("button",{onClick:$,disabled:ne||k.size===0,className:"w-full bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:ne?e.jsxs(e.Fragment,{children:[e.jsx(Ie,{className:"animate-spin",size:14}),l==="zh"?"正在导入...":"Importing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ds,{size:14}),l==="zh"?`确认导入选中的 ${k.size} 条课程`:`Import ${k.size} Selected Entries`]})})]})]}),bs=({classes:l,lessons:b,lang:r,onSchedulesUpdated:N,onClassesUpdated:T})=>{const[v,I]=c.useState("view"),[G,B]=c.useState("week"),P=t=>{const s=new Date(t.getTime()),n=s.getDay(),i=s.getDate()-n+(n===0?-6:1),o=new Date(s.setDate(i));return o.setHours(0,0,0,0),o},[U,C]=c.useState(()=>P(new Date)),E=t=>{const s=new Date(t.getTime()+5184e5),n=i=>{const o=i.getFullYear(),d=String(i.getMonth()+1).padStart(2,"0"),u=String(i.getDate()).padStart(2,"0");return`${o}-${d}-${u}`};return`${n(t)} ~ ${n(s)}`},[X,O]=c.useState(null),[ae,Q]=c.useState(""),[L,J]=c.useState("dow"),[F,k]=c.useState(""),[ie,ee]=c.useState({}),[xe,he]=c.useState(!1),[$,ne]=c.useState("all"),[p,W]=c.useState(""),[te,ve]=c.useState("all"),[Y,de]=c.useState([]),[se,M]=c.useState(!1),[le,K]=c.useState(!1),[Pe,ue]=c.useState(!1),[re,V]=c.useState(null),[a,x]=c.useState(""),[h,S]=c.useState(""),[f,j]=c.useState(""),[D,y]=c.useState("09:00 - 10:30"),[g,H]=c.useState("scheduled"),[we,fe]=c.useState(""),[Ee,Ye]=c.useState(""),[Oe,pt]=c.useState(""),[bt,ze]=c.useState(null),[ge,Ke]=c.useState(""),[je,qe]=c.useState(""),[ye,ft]=c.useState("holiday"),[Ze,Xe]=c.useState(""),[gt,Le]=c.useState(null),[Fe,Re]=c.useState(null),[jt,Qe]=c.useState(!1),[yt,Se]=c.useState(0),[Nt,me]=c.useState(""),[Ce,Ne]=c.useState([]),[vt,A]=c.useState(null),[fs,gs]=c.useState(""),[js,ys]=c.useState(""),[wt,Je]=c.useState(!1),[ke,ce]=c.useState(new Set),zt=c.useRef(null),[St,et]=c.useState([]),[tt,Ct]=c.useState(""),st=["08:00 - 09:30","09:45 - 11:15","11:30 - 13:00","13:30 - 15:00","15:15 - 16:45","19:00 - 20:30"],lt=c.useRef(""),rt=c.useRef(""),kt=t=>{try{const s=t.split("-");if(s.length<3)return 1;const n=parseInt(s[0],10),i=parseInt(s[1],10)-1,o=parseInt(s[2],10),u=new Date(n,i,o).getDay();return u===0?7:u}catch{return 1}},oe=async()=>{M(!0);try{let t=[];if($==="all"){const s=await fetch("/api/schedules");s.ok&&(t=await s.json())}else{const s=l.find(n=>n.id===$);if(s){const n=await fetch(`/api/classes/${s.id}/schedules`);n.ok&&(t=await n.json(),t.forEach(i=>{i.class_name=s.name}))}}t.sort((s,n)=>{const i=n.scheduled_date.localeCompare(s.scheduled_date);return i!==0?i:(s.time_slot||"").localeCompare(n.time_slot||"")}),de(t)}catch(t){console.error(t)}finally{M(!1)}};c.useEffect(()=>{const t=l.map(i=>`${i.id}:${i.name}`).join(","),s=t!==lt.current,n=$!==rt.current;l.length>0&&(s||n)&&(lt.current=t,rt.current=$,oe())},[$,l]),c.useEffect(()=>{fetch("/api/ai-providers").then(t=>t.ok?t.json():[]).then(t=>et(Array.isArray(t)?t:[])).catch(()=>et([]))},[]);const $t=async t=>{if(t.preventDefault(),!a||!f){alert(r==="zh"?"请填写所有必填字段":"Please fill all required fields");return}try{const s=await fetch(`/api/classes/${a}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:h,scheduledDate:f,timeSlot:D,status:g,notes:we})});if(s.ok)K(!1),x(""),S(""),j(""),fe(""),H("scheduled"),oe(),N();else{const n=await s.json();alert(n.error||"Failed to schedule")}}catch(s){alert(s.message)}},_t=async t=>{if(t.preventDefault(),!!re)try{const s=re.isRepeating,n=s?`/api/classes/${re.class_id}/schedules`:`/api/classes/${re.class_id}/schedules/${re.id}`,o=await fetch(n,{method:s?"POST":"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:h,scheduledDate:f,timeSlot:D,status:g,notes:we})});if(o.ok)ue(!1),V(null),oe(),N();else{const d=await o.json();alert(d.error||"Failed to update schedule")}}catch(s){alert(s.message)}},Dt=async(t,s,n,i)=>{if(n&&i){if(!confirm(r==="zh"?"该课程是由上周循环生成的。您确定要取消(停课)本周这一天的课程安排吗?":"This is a repeating class. Do you want to cancel (set to Cancelled) this class for this week?"))return;try{const u=Y.find(w=>w.id===t);(await fetch(`/api/classes/${s}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:u?.lesson_id||"",scheduledDate:i,timeSlot:u?.time_slot||"",status:"cancelled",notes:r==="zh"?"循环排课取消":"Repeating schedule cancelled"})})).ok?(oe(),N()):alert("Cancel failed")}catch(u){alert(u.message)}return}if(confirm(r==="zh"?"您确定要完全删除该条课表排课记录吗?关联的考勤记录也将一并清除!":"Are you sure you want to completely delete this schedule record? Associated attendance logs will be cleared as well!"))try{(await fetch(`/api/classes/${s}/schedules/${t}`,{method:"DELETE"})).ok?(oe(),N()):alert("Delete failed")}catch(d){alert(d.message)}},Tt=t=>{V(t),x(t.class_id),S(t.lesson_id),j(t.scheduled_date),y(t.time_slot||"09:00 - 10:30"),H(t.status||"scheduled"),fe(t.notes||""),ue(!0)},It=async()=>{if(!ge||!je){alert(r==="zh"?"请选择开始日期和结束日期":"Please select both start and end dates");return}const t=Y.filter(i=>{const o=i.scheduled_date;return o>=ge&&o<=je&&i.status!==ye});if(t.length===0){alert(r==="zh"?"在此日期范围内没有找到可调整的研究课表记录!":"No schedules found in the selected date range to adjust!");return}const s=r==="zh"?`此操作将会把 ${ge} 到 ${je} 之间的共 ${t.length} 个课时记录一键标记为 [${ye==="holiday"?"假日停课":"异常停课"}]。确认执行吗?`:`This will mark ${t.length} active classes between ${ge} and ${je} as [${ye}]. Continue?`;if(!confirm||!confirm(s))return;M(!0);let n=0;try{for(const i of t)(await fetch(`/api/classes/${i.class_id}/schedules/${i.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:i.lesson_id,scheduledDate:i.scheduled_date,timeSlot:i.time_slot,status:ye,notes:Ze||(r==="zh"?"假期统一调休":"Holiday adjustments")})})).ok&&n++;alert(r==="zh"?`调整成功!共更新 ${n} 个课表安排。`:`Success! Updated ${n} entries.`),Ke(""),qe(""),Xe(""),oe(),N()}catch(i){alert(i.message)}finally{M(!1)}},We=t=>{if(!t.type.startsWith("image/")){A({type:"error",text:r==="zh"?"请选择图片文件(PNG, JPG, JPEG)":"Please select an image file (PNG, JPG, JPEG)"});return}if(t.size>20*1024*1024){A({type:"error",text:r==="zh"?"图片大小不能超过 20MB":"Image size must be under 20MB"});return}const s=new FileReader;s.onload=n=>{const i=n.target?.result;Le(i),Re(i),Ne([]),A(null),ce(new Set)},s.readAsDataURL(t)},At=t=>{const s=t.target.files?.[0];s&&We(s)},Pt=t=>{const s=t.clipboardData?.items;if(s){for(let n=0;n<s.length;n++)if(s[n].type.startsWith("image/")){t.preventDefault();const i=s[n].getAsFile();i&&We(i);return}}},Et=t=>{t.preventDefault(),t.stopPropagation();const s=t.dataTransfer?.files?.[0];s&&s.type.startsWith("image/")&&We(s)};c.useEffect(()=>{if(v!=="ocr_import")return;const t=s=>Pt(s);return document.addEventListener("paste",t),()=>document.removeEventListener("paste",t)},[v,r]);const Ot=async()=>{if(!Fe){A({type:"error",text:r==="zh"?"请先上传课表图片":"Please upload a timetable image first"});return}Qe(!0),Se(0),me(r==="zh"?"📤 正在上传并优化图像...":"📤 Uploading and optimizing image..."),A({type:"info",text:r==="zh"?"🔍 AI 正在分析课表图片,请稍候...":"🔍 AI is analyzing the timetable image, please wait..."}),Ne([]);let t=0;const s=setInterval(()=>{t+=Math.random()*6+1,t>=95&&(t=95,clearInterval(s)),Se(Math.round(t)),t<20?me(r==="zh"?"📤 正在上传并优化图像...":"📤 Uploading and optimizing image..."):t<50?me(r==="zh"?"🧠 AI 正在分析表格排版与单元格...":"🧠 AI analyzing table layout..."):t<75?me(r==="zh"?"📝 提取课程、班级及教师信息...":"📝 Extracting lesson and teacher info..."):me(r==="zh"?"🔮 正在进行最终数据格式校验...":"🔮 Verifying data formats...")},400);try{const n=await fetch("/api/timetable/ocr",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageBase64:Fe,lang:r,providerId:tt||void 0})}),i=await n.text();let o;try{o=JSON.parse(i)}catch{throw new Error(r==="zh"?`服务端返回了无效响应: ${i.substring(0,150)}`:`Server returned invalid response: ${i.substring(0,150)}`)}if(!n.ok||!o.success)throw new Error(o.error||"OCR recognition failed");clearInterval(s),Se(100),me(r==="zh"?"✅ 识别成功,正在载入结果...":"✅ Recognition complete, loading results..."),o.entries&&o.entries.length>0?(Ne(o.entries),ce(new Set(o.entries.map((d,u)=>u))),A({type:"success",text:r==="zh"?`✅ 识别成功!共检测到 ${o.entries.length} 节课程安排,请审核后导入。`:`✅ Success! Detected ${o.entries.length} class entries. Review and import below.`})):A({type:"error",text:r==="zh"?"未能从图片中识别出课程信息,请尝试更清晰的图片。":"No class entries detected. Try a clearer image."})}catch(n){clearInterval(s),Se(0),A({type:"error",text:`${r==="zh"?"AI 识别失败:":"OCR Failed: "}${n.message}`})}finally{Qe(!1)}},Lt=(t,s)=>{if(!s)return"";try{const n=new Date(s);let i=Number(t);isNaN(i)&&typeof t=="string"&&(t.includes("一")||t.includes("1")||t.includes("Mon")?i=1:t.includes("二")||t.includes("2")||t.includes("Tue")?i=2:t.includes("三")||t.includes("3")||t.includes("Wed")?i=3:t.includes("四")||t.includes("4")||t.includes("Thu")?i=4:t.includes("五")||t.includes("5")||t.includes("Fri")?i=5:t.includes("六")||t.includes("6")||t.includes("Sat")?i=6:(t.includes("日")||t.includes("天")||t.includes("7")||t.includes("Sun"))&&(i=7)),(isNaN(i)||i<1||i>7)&&(i=1);const o=i-1,d=new Date(n);return d.setDate(n.getDate()+o),d.toISOString().split("T")[0]}catch(n){return console.error("Failed to convert day of week to date:",n),s}},at=t=>{if(!t)return null;const s=t.replace(/\s+/g,"").trim(),n=s.match(/(\d+)(?:班)?\)?$/)||s.match(/\((\d+)\)/);if(!n)return null;const i=n[1];let o="",d=0;if(s.startsWith("高")?(o="高",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:(s.includes("三")||s.includes("3"))&&(d=3)):s.startsWith("初")?(o="初",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:(s.includes("三")||s.includes("3"))&&(d=3)):s.startsWith("七")||s.startsWith("7")?(o="初",d=1):s.startsWith("八")||s.startsWith("8")?(o="初",d=2):s.startsWith("九")||s.startsWith("9")?(o="初",d=3):s.startsWith("小")?(o="小",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:s.includes("三")||s.includes("3")?d=3:s.includes("四")||s.includes("4")?d=4:s.includes("五")||s.includes("5")?d=5:(s.includes("六")||s.includes("6"))&&(d=6)):s.startsWith("一")||s.startsWith("1")?(o="小",d=1):s.startsWith("二")||s.startsWith("2")?(o="小",d=2):s.startsWith("三")||s.startsWith("3")?(o="小",d=3):s.startsWith("四")||s.startsWith("4")?(o="小",d=4):s.startsWith("五")||s.startsWith("5")?(o="小",d=5):(s.startsWith("六")||s.startsWith("6"))&&(o="小",d=6),!o||d===0)return null;const u=new Date,R=u.getFullYear(),pe=(u.getMonth()+1>=9?R:R-1)-(d-1);return`${o}${pe}级${i}班`},Ft=t=>{if(!t)return null;const s=t.match(/^(初|高|小|小学)(\d{4})级(\d+)班$/);if(!s)return null;const n=s[1],i=parseInt(s[2],10),o=s[3],d=new Date,u=d.getFullYear(),R=d.getMonth()+1;let w=u-i;if(R>=9&&(w+=1),w<1)return r==="zh"?"未开学":"Not Started";if(w>(n==="高"||n==="初"?3:6))return r==="zh"?"已毕业":"Graduated";const q=r==="zh"&&["","一","二","三","四","五","六","七","八","九","十"][w]||w.toString();return`${n}${q}(${o})`},Ge=t=>{const s=Ft(t);return s?`${t} (${s})`:t},Me=t=>{if(!t)return null;const s=t.replace(/\s+/g,"").toLowerCase();let n=l.find(i=>{if(!i||!i.name)return!1;const o=i.name.replace(/\s+/g,"").toLowerCase();return o===s||o.includes(s)||s.includes(o)});if(!n){const i=s.replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");n=l.find(o=>{if(!o||!o.name)return!1;const d=o.name.replace(/\s+/g,"").toLowerCase().replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");return d===i||d.includes(i)||i.includes(d)})}return n||null},Rt=async()=>{try{if(ke.size===0){A({type:"error",text:r==="zh"?"请至少选择一条课程记录":"Please select at least one entry"});return}const t={1:"08:00 - 08:40",2:"08:50 - 09:30",3:"10:00 - 10:40",4:"10:50 - 11:30",5:"11:40 - 12:15",6:"14:20 - 15:00",7:"15:10 - 15:50",8:"16:20 - 17:00",9:"19:00 - 20:30"},s=new Date,n=s.getDay(),i=s.getDate()-n+(n===0?-6:1),d=new Date(s.setDate(i)).toISOString().split("T")[0];Je(!0),A(null);const u=Ce.filter((m,_)=>ke.has(_)),R=new Set;u.forEach(m=>{if(m.className){const _=at(m.className)||m.className.trim();Me(_)||R.add(_)}});const w={};R.size>0&&(await Promise.all(Array.from(R).map(async m=>{try{const _=await fetch("/api/classes",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:m,description:"OCR自动生成规范班级"})});if(_.ok){const Z=await _.json();Z.success&&Z.id&&(w[m]=Z.id)}}catch(_){console.error(`Failed to dynamically create class ${m}:`,_)}})),T&&T());const z={},pe=new Set;u.forEach(m=>{const _=Lt(m.dayOfWeek||1,d),Z=m.timeSlot||t[m.periodNumber]||"09:00 - 10:30",$e=m.className?at(m.className)||m.className.trim():"",it=Me($e),_e=it?it.id:$e?w[$e]:null;if(!_e){m.className&&pe.add(m.className);return}const Ut=b.find(Yt=>{const He=Yt.title.toLowerCase(),nt=$e.toLowerCase(),Kt=(m.subject||"").toLowerCase();return He.includes(nt)||He.includes(Kt)||nt.includes(He)});z[_e]||(z[_e]=[]),z[_e].push({lessonId:Ut?.id||"",scheduledDate:_,timeSlot:Z,status:"scheduled",notes:`${m.className||""} ${m.subject||""} ${m.location?"教室:"+m.location:""} ${m.teacherName?"教师:"+m.teacherName:""}`.trim()})});const q=Object.keys(z);if(q.length===0){A({type:"error",text:r==="zh"?"无法导入:没有解析出任何有效的班级名称。":"Could not match or create any classes for import."}),Je(!1);return}let Ve=0;await Promise.all(q.map(async m=>{const _=await fetch(`/api/classes/${m}/schedules/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({schedules:z[m]})});if(_.ok){const Z=await _.json();Ve+=Z.count||0}else{const Z=await _.json().catch(()=>({}));throw new Error(Z.error||`Failed to import schedules for class ${m}`)}})),Ne([]),ce(new Set),Le(null),Re(null);let ot=r==="zh"?`🎉 导入成功!共写入 ${Ve} 节课时安排。`:`🎉 Import successful! Saved ${Ve} schedule entries.`;if(R.size>0){const m=Array.from(R).filter(_=>w[_]);m.length>0&&(ot+=r==="zh"?`(自动创建并规范了新班级:${m.join(", ")})`:` (Automatically created classes: ${m.join(", ")})`)}A({type:"success",text:ot}),oe(),N()}catch(t){console.error("OCR Import Error:",t),alert(`${r==="zh"?"导入出错提示:":"Import error alert: "}${t.message}`),A({type:"error",text:`${r==="zh"?"导入失败:":"Import failed: "}${t.message}`})}finally{Je(!1)}},Jt=t=>{ce(s=>{const n=new Set(s);return n.has(t)?n.delete(t):n.add(t),n})},Wt=()=>{ke.size===Ce.length?ce(new Set):ce(new Set(Ce.map((t,s)=>s)))},Gt=r==="zh"?["","周一","周二","周三","周四","周五","周六","周日"]:["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],Mt=()=>{const t=["Date","Class Name","Lesson Title","Time Slot","Status","Notes","Class ID","Lesson ID"],s=Y.map(d=>[d.scheduled_date,d.class_name||"",d.lesson_title||"",d.time_slot||"",d.status||"scheduled",d.notes||"",d.class_id,d.lesson_id]),n="data:text/csv;charset=utf-8,"+[t.join(","),...s.map(d=>d.map(u=>`"${String(u).replace(/"/g,'""')}"`).join(","))].join(`
4
+ 2026-06-15,les-1,09:00 - 10:30,scheduled,First Class`,className:"w-full bg-white border border-gray-250 text-xs p-2 rounded-lg font-mono placeholder:text-gray-350 focus:outline-hidden",value:G,onChange:C=>B(C.target.value)}),e.jsx("span",{className:"text-[10px] text-gray-400 mt-1 block",children:l==="zh"?"首行必须为属性列(支持:date, lesson_id, time_slot, status, notes)。支持复制 JSON 树粘贴直接解析。":"Ensure first line consists of column keys (date, lesson_id, time_slots)."})]}),P&&e.jsxs("div",{className:`p-2.5 rounded-lg text-xs border flex items-center gap-1.5 ${P.type==="error"?"bg-red-50 border-red-200 text-red-700":"bg-green-50 border-green-200 text-green-700"}`,children:[e.jsx(rs,{size:14}),e.jsx("span",{children:P.text})]}),e.jsxs("button",{onClick:U,className:"w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs py-2 rounded-lg cursor-pointer transition-all flex items-center justify-center gap-1 shadow-xs",children:[e.jsx(mt,{size:13}),l==="zh"?"开始解析并安全导入":"Execute Schema Check & Upload"]})]})]})]}),ps=({lang:l,ocrProviderId:b,setOcrProviderId:r,aiProviders:N,ocrFileInputRef:T,handleOcrDrop:v,handleOcrImageSelect:I,ocrImagePreview:G,setOcrImagePreview:B,setOcrImageBase64:P,setOcrEntries:U,setOcrMessage:C,setOcrSelectedEntries:E,ocrImageBase64:Q,ocrLoading:O,handleOcrRecognize:ae,ocrProgressStatus:X,ocrProgress:L,ocrMessage:J,ocrEntries:F,ocrSelectedEntries:k,toggleAllOcrEntries:ie,toggleOcrEntry:ee,dayNames:xe,findMatchedClass:he,handleOcrImport:$,ocrImporting:ne})=>e.jsxs("div",{className:"flex flex-col gap-5",children:[e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(as,{className:"text-violet-500 shrink-0",size:18}),l==="zh"?"第一步:上传课表图片":"Step 1: Upload Timetable Image"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-4 leading-relaxed",children:l==="zh"?"拍照或截图您的纸质/电子课表,AI 将自动识别课程信息并生成结构化数据。支持 PNG、JPG 格式,建议图片清晰、文字可辨。":"Upload a photo or screenshot of your timetable. AI will automatically recognize class information and generate structured data."}),e.jsxs("div",{className:"mb-4 p-3 bg-white rounded-xl border border-slate-200",children:[e.jsxs("label",{className:"block text-xs font-semibold text-gray-700 mb-1.5 flex items-center gap-1.5",children:[e.jsx(Ae,{size:12,className:"text-violet-500"}),l==="zh"?"AI 识别引擎":"AI Recognition Engine"]}),e.jsxs("select",{title:"OCR AI Provider",className:"w-full bg-slate-50 border border-gray-200 rounded-lg text-xs p-2.5 text-gray-750 cursor-pointer focus:outline-hidden focus:ring-1 focus:ring-violet-500",value:b,onChange:p=>r(p.target.value),children:[e.jsx("option",{value:"",children:l==="zh"?"默认 (Gemini)":"Default (Gemini)"}),N.map(p=>e.jsxs("option",{value:p.id,children:[p.name," (",p.model_name,")"]},p.id))]}),e.jsx("span",{className:"text-[10px] text-gray-400 mt-1 block",children:l==="zh"?"选择用于识别课表图片的 AI 模型。需要支持图片输入的模型(如 GPT-4o、Gemini 等)。":"Choose the AI model for timetable recognition. Must support vision/image input."})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"flex-1 border-2 border-dashed border-slate-300 rounded-xl p-6 flex flex-col items-center justify-center gap-3 cursor-pointer hover:border-violet-400 hover:bg-violet-50/30 transition-all group",onClick:()=>T.current?.click(),onDragOver:p=>{p.preventDefault(),p.stopPropagation()},onDrop:v,children:[e.jsx("input",{ref:T,type:"file",accept:"image/png,image/jpeg,image/jpg,image/webp",className:"hidden",onChange:I}),e.jsx(os,{className:"text-slate-400 group-hover:text-violet-500 transition-colors",size:36}),e.jsx("span",{className:"text-xs font-semibold text-slate-500 group-hover:text-violet-600 transition-colors",children:l==="zh"?"点击选择、拖拽图片至此处 或 Ctrl+V 粘贴截图":"Click, drag & drop, or Ctrl+V to paste screenshot"}),e.jsx("span",{className:"text-[10px] text-slate-400",children:l==="zh"?"支持 PNG / JPG / JPEG / WebP,最大 20MB":"Supports PNG / JPG / JPEG / WebP, max 20MB"})]}),G&&e.jsxs("div",{className:"flex-1 relative rounded-xl overflow-hidden border border-slate-200 bg-white shadow-sm",children:[e.jsx("img",{src:G,alt:"Timetable preview",className:"w-full h-full object-contain max-h-[280px]"}),e.jsx("button",{onClick:p=>{p.stopPropagation(),B(null),P(null),U([]),C(null),E(new Set),T.current&&(T.current.value="")},className:"absolute top-2 right-2 bg-black/50 hover:bg-black/70 text-white p-1.5 rounded-lg transition-colors cursor-pointer",title:l==="zh"?"移除图片":"Remove image",children:e.jsx(be,{size:14})}),e.jsxs("div",{className:"absolute bottom-2 left-2 bg-black/50 text-white text-[10px] px-2 py-1 rounded-lg flex items-center gap-1",children:[e.jsx(is,{size:10}),l==="zh"?"课表预览":"Preview"]})]})]}),e.jsx("button",{onClick:ae,disabled:!Q||O,className:"mt-4 w-full bg-violet-600 hover:bg-violet-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:O?e.jsxs(e.Fragment,{children:[e.jsx(Ie,{className:"animate-spin",size:14}),l==="zh"?"AI 识别中,请稍候...":"AI recognizing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ht,{size:14}),l==="zh"?"开始 AI 智能识别":"Start AI Recognition"]})})]}),O&&e.jsxs("div",{className:"bg-slate-50 border border-slate-200 rounded-xl p-3.5 space-y-2.5 animate-in fade-in duration-200 text-left",children:[e.jsxs("div",{className:"flex justify-between items-center text-xs",children:[e.jsx("span",{className:"font-semibold text-slate-700",children:X}),e.jsxs("span",{className:"font-mono font-bold text-indigo-600",children:[L,"%"]})]}),e.jsx("div",{className:"w-full h-2 bg-slate-200 rounded-full overflow-hidden shrink-0",children:e.jsx("div",{className:"h-full bg-gradient-to-r from-violet-500 to-indigo-600 transition-all duration-300 rounded-full",style:{width:`${L}%`}})})]}),J&&e.jsxs("div",{className:`p-3 rounded-xl text-xs border flex items-start gap-2 ${J.type==="error"?"bg-red-50 border-red-200 text-red-700":J.type==="success"?"bg-green-50 border-green-200 text-green-700":"bg-blue-50 border-blue-200 text-blue-700"}`,children:[J.type==="error"?e.jsx(ns,{size:14,className:"shrink-0 mt-0.5"}):J.type==="success"?e.jsx(Be,{size:14,className:"shrink-0 mt-0.5"}):e.jsx(ht,{size:14,className:"shrink-0 mt-0.5 animate-pulse"}),e.jsx("span",{children:J.text})]}),F.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Be,{className:"text-emerald-500 shrink-0",size:18}),l==="zh"?"第二步:审核识别结果":"Step 2: Review Recognized Entries"]}),e.jsx("p",{className:"text-xs text-gray-500 mb-3",children:l==="zh"?"以下是 AI 从课表图片中识别出的课程安排,请勾选需要导入的条目。":"Below are the class entries recognized by AI. Select the ones you want to import."}),e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs font-medium text-slate-700 cursor-pointer select-none",children:[e.jsx("input",{type:"checkbox",checked:k.size===F.length,onChange:ie,className:"accent-violet-600 cursor-pointer rounded"}),l==="zh"?`全选 (${k.size}/${F.length})`:`Select All (${k.size}/${F.length})`]}),e.jsx("span",{className:"text-[10px] text-slate-400",children:l==="zh"?"取消勾选可排除不需要导入的条目":"Uncheck to exclude entries from import"})]}),e.jsx("div",{className:"border border-slate-200 rounded-xl overflow-hidden shadow-2xs",children:e.jsxs("table",{className:"w-full text-left border-collapse table-auto text-xs bg-white",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-slate-50 border-b border-slate-200 text-gray-600 font-semibold text-[10px] uppercase tracking-wide",children:[e.jsx("th",{className:"p-2.5 w-[40px] text-center",children:"✓"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"星期":"Day"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"节次":"Period"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"班级":"Class"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"科目":"Subject"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"时间段":"Time"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"教室":"Room"}),e.jsx("th",{className:"p-2.5",children:l==="zh"?"教师":"Teacher"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:F.map((p,W)=>e.jsxs("tr",{className:`hover:bg-violet-50/30 transition-colors cursor-pointer ${k.has(W)?"bg-violet-50/20":"opacity-50"}`,onClick:()=>ee(W),children:[e.jsx("td",{className:"p-2.5 text-center",children:e.jsx("input",{type:"checkbox",checked:k.has(W),onChange:()=>ee(W),onClick:te=>te.stopPropagation(),className:"accent-violet-600 cursor-pointer"})}),e.jsx("td",{className:"p-2.5 font-medium",children:e.jsx("span",{className:"inline-block bg-indigo-100 text-indigo-700 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:xe[p.dayOfWeek]||`Day${p.dayOfWeek}`})}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-slate-100 text-slate-700 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:l==="zh"?`第${p.periodNumber}节`:`P${p.periodNumber}`})}),e.jsx("td",{className:"p-2.5 font-semibold text-slate-800",children:p.className||"-"}),e.jsx("td",{className:"p-2.5",children:e.jsx("span",{className:"inline-block bg-amber-100 text-amber-800 px-1.5 py-0.5 rounded-md text-[10px] font-bold",children:p.subject||"-"})}),e.jsx("td",{className:"p-2.5 font-mono text-slate-600",children:p.timeSlot||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:p.location||"-"}),e.jsx("td",{className:"p-2.5 text-slate-600",children:p.teacherName||"-"})]},W))})]})})]}),F.length>0&&e.jsxs("div",{className:"bg-slate-50/50 border border-slate-200 rounded-2xl p-5",children:[e.jsxs("h2",{className:"text-base font-bold text-slate-800 flex items-center gap-2 border-b border-slate-200 pb-3 mb-4",children:[e.jsx(Be,{className:"text-emerald-500 shrink-0",size:18}),l==="zh"?"第三步:确认导入日程":"Step 3: Confirm Import"]}),(()=>{const p=new Date,W=p.getDay(),te=p.getDate()-W+(W===0?-6:1),Y=new Date(p.setDate(te)).toISOString().split("T")[0],de=F.filter((le,K)=>k.has(K)),se=new Set;let M=0;return de.forEach(le=>{he(le.className||"")?M++:le.className&&se.add(le.className.trim())}),e.jsxs("div",{className:"flex flex-col gap-4 mb-4",children:[e.jsxs("div",{className:"p-3.5 bg-indigo-50 border border-indigo-100 rounded-xl text-xs leading-relaxed",children:[e.jsxs("div",{className:"font-semibold text-indigo-900 flex items-center gap-1.5 mb-1.5",children:[e.jsx(Ae,{size:14,className:"text-indigo-600 animate-pulse"}),l==="zh"?"智能自动匹配规则":"Intelligent Auto-Mapping"]}),e.jsxs("div",{className:"text-gray-650 space-y-1",children:[e.jsxs("div",{children:["• ",l==="zh"?`本周起始日期(周一):${Y}`:`Week Start Date (Monday): ${Y}`]}),e.jsxs("div",{children:["• ",l==="zh"?"班级匹配:系统将根据识别到的班级名称自动导入至系统中对应班级。若班级不存在,将自动创建。":"Class Matching: System will automatically import entries into matched classes or create new classes on the fly."]})]})]}),e.jsxs("div",{className:"text-xs",children:[e.jsx("div",{className:"font-semibold text-gray-700",children:l==="zh"?`已选择 ${de.length} 条记录,其中 ${M} 条可直接匹配到系统班级。`:`${de.length} entries selected, ${M} matched existing classes.`}),se.size>0&&e.jsxs("div",{className:"mt-2 p-2.5 bg-violet-50 border border-violet-200 text-violet-800 rounded-lg leading-relaxed",children:["💡 ",l==="zh"?`以下识别出的班级在系统中暂不存在,导入时将自动创建:${Array.from(se).join(", ")}`:`The following recognized classes do not exist and will be automatically created on import: ${Array.from(se).join(", ")}.`]})]})]})})(),e.jsx("button",{onClick:$,disabled:ne||k.size===0,className:"w-full bg-emerald-600 hover:bg-emerald-700 disabled:bg-slate-300 text-white font-bold text-xs py-2.5 rounded-xl cursor-pointer transition-all flex items-center justify-center gap-2 shadow-sm disabled:cursor-not-allowed",children:ne?e.jsxs(e.Fragment,{children:[e.jsx(Ie,{className:"animate-spin",size:14}),l==="zh"?"正在导入...":"Importing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ds,{size:14}),l==="zh"?`确认导入选中的 ${k.size} 条课程`:`Import ${k.size} Selected Entries`]})})]})]}),bs=({classes:l,lessons:b,lang:r,onSchedulesUpdated:N,onClassesUpdated:T})=>{const[v,I]=c.useState("view"),[G,B]=c.useState("week"),P=t=>{const s=new Date(t.getTime()),n=s.getDay(),i=s.getDate()-n+(n===0?-6:1),o=new Date(s.setDate(i));return o.setHours(0,0,0,0),o},[U,C]=c.useState(()=>P(new Date)),E=t=>{const s=new Date(t.getTime()+5184e5),n=i=>{const o=i.getFullYear(),d=String(i.getMonth()+1).padStart(2,"0"),u=String(i.getDate()).padStart(2,"0");return`${o}-${d}-${u}`};return`${n(t)} ~ ${n(s)}`},[Q,O]=c.useState(null),[ae,X]=c.useState(""),[L,J]=c.useState("dow"),[F,k]=c.useState(""),[ie,ee]=c.useState({}),[xe,he]=c.useState(!1),[$,ne]=c.useState("all"),[p,W]=c.useState(""),[te,ve]=c.useState("all"),[Y,de]=c.useState([]),[se,M]=c.useState(!1),[le,K]=c.useState(!1),[Pe,ue]=c.useState(!1),[re,V]=c.useState(null),[a,x]=c.useState(""),[h,S]=c.useState(""),[f,j]=c.useState(""),[D,y]=c.useState("09:00 - 10:30"),[g,H]=c.useState("scheduled"),[we,fe]=c.useState(""),[Ee,Ye]=c.useState(""),[Oe,pt]=c.useState(""),[bt,ze]=c.useState(null),[ge,Ke]=c.useState(""),[je,qe]=c.useState(""),[ye,ft]=c.useState("holiday"),[Ze,Qe]=c.useState(""),[gt,Le]=c.useState(null),[Fe,Re]=c.useState(null),[jt,Xe]=c.useState(!1),[yt,Se]=c.useState(0),[Nt,me]=c.useState(""),[Ce,Ne]=c.useState([]),[vt,A]=c.useState(null),[fs,gs]=c.useState(""),[js,ys]=c.useState(""),[wt,Je]=c.useState(!1),[ke,ce]=c.useState(new Set),zt=c.useRef(null),[St,et]=c.useState([]),[tt,Ct]=c.useState(""),st=["08:00 - 09:30","09:45 - 11:15","11:30 - 13:00","13:30 - 15:00","15:15 - 16:45","19:00 - 20:30"],lt=c.useRef(""),rt=c.useRef(""),kt=t=>{try{const s=t.split("-");if(s.length<3)return 1;const n=parseInt(s[0],10),i=parseInt(s[1],10)-1,o=parseInt(s[2],10),u=new Date(n,i,o).getDay();return u===0?7:u}catch{return 1}},oe=async()=>{M(!0);try{let t=[];if($==="all"){const s=await fetch("/api/schedules");s.ok&&(t=await s.json())}else{const s=l.find(n=>n.id===$);if(s){const n=await fetch(`/api/classes/${s.id}/schedules`);n.ok&&(t=await n.json(),t.forEach(i=>{i.class_name=s.name}))}}t.sort((s,n)=>{const i=n.scheduled_date.localeCompare(s.scheduled_date);return i!==0?i:(s.time_slot||"").localeCompare(n.time_slot||"")}),de(t)}catch(t){console.error(t)}finally{M(!1)}};c.useEffect(()=>{const t=l.map(i=>`${i.id}:${i.name}`).join(","),s=t!==lt.current,n=$!==rt.current;l.length>0&&(s||n)&&(lt.current=t,rt.current=$,oe())},[$,l]),c.useEffect(()=>{fetch("/api/ai-providers").then(t=>t.ok?t.json():[]).then(t=>et(Array.isArray(t)?t:[])).catch(()=>et([]))},[]);const $t=async t=>{if(t.preventDefault(),!a||!f){alert(r==="zh"?"请填写所有必填字段":"Please fill all required fields");return}try{const s=await fetch(`/api/classes/${a}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:h,scheduledDate:f,timeSlot:D,status:g,notes:we})});if(s.ok)K(!1),x(""),S(""),j(""),fe(""),H("scheduled"),oe(),N();else{const n=await s.json();alert(n.error||"Failed to schedule")}}catch(s){alert(s.message)}},_t=async t=>{if(t.preventDefault(),!!re)try{const s=re.isRepeating,n=s?`/api/classes/${re.class_id}/schedules`:`/api/classes/${re.class_id}/schedules/${re.id}`,o=await fetch(n,{method:s?"POST":"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:h,scheduledDate:f,timeSlot:D,status:g,notes:we})});if(o.ok)ue(!1),V(null),oe(),N();else{const d=await o.json();alert(d.error||"Failed to update schedule")}}catch(s){alert(s.message)}},Dt=async(t,s,n,i)=>{if(n&&i){if(!confirm(r==="zh"?"该课程是由上周循环生成的。您确定要取消(停课)本周这一天的课程安排吗?":"This is a repeating class. Do you want to cancel (set to Cancelled) this class for this week?"))return;try{const u=Y.find(w=>w.id===t);(await fetch(`/api/classes/${s}/schedules`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:u?.lesson_id||"",scheduledDate:i,timeSlot:u?.time_slot||"",status:"cancelled",notes:r==="zh"?"循环排课取消":"Repeating schedule cancelled"})})).ok?(oe(),N()):alert("Cancel failed")}catch(u){alert(u.message)}return}if(confirm(r==="zh"?"您确定要完全删除该条课表排课记录吗?关联的考勤记录也将一并清除!":"Are you sure you want to completely delete this schedule record? Associated attendance logs will be cleared as well!"))try{(await fetch(`/api/classes/${s}/schedules/${t}`,{method:"DELETE"})).ok?(oe(),N()):alert("Delete failed")}catch(d){alert(d.message)}},Tt=t=>{V(t),x(t.class_id),S(t.lesson_id),j(t.scheduled_date),y(t.time_slot||"09:00 - 10:30"),H(t.status||"scheduled"),fe(t.notes||""),ue(!0)},It=async()=>{if(!ge||!je){alert(r==="zh"?"请选择开始日期和结束日期":"Please select both start and end dates");return}const t=Y.filter(i=>{const o=i.scheduled_date;return o>=ge&&o<=je&&i.status!==ye});if(t.length===0){alert(r==="zh"?"在此日期范围内没有找到可调整的研究课表记录!":"No schedules found in the selected date range to adjust!");return}const s=r==="zh"?`此操作将会把 ${ge} 到 ${je} 之间的共 ${t.length} 个课时记录一键标记为 [${ye==="holiday"?"假日停课":"异常停课"}]。确认执行吗?`:`This will mark ${t.length} active classes between ${ge} and ${je} as [${ye}]. Continue?`;if(!confirm||!confirm(s))return;M(!0);let n=0;try{for(const i of t)(await fetch(`/api/classes/${i.class_id}/schedules/${i.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({lessonId:i.lesson_id,scheduledDate:i.scheduled_date,timeSlot:i.time_slot,status:ye,notes:Ze||(r==="zh"?"假期统一调休":"Holiday adjustments")})})).ok&&n++;alert(r==="zh"?`调整成功!共更新 ${n} 个课表安排。`:`Success! Updated ${n} entries.`),Ke(""),qe(""),Qe(""),oe(),N()}catch(i){alert(i.message)}finally{M(!1)}},We=t=>{if(!t.type.startsWith("image/")){A({type:"error",text:r==="zh"?"请选择图片文件(PNG, JPG, JPEG)":"Please select an image file (PNG, JPG, JPEG)"});return}if(t.size>20*1024*1024){A({type:"error",text:r==="zh"?"图片大小不能超过 20MB":"Image size must be under 20MB"});return}const s=new FileReader;s.onload=n=>{const i=n.target?.result;Le(i),Re(i),Ne([]),A(null),ce(new Set)},s.readAsDataURL(t)},At=t=>{const s=t.target.files?.[0];s&&We(s)},Pt=t=>{const s=t.clipboardData?.items;if(s){for(let n=0;n<s.length;n++)if(s[n].type.startsWith("image/")){t.preventDefault();const i=s[n].getAsFile();i&&We(i);return}}},Et=t=>{t.preventDefault(),t.stopPropagation();const s=t.dataTransfer?.files?.[0];s&&s.type.startsWith("image/")&&We(s)};c.useEffect(()=>{if(v!=="ocr_import")return;const t=s=>Pt(s);return document.addEventListener("paste",t),()=>document.removeEventListener("paste",t)},[v,r]);const Ot=async()=>{if(!Fe){A({type:"error",text:r==="zh"?"请先上传课表图片":"Please upload a timetable image first"});return}Xe(!0),Se(0),me(r==="zh"?"📤 正在上传并优化图像...":"📤 Uploading and optimizing image..."),A({type:"info",text:r==="zh"?"🔍 AI 正在分析课表图片,请稍候...":"🔍 AI is analyzing the timetable image, please wait..."}),Ne([]);let t=0;const s=setInterval(()=>{t+=Math.random()*6+1,t>=95&&(t=95,clearInterval(s)),Se(Math.round(t)),t<20?me(r==="zh"?"📤 正在上传并优化图像...":"📤 Uploading and optimizing image..."):t<50?me(r==="zh"?"🧠 AI 正在分析表格排版与单元格...":"🧠 AI analyzing table layout..."):t<75?me(r==="zh"?"📝 提取课程、班级及教师信息...":"📝 Extracting lesson and teacher info..."):me(r==="zh"?"🔮 正在进行最终数据格式校验...":"🔮 Verifying data formats...")},400);try{const n=await fetch("/api/timetable/ocr",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageBase64:Fe,lang:r,providerId:tt||void 0})}),i=await n.text();let o;try{o=JSON.parse(i)}catch{throw new Error(r==="zh"?`服务端返回了无效响应: ${i.substring(0,150)}`:`Server returned invalid response: ${i.substring(0,150)}`)}if(!n.ok||!o.success)throw new Error(o.error||"OCR recognition failed");clearInterval(s),Se(100),me(r==="zh"?"✅ 识别成功,正在载入结果...":"✅ Recognition complete, loading results..."),o.entries&&o.entries.length>0?(Ne(o.entries),ce(new Set(o.entries.map((d,u)=>u))),A({type:"success",text:r==="zh"?`✅ 识别成功!共检测到 ${o.entries.length} 节课程安排,请审核后导入。`:`✅ Success! Detected ${o.entries.length} class entries. Review and import below.`})):A({type:"error",text:r==="zh"?"未能从图片中识别出课程信息,请尝试更清晰的图片。":"No class entries detected. Try a clearer image."})}catch(n){clearInterval(s),Se(0),A({type:"error",text:`${r==="zh"?"AI 识别失败:":"OCR Failed: "}${n.message}`})}finally{Xe(!1)}},Lt=(t,s)=>{if(!s)return"";try{const n=new Date(s);let i=Number(t);isNaN(i)&&typeof t=="string"&&(t.includes("一")||t.includes("1")||t.includes("Mon")?i=1:t.includes("二")||t.includes("2")||t.includes("Tue")?i=2:t.includes("三")||t.includes("3")||t.includes("Wed")?i=3:t.includes("四")||t.includes("4")||t.includes("Thu")?i=4:t.includes("五")||t.includes("5")||t.includes("Fri")?i=5:t.includes("六")||t.includes("6")||t.includes("Sat")?i=6:(t.includes("日")||t.includes("天")||t.includes("7")||t.includes("Sun"))&&(i=7)),(isNaN(i)||i<1||i>7)&&(i=1);const o=i-1,d=new Date(n);return d.setDate(n.getDate()+o),d.toISOString().split("T")[0]}catch(n){return console.error("Failed to convert day of week to date:",n),s}},at=t=>{if(!t)return null;const s=t.replace(/\s+/g,"").trim(),n=s.match(/(\d+)(?:班)?\)?$/)||s.match(/\((\d+)\)/);if(!n)return null;const i=n[1];let o="",d=0;if(s.startsWith("高")?(o="高",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:(s.includes("三")||s.includes("3"))&&(d=3)):s.startsWith("初")?(o="初",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:(s.includes("三")||s.includes("3"))&&(d=3)):s.startsWith("七")||s.startsWith("7")?(o="初",d=1):s.startsWith("八")||s.startsWith("8")?(o="初",d=2):s.startsWith("九")||s.startsWith("9")?(o="初",d=3):s.startsWith("小")?(o="小",s.includes("一")||s.includes("1")?d=1:s.includes("二")||s.includes("2")?d=2:s.includes("三")||s.includes("3")?d=3:s.includes("四")||s.includes("4")?d=4:s.includes("五")||s.includes("5")?d=5:(s.includes("六")||s.includes("6"))&&(d=6)):s.startsWith("一")||s.startsWith("1")?(o="小",d=1):s.startsWith("二")||s.startsWith("2")?(o="小",d=2):s.startsWith("三")||s.startsWith("3")?(o="小",d=3):s.startsWith("四")||s.startsWith("4")?(o="小",d=4):s.startsWith("五")||s.startsWith("5")?(o="小",d=5):(s.startsWith("六")||s.startsWith("6"))&&(o="小",d=6),!o||d===0)return null;const u=new Date,R=u.getFullYear(),pe=(u.getMonth()+1>=9?R:R-1)-(d-1);return`${o}${pe}级${i}班`},Ft=t=>{if(!t)return null;const s=t.match(/^(初|高|小|小学)(\d{4})级(\d+)班$/);if(!s)return null;const n=s[1],i=parseInt(s[2],10),o=s[3],d=new Date,u=d.getFullYear(),R=d.getMonth()+1;let w=u-i;if(R>=9&&(w+=1),w<1)return r==="zh"?"未开学":"Not Started";if(w>(n==="高"||n==="初"?3:6))return r==="zh"?"已毕业":"Graduated";const q=r==="zh"&&["","一","二","三","四","五","六","七","八","九","十"][w]||w.toString();return`${n}${q}(${o})`},Ge=t=>{const s=Ft(t);return s?`${t} (${s})`:t},Me=t=>{if(!t)return null;const s=t.replace(/\s+/g,"").toLowerCase();let n=l.find(i=>{if(!i||!i.name)return!1;const o=i.name.replace(/\s+/g,"").toLowerCase();return o===s||o.includes(s)||s.includes(o)});if(!n){const i=s.replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");n=l.find(o=>{if(!o||!o.name)return!1;const d=o.name.replace(/\s+/g,"").toLowerCase().replace(/[^0-9a-zA-Z\u4e00-\u9fa5]/g,"");return d===i||d.includes(i)||i.includes(d)})}return n||null},Rt=async()=>{try{if(ke.size===0){A({type:"error",text:r==="zh"?"请至少选择一条课程记录":"Please select at least one entry"});return}const t={1:"08:00 - 08:40",2:"08:50 - 09:30",3:"10:00 - 10:40",4:"10:50 - 11:30",5:"11:40 - 12:15",6:"14:20 - 15:00",7:"15:10 - 15:50",8:"16:20 - 17:00",9:"19:00 - 20:30"},s=new Date,n=s.getDay(),i=s.getDate()-n+(n===0?-6:1),d=new Date(s.setDate(i)).toISOString().split("T")[0];Je(!0),A(null);const u=Ce.filter((m,_)=>ke.has(_)),R=new Set;u.forEach(m=>{if(m.className){const _=at(m.className)||m.className.trim();Me(_)||R.add(_)}});const w={};R.size>0&&(await Promise.all(Array.from(R).map(async m=>{try{const _=await fetch("/api/classes",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:m,description:"OCR自动生成规范班级"})});if(_.ok){const Z=await _.json();Z.success&&Z.id&&(w[m]=Z.id)}}catch(_){console.error(`Failed to dynamically create class ${m}:`,_)}})),T&&T());const z={},pe=new Set;u.forEach(m=>{const _=Lt(m.dayOfWeek||1,d),Z=m.timeSlot||t[m.periodNumber]||"09:00 - 10:30",$e=m.className?at(m.className)||m.className.trim():"",it=Me($e),_e=it?it.id:$e?w[$e]:null;if(!_e){m.className&&pe.add(m.className);return}const Ut=b.find(Yt=>{const He=Yt.title.toLowerCase(),nt=$e.toLowerCase(),Kt=(m.subject||"").toLowerCase();return He.includes(nt)||He.includes(Kt)||nt.includes(He)});z[_e]||(z[_e]=[]),z[_e].push({lessonId:Ut?.id||"",scheduledDate:_,timeSlot:Z,status:"scheduled",notes:`${m.className||""} ${m.subject||""} ${m.location?"教室:"+m.location:""} ${m.teacherName?"教师:"+m.teacherName:""}`.trim()})});const q=Object.keys(z);if(q.length===0){A({type:"error",text:r==="zh"?"无法导入:没有解析出任何有效的班级名称。":"Could not match or create any classes for import."}),Je(!1);return}let Ve=0;await Promise.all(q.map(async m=>{const _=await fetch(`/api/classes/${m}/schedules/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({schedules:z[m]})});if(_.ok){const Z=await _.json();Ve+=Z.count||0}else{const Z=await _.json().catch(()=>({}));throw new Error(Z.error||`Failed to import schedules for class ${m}`)}})),Ne([]),ce(new Set),Le(null),Re(null);let ot=r==="zh"?`🎉 导入成功!共写入 ${Ve} 节课时安排。`:`🎉 Import successful! Saved ${Ve} schedule entries.`;if(R.size>0){const m=Array.from(R).filter(_=>w[_]);m.length>0&&(ot+=r==="zh"?`(自动创建并规范了新班级:${m.join(", ")})`:` (Automatically created classes: ${m.join(", ")})`)}A({type:"success",text:ot}),oe(),N()}catch(t){console.error("OCR Import Error:",t),alert(`${r==="zh"?"导入出错提示:":"Import error alert: "}${t.message}`),A({type:"error",text:`${r==="zh"?"导入失败:":"Import failed: "}${t.message}`})}finally{Je(!1)}},Jt=t=>{ce(s=>{const n=new Set(s);return n.has(t)?n.delete(t):n.add(t),n})},Wt=()=>{ke.size===Ce.length?ce(new Set):ce(new Set(Ce.map((t,s)=>s)))},Gt=r==="zh"?["","周一","周二","周三","周四","周五","周六","周日"]:["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],Mt=()=>{const t=["Date","Class Name","Lesson Title","Time Slot","Status","Notes","Class ID","Lesson ID"],s=Y.map(d=>[d.scheduled_date,d.class_name||"",d.lesson_title||"",d.time_slot||"",d.status||"scheduled",d.notes||"",d.class_id,d.lesson_id]),n="data:text/csv;charset=utf-8,"+[t.join(","),...s.map(d=>d.map(u=>`"${String(u).replace(/"/g,'""')}"`).join(","))].join(`
5
5
  `),i=encodeURI(n),o=document.createElement("a");o.setAttribute("href",i),o.setAttribute("download",`timetable_export_${new Date().toISOString().split("T")[0]}.csv`),document.body.appendChild(o),o.click(),document.body.removeChild(o)},Vt=()=>{const t="data:text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(Y,null,2)),s=document.createElement("a");s.setAttribute("href",t),s.setAttribute("download",`timetable_export_${new Date().toISOString().split("T")[0]}.json`),document.body.appendChild(s),s.click(),document.body.removeChild(s)},Ht=async()=>{if(!Oe){ze({type:"error",text:r==="zh"?"请先选择需要导入的班级!":"Please select a Class first!"});return}if(!Ee.trim()){ze({type:"error",text:r==="zh"?"请在框中输入或粘贴数据内容":"Please paste formatting data content!"});return}try{let t=[];const s=Ee.trim();if(s.startsWith("[")){const o=JSON.parse(s);t=Array.isArray(o)?o:[o]}else{const o=s.split(`
6
- `).map(u=>u.trim()).filter(Boolean);if(o.length<=1)throw new Error(r==="zh"?"CSV 数据行不足(必须包含表头与内容行)":"Insufficient CSV rows!");const d=o[0].split(",").map(u=>u.trim().toLowerCase().replace(/"/g,""));for(let u=1;u<o.length;u++){const R=o[u].split(",").map(z=>z.trim().replace(/"/g,"")),w={};d.forEach((z,pe)=>{const q=R[pe];z==="date"||z==="scheduled_date"?w.scheduledDate=q:z==="lesson_id"||z==="lesson id"||z==="lesson"?w.lessonId=q:z==="time_slot"||z==="time slot"||z==="time"?w.timeSlot=q:z==="status"?w.status=q:(z==="notes"||z==="note")&&(w.notes=q)}),w.scheduledDate&&t.push(w)}}if(t.length===0)throw new Error(r==="zh"?"未解析到合法的课时数据记录。请保证包含日期字段!":"No valid schedules parsed. Date is required!");const n=t.map(o=>{const d=o.lessonId?b.find(u=>u.id===o.lessonId||u.title.toLowerCase()===o.lessonId.toLowerCase()):null;return{lessonId:d?d.id:"",scheduledDate:o.scheduledDate,timeSlot:o.timeSlot||"09:00 - 10:30",status:o.status||"scheduled",notes:o.notes||""}}),i=await fetch(`/api/classes/${Oe}/schedules/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({schedules:n})});if(i.ok){const o=await i.json();ze({type:"success",text:r==="zh"?`👍 导入成功!共写入 ${o.count} 节课时安排至所选班级。`:`Success! Imported ${o.count} schedules layout.`}),Ye(""),oe(),N()}else{const o=await i.json();throw new Error(o.error||"Batch insert error")}}catch(t){ze({type:"error",text:`${r==="zh"?"导入失败: ":"Import failed: "}${t.message}`})}},Bt=Y.filter(t=>{if($!=="all"&&t.class_id!==$||te!=="all"&&t.status!==te)return!1;if(p.trim()){const s=p.toLowerCase(),n=(t.lesson_title||"").toLowerCase().includes(s),i=(t.class_name||"").toLowerCase().includes(s),o=(t.notes||"").toLowerCase().includes(s);return n||i||o}return!0});return e.jsxs("div",{className:"flex-1 flex flex-col min-h-0 bg-white rounded-2xl border border-gray-200 overflow-hidden shadow-sm font-sans",id:"timetable_manager_container",children:[e.jsxs("div",{className:"p-4 border-b border-gray-100 bg-gray-50/50 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 shrink-0",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-xl font-bold text-gray-800 flex items-center gap-2",children:[e.jsx(cs,{className:"text-indigo-600 animate-pulse",size:22}),r==="zh"?"班级课表中心 & 动态调整":"Timetable Center & Adjustments"]}),e.jsx("p",{className:"text-xs text-gray-400 mt-0.5",children:r==="zh"?"统一管理日常排课,支持节假日批量停课、讲师临时换课、换班及 CSV 导入导出。":"Orchestrate routines schedules, holidays exclusions, and instructors swapping items."})]}),e.jsxs("div",{className:"flex bg-gray-100 p-1 rounded-xl shrink-0 self-start sm:self-auto shadow-inner border border-slate-200/50",children:[e.jsx("button",{onClick:()=>I("view"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="view"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"🗓️ 课表看板":"Schedule Grid"}),e.jsx("button",{onClick:()=>I("adjust"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="adjust"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"🛠️ 临时调休调课":"Holiday Adjusts"}),e.jsx("button",{onClick:()=>I("import_export"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="import_export"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"📥 快速导入导出":"Import / Export"}),e.jsx("button",{onClick:()=>I("ocr_import"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="ocr_import"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"📷 AI 图片识课":"AI Image OCR"})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-5",children:[v==="view"&&e.jsx(hs,{lang:r,viewMode:G,setViewMode:B,selectedClassId:$,setSelectedClassId:ne,statusFilter:te,setStatusFilter:ve,searchQuery:p,setSearchQuery:W,classes:l,getClassDisplayName:Ge,loading:se,filteredSchedules:Bt,currentWeekMonday:U,setCurrentWeekMonday:C,showWeekend:xe,setShowWeekend:he,dateOverrides:ie,setDateOverrides:ee,setOverridingDateKey:O,setOverrideMode:J,setOverrideTargetDow:k,setOverrideTargetDate:Q,openEditModal:Tt,handleDeleteSchedule:Dt,getDayOfWeekIndex:kt,getMonday:P,getWeekRangeString:E,setFormClassId:x,setFormLessonId:S,setFormDate:j,setFormStatus:H,setFormNotes:fe,setIsAddOpen:K}),v==="adjust"&&e.jsx(us,{lang:r,holStartDate:ge,setHolStartDate:Ke,holEndDate:je,setHolEndDate:qe,holType:ye,setHolType:ft,holNotes:Ze,setHolNotes:Xe,handleBatchHolidayAdjustment:It,loading:se}),v==="import_export"&&e.jsx(ms,{lang:r,classes:l,getClassDisplayName:Ge,handleExportCSV:Mt,handleExportJSON:Vt,importClassId:Oe,setImportClassId:pt,csvText:Ee,setCsvText:Ye,importMessage:bt,handleImportData:Ht}),v==="ocr_import"&&e.jsx(ps,{lang:r,ocrProviderId:tt,setOcrProviderId:Ct,aiProviders:St,ocrFileInputRef:zt,handleOcrDrop:Et,handleOcrImageSelect:At,ocrImagePreview:gt,setOcrImagePreview:Le,setOcrImageBase64:Re,setOcrEntries:Ne,setOcrMessage:A,setOcrSelectedEntries:ce,ocrImageBase64:Fe,ocrLoading:jt,handleOcrRecognize:Ot,ocrProgressStatus:Nt,ocrProgress:yt,ocrMessage:vt,ocrEntries:Ce,ocrSelectedEntries:ke,toggleAllOcrEntries:Wt,toggleOcrEntry:Jt,dayNames:Gt,findMatchedClass:Me,handleOcrImport:Rt,ocrImporting:wt})]}),le&&e.jsx("div",{className:"fixed inset-0 z-55 bg-black/40 backdrop-blur-xs flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white border border-slate-200 shadow-2xl rounded-2xl w-full max-w-md overflow-hidden animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border-b border-slate-100 flex items-center justify-between",children:[e.jsxs("h3",{className:"font-bold text-gray-800 flex items-center gap-1.5 text-sm xl:text-base",children:[e.jsx(De,{className:"text-indigo-600",size:18}),r==="zh"?"为班级排排定课次":"Arrange Timetable Scheduled"]}),e.jsx("button",{onClick:()=>K(!1),className:"text-gray-400 hover:text-gray-600 p-1 rounded-full hover:bg-gray-150 transition-colors",children:e.jsx(be,{size:16})})]}),e.jsxs("form",{onSubmit:$t,className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"选择对应上课班级 *":"Target Class *"}),e.jsxs("select",{title:"Form Class ID",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden",value:a,onChange:t=>x(t.target.value),required:!0,children:[e.jsx("option",{value:"",children:r==="zh"?"请选择班级...":"Select Class..."}),l.map(t=>e.jsx("option",{value:t.id,children:Ge(t.name)},t.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"对应授课课题 / 课时 (可空,上课时自选)":"Syllabus Lesson (Optional, select during class)"}),e.jsxs("select",{title:"Form Lesson ID",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden rounded-lg",value:h,onChange:t=>S(t.target.value),children:[e.jsx("option",{value:"",children:r==="zh"?"暂不设定内容 (上课时自由选择)":"No fixed content (select during class)"}),b.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"公历排定日期 *":"Scheduled Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:f,onChange:t=>j(t.target.value),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"日常状态":"Daily Status"}),e.jsxs("select",{title:"Form Status",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",value:g,onChange:t=>H(t.target.value),children:[e.jsx("option",{value:"scheduled",children:r==="zh"?"正常授课":"Scheduled"}),e.jsx("option",{value:"cancelled",children:r==="zh"?"停课":"Cancelled"}),e.jsx("option",{value:"holiday",children:r==="zh"?"假期调休":"Holiday"}),e.jsx("option",{value:"swap",children:r==="zh"?"临时授课/换课":"Swapped"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"具体上课时间段":"Class Period / Time Slot"}),e.jsxs("div",{className:"flex gap-1.5 items-center",children:[e.jsx("input",{type:"text",className:"flex-1 border border-gray-200 rounded-lg text-xs p-2 bg-white text-gray-750 focus:outline-hidden",value:D,onChange:t=>y(t.target.value),placeholder:"e.g. 09:00 - 10:30"}),e.jsxs("select",{title:"Preset Time Slot",className:"border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",onChange:t=>{t.target.value&&y(t.target.value)},children:[e.jsx("option",{value:"",children:r==="zh"?"建议课时...":"Presets..."}),st.map(t=>e.jsx("option",{value:t,children:t},t))]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"调课备注说明":"Schedule Notes"}),e.jsx("input",{type:"text",placeholder:r==="zh"?"例如:节假日补课、更替老师讲义,不填则无":"e.g. Substitute instructor lesson outline",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:we,onChange:t=>fe(t.target.value)})]}),e.jsxs("div",{className:"flex justify-end gap-2 border-t border-slate-100 pt-3 mt-4",children:[e.jsx("button",{type:"button",onClick:()=>K(!1),className:"px-3 py-1.5 rounded-lg border text-xs font-medium text-gray-500 hover:bg-gray-150 transition-colors",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{type:"submit",className:"px-4 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold shadow-sm transition-colors",children:r==="zh"?"排定并发布":"Publish & Save"})]})]})]})}),Pe&&re&&e.jsx("div",{className:"fixed inset-0 z-55 bg-black/40 backdrop-blur-xs flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white border border-slate-200 shadow-2xl rounded-2xl w-full max-w-md overflow-hidden animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border-b border-slate-100 flex items-center justify-between",children:[e.jsxs("h3",{className:"font-bold text-gray-800 flex items-center gap-1.5 text-sm xl:text-base",children:[e.jsx(Te,{className:"text-indigo-600",size:18}),r==="zh"?"微调/临时变动排课记录":"Custom Adjust Schedule"]}),e.jsx("button",{onClick:()=>{ue(!1),V(null)},className:"text-gray-400 hover:text-gray-600 p-1 rounded-full hover:bg-gray-150 transition-colors",children:e.jsx(be,{size:16})})]}),e.jsxs("form",{onSubmit:_t,className:"p-4 space-y-4",children:[e.jsxs("div",{className:"p-2.5 bg-indigo-50 border border-indigo-100 rounded-lg text-xs leading-5",children:[e.jsx("div",{className:"font-semibold text-indigo-850",children:r==="zh"?"提示:课表的临时变动将实时更新至今日课程气泡及学生白板客户端。":"Changes will load instantly on students whiteboards and dashboards."}),e.jsxs("div",{className:"text-gray-600 mt-1",children:[r==="zh"?"目标班级:":"Target Class: "," ",e.jsx("span",{className:"font-bold",children:re.class_name})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"换课:关联授课主体 (可空,上课时自选)":"Swap Topic / Lesson (Optional, select during class)"}),e.jsxs("select",{id:"edit_lesson_select",title:"Edit Lesson",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden rounded-lg",value:h,onChange:t=>S(t.target.value),children:[e.jsx("option",{value:"",children:r==="zh"?"暂不设定内容 (上课时自由选择)":"No fixed content (select during class)"}),b.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"换时间:上课日期 *":"Scheduled Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:f,onChange:t=>j(t.target.value),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"临时教务状态":"Ad-hoc Status"}),e.jsxs("select",{id:"edit_status_select",title:"Edit Status",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",value:g,onChange:t=>H(t.target.value),children:[e.jsx("option",{value:"scheduled",children:r==="zh"?"正常授课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:r==="zh"?"临时停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:r==="zh"?"节日假期 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:r==="zh"?"换课/代授课 (Swapped)":"Swapped"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"具体上课时段":"Class Time Slot"}),e.jsxs("div",{className:"flex gap-1.5 items-center",children:[e.jsx("input",{type:"text",className:"flex-1 border border-gray-200 rounded-lg text-xs p-2 bg-white text-gray-750 focus:outline-hidden",value:D,onChange:t=>y(t.target.value),placeholder:"e.g. 09:00 - 10:30"}),e.jsxs("select",{title:"Edit Preset Time",className:"border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",onChange:t=>{t.target.value&&y(t.target.value)},children:[e.jsx("option",{value:"",children:r==="zh"?"建议时段...":"Presets..."}),st.map(t=>e.jsx("option",{value:t,children:t},t))]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"微调备注(说明换课/放假原因)":"Notes/Adjustments Reason"}),e.jsx("input",{type:"text",placeholder:r==="zh"?"例:国庆假停课 / 本课更替为第二节":"Explain reasons of ad-hoc swaps",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:we,onChange:t=>fe(t.target.value)})]}),e.jsxs("div",{className:"flex justify-end gap-2 border-t border-slate-100 pt-3 mt-4",children:[e.jsx("button",{type:"button",onClick:()=>{ue(!1),V(null)},className:"px-3 py-1.5 rounded-lg border text-xs font-medium text-gray-500 hover:bg-gray-150 transition-colors",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{type:"submit",className:"px-4 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold shadow-sm transition-colors",children:r==="zh"?"保存调整":"Apply Adjustment"})]})]})]})}),X&&e.jsx("div",{className:"fixed inset-0 bg-slate-900/40 backdrop-blur-xs flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-white rounded-2xl border border-slate-200 shadow-2xl max-w-sm w-full p-5 flex flex-col gap-4 animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"flex items-center justify-between pb-2 border-b border-slate-100",children:[e.jsxs("h3",{className:"font-bold text-sm text-slate-800 flex items-center gap-1.5",children:[e.jsx(Ue,{size:16,className:"text-amber-500"}),r==="zh"?"临时切换显示课程日期":"Temporarily Override Date"]}),e.jsx("button",{onClick:()=>{O(null),Q(""),k("")},className:"text-slate-400 hover:text-slate-600 hover:bg-slate-50 p-1 rounded-lg transition-colors cursor-pointer",children:e.jsx(be,{size:16})})]}),e.jsxs("div",{className:"text-xs text-slate-500 leading-relaxed",children:[e.jsx("p",{children:r==="zh"?`您正在设置 [${X}] 的课程显示。`:`You are overriding schedules displayed for [${X}].`}),e.jsx("p",{className:"mt-1",children:r==="zh"?"您可以将某一个日期的课临时指定为星期几的常规课表,或者指定为系统内的任意其他具体日期课程。":"Specify a day of the week or another target date to temporarily view its lessons."})]}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-xl",children:[e.jsx("button",{type:"button",onClick:()=>J("dow"),className:`flex-1 text-center py-1.5 text-xs font-bold rounded-lg transition-all cursor-pointer ${L==="dow"?"bg-white text-indigo-700 shadow-3xs":"text-slate-500 hover:text-slate-700"}`,children:r==="zh"?"常规星期几":"Day of Week"}),e.jsx("button",{type:"button",onClick:()=>J("date"),className:`flex-1 text-center py-1.5 text-xs font-bold rounded-lg transition-all cursor-pointer ${L==="date"?"bg-white text-indigo-700 shadow-3xs":"text-slate-500 hover:text-slate-700"}`,children:r==="zh"?"具体日期":"Specific Date"})]}),L==="dow"?e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:r==="zh"?"选择常规星期几 *":"Select Day of Week *"}),e.jsxs("select",{value:F,onChange:t=>k(t.target.value),className:"w-full border border-gray-250 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750 cursor-pointer",children:[e.jsx("option",{value:"",children:r==="zh"?"-- 请选择星期 --":"-- Select Day --"}),e.jsx("option",{value:"1",children:r==="zh"?"星期一":"Monday"}),e.jsx("option",{value:"2",children:r==="zh"?"星期二":"Tuesday"}),e.jsx("option",{value:"3",children:r==="zh"?"星期三":"Wednesday"}),e.jsx("option",{value:"4",children:r==="zh"?"星期四":"Thursday"}),e.jsx("option",{value:"5",children:r==="zh"?"星期五":"Friday"}),e.jsx("option",{value:"6",children:r==="zh"?"星期六":"Saturday"}),e.jsx("option",{value:"7",children:r==="zh"?"星期日":"Sunday"})]})]}):e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:r==="zh"?"选择具体日期 *":"Select Target Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750 cursor-pointer",value:ae,onChange:t=>Q(t.target.value)})]}),e.jsxs("div",{className:"flex gap-2 justify-end pt-2 border-t border-slate-100",children:[e.jsx("button",{onClick:()=>{O(null),Q(""),k("")},className:"px-3.5 py-2 rounded-lg text-xs font-bold text-slate-500 bg-slate-100 hover:bg-slate-200/80 transition-all cursor-pointer",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{onClick:()=>{let t="";if(L==="dow"){if(!F){alert(r==="zh"?"请选择星期几":"Please select a day of the week");return}t=`dow-${F}`}else{if(!ae){alert(r==="zh"?"请选择一个日期":"Please select a date");return}t=ae}ee(s=>({...s,[X]:t})),O(null),Q(""),k("")},className:"px-3.5 py-2 rounded-lg text-xs font-bold text-white bg-indigo-600 hover:bg-indigo-700 shadow-sm transition-all cursor-pointer",children:r==="zh"?"应用切换":"Apply Switch"})]})]})})]})};function ws({classes:l,lessons:b,lang:r,onSchedulesUpdated:N}){return e.jsx("div",{className:"flex-1 overflow-hidden flex flex-col bg-white",id:"teacher_timetable_tab_panel",children:e.jsx(bs,{classes:l,lessons:b,lang:r,onSchedulesUpdated:N})})}export{ws as TimetableView};
6
+ `).map(u=>u.trim()).filter(Boolean);if(o.length<=1)throw new Error(r==="zh"?"CSV 数据行不足(必须包含表头与内容行)":"Insufficient CSV rows!");const d=o[0].split(",").map(u=>u.trim().toLowerCase().replace(/"/g,""));for(let u=1;u<o.length;u++){const R=o[u].split(",").map(z=>z.trim().replace(/"/g,"")),w={};d.forEach((z,pe)=>{const q=R[pe];z==="date"||z==="scheduled_date"?w.scheduledDate=q:z==="lesson_id"||z==="lesson id"||z==="lesson"?w.lessonId=q:z==="time_slot"||z==="time slot"||z==="time"?w.timeSlot=q:z==="status"?w.status=q:(z==="notes"||z==="note")&&(w.notes=q)}),w.scheduledDate&&t.push(w)}}if(t.length===0)throw new Error(r==="zh"?"未解析到合法的课时数据记录。请保证包含日期字段!":"No valid schedules parsed. Date is required!");const n=t.map(o=>{const d=o.lessonId?b.find(u=>u.id===o.lessonId||u.title.toLowerCase()===o.lessonId.toLowerCase()):null;return{lessonId:d?d.id:"",scheduledDate:o.scheduledDate,timeSlot:o.timeSlot||"09:00 - 10:30",status:o.status||"scheduled",notes:o.notes||""}}),i=await fetch(`/api/classes/${Oe}/schedules/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({schedules:n})});if(i.ok){const o=await i.json();ze({type:"success",text:r==="zh"?`👍 导入成功!共写入 ${o.count} 节课时安排至所选班级。`:`Success! Imported ${o.count} schedules layout.`}),Ye(""),oe(),N()}else{const o=await i.json();throw new Error(o.error||"Batch insert error")}}catch(t){ze({type:"error",text:`${r==="zh"?"导入失败: ":"Import failed: "}${t.message}`})}},Bt=Y.filter(t=>{if($!=="all"&&t.class_id!==$||te!=="all"&&t.status!==te)return!1;if(p.trim()){const s=p.toLowerCase(),n=(t.lesson_title||"").toLowerCase().includes(s),i=(t.class_name||"").toLowerCase().includes(s),o=(t.notes||"").toLowerCase().includes(s);return n||i||o}return!0});return e.jsxs("div",{className:"flex-1 flex flex-col min-h-0 bg-white rounded-2xl border border-gray-200 overflow-hidden shadow-sm font-sans",id:"timetable_manager_container",children:[e.jsxs("div",{className:"p-4 border-b border-gray-100 bg-gray-50/50 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 shrink-0",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-xl font-bold text-gray-800 flex items-center gap-2",children:[e.jsx(cs,{className:"text-indigo-600 animate-pulse",size:22}),r==="zh"?"班级课表中心 & 动态调整":"Timetable Center & Adjustments"]}),e.jsx("p",{className:"text-xs text-gray-400 mt-0.5",children:r==="zh"?"统一管理日常排课,支持节假日批量停课、讲师临时换课、换班及 CSV 导入导出。":"Orchestrate routines schedules, holidays exclusions, and instructors swapping items."})]}),e.jsxs("div",{className:"flex bg-gray-100 p-1 rounded-xl shrink-0 self-start sm:self-auto shadow-inner border border-slate-200/50",children:[e.jsx("button",{onClick:()=>I("view"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="view"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"🗓️ 课表看板":"Schedule Grid"}),e.jsx("button",{onClick:()=>I("adjust"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="adjust"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"🛠️ 临时调休调课":"Holiday Adjusts"}),e.jsx("button",{onClick:()=>I("import_export"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="import_export"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"📥 快速导入导出":"Import / Export"}),e.jsx("button",{onClick:()=>I("ocr_import"),className:`px-3 py-1.5 rounded-lg text-xs font-semibold tracking-wide transition-all ${v==="ocr_import"?"bg-white text-indigo-700 shadow-sm":"text-gray-500 hover:text-gray-800"}`,children:r==="zh"?"📷 AI 图片识课":"AI Image OCR"})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-5",children:[v==="view"&&e.jsx(hs,{lang:r,viewMode:G,setViewMode:B,selectedClassId:$,setSelectedClassId:ne,statusFilter:te,setStatusFilter:ve,searchQuery:p,setSearchQuery:W,classes:l,getClassDisplayName:Ge,loading:se,filteredSchedules:Bt,currentWeekMonday:U,setCurrentWeekMonday:C,showWeekend:xe,setShowWeekend:he,dateOverrides:ie,setDateOverrides:ee,setOverridingDateKey:O,setOverrideMode:J,setOverrideTargetDow:k,setOverrideTargetDate:X,openEditModal:Tt,handleDeleteSchedule:Dt,getDayOfWeekIndex:kt,getMonday:P,getWeekRangeString:E,setFormClassId:x,setFormLessonId:S,setFormDate:j,setFormStatus:H,setFormNotes:fe,setIsAddOpen:K}),v==="adjust"&&e.jsx(us,{lang:r,holStartDate:ge,setHolStartDate:Ke,holEndDate:je,setHolEndDate:qe,holType:ye,setHolType:ft,holNotes:Ze,setHolNotes:Qe,handleBatchHolidayAdjustment:It,loading:se}),v==="import_export"&&e.jsx(ms,{lang:r,classes:l,getClassDisplayName:Ge,handleExportCSV:Mt,handleExportJSON:Vt,importClassId:Oe,setImportClassId:pt,csvText:Ee,setCsvText:Ye,importMessage:bt,handleImportData:Ht}),v==="ocr_import"&&e.jsx(ps,{lang:r,ocrProviderId:tt,setOcrProviderId:Ct,aiProviders:St,ocrFileInputRef:zt,handleOcrDrop:Et,handleOcrImageSelect:At,ocrImagePreview:gt,setOcrImagePreview:Le,setOcrImageBase64:Re,setOcrEntries:Ne,setOcrMessage:A,setOcrSelectedEntries:ce,ocrImageBase64:Fe,ocrLoading:jt,handleOcrRecognize:Ot,ocrProgressStatus:Nt,ocrProgress:yt,ocrMessage:vt,ocrEntries:Ce,ocrSelectedEntries:ke,toggleAllOcrEntries:Wt,toggleOcrEntry:Jt,dayNames:Gt,findMatchedClass:Me,handleOcrImport:Rt,ocrImporting:wt})]}),le&&e.jsx("div",{className:"fixed inset-0 z-55 bg-black/40 backdrop-blur-xs flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white border border-slate-200 shadow-2xl rounded-2xl w-full max-w-md overflow-hidden animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border-b border-slate-100 flex items-center justify-between",children:[e.jsxs("h3",{className:"font-bold text-gray-800 flex items-center gap-1.5 text-sm xl:text-base",children:[e.jsx(De,{className:"text-indigo-600",size:18}),r==="zh"?"为班级排排定课次":"Arrange Timetable Scheduled"]}),e.jsx("button",{onClick:()=>K(!1),className:"text-gray-400 hover:text-gray-600 p-1 rounded-full hover:bg-gray-150 transition-colors",children:e.jsx(be,{size:16})})]}),e.jsxs("form",{onSubmit:$t,className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"选择对应上课班级 *":"Target Class *"}),e.jsxs("select",{title:"Form Class ID",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden",value:a,onChange:t=>x(t.target.value),required:!0,children:[e.jsx("option",{value:"",children:r==="zh"?"请选择班级...":"Select Class..."}),l.map(t=>e.jsx("option",{value:t.id,children:Ge(t.name)},t.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"对应授课课题 / 课时 (可空,上课时自选)":"Syllabus Lesson (Optional, select during class)"}),e.jsxs("select",{title:"Form Lesson ID",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden rounded-lg",value:h,onChange:t=>S(t.target.value),children:[e.jsx("option",{value:"",children:r==="zh"?"暂不设定内容 (上课时自由选择)":"No fixed content (select during class)"}),b.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"公历排定日期 *":"Scheduled Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:f,onChange:t=>j(t.target.value),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"日常状态":"Daily Status"}),e.jsxs("select",{title:"Form Status",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",value:g,onChange:t=>H(t.target.value),children:[e.jsx("option",{value:"scheduled",children:r==="zh"?"正常授课":"Scheduled"}),e.jsx("option",{value:"cancelled",children:r==="zh"?"停课":"Cancelled"}),e.jsx("option",{value:"holiday",children:r==="zh"?"假期调休":"Holiday"}),e.jsx("option",{value:"swap",children:r==="zh"?"临时授课/换课":"Swapped"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"具体上课时间段":"Class Period / Time Slot"}),e.jsxs("div",{className:"flex gap-1.5 items-center",children:[e.jsx("input",{type:"text",className:"flex-1 border border-gray-200 rounded-lg text-xs p-2 bg-white text-gray-750 focus:outline-hidden",value:D,onChange:t=>y(t.target.value),placeholder:"e.g. 09:00 - 10:30"}),e.jsxs("select",{title:"Preset Time Slot",className:"border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",onChange:t=>{t.target.value&&y(t.target.value)},children:[e.jsx("option",{value:"",children:r==="zh"?"建议课时...":"Presets..."}),st.map(t=>e.jsx("option",{value:t,children:t},t))]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"调课备注说明":"Schedule Notes"}),e.jsx("input",{type:"text",placeholder:r==="zh"?"例如:节假日补课、更替老师讲义,不填则无":"e.g. Substitute instructor lesson outline",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:we,onChange:t=>fe(t.target.value)})]}),e.jsxs("div",{className:"flex justify-end gap-2 border-t border-slate-100 pt-3 mt-4",children:[e.jsx("button",{type:"button",onClick:()=>K(!1),className:"px-3 py-1.5 rounded-lg border text-xs font-medium text-gray-500 hover:bg-gray-150 transition-colors",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{type:"submit",className:"px-4 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold shadow-sm transition-colors",children:r==="zh"?"排定并发布":"Publish & Save"})]})]})]})}),Pe&&re&&e.jsx("div",{className:"fixed inset-0 z-55 bg-black/40 backdrop-blur-xs flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white border border-slate-200 shadow-2xl rounded-2xl w-full max-w-md overflow-hidden animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"p-4 bg-slate-50 border-b border-slate-100 flex items-center justify-between",children:[e.jsxs("h3",{className:"font-bold text-gray-800 flex items-center gap-1.5 text-sm xl:text-base",children:[e.jsx(Te,{className:"text-indigo-600",size:18}),r==="zh"?"微调/临时变动排课记录":"Custom Adjust Schedule"]}),e.jsx("button",{onClick:()=>{ue(!1),V(null)},className:"text-gray-400 hover:text-gray-600 p-1 rounded-full hover:bg-gray-150 transition-colors",children:e.jsx(be,{size:16})})]}),e.jsxs("form",{onSubmit:_t,className:"p-4 space-y-4",children:[e.jsxs("div",{className:"p-2.5 bg-indigo-50 border border-indigo-100 rounded-lg text-xs leading-5",children:[e.jsx("div",{className:"font-semibold text-indigo-850",children:r==="zh"?"提示:课表的临时变动将实时更新至今日课程气泡及学生白板客户端。":"Changes will load instantly on students whiteboards and dashboards."}),e.jsxs("div",{className:"text-gray-600 mt-1",children:[r==="zh"?"目标班级:":"Target Class: "," ",e.jsx("span",{className:"font-bold",children:re.class_name})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"换课:关联授课主体 (可空,上课时自选)":"Swap Topic / Lesson (Optional, select during class)"}),e.jsxs("select",{id:"edit_lesson_select",title:"Edit Lesson",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white select-none cursor-pointer focus:outline-hidden rounded-lg",value:h,onChange:t=>S(t.target.value),children:[e.jsx("option",{value:"",children:r==="zh"?"暂不设定内容 (上课时自由选择)":"No fixed content (select during class)"}),b.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"换时间:上课日期 *":"Scheduled Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:f,onChange:t=>j(t.target.value),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"临时教务状态":"Ad-hoc Status"}),e.jsxs("select",{id:"edit_status_select",title:"Edit Status",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",value:g,onChange:t=>H(t.target.value),children:[e.jsx("option",{value:"scheduled",children:r==="zh"?"正常授课 (Scheduled)":"Scheduled"}),e.jsx("option",{value:"cancelled",children:r==="zh"?"临时停课 (Cancelled)":"Cancelled"}),e.jsx("option",{value:"holiday",children:r==="zh"?"节日假期 (Holiday)":"Holiday"}),e.jsx("option",{value:"swap",children:r==="zh"?"换课/代授课 (Swapped)":"Swapped"})]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"具体上课时段":"Class Time Slot"}),e.jsxs("div",{className:"flex gap-1.5 items-center",children:[e.jsx("input",{type:"text",className:"flex-1 border border-gray-200 rounded-lg text-xs p-2 bg-white text-gray-750 focus:outline-hidden",value:D,onChange:t=>y(t.target.value),placeholder:"e.g. 09:00 - 10:30"}),e.jsxs("select",{title:"Edit Preset Time",className:"border border-gray-250 text-xs p-2 rounded-lg bg-white cursor-pointer focus:outline-hidden",onChange:t=>{t.target.value&&y(t.target.value)},children:[e.jsx("option",{value:"",children:r==="zh"?"建议时段...":"Presets..."}),st.map(t=>e.jsx("option",{value:t,children:t},t))]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-gray-700 mb-1",children:r==="zh"?"微调备注(说明换课/放假原因)":"Notes/Adjustments Reason"}),e.jsx("input",{type:"text",placeholder:r==="zh"?"例:国庆假停课 / 本课更替为第二节":"Explain reasons of ad-hoc swaps",className:"w-full border border-gray-250 text-xs p-2 rounded-lg bg-white focus:outline-hidden",value:we,onChange:t=>fe(t.target.value)})]}),e.jsxs("div",{className:"flex justify-end gap-2 border-t border-slate-100 pt-3 mt-4",children:[e.jsx("button",{type:"button",onClick:()=>{ue(!1),V(null)},className:"px-3 py-1.5 rounded-lg border text-xs font-medium text-gray-500 hover:bg-gray-150 transition-colors",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{type:"submit",className:"px-4 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold shadow-sm transition-colors",children:r==="zh"?"保存调整":"Apply Adjustment"})]})]})]})}),Q&&e.jsx("div",{className:"fixed inset-0 bg-slate-900/40 backdrop-blur-xs flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-white rounded-2xl border border-slate-200 shadow-2xl max-w-sm w-full p-5 flex flex-col gap-4 animate-in fade-in zoom-in duration-150",children:[e.jsxs("div",{className:"flex items-center justify-between pb-2 border-b border-slate-100",children:[e.jsxs("h3",{className:"font-bold text-sm text-slate-800 flex items-center gap-1.5",children:[e.jsx(Ue,{size:16,className:"text-amber-500"}),r==="zh"?"临时切换显示课程日期":"Temporarily Override Date"]}),e.jsx("button",{onClick:()=>{O(null),X(""),k("")},className:"text-slate-400 hover:text-slate-600 hover:bg-slate-50 p-1 rounded-lg transition-colors cursor-pointer",children:e.jsx(be,{size:16})})]}),e.jsxs("div",{className:"text-xs text-slate-500 leading-relaxed",children:[e.jsx("p",{children:r==="zh"?`您正在设置 [${Q}] 的课程显示。`:`You are overriding schedules displayed for [${Q}].`}),e.jsx("p",{className:"mt-1",children:r==="zh"?"您可以将某一个日期的课临时指定为星期几的常规课表,或者指定为系统内的任意其他具体日期课程。":"Specify a day of the week or another target date to temporarily view its lessons."})]}),e.jsxs("div",{className:"flex bg-slate-100 p-1 rounded-xl",children:[e.jsx("button",{type:"button",onClick:()=>J("dow"),className:`flex-1 text-center py-1.5 text-xs font-bold rounded-lg transition-all cursor-pointer ${L==="dow"?"bg-white text-indigo-700 shadow-3xs":"text-slate-500 hover:text-slate-700"}`,children:r==="zh"?"常规星期几":"Day of Week"}),e.jsx("button",{type:"button",onClick:()=>J("date"),className:`flex-1 text-center py-1.5 text-xs font-bold rounded-lg transition-all cursor-pointer ${L==="date"?"bg-white text-indigo-700 shadow-3xs":"text-slate-500 hover:text-slate-700"}`,children:r==="zh"?"具体日期":"Specific Date"})]}),L==="dow"?e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:r==="zh"?"选择常规星期几 *":"Select Day of Week *"}),e.jsxs("select",{value:F,onChange:t=>k(t.target.value),className:"w-full border border-gray-250 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750 cursor-pointer",children:[e.jsx("option",{value:"",children:r==="zh"?"-- 请选择星期 --":"-- Select Day --"}),e.jsx("option",{value:"1",children:r==="zh"?"星期一":"Monday"}),e.jsx("option",{value:"2",children:r==="zh"?"星期二":"Tuesday"}),e.jsx("option",{value:"3",children:r==="zh"?"星期三":"Wednesday"}),e.jsx("option",{value:"4",children:r==="zh"?"星期四":"Thursday"}),e.jsx("option",{value:"5",children:r==="zh"?"星期五":"Friday"}),e.jsx("option",{value:"6",children:r==="zh"?"星期六":"Saturday"}),e.jsx("option",{value:"7",children:r==="zh"?"星期日":"Sunday"})]})]}):e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:r==="zh"?"选择具体日期 *":"Select Target Date *"}),e.jsx("input",{type:"date",className:"w-full border border-gray-250 rounded-lg text-xs p-2.5 bg-white focus:outline-hidden focus:ring-1 focus:ring-indigo-500 transition-all font-sans text-gray-750 cursor-pointer",value:ae,onChange:t=>X(t.target.value)})]}),e.jsxs("div",{className:"flex gap-2 justify-end pt-2 border-t border-slate-100",children:[e.jsx("button",{onClick:()=>{O(null),X(""),k("")},className:"px-3.5 py-2 rounded-lg text-xs font-bold text-slate-500 bg-slate-100 hover:bg-slate-200/80 transition-all cursor-pointer",children:r==="zh"?"取消":"Cancel"}),e.jsx("button",{onClick:()=>{let t="";if(L==="dow"){if(!F){alert(r==="zh"?"请选择星期几":"Please select a day of the week");return}t=`dow-${F}`}else{if(!ae){alert(r==="zh"?"请选择一个日期":"Please select a date");return}t=ae}ee(s=>({...s,[Q]:t})),O(null),X(""),k("")},className:"px-3.5 py-2 rounded-lg text-xs font-bold text-white bg-indigo-600 hover:bg-indigo-700 shadow-sm transition-all cursor-pointer",children:r==="zh"?"应用切换":"Apply Switch"})]})]})})]})};function ws({classes:l,lessons:b,lang:r,onSchedulesUpdated:N}){return e.jsx("div",{className:"flex-1 overflow-hidden flex flex-col bg-white",id:"teacher_timetable_tab_panel",children:e.jsx(bs,{classes:l,lessons:b,lang:r,onSchedulesUpdated:N})})}export{ws as TimetableView};