PageSourceSearch

https://seodoon-church-admin.web.app/assets/SystemSettingsPage-2wEXEVnb.js

js seodoon-church-admin.web.app collected 2026-10-03 12:36:37 UTC 24,977 bytes, 2 lines download raw bytes

1import{j as e}from"./vendor-data-Z5doMMu-.js";import{r as o}from"./vendor-react-zNM0AU50.js";import{m as oe,l as de,j as xe,k as S,K as q,u as B}from"./vendor-firebase-Da9KY1q_.js";import{D as L,u as me,i as pe,R as j,d as N,j as z,k as ue,l as F,n as he}from"./index-D1K3lVhu.js";import{a7 as u,U as ge,bm as T,d as be,n as K,E as V,T as ye,X as W,ae as Z,az as X,ak as H,bn as J,g as fe,a as je,j as Ne,S as ee,bk as ve,bl as we,B as ke,bo as Se}from"./vendor-ui-CW5bJ11U.js";import{s as Y}from"./settingsService-BWi-XAI3.js";import"./vendor-charts-08G1rM8P.js";function _e(){const[x,y]=o.useState([]),[E,_]=o.useState(L),[n,h]=o.useState(!0),[$,A]=o.useState(!1),[O,P]=o.useState("roles"),[v,R]=o.useState(""),[g,M]=o.useState(null),[D,t]=o.useState(!1),[b,f]=o.useState(null),{user:m}=me(),p=(m==null?void 0:m.role)==="최고관리자"?"super_admin":"admin",w=(m==null?void 0:m.role)==="최고관리자",Q=pe(p),C=o.useMemo(()=>{const s={};return Object.keys(j).forEach(a=>{s[a]=x.filter(r=>k(r).includes(a))}),s},[x]),se=o.useMemo(()=>x.filter(s=>k(s).length>0).length,[x]),G=o.useMemo(()=>{if(!v.trim()||!b)return[];const s=v.toLowerCase();return x.filter(a=>k(a).includes(b)?!1:a.name.toLowerCase().includes(s)).sort((a,r)=>a.name.localeCompare(r.name,"ko")).slice(0,10)},[x,v,b]);o.useEffect(()=>{te()},[]);function k(s){return s.roles&&s.roles.length>0?s.roles:s.role?[s.role]:[]}async function te(){try{h(!0);const a=(await oe(de(N,"members"))).docs.map(l=>{const c=l.data();return{id:l.id,name:c.name,role:c.role,roles:c.roles}});y(a);const r=await xe(S(N,"system","permissions"));if(r.exists()){const l=r.data(),c={};let i=!1;for(const d of Object.keys(L))l[d]||(i=!0),c[d]={...L[d],...l[d]};if(i)try{await q(S(N,"system","permissions"),c,{merge:!0})}catch(d){console.warn("권한 문서 보강 저장 실패:",d)}_(c)}else await q(S(N,"system","permissions"),L),_(L)}catch(s){console.error("데이터 로드 실패:",s),u.error("데이터를 불러오는데 실패했습니다.")}finally{h(!1)}}async function re(s,a){if(!Q.includes(a)){u.error("이 역할을 부여할 권한이 없습니다.");return}try{const r=x.find(i=>i.id===s);if(!r)return;const c=[...k(r),a];await B(S(N,"members",s),{roles:c,role:null,updated_at:new Date().toISOString()}),y(i=>i.map(d=>d.id===s?{...d,roles:c,role:void 0}:d)),u.success(`${r.name}님에게 ${j[a]} 역할을 부여했습니다.`),R(""),t(!1),f(null)}catch(r){console.error("역할 부여 실패:",r),u.error("역할 부여에 실패했습니다.")}}async function ae(s,a){try{const r=x.find(i=>i.id===s);if(!r)return;const c=k(r).filter(i=>i!==a);await B(S(N,"members",s),{roles:c,role:null,updated_at:new Date().toISOString()}),u.success(`${r.name}님의 ${j[a]} 역할이 제거되었습니다.`),y(i=>i.map(d=>d.id===s?{...d,roles:c,role:void 0}:d))}catch(r){console.error("역할 제거 실패:",r),u.error("역할 제거에 실패했습니다.")}}async function le(s,a){if(confirm(`"${s}" 그룹의 모든 역할을 삭제하시겠습니까?
2해당 그룹의 모든 교인에게서 역할이 제거됩니다.`))try{let r=0;for(const l of a){const c=C[l];for(const i of c){const U=k(i).filter(ie=>ie!==l);await B(S(N,"members",i.id),{roles:U,role:null,updated_at:new Date().toISOString()}),r++}}y(l=>l.map(c=>{const d=k(c).filter(U=>!a.includes(U));return{...c,roles:d,role:void 0}})),u.success(`"${s}" 그룹의 ${r}명의 역할이 제거되었습니다.`)}catch(r){console.error("역할 그룹 삭제 실패:",r),u.error("역할 그룹 삭제에 실패했습니다.")}}function I(s,a,r,l){_(c=>{var i;return{...c,[s]:{...c[s],[a]:{...((i=c[s])==null?void 0:i[a])||{read:!1,write:!1},[r]:l,...r==="read"&&!l?{write:!1}:{}}}}})}async function ne(){if(p!=="super_admin"){u.error("권한 설정은 최고관리자만 변경할 수 있습니다.");return}try{A(!0),await q(S(N,"system","permissions"),E),u.success("권한 설정이 저장되었습니다. 해당 역할의 사용자가 다시 로그인하면 적용됩니다.")}catch(s){console.error("권한 저장 실패:",s),u.error("권한 저장에 실패했습니다.")}finally{A(!1)}}function ce({read:s,write:a}){return a?e.jsx(X,{className:"w-4 h-4 text-green-600"}):s?e.jsx(H,{className:"w-4 h-4 text-blue-500"}):e.jsx(J,{className:"w-4 h-4 text-gray-300"})}return n?e.jsx("div",{className:"flex items-center justify-center h-64",children:e.jsx("div",{className:"text-gray-500 text-[13px]",children:"로딩 중..."})}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-4 gap-3",children:[e.jsxs("div",{className:"bg-white border border-gray-200 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(ge,{className:"w-4 h-4 text-blue-600"}),e.jsx("span",{className:"text-[11px] text-gray-500 font-medium",children:"총 관리자"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900 tabular-nums",children:[se,"명"]})]}),e.jsxs("div",{className:"bg-white border border-gray-200 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(T,{className:"w-4 h-4 text-blue-600"}),e.jsx("span",{className:"text-[11px] text-gray-500 font-medium",children:"역할 종류"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900 tabular-nums",children:[Object.keys(j).length,"개"]})]}),e.jsxs("div",{className:"bg-white border border-gray-200 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(be,{className:"w-4 h-4 text-blue-600"}),e.jsx("span",{className:"text-[11px] text-gray-500 font-medium",children:"메뉴 항목"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900 tabular-nums",children:[Object.keys(z).length,"개"]})]}),e.jsxs("div",{className:"bg-white border border-gray-200 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(K,{className:"w-4 h-4 text-blue-600"}),e.jsx("span",{className:"text-[11px] text-gray-500 font-medium",children:"전체 교인"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900 tabular-nums",children:[x.length,"명"]})]})]}),e.jsxs("div",{className:"bg-white border border-gray-200 rounded-lg shadow-sm",children:[e.jsxs("div",{className:"flex border-b border-gray-200",children:[e.jsxs("button",{onClick:()=>P("roles"),className:`flex-1 px-4 py-3 text-[13px] font-medium transition-colors flex items-center justify-center gap-2 ${O==="roles"?"text-blue-600 border-b-2 border-blue-600 bg-blue-50":"text-gray-600 hover:text-gray-900 hover:bg-gray-50"}`,children:[e.jsx(V,{className:"w-4 h-4"}),"역할 부여"]}),e.jsxs("button",{onClick:()=>P("permissions"),className:`flex-1 px-4 py-3 text-[13px] font-medium transition-colors flex items-center justify-center gap-2 ${O==="permissions"?"text-blue-600 border-b-2 border-blue-600 bg-blue-50":"text-gray-600 hover:text-gray-900 hover:bg-gray-50"}`,children:[e.jsx(T,{className:"w-4 h-4"}),"권한 설정"]})]}),e.jsx("div",{className:"p-4",children:O==="roles"?e.jsx("div",{className:"space-y-4",children:Object.entries(ue).map(([s,a])=>{const r=a.reduce((l,c)=>l+C[c].length,0);return e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("div",{className:"bg-gray-50 px-4 py-2 border-b border-gray-200 flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h3",{className:"text-[13px] font-bold text-gray-700",children:s}),e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-gray-200 text-gray-600",children:[r,"명"]})]}),w&&r>0&&e.jsxs("button",{onClick:()=>le(s,a),className:"text-[11px] px-2 py-1 text-red-600 hover:bg-red-50 rounded transition-colors flex items-center gap-1",title:"그룹 내 모든 역할 삭제",children:[e.jsx(ye,{className:"w-3 h-3"}),"전체삭제"]})]}),e.jsx("div",{className:"divide-y divide-gray-100",children:a.map(l
2=>e.jsxs("div",{className:"p-3 hover:bg-gray-50",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[13px] font-medium text-gray-900",children:j[l]}),e.jsxs("span",{className:`text-[10px] px-1.5 py-0.5 rounded ${C[l].length>0?"bg-green-100 text-green-700":"bg-gray-100 text-gray-500"}`,children:[C[l].length,"명"]})]}),Q.includes(l)&&e.jsxs("button",{onClick:()=>{f(l),t(!0)},className:"text-[11px] px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors flex items-center gap-1",children:[e.jsx(V,{className:"w-3 h-3"}),"추가"]})]}),C[l].length>0&&e.jsx("div",{className:"flex flex-wrap gap-2",children:C[l].map(c=>e.jsxs("div",{className:"flex items-center gap-1 px-2 py-1 bg-blue-50 text-blue-700 rounded-full text-[12px] group",children:[e.jsx("span",{children:c.name}),e.jsx("button",{onClick:()=>ae(c.id,l),className:"w-4 h-4 rounded-full bg-blue-200 hover:bg-red-400 hover:text-white flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",children:e.jsx(W,{className:"w-3 h-3"})})]},c.id))})]},l))})]},s)})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"bg-blue-50 border border-blue-200 rounded-lg px-4 py-3",children:e.jsxs("p",{className:"text-[11px] text-blue-700",children:["각 역할별로 접근할 수 있는 메뉴를 설정합니다. 사이드바 메뉴 구조와 동일합니다.",e.jsx("br",{}),"저장 후 해당 역할의 사용자가 다시 로그인하면 변경된 권한이 적용됩니다."]})}),e.jsx("div",{className:"flex flex-wrap gap-2 pb-4 border-b border-gray-200",children:Object.entries(j).sort((s,a)=>F[a[0]]-F[s[0]]).map(([s,a])=>e.jsxs("button",{onClick:()=>M(s),className:`px-3 py-1.5 rounded-full text-[12px] font-medium transition-all ${g===s?"bg-blue-600 text-white shadow-sm":s==="super_admin"?"bg-red-50 text-red-600 hover:bg-red-100":"bg-gray-100 text-gray-600 hover:bg-gray-200"}`,children:[a,s==="super_admin"&&" (전체권한)"]},s))}),g?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900",children:[j[g]," 권한"]}),e.jsx("p",{className:"text-[11px] text-gray-500 mt-0.5",children:g==="super_admin"?"최고관리자는 모든 메뉴에 전체 권한을 가집니다":"이 역할이 접근할 수 있는 메뉴와 기능을 설정합니다"})]}),g!=="super_admin"&&e.jsxs("button",{onClick:ne,disabled:$||p!=="super_admin",className:"flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-[12px] font-medium disabled:bg-gray-400 disabled:cursor-not-allowed",children:[e.jsx(Z,{className:"w-4 h-4"}),$?"저장 중...":"저장"]})]}),e.jsxs("div",{className:"flex items-center gap-4 text-[11px] text-gray-500 bg-gray-50 rounded-lg px-3 py-2",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(X,{className:"w-3 h-3 text-green-600"})," 읽기+쓰기"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(H,{className:"w-3 h-3 text-blue-500"})," 읽기만"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(J,{className:"w-3 h-3 text-gray-300"})," 권한없음"]})]}),Object.entries(he).map(([s,a])=>e.jsxs("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[e.jsxs("div",{className:"bg-gray-50 px-4 py-2 border-b border-gray-200 flex items-center justify-between",children:[e.jsx("h4",{className:"text-[12px] font-bold text-gray-700",children:s}),e.jsxs("div",{className:"flex gap-6 text-[10px] text-gray-500",children:[e.jsx("span",{className:"w-12 text-center",children:"읽기"}),e.jsx("span",{className:"w-12 text-center",children:"쓰기"})]})]}),e.jsx("div",{className:"divide-y divide-gray-100",children:a.map(r=>{var c;const l=((c=E[g])==null?void 0:c[r])||{read:!1,write:!1};return e.jsxs("div",{className:"px-4 py-2.5 flex items-center justify-between hover:bg-gray-50",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ce,{read:l.read,write:l.write}),e.jsx("span",{className:"text-[12px] text-gray-700",children:z[r]})]}),e.jsxs("div",{className:"flex gap-6",children:[e.jsx("label",{className:"w-12 flex justify-center",children:e.jsx("input",{type:"checkbox",checked:l.read,onChange:i=>I(g,r,"read",i.target.checked),disabled:p!=="super_admin"||g==="super_admin",className:"w-4 h-4 accent-blue-500 cursor-pointer disabled:cursor-not-allowed"})}),e.jsx("label",{className:"w-12 flex justify-center",children:e.jsx("input",{type:"checkbox",checked:l.write,onChange:i=>I(g,r,"write",i.target.checked),disabled:p!=="super_admin"||g==="super_admin"||!l.read,className:"w-4 h-4 accent-green-500 cursor-pointer disabled:cursor-not-allowed disabled:opacity-30"})})]})]},r)})})]},s))]}):e.jsxs("div",{className:"text-center py-12 text-gray-500",children:[e.jsx(T,{className:"w-12 h-12 mx-auto mb-3 text-gray-300"}),e.jsx("p",{className:"text-[13px]",children:"역할을 선택하여 권한을 설정하세요"}),e.jsx("p",{className:"text-[11px] text-gray-400 mt-1",children:"각 역할이 접근할 수 있는 사이드바 메뉴를 설정합니다"})]})]})})]}),D&&b&&e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"bg-white rounded-xl shadow-2xl w-full max-w-md mx-4",children:[e.jsxs("div",{className:"p-4 border-b border-gray-200 flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900",children:[j[b]," 역할 부여"]}),e.jsx("p",{className:"text-[11px] text-gray-500 mt-0.5",children:"교인을 검색하여 역할을 부여하세요"})]}),e.jsx("button",{onClick:()=>{t(!1),f(null),R("")},className:"p-1 hover:bg-gray-100 rounded",children:e.jsx(W,{className:"w-5 h-5 text-gray-500"})})]}),e.jsxs("div",{className:"p-4",children:[e.jsxs("div",{className:"relative",children:[e.jsx(fe,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400"}
2),e.jsx("input",{type:"text",value:v,onChange:s=>R(s.target.value),placeholder:"교인 이름 검색...",className:"w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-[13px]",autoFocus:!0})]}),e.jsx("div",{className:"mt-3 max-h-64 overflow-y-auto",children:v.trim()===""?e.jsx("div",{className:"text-center py-8 text-gray-400 text-[12px]",children:"이름을 입력하여 검색하세요"}):G.length===0?e.jsx("div",{className:"text-center py-8 text-gray-400 text-[12px]",children:"검색 결과가 없습니다"}):e.jsx("div",{className:"space-y-1",children:G.map(s=>e.jsxs("button",{onClick:()=>re(s.id,b),className:"w-full flex items-center justify-between px-3 py-2.5 hover:bg-blue-50 rounded-lg transition-colors group",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center",children:e.jsx(K,{className:"w-4 h-4 text-gray-500"})}),e.jsx("span",{className:"text-[13px] text-gray-900",children:s.name})]}),e.jsx(je,{className:"w-4 h-4 text-gray-300 group-hover:text-blue-600 transition-colors"})]},s.id))})})]})]})})]})}function Me(){const[x,y]=o.useState("permissions");return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-[18px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(Ne,{className:"w-5 h-5 text-blue-600"}),"시스템 설정"]}),e.jsx("p",{className:"text-[12px] text-gray-500 mt-1",children:"역할별 권한 및 시스템 설정을 관리합니다"})]}),e.jsxs("div",{className:"bg-white border border-gray-200 rounded shadow-sm",children:[e.jsxs("div",{className:"flex border-b border-gray-200",children:[e.jsxs("button",{onClick:()=>y("permissions"),className:`flex-1 px-4 py-3 text-[13px] font-medium transition-colors ${x==="permissions"?"text-blue-600 border-b-2 border-blue-600":"text-gray-600 hover:text-gray-900"}`,children:[e.jsx(T,{className:"w-4 h-4 inline mr-2"}),"권한 관리"]}),e.jsxs("button",{onClick:()=>y("app"),className:`flex-1 px-4 py-3 text-[13px] font-medium transition-colors ${x==="app"?"text-blue-600 border-b-2 border-blue-600":"text-gray-600 hover:text-gray-900"}`,children:[e.jsx(ee,{className:"w-4 h-4 inline mr-2"}),"앱 설정"]})]}),e.jsx("div",{className:"p-6",children:x==="permissions"?e.jsx(_e,{}):e.jsx(Re,{})})]})]})}function Re(){var R,g,M,D;const[x,y]=o.useState(!0),[E,_]=o.useState(!1),[n,h]=o.useState({app_name:"서둔동행",app_version:"1.0.0",departments:{youth:!0,baby:!0,yunyen:!0,sonyeon:!0,middle:!0,high:!0,together:!0,elders:!0,men:!0,women:!0,deacons:!0,elders_women:!0},features:{bulletin:!0,qt:!0,prayer:!0,offering:!0,streaming:!0,directory:!0,attendance:!0,new_family:!0,youtube:!0},notifications:{worship_reminder:!0,qt_reminder:!0,event_reminder:!0,notice_reminder:!0,prayer_reminder:!0},theme:{primary_color:"#03C75A",secondary_color:"#233170"},updated_by:"admin"});o.useEffect(()=>{$()},[]);async function $(){try{y(!0);const t=await Y.getAppSettings();t&&h(t)}catch(t){console.error("앱 설정 로딩 실패:",t),u.error("앱 설정을 불러올 수 없습니다")}finally{y(!1)}}async function A(){try{_(!0),await Y.saveAppSettings(n),u.success("앱 설정이 저장되었습니다")}catch{u.error("저장에 실패했습니다")}finally{_(!1)}}if(x)return e.jsx("div",{className:"text-gray-500 text-[13px] text-center py-8",children:"설정을 불러오는 중..."});const O=[{key:"youth",label:"청년부",icon:"👨‍👩‍👧"},{key:"baby",label:"영아부",icon:"👶"},{key:"yunyen",label:"유년부",icon:"🧒"},{key:"sonyeon",label:"소년부",icon:"👦"},{key:"middle",label:"중등부",icon:"🎓"},{key:"high",label:"고등부",icon:"📚"},{key:"together",label:"투게더(장년)",icon:"👨‍👩‍👧‍👦"},{key:"elders",label:"당회",icon:"⛪"},{key:"men",label:"남전도회",icon:"👔"},{key:"women",label:"여전도회",icon:"👗"},{key:"deacons",label:"권사회",icon:"🙏"},{key:"elders_women",label:"여장로회",icon:"✨"}],P=[{key:"bulletin",label:"주보",desc:"주간 주보 열람"},{key:"qt",label:"QT",desc:"매일 말씀묵상"},{key:"prayer",label:"기도요청",desc:"중보기도 나눔"},{key:"offering",label:"헌금",desc:"온라인 헌금 안내"},{key:"streaming",label:"실시간 예배",desc:"유튜브 예배 연결"},{key:"directory",label:"교회 주소록",desc:"성도 연락처 검색"},{key:"attendance",label:"출석체크",desc:"예배 출석 관리"},{key:"new_family",label:"새가족 등록",desc:"새가족 접수"},{key:"youtube",label:"유튜브",desc:"설교 영상 시청"}],v=[{key:"worship_reminder",label:"예배 알림",desc:"예배 시작 30분 전 알림"},{key:"qt_reminder",label:"QT 알림",desc:"매일 오전 6시 QT 알림"},{key:"event_reminder",label:"행사 알림",desc:"교회 행사 사전 알림"},{key:"notice_reminder",label:"공지 알림",desc:"새 공지사항 알림"},{key:"prayer_reminder",label:"기도요청 알림",desc:"새 기도요청 알림"}];return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(ee,{className:"w-4 h-4"}),"앱 정보"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"앱 이름"}),e.jsx("input",{type:"text",value:n.app_name,onChange:t=>h({...n,app_name:t.target.value}),className:"compact-input",placeholder:"서둔동행"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"앱 버전"}),e.jsx("input",{type:"text",value:n.app_version,onChange:t=>h({...n,app_version:t.target.value}),className:"compact-input",placeholder:"1.0.0"})]})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(ve,{className:"w-4 h-4"}),"부서별 활성화"]}),e.jsx("p",{className:"text-[11px] text-gray-500",children:"비활성화된 부서는 앱 메뉴에서 숨겨집니다"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:O.map(({key:t,label:b,icon:f})=>{var m,p;return e.jsxs("label",{className:`flex items-center gap-3 p-3 rounded border cursor-pointer transition-colors ${(m=n.departments)!=null&&m[t]?"bg-green-50 border-green-200":"bg-gray-50 border-gray-200"}`,children:[e.jsx("input",{type:"checkbox",checked:((p=n.departments)==null?void 0:p[t])??!0,onChange:w=>h({...n,departments:{...n.departments,[t]:w.target.checked}}),className:"w-4 h-4 accent-blue-600"}),e.jsx("span",{className:"text-[16px]",children:f}),e.jsx("span",{className:"text-[13px] text-gray-900",children:b})]},t)})})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(we,{className:"w-4 h-4"}),"기능 활성화"]}),e.jsx("p",{className:"text-[11px] text-gray-500",children:"비활성화된 기능은 앱에서 사용할 수 없습니다"}),e.jsx("div",{className:"grid grid-cols-3 gap-2",children:P.map(({key:t,label:b,desc:f})=>{var m,p;return e.jsxs("label",{className:`flex flex-col p-3 rounded border cursor-pointer transition-colors ${(m=n.features)!=null&&m[t]?"bg-green-50 border-green-200":"bg-gray-50 border-gray-200"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("input",{type:"checkbox",checked:((p=n.features)==null?void 0:p[t])??!0,onChange:w=>h({...n,features:{...n.features,[t]:w.target.checked}}),className:"w-4 h-4 accent-blue-600"}),e.jsx("span",{className:"text-[13px] font-medium text-gray-900",children:b})]}),e.jsx("span",{className:"text-[10px] text-gray-500 ml-6",children:f})]},t)})})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(ke,{className:"w-4 h-4"}),"푸시 알림 설정"]}),e.jsx("p",{className:"text-[11px] text-gray-500",children:"전역 푸시 알림 설정 (사용자별로 재설정 가능)"}),e.jsx("div",{className:"space-y-2",children:v.map(({key:t,label:b,desc:f})=>{var m,p;return e.jsxs("label",{className:`flex items-center justify-between p-3 rounded border cursor-pointer transition-colors ${(m=n.notifications)!=null&&m[t]?"bg-green-50 border-green-200":"bg-gray-50 border-gray-200"}`,children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("input",{type:"checkbox",checked:((p=n.notifications)==null?void 0:p[t])??!0,onChange:w=>h({...n,notifications:{...n.notifications,[t]:w.target.checked}}),className:"w-4 h-4 accent-blue-600"}),e.jsx("span",{className:"text-[13px] font-medium text-gray-900",children:b})]}),e.jsx("span",{className:"text-[11px] text-gray-500",children:f})]},t)})})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h3",{className:"text-[14px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(Se,{className:"w-4 h-4"}),"테마 색상"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"주 색상 (네이버 그린)"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"color",value:(R=n.theme)==null?void 0:R.primary_color,onChange:t=>h({...n,theme:{...n.theme,primary_color:t.target.value}}),className:"w-12 h-10 rounded cursor-pointer border border-gray-200"}),e.jsx("input",{type:"text",value:(g=n.theme)==null?void 0:g.primary_color,onChange:t=>h({...n,theme:{...n.theme,primary_color:t.target.value}}),className:"compact-input flex-1",placeholder:"#03C75A"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"보조 색상 (서둔 블루)"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{type:"color",value:(M=n.theme)==null?void 0:M.secondary_color,onChange:t=>h({...n,theme:{...n.theme,secondary_color:t.target.value}}),className:"w-12 h-10 rounded cursor-pointer border border-gray-200"}),e.jsx("input",{type:"text",value:(D=n.theme)==null?void 0:D.secondary_color,onChange:t=>h({...n,theme:{...n.theme,secondary_color:t.target.value}}),className:"compact-input flex-1",placeholder:"#233170"})]})]})]})]}),e.jsx("div",{className:"pt-4 border-t border-gray-200",children:e.jsxs("button",{onClick:A,disabled:E,className:"w-full flex items-center justify-center gap-2 px-4 py-3 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors text-[13px] font-medium disabled:opacity-50",children:[e.jsx(Z,{className:"w-4 h-4"}),E?"저장 중...":"설정 저장"]})})]})}export{Me as SystemSettingsPage};

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.