PageSourceSearch

https://teacherss.kr/assets/BoardWritePage-Cn_cCw9o.js

js teacherss.kr collected 2026-10-02 02:01:42 UTC 9,625 bytes, 2 lines download raw bytes

1import{m as $e,k as Fe,p as Te,r,n as ze,j as t}from"./vendor-react-D4NFYCVY.js";import{p as Be}from"./purify.es-Bc-0F0ao.js";import{u as Ee,ac as Le,bt as Re,bu as Ue,bv as _e,B as v,h as Oe,bb as ne,ax as re,_ as Me,$ as We,a0 as Ve,a1 as qe,a2 as Ge,a3 as He,a4 as Xe,a5 as Ye,aX as f,aY as oe,aZ as ie,t as x,a_ as P,a$ as j}from"./index-Bo7vBx4r.js";import{S as le}from"./switch-C4rXSf0k.js";import{L as ce}from"./label-B3SoQVvX.js";import{S as de,a as me,b as ue,c as pe,d as k}from"./select-tgHeBxeb.js";import{u as Ke}from"./useApplications-DFYlhptl.js";import{T as Ze}from"./TiptapEditor-DsWqh4i0.js";import{B as Je}from"./index-CvjPjAR0.js";import{A as Qe}from"./arrow-left-BQUWkU7y.js";import{P as et}from"./paperclip-C5o16iKb.js";import"./vendor-data-DiuZHwsT.js";import"./vendor-state-mPENyaSF.js";import"./vendor-firebase-BXtaSaVx.js";import"./vendor-ui-DW-ZtMoV.js";import"./vendor-utils-CBGDym6X.js";import"./vendor-motion-LReuCgk7.js";import"./vendor-tiptap-DOlczfgE.js";import"./roleSeed-C1Nlu43P.js";import"./teachingDisplay-CMk_gGdr.js";import"./yearRoleWriter-DzpUnKmW.js";import"./browser-DDvdGHJx.js";import"./input-D7jdUXkC.js";import"./undo-2-CIcJZn-D.js";import"./redo-2-BJ0ZxVQD.js";import"./minus-CbQRaQ5S.js";import"./image-plus-BDk4ozoj.js";import"./table-CyiS8DXI.js";const tt={ALLOWED_TAGS:["p","br","strong","em","u","s","h2","h3","ul","ol","li","blockquote","hr","a","img","table","thead","tbody","tr","th","td","span","mark"],ALLOWED_ATTR:["href","src","alt","style","class","target","rel","colspan","rowspan","width","height"]};function Dt(){var ee;const{id:b}=$e(),O=Fe(),he=Te(),{user:D,tenant:$,isAdmin:F,teacherProfile:m,memberships:xe}=Ee(),i=$==null?void 0:$.id,c=!!b,T=xe.find(e=>e.tenantId===i),ge=(m==null?void 0:m.id)||(T==null?void 0:T.teacherProfileId)||"",fe=m?Le(m):(D==null?void 0:D.name)||(F?"관리자":""),je=F||!!(m!=null&&m.fixedManagerPosition),{data:be=[]}=Ke(i),Ne=[...new Set(be.filter(e=>e.type==="manager").map(e=>e.name+(e.name.endsWith("부")?"":"부")))],[w,M]=r.useState(""),[A,z]=r.useState(""),S=(ee=he.state)==null?void 0:ee.tab,[B,W]=r.useState(S&&S!=="all"&&S!=="collect"?S:"notice"),[E,V]=r.useState("none"),[q,G]=r.useState(!1),[H,X]=r.useState(!1),[C,Y]=r.useState(!1),[L,l]=r.useState(!1),[N,K]=r.useState([]),[g,Z]=r.useState([]),I=r.useRef(null),[y,J]=r.useState([]),{data:a}=Re(i,c?b:""),ve=Ue(),we=_e();r.useEffect(()=>{if(a&&c){if(M(a.title),a.contentType!=="html"){const e=a.content.split(`
2`).map(s=>`<p>${s||"<br>"}</p>`).join("");z(e)}else z(a.content);W(a.tab||"general"),V(a.department||"none"),G(a.isPinned),X(a.isAnnouncement),Z(a.attachments||[]),J(a.inlineImages||[])}},[a,c]);const Ae=async e=>{if(!i)throw new Error("tenantId required");const s=`tenants/${i}/board/images/${Date.now()}_${e.name}`,d=f(j,s);await oe(d,e);const o=await ie(d);return J(U=>[...U,{storagePath:s,url:o}]),l(!0),o},Se=e=>{const s=Array.from(e.target.files||[]);if(g.length+N.length+s.length>5){x.error("첨부파일은 최대 5개까지 가능합니다");return}for(const o of s)if(o.size>10*1024*1024){x.error(`${o.name}: 10MB 이하 파일만 가능합니다`);return}K(o=>[...o,...s]),l(!0),I.current&&(I.current.value="")},Ce=e=>{K(s=>s.filter((d,o)=>o!==e))},Ie=e=>{Z(s=>s.filter(d=>d.url!==e)),l(!0)},Q=e=>e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(1)}MB`,ye=async()=>{if(!i){x.error("학교 정보를 불러올 수 없습니다");return}if(!w.trim()){x.error("제목을 입력하세요");return}if(!A.trim()||A==="<p></p>"){x.error("내용을 입력하세요");return}Y(!0);try{const e=Be.sanitize(A,tt),s=(n,p)=>p.includes(n)||p.includes(n.replace(/&/g,"&amp;")),d=y.filter(n=>s(n.url,e)),o=y.filter(n=>!s(n.url,e));await Promise.allSettled(o.map(n=>P(f(j,n.storagePath))));const U=c?b:crypto.randomUUID(),te=[];for(const n of N){const p=f(j,`tenants/${i}/board/${U}/${n.name}`);await oe(p,n);const ae=await ie(p);te.push({name:n.name,url:ae,size:n.size,type:n.type})}if(c&&a){const p=(a.attachments||[]).filter(h=>!g.some(_=>_.url===h.url));await Promise.allSettled(p.map(h=>P(f(j,`tenants/${i}/board/${b}/${h.name}`))));const De=(a.inlineImages||[]).filter(h=>!d.some(_=>_.url===h.url));await Promise.allSettled(De.map(h=>P(f(j,h.storagePath))))}const ke=[...g,...te],se={title:w.trim(),content:e,contentType:"html",inlineImages:d,tab:B,department:E==="none"?null:E,category:B,isPinned:q,isAnnouncement:H,attachments:ke};c?await we.mutateAsync({tenantId:i,postId:b,data:se}):await ve.mutateAsync({tenantId:i,data:{...se,authorId:ge,authorName:fe}}),l(!1),O("/app/board"),x.success(c?"게시글이 수정되었습니다":"게시글이 등록되었습니다")}catch{x.error("저장에 실패했습니다")}finally{Y(!1)}},Pe=async()=>{!c&&y.length>0&&await Promise.allSettled(y.map(e=>P(f(j,e.storagePath)))),O("/app/board")},u=ze(({currentLocation:e,nextLocation:s})=>L&&!C&&e.pathname!==s.pathname);r.useEffect(()=>{const e=s=>{L&&s.preventDefault()};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[L]);const R=g.length+N.length;return t.jsxs("div",{className:"flex flex-col min-h-screen bg-background",children:[t.jsxs("div",{className:"sticky top-16 z-10 bg-background border-b px-4 py-2 flex items-center gap-2",children:[t.jsxs(v,{variant:"ghost",size:"sm",onClick:Pe,disabled:C,className:"gap-1 text-muted-foreground",children:[t.jsx(Qe,{className:"w-4 h-4"}),"취소"]}),t.jsx("div",{className:"flex-1"}),t.jsx(v,{size:"sm",onClick:ye,disabled:C||!w.trim(),className:"gap-1",children:C?t.jsxs(t.Fragment,{children:[t.jsx(Oe,{className:"w-4 h-4 animate-spin"}),"저장 중..."]}):c?"수정 완료":"등록"})]}),t.jsxs("div",{className:"flex-1 w-full px-4 sm:px-6 py-6 flex flex-col",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[t.jsxs(de,{value:B,onValueChange:e=>{W(e),l(!0)},children:[t.jsx(me,{className:"w-auto h-7 text-xs gap-1 rounded-full border-border/60 px-3 text-muted-foreground hover:text-foreground",children:t.jsx(ue,{})}),t.jsx(pe,{children:Je.filter(e=>e.id!=="collect"&&e.id!=="all").map(e=>t.jsx(k,{value:e.id,disabled:e.adminOnly&&!je,children:e.label},e.id))})]}),t.jsxs(de,{value:E,onValueChange:e=>{V(e),l(!0)},children:[t.jsx(me,{className:"w-auto h-7 text-xs gap-1 rounded-full border-border/60 px-3 text-muted-foreground hover:text-foreground",children:t.jsx(ue,{placeholder:"부서"})}),t.jsxs(pe,{children:[t.jsx(k,{value:"none",children:"부서 없음"}),Ne.map(e=>t.jsx(k,{value:e,children:e},e)),t.jsx(k,{value:"기타",children:"기타"})]})]})]}),t.jsx("input",{value:w,onChange:e=>{M(e.target.value),l(!0)},placeholder:"제목을 입력하세요",className:"w-full text-2xl sm:text-3xl font-bold bg-transparent outline-none placeholder:text-muted-foreground
2/40 pb-4 border-b border-border/40"}),t.jsxs("div",{className:"pt-4",children:[t.jsx(Ze,{content:A,onChange:e=>{z(e),l(!0)},onImageUpload:Ae,placeholder:"내용을 입력하세요..."}),t.jsxs("div",{className:"flex items-center gap-3 mt-3 flex-wrap",children:[t.jsxs(v,{type:"button",variant:"outline",size:"sm",onClick:()=>{var e;return(e=I.current)==null?void 0:e.click()},disabled:R>=5,className:"gap-1.5 text-sm",children:[t.jsx(et,{className:"w-4 h-4"}),"파일 첨부",R>0&&t.jsxs("span",{className:"text-muted-foreground",children:["(",R,"/5)"]})]}),F&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(le,{id:"isPinned",checked:q,onCheckedChange:e=>{G(e),l(!0)},className:"scale-90"}),t.jsx(ce,{htmlFor:"isPinned",className:"text-xs cursor-pointer text-muted-foreground",children:"고정"})]}),t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(le,{id:"isAnnouncement",checked:H,onCheckedChange:e=>{X(e),l(!0)},className:"scale-90"}),t.jsx(ce,{htmlFor:"isAnnouncement",className:"text-xs cursor-pointer text-muted-foreground",children:"공지"})]})]})]}),t.jsx("input",{ref:I,type:"file",multiple:!0,className:"hidden",onChange:Se}),(g.length>0||N.length>0)&&t.jsxs("ul",{className:"space-y-1 mt-2",children:[g.map(e=>t.jsxs("li",{className:"flex items-center gap-2 text-sm px-3 py-1.5 bg-muted/50 rounded-md",children:[t.jsx(ne,{className:"w-4 h-4 text-muted-foreground shrink-0"}),t.jsx("span",{className:"flex-1 truncate",children:e.name}),t.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:Q(e.size)}),t.jsx(v,{type:"button",variant:"ghost",size:"icon",className:"w-6 h-6 shrink-0",onClick:()=>Ie(e.url),children:t.jsx(re,{className:"w-3 h-3"})})]},e.url)),N.map((e,s)=>t.jsxs("li",{className:"flex items-center gap-2 text-sm px-3 py-1.5 bg-muted/50 rounded-md",children:[t.jsx(ne,{className:"w-4 h-4 text-muted-foreground shrink-0"}),t.jsx("span",{className:"flex-1 truncate",children:e.name}),t.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:Q(e.size)}),t.jsx(v,{type:"button",variant:"ghost",size:"icon",className:"w-6 h-6 shrink-0",onClick:()=>Ce(s),children:t.jsx(re,{className:"w-3 h-3"})})]},s))]})]})]}),t.jsx(Me,{open:u.state==="blocked",children:t.jsxs(We,{children:[t.jsxs(Ve,{children:[t.jsx(qe,{children:"작성 중인 내용이 있습니다"}),t.jsx(Ge,{children:"페이지를 나가면 작성 중인 내용이 사라집니다. 정말 나가시겠습니까?"})]}),t.jsxs(He,{children:[t.jsx(Xe,{onClick:()=>{var e;return(e=u.reset)==null?void 0:e.call(u)},children:"계속 작성"}),t.jsx(Ye,{onClick:()=>{var e;return(e=u.proceed)==null?void 0:e.call(u)},className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"나가기"})]})]})})]})}export{Dt as default};

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.