PageSourceSearch

https://naemo.ai/_next/static/chunks/5238.725c8982a9cecd9a.js

js naemo.ai collected 2026-09-24 14:31:10 UTC 23,705 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[5238],{55238:function(e,t,n){n.r(t),n.d(t,{default:function(){return B}});var s=n(57437),r=n(2265),a=n(27526),i=n(54696),l=n(49717),o=n(67920),c=n(4908),d=n(83008),u=n(70809),x=n(8390),m=n(80726),h=n(46954);function b(){return(0,s.jsxs)("div",{"data-testid":"native-roster-setup-banner",className:"mx-3 mt-3 md:mx-0 md:mt-0 mb-3 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 px-4 py-3 flex items-center gap-3",children:[(0,s.jsx)("p",{className:"flex-1 min-w-0 text-[13px] leading-5 text-zinc-600 dark:text-zinc-300",children:"학급\xb7명단은 PC/웹에서 설정"}),(0,s.jsx)("button",{type:"button","data-testid":"native-roster-setup-cta",onClick:()=>{(0,h.R)(m.hI)},className:"shrink-0 h-9 px-3 rounded-xl bg-[#007AFF] dark:bg-[#2883DE] text-white text-[13px] font-medium hover:opacity-90 transition-opacity",children:"웹에서 설정하기"})]})}var p=n(9244),f=n(39561),v=n(15563),g=n(32489),z=n(45007),w=n(60850),k=n(79205);let y=(0,k.Z)("UtensilsCrossed",[["path",{d:"m16 2-2.3 2.3a3 3 0 0 0 0 4.2l1.8 1.8a3 3 0 0 0 4.2 0L22 8",key:"n7qcjb"}],["path",{d:"M15 15 3.3 3.3a4.2 4.2 0 0 0 0 6l7.3 7.3c.7.7 2 .7 2.8 0L15 15Zm0 0 7 7",key:"d0u48b"}],["path",{d:"m2.1 21.8 6.4-6.3",key:"yn04lh"}],["path",{d:"m19 5-7 7",key:"194lzd"}]]),j=(0,k.Z)("NotebookPen",[["path",{d:"M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4",key:"re6nr2"}],["path",{d:"M2 6h4",key:"aawbzj"}],["path",{d:"M2 10h4",key:"l0bgd4"}],["path",{d:"M2 14h4",key:"1gsvsf"}],["path",{d:"M2 18h4",key:"1bu2t1"}],["path",{d:"M18.4 2.6a2.17 2.17 0 0 1 3 3L16 11l-4 1 1-4Z",key:"1dba1m"}]]);var N=n(73247),C=n(51817),S=n(92934);function E(e){let{isOpen:t,onClose:n,onWantSchedule:a}=e,i=(0,r.useRef)(null),[l,o]=(0,r.useState)(""),[c,d]=(0,r.useState)([]),[u,x]=(0,r.useState)(null),[m,h]=(0,r.useState)(!1),[b,p]=(0,r.useState)(!1),[f,v]=(0,r.useState)(null),[z,k]=(0,r.useState)(null),[E,L]=(0,r.useState)(!1),D=parseInt(new Date().toLocaleString("en-US",{timeZone:"Asia/Seoul",hour:"2-digit",hour12:!1}))>=14?"3":"2";(0,r.useEffect)(()=>{t&&(o(""),d([]),x(null),v(null),k(null),L(!1),setTimeout(()=>{var e;return null===(e=i.current)||void 0===e?void 0:e.focus()},80))},[t]),(0,r.useEffect)(()=>{if(!t)return;let e=e=>{"Escape"===e.key&&n()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[t,n]),(0,r.useEffect)(()=>{if(!t||z)return;let e=l.trim();if(e.length<2||u&&e===u.schoolName){d([]);return}let n=setTimeout(async()=>{h(!0);try{let t=await (0,w.R2)(e);d(t.success?t.data:[])}catch(e){d([])}finally{h(!1)}},300);return()=>clearTimeout(n)},[t,l,u,z]);let R=e=>{x(e),o(e.schoolName),d([]),v(null)},M=async()=>{if(u){p(!0),v(null);try{if(!(await (0,w.fk)(u.schoolCode,u.officeCode)).success){v("학교 저장에 실패했어요. 다시 시도해 주세요.");return}window.dispatchEvent(new CustomEvent("school-settings-updated")),L(!0);let e=await (0,w.mK)(u.officeCode,u.schoolCode,D);k(e.success?e.data:[e.error||"급식 정보를 불러오지 못했어요."])}catch(e){v("오류가 발생했어요. 다시 시도해 주세요.")}finally{p(!1),L(!1)}}};if(!t)return null;let Z=null!==z||E;return(0,s.jsx)("div",{className:"modal-viewport z-[120000] flex items-center justify-center bg-black/40 p-4 backdrop-blur-sm dark:bg-black/60",onClick:n,children:(0,s.jsxs)("div",{className:"w-full max-w-sm overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-2xl animate-in zoom-in-95 duration-200 dark:border-zinc-800 dark:bg-zinc-900",onClick:e=>e.stopPropagation(),children:[(0,s.jsxs)("div",{className:"flex items-start justify-between px-7 pb-5 pt-7",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[Z?(0,s.jsx)(y,{size:18,className:"text-zinc-900 dark:text-zinc-100"}):(0,s.jsx)(j,{size:18,className:"text-zinc-900 dark:text-zinc-100"}),(0,s.jsx)("h2",{className:"text-[18px] font-black tracking-tight text-zinc-900 dark:text-white",children:Z?"오늘의 급식":"학교 등록"})]}),(0,s.jsx)("p",{className:"mt-1 text-[13px] text-zinc-500 dark:text-zinc-400",children:Z?null==u?void 0:u.schoolName:"매일 급식 정보를 보여드려요"})]}),(0,s.jsx)("button",{onClick:n,"aria-label":"닫기",className:"rounded-md p-1 text-zinc-400 transition-colors hover:text-zinc-600 dark:hover:text-zinc-300",children:(0,s.jsx)(g.Z,{size:18})})]}),(0,s.jsx)("div",{className:"space-y-3 px-7 pb-7",children:Z?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"min-h-[120px] rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-800/40",children:E?(0,s.jsx)("div",{className:"flex h-[120px] items-center justify-center text-zinc-400",children:(0,s.jsx)(C.Z,{className:"animate-spin"})}):(0,s.jsx)("ul",{className:"space-y-1.5",children:null==z?void 0:z.map((e,t)=>(0,s.jsx)("li",{className:"break-keep text-[14px] font-medium text-zinc-700 dark:text-zinc-200",children:e.trim()},t))})}),!E&&(0,s.jsxs)("div",{className:"flex items-center gap-1.5 pt-1 text-[12px] font-semibold text-zinc-600 dark:text-zinc-400",children:[(0,s.jsx)(S.Z,{size:14,className:"text-zinc-700 dark:text-zinc-300"}),"학교가 등록됐어요. 이제 매일 급식이 표시됩니다."]}),(0,s.jsxs)("div",{className:"space-y-2 pt-2",children:[(0,s.jsx)("button",{onClick:a,className:"school-meal-primary w-full rounded-xl py-2.5 text-[14px] font-bold transition-colors",children:"학사일정도 불러오기"}),(0,s.jsx)("button",{onClick:n,className:"w-full rounded-xl py-2 text-[13px] font-semibold text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-200",children:"나중에 할게요"})]})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"relative",children:[(0,s.jsx)(N.Z,{size:15,className:"pointer-events-none absolute left-3.5 to
1p-1/2 -translate-y-1/2 text-zinc-400"}),(0,s.jsx)("input",{ref:i,type:"text",value:l,onChange:e=>{o(e.target.value),x(null)},placeholder:"학교 이름을 입력하세요",className:"w-full rounded-xl border-2 border-zinc-200 bg-white py-2.5 pl-9 pr-4 text-[14px] text-zinc-900 outline-none transition-colors placeholder:text-zinc-400 focus:border-zinc-900 dark:border-zinc-700 dark:bg-zinc-800/60 dark:text-white dark:placeholder:text-zinc-600 dark:focus:border-zinc-400"}),m&&(0,s.jsx)(C.Z,{size:13,className:"absolute right-3.5 top-1/2 -translate-y-1/2 animate-spin text-zinc-400"})]}),c.length>0&&(0,s.jsx)("div",{className:"max-h-[200px] overflow-y-auto overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700",children:c.map(e=>(0,s.jsxs)("button",{onMouseDown:t=>{t.preventDefault(),R(e)},className:"w-full border-b border-zinc-100 px-4 py-2.5 text-left transition-colors last:border-none hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800",children:[(0,s.jsx)("p",{className:"text-[13px] font-semibold text-zinc-900 dark:text-white",children:e.schoolName}),(0,s.jsx)("p",{className:"mt-0.5 text-[11px] text-zinc-400 dark:text-zinc-500",children:e.address||e.schoolCode})]},"".concat(e.officeCode,"-").concat(e.schoolCode)))}),f&&(0,s.jsx)("p",{className:"text-right text-[12px] text-red-500 dark:text-red-400",children:f}),(0,s.jsx)("button",{onClick:M,disabled:!u||b,className:"school-meal-primary flex w-full items-center justify-center gap-2 rounded-xl py-2.5 text-[14px] font-bold transition-colors",children:b?(0,s.jsx)(C.Z,{size:15,className:"animate-spin"}):(0,s.jsx)(s.Fragment,{children:"오늘의 급식 보기"})})]})})]})})}var L=n(67650);let D="schoolRegisterBannerDismissed";function R(e){let{isGuest:t=!1,hasStudents:n=!1,onImported:a}=e,[i,l]=(0,r.useState)(!1),[o,c]=(0,r.useState)("closed");return((0,r.useEffect)(()=>{if(t||!n){l(!1);return}if(sessionStorage.getItem(D))return;let e=!1,s=async()=>{try{var t;let n=await (0,w.T9)(),s=n.success&&!!(null===(t=n.data)||void 0===t?void 0:t.neisSchoolCode);e||l(!s)}catch(t){e||l(!1)}};s();let r=()=>s();return window.addEventListener("school-settings-updated",r),()=>{e=!0,window.removeEventListener("school-settings-updated",r)}},[t,n]),i||"closed"!==o)?(0,s.jsxs)(s.Fragment,{children:[i&&(0,s.jsx)("div",{className:"fixed bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 z-50 -translate-x-1/2 px-4 animate-in slide-in-from-bottom-4 fade-in duration-300",children:(0,s.jsxs)("div",{className:"flex w-max min-w-[390px] max-w-[calc(100vw-2rem)] items-center gap-3.5 rounded-2xl border border-zinc-300 bg-white px-5 py-3.5 shadow-[0_8px_30px_rgba(0,0,0,0.18)] dark:border-zinc-700 dark:bg-zinc-900 dark:shadow-[0_8px_30px_rgba(0,0,0,0.55)]",children:[(0,s.jsx)("div",{className:"shrink-0 flex items-center justify-center -my-1",children:(0,s.jsx)(z.w,{src:"/lordicons/school.json",size:28,trigger:"loop",originalColors:!0})}),(0,s.jsxs)("p",{className:"text-[13px] leading-snug text-zinc-900 dark:text-zinc-100",children:["학교를 등록하면",(0,s.jsx)("br",{}),(0,s.jsx)("b",{className:"font-bold",children:"오늘의 급식\xb7학사일정"}),"을 볼 수 있어요"]}),(0,s.jsx)("button",{type:"button",onClick:()=>c("meal"),className:"ml-auto shrink-0 whitespace-nowrap rounded-lg bg-blue-600 px-5 py-2 text-[12px] font-extrabold text-white transition-colors hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600",children:"등록"}),(0,s.jsx)("button",{type:"button",onClick:()=>{sessionStorage.setItem(D,"1"),l(!1)},"aria-label":"배너 닫기",className:"shrink-0 rounded-md p-0.5 text-zinc-400 transition-colors hover:text-zinc-600 dark:text-zinc-500 dark:hover:text-zinc-300",children:(0,s.jsx)(g.Z,{size:16})})]})}),(0,s.jsx)(E,{isOpen:"meal"===o,onClose:()=>c("closed"),onWantSchedule:()=>c("schedule")}),(0,s.jsx)(L.k,{isOpen:"schedule"===o,onClose:()=>c("closed"),onImported:e=>{l(!1),null==a||a(e)}})]}):null}var M=n(96214),Z=n(93448),I=n(22606),W=n(98319),A=n(10136),F=n(99397),V=n(40875),T=n(69076),_=n(30401);function H(e){let{className:t,size:n=15}=e;return(0,s.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"
1currentColor",className:t,children:(0,s.jsx)("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M9.25 15c.966 0 1.75.784 1.75 1.75v2.5A1.75 1.75 0 0 1 9.25 21h-4.5A1.75 1.75 0 0 1 3 19.25v-2.5c0-.966.784-1.75 1.75-1.75zm-4.5 1.5a.25.25 0 0 0-.25.25v2.5c0 .138.112.25.25.25h4.5a.25.25 0 0 0 .25-.25v-2.5a.25.25 0 0 0-.25-.25zm14.5-5.5c.966 0 1.75.784 1.75 1.75v6.5A1.75 1.75 0 0 1 19.25 21h-4.5A1.75 1.75 0 0 1 13 19.25v-6.5c0-.966.784-1.75 1.75-1.75zm-4.5 1.5a.25.25 0 0 0-.25.25v6.5c0 .138.112.25.25.25h4.5a.25.25 0 0 0 .25-.25v-6.5a.25.25 0 0 0-.25-.25zM9.252 3A1.75 1.75 0 0 1 11 4.751v6.498A1.75 1.75 0 0 1 9.252 13H4.748A1.75 1.75 0 0 1 3 11.249V4.75C3 3.786 3.78 3 4.748 3zM4.748 4.5a.25.25 0 0 0-.248.251v6.498c0 .14.113.251.248.251h4.504a.25.25 0 0 0 .248-.251V4.75a.25.25 0 0 0-.248-.251zM19.25 3c.966 0 1.75.784 1.75 1.75v2.5A1.75 1.75 0 0 1 19.25 9h-4.5A1.75 1.75 0 0 1 13 7.25v-2.5c0-.966.784-1.75 1.75-1.75zm-4.5 1.5a.25.25 0 0 0-.25.25v2.5c0 .138.112.25.25.25h4.5a.25.25 0 0 0 .25-.25v-2.5a.25.25 0 0 0-.25-.25z"})})}function B(e){let{onNavigateToStudent:t}=e,{data:n}=(0,a.kP)(),{students:m,isLoaded:h}=(0,c.AF)(),z=(0,o.XC)(),{openSettings:w}=(0,u.Y)(),{showToast:k}=(0,W.p)(),y=(0,A.N)(),j=(0,i.Dv)(),N=!!(null==n?void 0:n.user)||(0,i.YY)(),[C,S]=(0,r.useState)(!1),E=(0,I.Ln)(e=>e.layouts),D=(0,I.Ln)(e=>e.visibleWidgets),B=(0,I.Ln)(e=>e.setConfig),[O,P]=(0,r.useState)(E),[U,X]=(0,r.useState)(D),[Y,G]=(0,r.useState)(!1),[J,q]=(0,r.useState)(!1),[K,Q]=(0,r.useState)(!1),$=(0,r.useRef)(null),[ee,et]=(0,r.useState)(!1),[en,es]=(0,r.useState)("my"),[er,ea]=(0,r.useState)(""),ei=(0,r.useRef)(null),el=(0,r.useRef)(null),eo=(0,r.useRef)(""),[ec,ed]=(0,r.useState)({}),[eu,ex]=(0,r.useState)([]),[em,eh]=(0,r.useState)([]),[eb,ep]=(0,r.useState)([]),[ef,ev]=(0,r.useState)([]),[eg,ez]=(0,r.useState)(null),[ew,ek]=(0,r.useState)([]),[ey,ej]=(0,r.useState)(!1),eN=(0,f.g)(),eC=(0,v.a8)({nativeShell:(0,p.I)(),previewQuery:"1"===new URLSearchParams(window.location.search).get("previewRosterWizard")}),eS=!!localStorage.getItem("rosterWizardCompleted"),eE=(0,v.vh)({nativeShell:eN,isGuest:j,studentCount:m.length,rosterWizardCompleted:eS}),eL=(0,r.useMemo)(()=>j?ew:m.filter(e=>"담임 학급"===e.homeClassId),[m,j,ew]),eD=(0,r.useMemo)(()=>{let e=new Date(new Date().toLocaleString("en-US",{timeZone:"Asia/Seoul"})),t=j?new Date("2026-03-12").getDay():e.getDay();return{index:t,key:["sun","mon","tue","wed","thu","fri","sat"][t]}},[j]),eR=(0,r.useRef)(0),eM=(0,r.useRef)(!0);(0,r.useEffect)(()=>(eM.current=!0,()=>{eM.current=!1}),[]);let eZ=(0,I.Ln)(e=>e.initFromData),eI=(0,I.Ln)(e=>e.setLoaded),eW=(0,r.useCallback)(async()=>{if(j){let e=await (0,M.getGuestData)();ek(e.students),eh(e.attendanceRecords),ep(e.roleAssignments),ex(e.scheduleEvents),ev(e.gradeRecords),ed(("my"===en?e.teacherTimetable:e.classTimetable)||{});return}let e=(0,Z.RJ)(),t=new Date(new Date().toLocaleString("en-US",{timeZone:"Asia/Seoul"}));t.setMonth(t.getMonth()+3);let n=(0,Z.FB)(t);try{let t=await (0,d.X)("getDashboardData",{startDate:e,endDate:n},z);if(t.success&&t.data){let{attendance:e,schedules:n,teacherTimetable:s,classTimetable:r,rolesTimetable:a,memo:i,students:l,gradeRecords:o=[],schoolInfo:c,dashboardConfig:d}=t.data;eM.current||console.warn("[DashboardView] Received valid data but component unmounted. Allowing state update to prevent stale UI on remount."),eh(null!=e?e:[]),ex(n),ea(i),eo.current=i,ed("my"===en?s:r),ev(o),c&&ez(c),I.Ln.getState().isLoaded||(d?eZ(d.layouts,d.visibleWidgets,d.widgetConfig||void 0):eI(!0));let u=[];(null==a?void 0:a.assignments)&&l.forEach(e=>{let t=a.assignments[e.id];t&&Object.entries(t).forEach(t=>{let[n,s]=t;s&&u.push({id:"".concat(e.id,"-").concat(n),studentId:e.id,studentName:e.name,role:s.toString()})})}),ep(u)}else t.success||"Session Expired"!==t.message||(console.warn("[DashboardView] Session still not recognized by server. Retrying one last time in 1s..."),setTimeout(eW,1e3))}catch(e){eM.current&&console.error("Dashboard data load failed",e)}},[j,en,z,eZ,eI]);(0,r.useEffect)(()=>{let e=!0,t=()=>{e&&(eR.current=Date.now(),eW())};t();let n=()=>{"visible"===document.visibilityState&&(Date.now()-eR.current<6e4||t())};return window.addEventListener("visibilitychange",n),window.addEventListener("focus",n),()=>{e=!1,window.removeEventListener("visibilitychange",n),window.removeEventListener("focus",n)}},[eW]),(0,r.useEffect)(()=>
1{if(!ee||!h)return;let e=(0,p.I)()||eN;if(e){ej(!1);return}(0,v.sg)({nativeShell:e,isGuest:j,hasSession:!!(null==n?void 0:n.user),studentCount:m.length,rosterWizardCompleted:!!localStorage.getItem("rosterWizardCompleted"),wizardInProgress:!!(0,v.Ys)()})&&ej(!0)},[ee,h,j,null==n?void 0:n.user,m.length,eN]);let[eA,eF]=(0,r.useState)(null),eV=(0,r.useCallback)(e=>{eF(e),eW()},[eW]),eT=(0,r.useCallback)(async e=>{N&&e!==eo.current&&(await (0,d.X)("saveDashboardMemo",{content:e},z)).success&&(eo.current=e)},[N,z]);(0,r.useEffect)(()=>()=>{ei.current&&clearTimeout(ei.current)},[]),(0,r.useEffect)(()=>{if(j){let e=localStorage.getItem("dashboard-memo");e&&(ea(e),eo.current=e)}},[j]);let e_=(0,r.useMemo)(()=>{let e=j?"2026-03-12":(0,Z.RJ)(),t=em.filter(t=>{let n=t.endDate||t.date;return e>=t.date&&e<=n});return{absent:t.filter(e=>"결석"===e.type).length,late:t.filter(e=>"지각"===e.type).length,early:t.filter(e=>"조퇴"===e.type).length,passing:t.filter(e=>"결과"===e.type).length}},[em,j]),eH=(0,r.useCallback)(()=>{if(window.innerWidth<768){w("dashboard-layout");return}P(E),X(D),G(!1),S(!0)},[w,E,D]),eB=(0,r.useCallback)(async()=>{(!Y||await y({title:"대시보드 편집을 취소할까요?",description:"저장하지 않은 변경사항은 모두 취소됩니다.",confirmLabel:"취소하고 나가기",cancelLabel:"계속 편집",tone:"default"}))&&(P(E),X(D),G(!1),S(!1),Q(!1))},[Y,y,E,D]),eO=(0,r.useCallback)(async()=>{await y({title:"기본 설정으로 되돌릴까요?",description:"위젯 구성 및 배치가 기본 상태로 돌아갑니다.",confirmLabel:"되돌리기",tone:"default"})&&(P(I.Gj),X(I.h4),G(!0))},[y]),eP=(0,r.useCallback)(e=>{X(t=>t.filter(t=>t!==e)),G(!0);let t=I.DV[e];k("".concat((null==t?void 0:t.label)||e," 위젯이 숨겨졌습니다."),"info")},[k]),eU=(0,r.useCallback)(e=>{X(t=>t.includes(e)?t:[...t,e]),P(t=>{let n={...t},s=I.DV[e];return["lg","md","sm"].forEach(t=>{let r=n[t]?[...n[t]]:[];if(!r.some(t=>t.i===e)&&s){let t=r.reduce((e,t)=>Math.max(e,(t.y||0)+(t.h||0)),0);r.push({i:e,x:0,y:t,w:s.defaultW,h:s.defaultH,minW:s.minW,minH:s.minH,maxW:s.maxW,maxH:s.maxH})}n[t]=r}),n}),G(!0),Q(!1);let t=I.DV[e];k("".concat((null==t?void 0:t.label)||e," 위젯이 추가되었습니다."),"success")},[k]),eX=(0,r.useCallback)(e=>{P(e),G(!0)},[]),eY=(0,r.useCallback)(async()=>{q(!0);try{if(j){B(O,U),G(!1),S(!1),Q(!1),k("체험 모드에서는 현재 브라우저에 임시 저장되었습니다.","info");return}let e=await (0,d.X)("saveDashboardConfig",{layouts:O,visibleWidgets:U},z);if(!e.success){k(e.error||"저장에 실패했습니다. 다시 시도해주세요.","error");return}B(O,U),G(!1),S(!1),Q(!1),k("대시보드 배치가 성공적으로 저장되었습니다.","success")}catch(e){console.error("Failed to save dashboard config:",e),k("저장 중 오류가 발생했습니다.","error")}finally{q(!1)}},[j,O,U,z,B,k]);(0,r.useEffect)(()=>{if(!C||!Y)return;let e=e=>{e.preventDefault(),e.returnValue=""};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[C,Y]),(0,r.useEffect)(()=>{if(!C)return;let e=e=>{"Escape"===e.key&&(K?Q(!1):eB())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[C,K,eB]),(0,r.useEffect)(()=>{if(!K)return;let e=e=>{$.current&&!$.current.contains(e.target)&&Q(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[K]);let eG=(0,r.useMemo)(()=>{let e=new Set(U);return Object.keys(I.DV).filter(t=>!e.has(t)).map(e=>I.DV[e])},[U]),eJ=(0,r.useCallback)(e=>{window.dispatchEvent(new CustomEvent("navigate-view",{detail:e}))},[]);return((0,r.useEffect)(()=>{et(!0)},[]),ee)?(0,s.jsxs)("div",{className:"h-full bg-[#FBFBF9] md:bg-zinc-50 dark:bg-black md:p-4 p-0 overflow-y-auto custom-scrollbar","data-pull-scroll":!0,children:[(0,s.jsxs)("div",{className:"mx-auto w-full min-h-full",children:[eE&&(0,s.jsx)(b,{}),C&&(0,s.jsxs)("div",{className:"sticky top-1.5 z-50 hidden md:flex items-center justify-between bg-white/95 dark:bg-[#18181b]/95 backdrop-blur-md border border-zinc-200 dark:border-[#27272a] shadow-lg rounded-2xl px-4 py-2 mx-auto max-w-2xl -mt-1.5 mb-3.5 animate-in fade-in slide-in-from-top-2 duration-200",children:[(0,s.jsx)("div",{className:"flex items-center gap-2",children:(0,s.jsxs)("div",{className:"relative",ref:$,children:[(0,s.jsxs)("button",{type:"button",onClick:()=>Q(e=>!e),className:"flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors border border-zinc-200 dark:border-zinc-700 cursor-pointer",children:[(0,s.jsx)(F.Z,{size:13,className:"text-blue-500"}),(0,s.jsx)("span",{children:"위젯 추가"}),(0,s.jsx)(V.Z,{size:12,className:"text-zinc-400"})]}),K&&(0,s.jsxs)("div",{className:"absolute left-0 top-[calc(100%+6px)] z-50 w-60 bg-white dark:bg-[#222225] rounded-xl shadow-xl border border-zinc-200 dark:border-zinc-700 py-1.5 overflow-hidden animate-in fade-in zoom-in-95 duration-150",children:[(0,s.jsx)("div",{className:"px-3 py-1.5 text-[11px] font-semibold text-zinc-400 uppercase tracking-wider",children:"추가 가능한 위젯"}),0===eG.length?(0,s.jsx)("div",{className:"px-3 py-3 text-xs text-zinc-400 text-center",children:"모든 위젯이 추가되어 있습니다."}):(0,s.jsx)("div",{className:"max-h-60 overflow-y-auto custom-scrollbar",children:eG.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>eU(e.id),className:"w-full flex items-center justify-between px-3 py-2 text-xs text-left text-zinc-800 dark:text-zinc-200 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors cursor-pointer",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("span",{className:"font-medium",children:e.label}),(0,s.jsxs)("span",{className:"text-[10px] text-zinc-400 font-mono bg-zinc-100 dark:bg-zinc-800 px-1 py-0.5 rounded",children:[e.defaultW,"\xd7",e.defaultH]})]}),(0,s.jsx)(F.Z,{size:13,className:"text-blue-500 shrink-0"})]},e.id))})]})]})}),(0,s.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,s.jsxs)("button",{type:"button",onClick:eO,className:"flex items-center gap-1 px-2.5 py-1.5 rounded-lg text-xs text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors cursor-pointer",title:"기본 배치로 복원",children:[(0,s.jsx)(T.Z,{size:13}),(0,s.jsx)("span",{className:"hidden sm:inline",children:"초기화"})]}),(0,s.jsxs)("button",{type:"button",onClick:eB,className:"flex items-center gap-1 px-2.5 py-1.5 rounded-lg text-xs text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors cursor-pointer",children:[(0,s.jsx)(g.Z,{size:13}),(0,s.jsx)("span",{children:"취소"})]}),(0,s.jsxs)("button",{type:"button",onClick:eY,disabled:J,className:"flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-semibold bg-[#007AFF] hover:bg-[#0062cc] dark:bg-[#2883DE] dark:hover:bg-[#1f6dbb] text-white shadow-sm transition-colors disabled:opacity-50 cursor-pointer",children:[(0,s.jsx)(_.Z,{size:14}),(0,s.jsx)("span",{children:J?"저장 중...":"저장 완료"})]})]})]}),(0,s.jsx)(R,{isGuest:j,hasStudents:m.length>0,onImported:eV}),(0,s.jsx)(l.Z,{data:{timetableView:en,setTimetableView:es,timetableData:ec,todayInfo:eD,memo:er,onMemoChange:e=>{let t=e.target.value;ea(t),N?(ei.current&&clearTimeout(ei.current),el.current=t,ei.current=setTimeout(()=>{ei.current=null;let e=el.current;el.current=null,null!==e&&eT(e)},700)):localStorage.setItem("dashboard-memo",t)},onMemoBlur:()=>{if(!N||null===el.current)return;ei.current&&(clearTimeout(ei.current),ei.current=null);let e=el.current;el.current=null,eT(e)},scheduleEvents:eu,isGuest:j,attendanceStats:e_,attendanceRecords:em,homeroomStudents:eL,roleAssignments:eb,schoolInfo:eg,onReload:()=>eW(),onNavigateToStudent:t,onOpenSettings:w,onNavigate:eJ},isEditing:C,customLayouts:C?O:void 0,customVisibleWidgets:C?U:void 0,onLayoutChangeOverride:eX,onRemoveWidget:eP}),!C&&(0,s.jsx)("div",{className:"flex justify-center pt-6 pb-12",children:(0,s.jsxs)("button",{type:"button",onClick:eH,className:"flex items-center gap-2 px-5 py-2.5 rounded-xl border border-dashed border-zinc-300 dark:border-zinc-700 bg-white/50 dark:bg-zinc-900/30 text-zinc-500 dark:text-zinc-400 hover:text-blue-600 dar
1k:hover:text-blue-400 hover:border-blue-400 dark:hover:border-blue-500 hover:bg-blue-50/40 dark:hover:bg-blue-950/20 transition-all duration-200 text-xs font-medium group shadow-xs cursor-pointer",children:[(0,s.jsx)(H,{size:15,className:"text-zinc-400 group-hover:text-blue-500 transition-colors"}),(0,s.jsx)("span",{children:"위젯 추가 및 배치 편집"})]})})]}),"number"==typeof eA&&(0,s.jsx)("div",{className:"fixed inset-x-0 bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] z-[120000] flex justify-center",children:(0,s.jsx)(L.h,{count:eA,onClose:()=>eF(null)})}),(0,v.fL)((0,p.I)()||eN)&&(ey||eC)&&(0,s.jsx)(x.V,{onClose:()=>{(0,v.X9)(),ej(!1)},onComplete:()=>{localStorage.setItem("rosterWizardCompleted","true"),(0,v.X9)(),ej(!1)}})]}):null}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.