PageSourceSearch

https://seodoon-church-admin.web.app/assets/BannerManagementPage-CvP1MRwD.js

js seodoon-church-admin.web.app collected 2026-10-03 12:35:55 UTC 26,513 bytes, 1 lines download raw bytes

1import{j as e}from"./vendor-data-Z5doMMu-.js";import{r as x}from"./vendor-react-zNM0AU50.js";import{k as q,m as _,q as k,l as b,w as C,u as T,y as O,z,x as F}from"./vendor-firebase-Da9KY1q_.js";import{d as p}from"./index-D1K3lVhu.js";import{s as $}from"./storageService-HxVmCucr.js";import{a7 as d,Y as P,aa as G,I as W,ad as Y,f as J,S as K,aT as X,ak as R,aU as L,g as H,aV as A,aW as Q,aX as Z,af as ee,T as te,aJ as se,aY as ae,a8 as le}from"./vendor-ui-CW5bJ11U.js";import"./vendor-charts-08G1rM8P.js";const h="banners",S={async getAllBanners(){try{const t=k(b(p,h),F("order","asc"));return(await _(t)).docs.map(c=>({id:c.id,...c.data()}))}catch(t){throw console.error("배너 목록 조회 실패:",t),t}},async getBannersByType(t){try{const a=k(b(p,h),C("type","==",t),C("is_active","==",!0),F("order","asc"));return(await _(a)).docs.map(i=>({id:i.id,...i.data()}))}catch(a){throw console.error("배너 조회 실패:",a),a}},async getActiveBanners(){try{const t=k(b(p,h),C("is_active","==",!0),F("order","asc"));return(await _(t)).docs.map(c=>({id:c.id,...c.data()}))}catch(t){throw console.error("활성 배너 조회 실패:",t),t}},async createBanner(t){try{return(await z(b(p,h),{...t,view_count:0,click_count:0,created_at:new Date().toISOString(),updated_at:new Date().toISOString()})).id}catch(a){throw console.error("배너 생성 실패:",a),a}},async updateBanner(t,a){try{const c=q(p,h,t);await T(c,{...a,updated_at:new Date().toISOString()})}catch(c){throw console.error("배너 수정 실패:",c),c}},async deleteBanner(t){try{await O(q(p,h,t))}catch(a){throw console.error("배너 삭제 실패:",a),a}},async toggleActive(t,a){try{await this.updateBanner(t,{is_active:a})}catch(c){throw console.error("활성화 토글 실패:",c),c}},async incrementViewCount(t){try{const a=q(p,h,t),i=(await _(k(b(p,h),C("__name__","==",t)))).docs[0].data().view_count||0;await T(a,{view_count:i+1})}catch(a){throw console.error("조회수 증가 실패:",a),a}},async incrementClickCount(t){try{const a=q(p,h,t),i=(await _(k(b(p,h),C("__name__","==",t)))).docs[0].data().click_count||0;await T(a,{click_count:i+1})}catch(a){throw console.error("클릭수 증가 실패:",a),a}}};function I(t){if(!t)return null;const a=[/(?:youtube\.com\/watch\?(?:.*&)?v=)([\w-]{11})/,/(?:youtu\.be\/)([\w-]{11})/,/(?:youtube\.com\/shorts\/)([\w-]{11})/,/(?:youtube\.com\/embed\/)([\w-]{11})/,/(?:youtube\.com\/live\/)([\w-]{11})/];for(const c of a){const i=t.match(c);if(i)return i[1]}return/^[\w-]{11}$/.test(t.trim())?t.trim():null}function he(){const[t,a]=x.useState(!0),[c,i]=x.useState([]),[j,B]=x.useState(""),[g,f]=x.useState("all"),[s,o]=x.useState("all"),[D,v]=x.useState(!1),[M,r]=x.useState(null),[n,u]=x.useState(!1);x.useEffect(()=>{m()},[]);async function m(){try{a(!0);const l=await S.getAllBanners();i(l)}catch(l){console.error("배너 로딩 실패:",l),d.error("배너를 불러올 수 없습니다")}finally{a(!1)}}const E=c.filter(l=>!(j&&!l.title.toLowerCase().includes(j.toLowerCase())||g!=="all"&&l.type!==g||s==="active"&&!l.is_active||s==="inactive"&&l.is_active)),N={total:c.length,rolling:c.filter(l=>l.type==="rolling").length,normal:c.filter(l=>l.type==="normal").length,active:c.filter(l=>l.is_active).length,totalViews:c.reduce((l,y)=>l+(y.view_count||0),0),totalClicks:c.reduce((l,y)=>l+(y.click_count||0),0)};async function U(l){if(confirm("이 배너를 삭제하시겠습니까?"))try{await S.deleteBanner(l),d.success("삭제되었습니다"),m()}catch{d.error("삭제에 실패했습니다")}}async function V(l,y){try{await S.toggleActive(l,!y),d.success(y?"비활성화되었습니다":"활성화되었습니다"),m()}catch{d.error("상태 변경에 실패했습니다")}}return t?e.jsx("div",{className:"flex items-center justify-center h-96",children:e.jsx("div",{className:"text-gray-500 text-[13px]",children:"배너를 불러오는 중..."})}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-[18px] font-bold text-gray-900 flex items-center gap-2",children:[e.jsx(P,{className:"w-5 h-5 text-blue-600"}),"배너 관리"]}),e.jsx("p",{className:"text-[12px] text-gray-500 mt-1",children:"앱 메인 화면에 표시될 배너를 관리합니다"})]}),e.jsxs("button",{onClick:()=>{r(null),v(!0)},className:"flex items-center gap-1.5 px-3 py-1.5 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors text-[13px] font-medium",children:[e.jsx(G,{className:"w-4 h-4"}),"배너 추가"]})]}),e.jsxs("div",{className:"bg-blue-50 border border-blue-200 rounded-lg overflow-hidden",children:[e.jsxs("button",{onClick:()=>u(!n),className:"w-full px-4 py-3 flex items-center justify-between hover:bg-blue-100/50 transition-colors",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(W,{className:"w-4 h-4 text-blue-600"}),e.jsx("span",{className:"text-[13px] font-medium text-blue-800",children:"배너 이미지 제작 가이드"})]}),n?e.jsx(Y,{className:"w-4 h-4 text-blue-600"}):e.jsx(J,{className:"w-4 h-4 text-blue-600"})]}),n&&e.jsxs("div",{className:"px-4 pb-4 border-t border-blue-200 bg-white/50",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mt-3",children:[e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(K,{className:"w-5 h-5 text-emerald-600"}),e.jsx("h4",{className:"text-[13px] font-bold text-gray-900",children:"모바일 배너 (권장)"})]}),e.jsxs("div",{className:"space-y-2 text-[12px]",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"권장 크기"}),e.jsx("span",{className:"font-semibold text-gray-900",children:"1200 x 600 px"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"비율"}),e.jsx("span",{className:"font-semibold text-emerald-600",children:"2:1 (표시 영역)"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"최소 크기"}),e.jsx("span",{className:"text-gray-900",children:"800 x 400 px"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"파일 크기"}),e.jsx("span",{className:"text-gray-900",children:"500KB 이하"})]})]}),e.jsx("div",{className:"mt-3 bg-gray-100 rounded overflow-hidden",style:{aspectRatio:"2/1"},children:e.jsx("div",{className:"w-full h-full flex items-center justify-center border-2 border-dashed border-gray-300",children:e.jsx("span",{className:"text-[11px] text-gray-500",children:"2:1 비율"})})})]}),e.jsxs("div",{className:"bg-white rounded-lg p-4 border border-gray-200",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(X,{className:"w-5 h-5 text-blue-600"}),e.jsx("h4",{className:"text-[13px] font-bold text-gray-900",children:"PC 배너"})]}),e.jsxs("div",{className:"space-y-2 text-[12px]",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"권장 크기"}),e.jsx("span",{className:"font-semibold text-gray-900",children:"1440 x 560 px"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"비율"}),e.jsx("span",{className:"font-semibold text-blue-600",children:"18:7 (와이드, 표시 영역)"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"고화질"}),e.jsx("span",{className:"text-gray-900",children:"2880 x 1120 px (2배)"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:"파일 크기"}),e.jsx("span",{className:"text-gray-900",children:"1MB 이하"})]})]}),e.jsx("div",{className:"mt-3 bg-gray-100 rounded overflow-hidden",style:{aspectRatio:"18/7"},children:e.jsx("div",{className:"w-full h-full flex items-center justify-center border-2 border-dashed border-gray-300",children:e.jsx("span",{className:"text-[11px] text-gray-500",children:"18:7 비율"})})})]})]}),e.jsxs("div",{className:"mt-4 p-3 bg-amber-50 rounded-lg border border-amber-200",children:[e.jsx("h4",{className:"text-[12px] font-bold text-amber-800 mb-2",children:"💡 제작 팁"}),e.jsxs("ul",{className:"text-[11px] text-amber-700 space-y-1",children:[e.jsxs("li",{children:["• ",e.jsx("strong",{children:"파일 형식"}),": JPG, PNG, WebP 권장 (WebP가 가장 용량 효율적)"]}),e.jsxs("li",{children:["• ",e.jsx("strong",{children:"원본 그대로 업로드"}),": 업로드 시 자르지 않고 원본을 저장하며, 게시 화면에서 PC(1440×560, 18:7)·모바일(2:1) 표시 영역에 맞춰 자동으로 보여줍니다"]}),e.jsxs("li",{children:["• ",e.jsx("strong",{children:"비율 주의"}),": PC와 모바일 표시 비율이 다르므로, 문구·로고 등 중요 요소는 상하좌우 중앙 안전영역에 배치 (기기별로 가장자리가 잘릴 수 있음)"]}),e.jsxs("li",{children:["• ",e.jsx("strong",{children:"텍스트"}),": 가독성을 위해 큰 글씨 사용, 상하 여백 충분히"]}),e.jsxs("li",{children:["• ",e.jsx("strong",{children:"Canva"}),": 사용자 지정 크기 ",e.jsx("strong",{children:"1440 x 560"}),"(PC) 또는 ",e.jsx("strong",{children:"1200 x 600"}),"(모바일)로 제작"]})]})]})]})]}),e.jsxs("div",{className:"grid grid-cols-6 gap-3",children:[e.jsx(w,{label:"전체",value:N.total}),e.jsx(w,{label:"롤링",value:N.rolling}),e.jsx(w,{label:"일반",value:N.normal}
1),e.jsx(w,{label:"활성",value:N.active,color:"green"}),e.jsx(w,{label:"총 조회",value:N.totalViews,icon:e.jsx(R,{className:"w-3 h-3"})}),e.jsx(w,{label:"총 클릭",value:N.totalClicks,icon:e.jsx(L,{className:"w-3 h-3"})})]}),e.jsx("div",{className:"bg-white border border-gray-200 rounded shadow-sm p-3",children:e.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"배너 타입"}),e.jsxs("select",{value:g,onChange:l=>f(l.target.value),className:"compact-input",children:[e.jsx("option",{value:"all",children:"전체"}),e.jsx("option",{value:"rolling",children:"롤링 배너"}),e.jsx("option",{value:"normal",children:"일반 배너"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"상태"}),e.jsxs("select",{value:s,onChange:l=>o(l.target.value),className:"compact-input",children:[e.jsx("option",{value:"all",children:"전체"}),e.jsx("option",{value:"active",children:"활성"}),e.jsx("option",{value:"inactive",children:"비활성"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"검색"}),e.jsxs("div",{className:"relative",children:[e.jsx(H,{className:"absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-gray-400"}),e.jsx("input",{type:"text",placeholder:"배너 제목...",value:j,onChange:l=>B(l.target.value),className:"compact-input pl-8"})]})]})]})}),e.jsx("div",{className:"grid grid-cols-2 gap-4",children:E.length===0?e.jsxs("div",{className:"col-span-2 bg-white border border-gray-200 rounded shadow-sm p-12 text-center",children:[e.jsx(P,{className:"w-12 h-12 text-gray-300 mx-auto mb-3"}),e.jsx("p",{className:"text-[13px] text-gray-500",children:"등록된 배너가 없습니다"})]}):E.map(l=>e.jsx(re,{banner:l,onEdit:()=>{r(l),v(!0)},onDelete:()=>U(l.id),onToggleActive:()=>V(l.id,l.is_active)},l.id))}),D&&e.jsx(ce,{banner:M,onClose:()=>{v(!1),r(null)},onSuccess:()=>{v(!1),r(null),m()}})]})}function w({label:t,value:a,color:c,icon:i}){return e.jsxs("div",{className:"bg-white border border-gray-200 rounded shadow-sm p-3",children:[e.jsxs("div",{className:"text-[22px] font-bold text-gray-900 flex items-center gap-2",children:[a,i]}),e.jsx("div",{className:"text-[11px] text-gray-500",children:t})]})}function re({banner:t,onEdit:a,onDelete:c,onToggleActive:i}){return e.jsxs("div",{className:"bg-white border border-gray-200 rounded shadow-sm overflow-hidden",children:[e.jsxs("div",{className:"relative aspect-[18/7] bg-gray-100",children:[t.media_type==="youtube"&&I(t.youtube_url||"")?e.jsx("div",{className:"w-full h-full bg-black flex items-center justify-center",children:e.jsxs("div",{className:"h-full relative",style:{aspectRatio:"16/9"},children:[e.jsx("img",{src:`https://img.youtube.com/vi/${I(t.youtube_url||"")}/hqdefault.jpg`,alt:t.title,className:"w-full h-full object-cover"}),e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx(A,{className:"w-10 h-10 text-red-600 drop-shadow",fill:"white"})})]})}):t.media_type==="video"&&t.video_url?e.jsx("video",{src:t.video_url,className:"w-full h-full object-cover",autoPlay:!0,muted:!0,loop:!0,playsInline:!0}):t.image_url?e.jsx("img",{src:t.image_url,alt:t.title,className:"w-full h-full object-cover"}):e.jsx("div",{className:"w-full h-full flex items-center justify-center",children:e.jsx(P,{className:"w-12 h-12 text-gray-300"})}),e.jsxs("div",{className:"absolute top-2 left-2 flex gap-2",children:[e.jsx("span",{className:`text-[10px] px-2 py-0.5 rounded font-medium ${t.type==="rolling"?"bg-blue-100 text-blue-700":"bg-slate-100 text-slate-700"}`,children:t.type==="rolling"?"롤링":"일반"}),t.media_type==="video"&&e.jsx("span",{className:"text-[10px] px-2 py-0.5 bg-orange-100 text-orange-700 rounded font-medium",children:"동영상"}),t.media_type==="youtube"&&e.jsx("span",{className:"text-[10px] px-2 py-0.5 bg-red-100 text-red-700 rounded font-medium",children:"유튜브"}),t.is_active?e.jsx("span",{className:"text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded font-medium",children:"활성"}):e.jsx("span",{className:"text-[10px] px-2 py-0.5 bg-gray-100 text-gray-700 rounded font-medium",children:"비활성"})]}),e.jsx("div",{className:"absolute top-2 right-2 w-8 h-8 bg-black bg-opacity-60 rounded-full flex items-center justify-center",children:e.jsx("span",{className:"text-[12px] font-bold text-white",children:t.order})})]}),e.jsxs("div",{className:"p-3",children:[e.jsx("h3",{className:"text-[14px] font-bold text-gray-900 mb-1",children:t.title}),t.description&&e.jsx("p",{className:"text-[11px] text-gray-600 mb-2 line-clamp-2",children:t.description}),e.jsxs("div",{className:"flex items-center gap-3 text-[11px] text-gray-500 mb-3",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(R,{className:"w-3 h-3"}),e.jsx("span",{children:t.view_count||0})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(L,{className:"w-3 h-3"}),e.jsx("span",{children:t.click_count||0})]}),t.link_url&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Q,{className:"w-3 h-3"}),e.jsx("span",{className:"truncate max-w-[100px]",children:t.link_url})]})]}),(t.start_date||t.end_date)&&e.jsxs("div",{className:"text-[10px] text-gray-500 mb-3",children:[t.start_date&&`시작: ${t.start_date}`,t.start_date&&t.end_date&&" ~ ",t.end_date&&`종료: ${t.end_date}`]}),e.jsxs("div",{className:"flex gap-1",children:[e.jsx("button",{onClick:i,className:`flex-1 flex items-center justify-center gap-1 px-2 py-1.5 rounded transition-colors text-[11px] ${t.is_active?"bg-gray-100 hover:bg-gray-200 text-gray-700":"bg-green-100 hover:bg-green-200 text-green-700"}`,children:t.is_active?e.jsxs(e.Fragment,{children:[e.jsx(Z,{className:"w-3 h-3"}),"비활성"]}
1):e.jsxs(e.Fragment,{children:[e.jsx(R,{className:"w-3 h-3"}),"활성"]})}),e.jsxs("button",{onClick:a,className:"flex-1 flex items-center justify-center gap-1 px-2 py-1.5 bg-blue-100 hover:bg-blue-200 text-blue-700 rounded transition-colors text-[11px]",children:[e.jsx(ee,{className:"w-3 h-3"}),"수정"]}),e.jsx("button",{onClick:c,className:"flex items-center justify-center px-2 py-1.5 bg-red-100 hover:bg-red-200 text-red-700 rounded transition-colors text-[11px]",children:e.jsx(te,{className:"w-3 h-3"})})]})]})]})}function ce({banner:t,onClose:a,onSuccess:c}){const i=!!t,[j,B]=x.useState(!1),[g,f]=x.useState(!1),[s,o]=x.useState({type:(t==null?void 0:t.type)||"rolling",media_type:(t==null?void 0:t.media_type)||"image",title:(t==null?void 0:t.title)||"",description:(t==null?void 0:t.description)||"",image_url:(t==null?void 0:t.image_url)||"",video_url:(t==null?void 0:t.video_url)||"",youtube_url:(t==null?void 0:t.youtube_url)||"",link_url:(t==null?void 0:t.link_url)||"",link_type:(t==null?void 0:t.link_type)||"none",is_active:(t==null?void 0:t.is_active)??!0,start_date:(t==null?void 0:t.start_date)||"",end_date:(t==null?void 0:t.end_date)||"",order:(t==null?void 0:t.order)||1});async function D(r){var u;const n=(u=r.target.files)==null?void 0:u[0];if(n)try{f(!0);const m=await $.uploadBannerImage(n);o({...s,image_url:m}),d.success("이미지가 업로드되었습니다")}catch{d.error("이미지 업로드에 실패했습니다")}finally{f(!1)}}async function v(r){var u;const n=(u=r.target.files)==null?void 0:u[0];if(n){if(n.size>50*1024*1024){d.error("동영상 파일은 50MB 이하여야 합니다");return}try{f(!0);const m=await $.uploadBannerVideo(n);o({...s,video_url:m}),d.success("동영상이 업로드되었습니다")}catch(m){d.error(m.message||"동영상 업로드에 실패했습니다")}finally{f(!1)}}}async function M(r){r.preventDefault();const n=s.media_type==="video"?!!s.video_url:s.media_type==="youtube"?!!I(s.youtube_url):!!s.image_url;if(!s.title||!n){d.error("필수 항목을 입력하세요 (제목 + 이미지/동영상/유튜브 링크)");return}try{B(!0);const u={...s,created_by:"admin"};i?(await S.updateBanner(t.id,u),d.success("배너가 수정되었습니다")):(await S.createBanner(u),d.success("배너가 추가되었습니다")),c()}catch{d.error(i?"수정에 실패했습니다":"추가에 실패했습니다")}finally{B(!1)}}return e.jsx("div",{className:"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto",children:[e.jsx("div",{className:"p-4 border-b border-gray-200",children:e.jsx("h2",{className:"text-[16px] font-bold text-gray-900",children:i?"배너 수정":"배너 추가"})}),e.jsxs("form",{onSubmit:M,className:"p-4 space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:["배너 타입 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsxs("select",{value:s.type,onChange:r=>o({...s,type:r.target.value}),className:"compact-input",required:!0,children:[e.jsx("option",{value:"rolling",children:"롤링 배너"}),e.jsx("option",{value:"normal",children:"일반 배너"})]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:["정렬 순서 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx("input",{type:"number",value:s.order,onChange:r=>o({...s,order:parseInt(r.target.value)}),className:"compact-input",min:"1",required:!0})]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:["제목 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx("input",{type:"text",value:s.title,onChange:r=>o({...s,title:r.target.value}),className:"compact-input",placeholder:"예: 2025 신년 특별집회",required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"설명"}),e.jsx("textarea",{value:s.description,onChange:r=>o({...s,description:r.target.value}),className:"compact-input",rows:2,placeholder:"배너에 대한 간단한 설명"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:["미디어 타입 ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{type:"button",onClick:()=>o({...s,media_type:"image"}),className:`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded border text-[13px] font-medium transition-colors ${s.media_type==="image"?"border-blue-500 bg-blue-50 text-blue-600":"border-gray-300 text-gray-600 hover:bg-gray-50"}`,children:[e.jsx(P,{className:"w-4 h-4"}),"이미지"]}),e.jsxs("button",{type:"button",onClick:()=>o({...s,media_type:"video"}),className:`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded border text-[13px] font-medium transition-colors ${s.media_type==="video"?"border-blue-500 bg-blue-50 text-blue-600":"border-gray-300 text-gray-600 hover:bg-gray-50"}`,children:[e.jsx(se,{className:"w-4 h-4"}),"동영상"]}
1),e.jsxs("button",{type:"button",onClick:()=>o({...s,media_type:"youtube"}),className:`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded border text-[13px] font-medium transition-colors ${s.media_type==="youtube"?"border-red-500 bg-red-50 text-red-600":"border-gray-300 text-gray-600 hover:bg-gray-50"}`,children:[e.jsx(A,{className:"w-4 h-4"}),"유튜브"]})]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:[s.media_type==="video"?"동영상":s.media_type==="youtube"?"유튜브 링크":"이미지"," ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx("div",{className:"space-y-2",children:s.media_type==="youtube"?e.jsxs(e.Fragment,{children:[e.jsx("input",{type:"text",value:s.youtube_url,onChange:r=>o({...s,youtube_url:r.target.value}),className:"compact-input",placeholder:"https://www.youtube.com/watch?v=... 또는 https://youtu.be/..."}),(()=>{const r=I(s.youtube_url);return s.youtube_url&&!r?e.jsx("p",{className:"text-[11px] text-red-500",children:"유효한 유튜브 링크가 아닙니다"}):r?e.jsx("div",{className:"relative aspect-[18/7] bg-black rounded overflow-hidden flex items-center justify-center",children:e.jsx("div",{className:"h-full",style:{aspectRatio:"16/9"},children:e.jsx("iframe",{src:`https://www.youtube.com/embed/${r}?rel=0`,className:"w-full h-full",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowFullScreen:!0})})}):null})(),e.jsx("p",{className:"text-[11px] text-gray-400",children:"영상은 16:9 비율 그대로 표시되며 높이를 배너에 맞춥니다(좌우 여백). 게시 화면에서는 자동재생·음소거·반복됩니다."})]}):s.media_type==="video"?e.jsxs(e.Fragment,{children:[s.video_url&&e.jsx("div",{className:"relative aspect-[18/7] bg-black rounded overflow-hidden",children:e.jsx("video",{src:s.video_url,className:"w-full h-full object-cover",autoPlay:!0,muted:!0,loop:!0,playsInline:!0})}),e.jsxs("label",{className:"flex items-center justify-center gap-2 px-4 py-2 border-2 border-dashed border-gray-300 rounded hover:border-blue-500 cursor-pointer transition-colors",children:[e.jsx(ae,{className:"w-4 h-4 text-gray-400"}),e.jsx("span",{className:"text-[13px] text-gray-600",children:g?"업로드 중...":"동영상 선택 (최대 50MB)"}),e.jsx("input",{type:"file",accept:"video/*",onChange:v,className:"hidden",disabled:g})]}),e.jsx("p",{className:"text-[11px] text-gray-400",children:"MP4, WebM 등 지원. PC 18:7(1440×560) / 모바일 2:1 표시."})]}):e.jsxs(e.Fragment,{children:[s.image_url&&e.jsx("div",{className:"relative aspect-[18/7] bg-gray-100 rounded overflow-hidden",children:e.jsx("img",{src:s.image_url,alt:"미리보기",className:"w-full h-full object-cover"})}),e.jsxs("label",{className:"flex items-center justify-center gap-2 px-4 py-2 border-2 border-dashed border-gray-300 rounded hover:border-blue-500 cursor-pointer transition-colors",children:[e.jsx(le,{className:"w-4 h-4 text-gray-400"}),e.jsx("span",{className:"text-[13px] text-gray-600",children:g?"업로드 중...":"이미지 선택 (원본 그대로 업로드)"}),e.jsx("input",{type:"file",accept:"image/*",onChange:D,className:"hidden",disabled:g})]})]})})]}),e.jsxs("div",{className:"space-y-3 p-3 bg-gray-50 rounded",children:[e.jsx("h3",{className:"text-[13px] font-bold text-gray-900",children:"링크 설정"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"링크 타입"}
1),e.jsxs("select",{value:s.link_type,onChange:r=>o({...s,link_type:r.target.value}),className:"compact-input",children:[e.jsx("option",{value:"none",children:"링크 없음"}),e.jsx("option",{value:"internal",children:"내부 링크 (앱 화면)"}),e.jsx("option",{value:"external",children:"외부 링크 (웹사이트)"})]})]}),s.link_type!=="none"&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"링크 URL"}),e.jsx("input",{type:"text",value:s.link_url,onChange:r=>o({...s,link_url:r.target.value}),className:"compact-input",placeholder:s.link_type==="internal"?"/bulletin":"https://example.com"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"시작일 (선택)"}),e.jsx("input",{type:"date",value:s.start_date,onChange:r=>o({...s,start_date:r.target.value}),className:"compact-input"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[12px] font-medium text-gray-700 mb-1",children:"종료일 (선택)"}),e.jsx("input",{type:"date",value:s.end_date,onChange:r=>o({...s,end_date:r.target.value}),className:"compact-input"})]})]}),e.jsx("div",{children:e.jsxs("label",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",checked:s.is_active,onChange:r=>o({...s,is_active:r.target.checked}),className:"w-4 h-4"}),e.jsx("span",{className:"text-[12px] font-medium text-gray-700",children:"활성화 (체크 해제 시 앱에 표시되지 않음)"})]})}),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsx("button",{type:"button",onClick:a,className:"flex-1 px-3 py-2 border border-gray-300 rounded hover:bg-gray-50 transition-colors text-[13px]",children:"취소"}),e.jsx("button",{type:"submit",disabled:j||g,className:"flex-1 px-3 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors text-[13px] font-medium disabled:opacity-50",children:j?"처리 중...":i?"수정":"추가"})]})]})]})})}export{he as BannerManagementPage};

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.