PageSourceSearch

https://seodoon-church-admin.web.app/assets/GuideImagesPage-DyCoj4SN.js

js seodoon-church-admin.web.app collected 2026-10-03 12:36:45 UTC 6,623 bytes, 1 lines download raw bytes

1import{j as e}from"./vendor-data-Z5doMMu-.js";import{r as c}from"./vendor-react-zNM0AU50.js";import{f as N,D as o,S as v,E as g,G as w,J as k}from"./vendor-firebase-Da9KY1q_.js";const R=[{id:"01-home.jpg",name:"홈 화면",description:"앱 첫 화면 (로그인 전)"},{id:"02-login-page.jpg",name:"로그인 페이지",description:"로그인/회원가입 버튼이 보이는 화면"},{id:"03-signup-form.jpg",name:"회원가입 폼",description:"회원가입 정보 입력 화면"},{id:"04-login.jpg",name:"로그인 화면",description:"이메일/비밀번호 입력 화면"},{id:"05-logged-in.jpg",name:"로그인 완료",description:"로그인 후 프로필이 보이는 화면"},{id:"06-home-overview.jpg",name:"홈 화면 전체",description:"홈 화면 전체 구성"},{id:"07-bulletin.jpg",name:"주보",description:"예배 > 주보 화면"},{id:"08-journey.jpg",name:"동행 메뉴",description:"동행 탭 메인 화면"},{id:"09-bible-plan.jpg",name:"성경읽기 계획",description:"계획 설정 화면"},{id:"10-bible-reading.jpg",name:"성경 읽기",description:"성경 본문 읽기 화면"},{id:"11-qt.jpg",name:"QT",description:"QT 탭 화면"},{id:"12-my-meditation.jpg",name:"나의 묵상",description:"묵상 기록 화면"},{id:"13-community.jpg",name:"소통",description:"소통 탭 화면"},{id:"14-gallery.jpg",name:"갤러리",description:"갤러리 화면"},{id:"15-profile.jpg",name:"나의 정보",description:"프로필 화면"}],C=()=>{const[r,m]=c.useState([]),[j,u]=c.useState(!0),[x,p]=c.useState(null),d=N();c.useEffect(()=>{f()},[]);const f=async()=>{u(!0);try{const s=o(d,"guide");let l=[];try{l=(await v(s)).items.map(n=>n.name)}catch{}const a=await Promise.all(R.map(async t=>{const n=l.includes(t.id);let i=null;if(n)try{i=await g(o(d,`guide/${t.id}`))}catch{}return{...t,url:i,uploaded:n&&i!==null}}));m(a)}catch(s){console.error("이미지 로드 실패:",s)}finally{u(!1)}},b=async(s,l)=>{p(s);try{const a=o(d,`guide/${s}`);await w(a,l);const t=await g(a);m(n=>n.map(i=>i.id===s?{...i,url:t,uploaded:!0}:i)),alert("업로드 완료!")}catch(a){console.error("업로드 실패:",a),alert("업로드에 실패했습니다.")}finally{p(null)}},y=async s=>{if(confirm("이미지를 삭제하시겠습니까?"))try{const l=o(d,`guide/${s}`);await k(l),m(a=>a.map(t=>t.id===s?{...t,url:null,uploaded:!1}:t)),alert("삭제 완료!")}catch(l){console.error("삭제 실패:",l),alert("삭제에 실패했습니다.")}},h=r.filter(s=>s.uploaded).length;return e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"사용자 가이드 이미지 관리"}),e.jsx("p",{className:"text-gray-600 mt-1",children:"앱 사용 가이드에 표시될 스크린샷을 업로드합니다."}),e.jsx("a",{href:"https://www.seodoon.org/guide/",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:underline text-sm mt-2 inline-block",children:"가이드 페이지 미리보기 →"})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-4 mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-700",children:"업로드 진행률"}),e.jsxs("span",{className:"text-sm text-gray-600",children:[h," / ",r.length]})]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-2",children:e.jsx("div",{className:"bg-blue-600 h-2 rounded-full transition-all",style:{width:`${h/r.length*100}%`}})})]}),j?e.jsxs("div",{className:"text-center py-12",children:[e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"}),e.jsx("p",{className:"text-gray-500 mt-2",children:"로딩 중..."})]}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:r.map(s=>e.jsxs("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:[e.jsxs("div",{className:"aspect-[9/16] bg-gray-100 relative",children:[s.url?e.jsx("img",{src:s.url,alt:s.name,className:"w-full h-full object-contain"}):e.jsx("div",{className:"w-full h-full flex items-center justify-center text-gray-400",children:e.jsxs("div",{className:"text-center",children:[e.jsx("svg",{className:"w-12 h-12 mx-auto mb-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:1.5,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),e.jsx("span",{className:"text-sm",children:"이미지 없음"})]})}),x===s.id&&e.jsx("div",{className:"absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-white"})})]}),e.jsxs("div",{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between mb-2",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-gray-900",children:s.name}),e.jsx("p",{className:"text-sm text-gray-500",children:s.description})]}),s.uploaded&&e.jsx("span",{className:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800",children:"완료"})]}),e.jsx("p",{className:"text-xs text-gray-400 mb-3 font-mono",children:s.id}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("label",{className:"flex-1",children:[e.jsx("input",{type:"file",accept:"image/*",className:"hidden",onChange:l=>{var t;const a=(t=l.target.files)==null?void 0:t[0];a&&b(s.id,a),l.target.value=""},disabled:x!==null}),e.jsx("span",{className:"block w-full text-center px-3 py-2 bg-blue-600 text-white text-sm rounded-lg cursor-pointer hover:bg-blue-700 transition-colors",children:s.uploaded?"변경":"업로드"})]}),s.uploaded&&e.jsx("button",{onClick:()=>y(s.id),className:"px-3 py-2 bg-red-100 text-red-600 text-sm rounded-lg hover:bg-red-200 transition-colors",children:"삭제"})]})]})]},s.id))}),e.jsxs("div",{className:"mt-8 bg-blue-50 rounded-lg p-4",children:[e.jsx("h3",{className:"font-medium text-blue-900 mb-2",children:"스크린샷 촬영 가이드"}),e.jsxs("ul",{className:"text-sm text-blue-800 space-y-1",children:[e.jsx("li",{children:"• 모바일 화면 비율(9:16)로 캡처해주세요"}),e.jsx("li",{children:"• 상태바가 보이지 않게 크롭하면 더 깔끔합니다"}),e.jsx("li",{children:"• PNG 또는 JPG 형식을 권장합니다"}),e.jsx("li",{children:"• 업로드 후 가이드 페이지에서 바로 확인할 수 있습니다"})]})]})]})};export{C 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.