PageSourceSearch

https://naemo.ai/_next/static/chunks/7597.da4565e0f8867896.js

js naemo.ai collected 2026-10-02 01:15:33 UTC 8,974 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7597],{17597:function(e,r,s){s.r(r),s.d(r,{default:function(){return m}});var c=s(57437),n=s(2265);s(83079);var t=(0,s(12119).$)("c733a24d646ac035805a67f3ca3cd125a7ec2cd1"),a=s(91351);let l=a.Z_().min(1).max(100),i=a.Ry({studentId:l.nullable(),grade:a.Rx().int().min(1).max(3),classNum:a.Rx().int().min(1).max(99),number:a.Rx().int().min(1).max(999),name:a.Z_().trim().min(1).max(60).transform(e=>e.normalize("NFC"))}).strict(),d={spaceId:l,fromYear:a.Rx().int().min(2e3).max(2099),rows:a.IX(i).min(1).max(4e3)};a.VK("action",[a.Ry({action:a.i0("preview"),...d}).strict(),a.Ry({action:a.i0("confirm"),...d,fingerprint:a.Z_().regex(/^[a-f0-9]{64}$/)}).strict()]);var o=s(50647),u=s.n(o);function m(e){let{detail:r,onComplete:s,onBusyChange:a}=e,[l,d]=(0,n.useState)(""),[o,m]=(0,n.useState)(null),[h,x]=(0,n.useState)(!1),[p,j]=(0,n.useState)(""),[f,b]=(0,n.useState)(!1),[g,N]=(0,n.useState)(""),w=(0,n.useRef)(!1),v=(0,n.useId)(),y=r.enrollments.flatMap(e=>{let s=r.classes.find(r=>r.id===e.classId);return s?[{studentId:e.student.id,name:e.student.name,number:e.number,grade:s.grade,classNum:s.classNum}]:[]});async function E(){if(!w.current){w.current=!0,b(!0),null==a||a(!0),N(""),x(!1),m(null);try{let e=function(e,r){if(e.length>4e5)throw Error("학생 명단이 너무 큽니다. 4,000명 이내로 입력해 주세요.");let s=e.trim().split(/\r?\n/).filter(e=>e.trim());if(!e.trim()||s.length>4e3)throw Error("새 학년도 학생 명단을 1~4,000명 입력해 주세요.");let c=s.map((e,s)=>{let c=e.includes("	")?e.split("	").map(e=>e.trim()):e.trim().split(/\s+/);for(;c.length>4&&""===c[c.length-1];)c.pop();if(![4,7].includes(c.length))throw Error("".concat(s+1,"행: 새 학년\xb7반\xb7번호\xb7이름을 입력하고, 재학생은 이전 학년\xb7반\xb7번호도 입력해 주세요."));let[n,t,a,l]=c,d=l.normalize("NFC"),o=null;if(7===c.length){let[e,n,t]=c.slice(4).map(Number);if(![e,n,t].every(e=>Number.isInteger(e)&&e>0))throw Error("".concat(s+1,"행: 이전 학년\xb7반\xb7번호를 모두 입력해 주세요."));let a=r.filter(r=>r.grade===e&&r.classNum===n&&r.number===t&&r.name===d);if(1!==a.length)throw Error("".concat(s+1,"행: 이전 학생 명단에서 이름과 학년\xb7반\xb7번호가 일치하는 학생을 찾지 못했습니다."));o=a[0].studentId}let u=i.safeParse({studentId:o,grade:Number(n),classNum:Number(t),number:Number(a),name:d});if(!u.success)throw Error("".concat(s+1,"행: 학년(1~3)\xb7반(1~99)\xb7번호(1~999)와 이름을 확인해 주세요."));return u.data});if(new Set(c.map(e=>"".concat(e.grade,":").concat(e.classNum,":").concat(e.number))).size!==c.length)throw Error("새 학생 명단에 같은 학년\xb7반\xb7번호가 두 번 있습니다.");let n=c.flatMap(e=>e.studentId?[e.studentId]:[]);if(new Set(n).size!==n.length)throw Error("같은 기존 학생이 새 학생 명단에 두 번 배정되어 있습니다.");return c}(l,y),s=await t({action:"preview",spaceId:r.space.id,fromYear:r.space.currentYear,rows:e});if(!s.success){N(s.error);return}if("preview"===s.data.kind){m({rows:e,preview:s.data.preview});let r=s.data.preview.classes[0];j(r?"".concat(r.grade,":").concat(r.classNum):"")}}catch(e){N(e instanceof Error?e.message:"학생 명단을 확인하지 못했습니다. 다시 시도해 주세요.")}finally{w.current=!1,b(!1),null==a||a(!1)}}}async function I(){if(o&&h&&!w.current){w.current=!0,b(!0),null==a||a(!0),N("");try{let e=await t({action:"confirm",spaceId:r.space.id,fromYear:r.space.currentYear,rows:o.rows,fingerprint:o.preview.fingerprint});if(!e.success){N(e.error),m(null),x(!1);return}"completed"===e.data.kind&&await s()}catch(e){N("결과를 확인하지 못했습니다. 학교 학년도를 새로고침해 확인해 주세요.")}finally{w.current=!1,b(!1),null==a||a(!1)}}}return r.me.operator?(0,c.jsxs)("details",{className:"".concat(u().section," ").concat(u().yearSection),children:[(0,c.jsx)("summary",{children:"새 학년도 준비"}),(0,c.jsxs)("p",{children:[r.space.currentYear,"학년도 학생 명단을 마치고 ",r.space.currentYear+1,"학년도를 시작합니다. 반이 바뀌어도 기존 학생을 연결하면 과거 성적이 이어집니다."]}),(0,c.jsx)("p",{className:u().note,children:"학교 관리자 역할은 다음 학년도에도 유지됩니다. 담임 등 학년도별 역할은 종료되므로, 전환 후 구성원에서 새 역할을 지정하세요."}),(0,c.jsxs)("form",{className:u().form,onSubmit:e=>{e.preventDefault(),E()},children:[(0,c.jsxs)("label",{children:["새 학년도 학생 명단",(0,c.jsx)("textarea",{rows:9,maxLength:4e5,disabled:f,value:l,onCh
1ange:e=>{d(e.target.value),m(null),x(!1)},placeholder:"새 학년  새 반  새 번호  이름  이전 학년  이전 반  이전 번호\n2  3  1  김민수  1  1  5\n1  1  1  이서연"})]}),(0,c.jsx)("p",{className:u().note,children:"엑셀 열을 탭으로 구분해 붙여 넣으세요. 재학생은 이전 학년\xb7반\xb7번호까지 총 7열, 신입\xb7전입생은 새 학년\xb7반\xb7번호\xb7이름 4열입니다. 이름만으로 기존 학생을 연결하지 않습니다."}),(0,c.jsx)("button",{className:u().secondary,type:"submit",disabled:f||!l.trim(),children:f?"처리 중":"학생 명단 미리보기"})]}),g&&(0,c.jsx)("p",{role:"alert",className:u().error,children:g}),o&&(0,c.jsxs)("div",{className:u().yearReview,children:[(0,c.jsxs)("h3",{children:[o.preview.nextYear,"학년도 반 배정 확인"]}),(0,c.jsxs)("p",{children:["기존 학생 ",o.preview.existingCount,"명 연결 \xb7 새 학생 ",o.preview.newCount,"명 등록"]}),(0,c.jsxs)("table",{className:u().table,children:[(0,c.jsx)("thead",{children:(0,c.jsxs)("tr",{children:[(0,c.jsx)("th",{scope:"col",children:"새 학급"}),(0,c.jsx)("th",{scope:"col",children:"학생 수"})]})}),(0,c.jsx)("tbody",{children:o.preview.classes.map(e=>(0,c.jsxs)("tr",{children:[(0,c.jsxs)("td",{children:[e.grade,"학년 ",e.classNum,"반"]}),(0,c.jsxs)("td",{children:[e.students,"명"]})]},"".concat(e.grade,":").concat(e.classNum)))})]}),(0,c.jsxs)("div",{className:u().form,children:[(0,c.jsx)("label",{htmlFor:v,children:"학생별 확인할 학급"}),(0,c.jsx)("select",{id:v,value:p,onChange:e=>j(e.target.value),children:o.preview.classes.map(e=>(0,c.jsxs)("option",{value:"".concat(e.grade,":").concat(e.classNum),children:[e.grade,"학년 ",e.classNum,"반"]},"".concat(e.grade,":").concat(e.classNum)))})]}),(0,c.jsx)("div",{className:u().yearExcluded,children:(0,c.jsxs)("table",{className:u().table,children:[(0,c.jsx)("thead",{children:(0,c.jsxs)("tr",{children:[(0,c.jsx)("th",{scope:"col",children:"번호"}),(0,c.jsx)("th",{scope:"col",children:"이름"}),(0,c.jsx)("th",{scope:"col",children:"자료 연결"})]})}),(0,c.jsx)("tbody",{children:o.rows.filter(e=>"".concat(e.grade,":").concat(e.classNum)===p).map(e=>(0,c.jsxs)("tr",{children:[(0,c.jsx)("td",{children:e.number}),(0,c.jsx)("td",{children:e.name}),(0,c.jsx)("td",{children:e.studentId?"기존 학생":"새 학생"})]},e.number))})]})}),o.preview.possibleDuplicates.length>0&&(0,c.jsxs)("div",{className:u().error,children:[(0,c.jsx)("p",{children:"기존 학생 명단에 같은 이름이 있지만 새 학생으로 입력한 항목이 있습니다. 재학생이면 이전 학년\xb7반\xb7번호를 추가해 다시 확인하세요."}),(0,c.jsx)("ul",{children:o.preview.possibleDuplicates.map(e=>(0,c.jsxs)("li",{children:[e.grade,"학년 ",e.classNum,"반 ",e.number,"번 ",e.name]},"".concat(e.grade,":").concat(e.classNum,":").concat(e.number)))})]}),(0,c.jsxs)("h3",{children:["새 학생 명단에 없는 학생 ",o.preview.excluded.length,"명"]}),(0,c.jsx)("p",{className:u().note,children:"졸업\xb7전출 학생뿐 아니라 누락된 재학생이 없는지 확인하세요. 이 학생들의 기존 학교 자료는 삭제되지 않습니다."}),o.preview.excluded.length>0&&(0,c.jsx)("div",{className:u().yearExcluded,children:(0,c.jsxs)("table",{className:u().table,children:[(0,c.jsx)("thead",{children:(0,c.jsxs)("tr",{children:[(0,c.jsx)("th",{scope:"col",children:"이전 학급"}),(0,c.jsx)("th",{scope:"col",children:"번호"}),(0,c.jsx)("th",{scope:"col",children:"이름"})]})}),(0,c.jsx)("tbody",{children:o.preview.excluded.map((e,r)=>(0,c.jsxs)("tr",{children:[(0,c.jsxs)("td",{children:[e.grade,"학년 ",e.classNum,"반"]}),(0,c.jsx)("td",{children:e.number}),(0,c.jsx)("td",{children:e.name})]},r))})]})}),(0,c.jsxs)("p",{className:u().note,children:["현재 담당 ",o.preview.endedAssignments,"건 종료"]}),(0,c.jsxs)("label",{className:u().checkbox,children:[(0,c.jsx)("input",{type:"checkbox",checked:h,disabled:f,onChange:e=>x(e.target.checked)}),"새 반 배정과 제외 학생을 확인했으며, 현재 담당을 종료합니다."]}),(0,c.jsxs)("button",{className:u().primary,disabled:f||!h,onClick:()=>void I(),children:[o.preview.nextYear,"학년도 시작하기"]})]})]}):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.