1import{j as e}from"./vendor-query-D1Mshrk-.js";import{r as l}from"./vendor-react-BfQMi0FG.js";import{I as Y,c as oe}from"./image-compression-CymqulNC.js";import{P as de}from"./page-header-C7x1KRLA.js";import{u as M,B as o,U as Q,S as me,I as A,e as Z,f as ee,j as se,t as h,X as ue,P as ae,L as k,r as $}from"./index-D3kn74s7.js";import{S as V,a as q,b as B,c as H,d as F}from"./select-Da-jnnzS.js";import{T as te,a as le,b as U}from"./tabs-nPG276U5.js";import{D as K,a as W,b as X,c as J,e as ne}from"./dialog-Dt-Wm_UE.js";import{C as re}from"./confirm-dialog-CV5i7jpD.js";import{u as ge,a as ie,b as he,c as xe,d as pe,e as je,f as fe,g as ve}from"./use-gallery-DobYRn7E.js";import{T as Ne}from"./tags-B7hjpAU5.js";import{P as ce}from"./pencil-BdlRQFJ9.js";import"./vendor-ui-nQy3bJlE.js";import"./check-CXo9hMCb.js";import"./alert-dialog-D07W3RYy.js";function Me(){const i=M(s=>s.isSuperAdmin),v=M(s=>s.managedClientId),w=!!v||!i,[j,f]=l.useState(""),[N,t]=l.useState(""),[u,g]=l.useState(i&&!v?"public":"all"),[c,r]=l.useState(""),[p,b]=l.useState(1),[C,n]=l.useState(!1),[x,S]=l.useState(null),[E,L]=l.useState(!1);l.useEffect(()=>{const s=setTimeout(()=>t(j),300);return()=>clearTimeout(s)},[j]),l.useEffect(()=>{b(1)},[N,u,c]);const{data:y,isLoading:T}=ge({page:p,limit:24,scope:u,tagId:c||void 0,search:N||void 0}),{data:D}=ie(),I=he(),_=async s=>{try{await I.mutateAsync(s),h.success("Image deleted")}catch{h.error("Failed to delete image")}},z=s=>s.clientId===null,O=s=>i?!0:!z(s);return e.jsxs("div",{className:"space-y-6",children:[e.jsx(de,{title:"Image Gallery",description:"Manage images for products, categories, and more",action:e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(o,{variant:"outline",onClick:()=>L(!0),children:[e.jsx(Ne,{className:"mr-2 h-4 w-4"}),"Tags"]}),e.jsxs(o,{onClick:()=>n(!0),children:[e.jsx(Q,{className:"mr-2 h-4 w-4"}),"Upload Image"]})]})}),e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(me,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(A,{placeholder:"Search images...",value:j,onChange:s=>f(s.target.value),className:"pl-9"})]}),e.jsxs(V,{value:c||"_all",onValueChange:s=>r(s==="_all"?"":s),children:[e.jsx(q,{className:"w-[180px]",children:e.jsx(B,{placeholder:"All tags"})}
1),e.jsxs(H,{children:[e.jsx(F,{value:"_all",children:"All tags"}),D?.map(s=>e.jsxs(F,{value:s.id,children:[s.name," (",s._count?.images??0,")"]},s.id))]})]}),w&&e.jsx(te,{value:u,onValueChange:s=>g(s),children:e.jsxs(le,{children:[e.jsx(U,{value:"all",children:"All"}),e.jsx(U,{value:"public",children:"Public"}),e.jsx(U,{value:"private",children:"Private"})]})})]}),T?e.jsx("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6",children:Array.from({length:12}).map((s,R)=>e.jsx(Z,{className:"aspect-square rounded-lg"},R))}):y?.images.length?e.jsx("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6",children:y.images.map(s=>e.jsxs("div",{className:"group relative overflow-hidden rounded-lg border bg-muted",children:[e.jsx("div",{className:"aspect-square",children:e.jsx("img",{src:s.url,alt:s.name,className:"h-full w-full object-cover",loading:"lazy"})}),z(s)&&e.jsx(ee,{variant:"secondary",className:"absolute left-1.5 top-1.5 text-[10px]",children:"Public"}),O(s)&&e.jsxs("div",{className:"absolute right-1.5 top-1.5 flex gap-1",children:[e.jsx(o,{variant:"secondary",size:"icon",className:"h-7 w-7",onClick:()=>S(s),children:e.jsx(ce,{className:"h-3.5 w-3.5"})}),e.jsx(re,{trigger:e.jsx(o,{variant:"destructive",size:"icon",className:"h-7 w-7",children:e.jsx(se,{className:"h-3.5 w-3.5"})}),title:"Delete Image",description:`Delete "${s.name}"? This will also remove it from Cloudinary.`,onConfirm:()=>_(s.id)})]}),e.jsxs("div",{className:"p-2",children:[e.jsx("p",{className:"truncate text-xs font-medium",children:s.name}),s.tag&&e.jsx("p",{className:"truncate text-[10px] text-muted-foreground",children:s.tag.name})]})]},s.id))}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 text-muted-foreground",children:[e.jsx(Y,{className:"mb-3 h-12 w-12"}),e.jsx("p",{className:"text-lg font-medium",children:"No images found"}),e.jsx("p",{className:"text-sm",children:"Upload your first image to get started"}),e.jsxs(o,{className:"mt-4",onClick:()=>n(!0),children:[e.jsx(Q,{className:"mr-2 h-4 w-4"}),"Upload Image"]})]}),y&&y.meta.totalPages>1&&e.jsxs("div",{className:"flex items-center justify-center gap-2",children:[e.jsx(o,{variant:"outline",size:"sm",disabled:p<=1,onClick:()=>b(p-1),children:"Previous"}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["Page ",p," of ",y.meta.totalPages]}),e.jsx(o,{variant:"outline",size:"sm",disabled:p>=y.meta.totalPages,onClick:()=>b(p+1),children:"Next"})]}),e.jsx(ye,{open:C,onOpenChange:n,tags:D??[]}),x&&e.jsx(be,{image:x,tags:D??[],open:!!x,onOpenChange:s=>{s||S(null)}}),e.jsx(we,{open:E,onOpenChange:L})]})}function ye({open:i,onOpenChange:v,tags:w}){const j=M(a=>a.isSuperAdmin),f=M(a=>a.managedClientId),N=!j||!!f,[t,u]=l.useState([]),[g,c]=l.useState(""),[r,p]=l.useState(""),[b,C]=l.useState("private"),[n,x]=l.useState(!1),[S,E]=l.useState(!1),[L,y]=l.useState(!1),T=l.useRef(null),D=xe(),I=t.length===1,_=async a=>{const d=a.filter(m=>m.type.startsWith("image/"));if(d.length===0){h.error("Please select image files");return}x(!0);try{const m=[];for(const P of d){let G;try{G=await oe(P)}catch{G=P}m.push({file:G,preview:URL.createObjectURL(G),name:P.name.replace(/\.[^.]+$/,"")})}u(P=>[...P,...m]),t.length===0&&m.length===1&&!g&&c(m[0].name)}finally{x(!1)}},z=a=>{u(d=>{const m=[...d];return URL.revokeObjectURL(m[a].preview),m.splice(a,1),m})},O=async()=>{if(t.length===0||I&&!g.trim())return;E(!0);let a=0;try{for(const d of t){const m=new FormData;m.append("file",d.file),m.append("name",I?g.trim():d.name),N&&m.append("scope",b),r&&m.append("tagId",r),await D.mutateAsync(m),a++}h.success(a===1?"Image uploaded":`${a} images uploaded`),s(),v(!1)}catch{a>0?h.error(`Uploaded ${a}/${t.length} â some failed`):h.error("Failed to upload images")}finally{E(!1)}},s=()=>{c(""),p(""),C("private");for(const a of t)URL.revokeObjectURL(a.preview);u([])};l.useEffect(()=>{i||s()},[i]);const R=a=>{a.preventDefault(),y(!1);const d=Array.from(a.dataTransfer.files);d.length&&_(d)};return e.jsx(K,{open:i,onOpenChange:v,children:e.jsxs(W,{children:[e.jsx(X,{children:e.jsxs(J,{children:["Upload ",t.length>1?"Images":"Image"]})}),e.jsxs("div",{className:"space-y-4",children:[t.length>0?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-3 gap-2 max-h-48 overflow-y-auto",children:[t.map((a,d)=>e.jsxs("div",{className:"relative group",children:[e.jsx("img",{src:a.preview,alt:a.name,className:"aspect-square w-full rounded-lg border object-cover"}),e.jsx(o,{type:"button",variant:"destructive",size:"icon",className:"absolute -right-1 -top-1 h-5 w-5 opacity-0 group-hover:opacity-100 transition-opacity",onClick:()=>z(d),children:e.jsx(ue,{className:"h-3 w-3"})})]},d)),e.jsx("button",{type:"button",className:"aspect-square flex items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground
1/25 hover:border-muted-foreground/50 text-muted-foreground",onClick:()=>T.current?.click(),children:e.jsx(ae,{className:"h-5 w-5"})})]}),t.length>1&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:[t.length," images selected"]})]}):e.jsx("button",{type:"button",className:`flex h-40 w-full items-center justify-center rounded-lg border-2 border-dashed transition-colors ${L?"border-primary bg-primary/5":"border-muted-foreground/25 hover:border-muted-foreground/50"}`,onClick:()=>T.current?.click(),onDragOver:a=>{a.preventDefault(),y(!0)},onDragLeave:()=>y(!1),onDrop:R,children:e.jsxs("div",{className:"text-center text-muted-foreground",children:[e.jsx(Y,{className:"mx-auto mb-2 h-8 w-8"}),e.jsx("p",{className:"text-sm",children:"Click or drag & drop images"}),e.jsx("p",{className:"text-xs mt-1",children:"Multiple images supported"})]})}),I&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{children:"Name"}),e.jsx(A,{value:g,onChange:a=>c(a.target.value),placeholder:"Image name"})]}),t.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs(k,{children:["Tag",t.length>1?" (applied to all)":""," ",e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsxs(V,{value:r||"_none",onValueChange:a=>p(a==="_none"?"":a),children:[e.jsx(q,{children:e.jsx(B,{placeholder:"Select a tag"})}),e.jsx(H,{children:w.map(a=>e.jsx(F,{value:a.id,children:a.name},a.id))})]}),!r&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Please select a tag before uploading"})]}),N&&t.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{children:"Visibility"}),e.jsx(te,{value:b,onValueChange:a=>C(a),children:e.jsxs(le,{className:"grid w-full grid-cols-2",children:[e.jsx(U,{value:"private",children:"Private (this client only)"}),e.jsx(U,{value:"public",children:"Public (all clients)"})]})})]})]}),e.jsxs(ne,{children:[e.jsx(o,{variant:"outline",onClick:()=>v(!1),children:"Cancel"}),e.jsxs(o,{disabled:t.length===0||I&&!g.trim()||!r||n||S,onClick:O,children:[(n||S)&&e.jsx($,{className:"mr-2 h-4 w-4 animate-spin"}),n?"Compressing...":S?"Uploading...":t.length>1?`Upload ${t.length}`:"Upload"]})]}),e.jsx("input",{ref:T,type:"file",accept:"image/jpeg,image/png,image/webp,image/gif",multiple:!0,className:"hidden",onChange:a=>{const d=Array.from(a.target.files??[]);d.length&&_(d),a.target.value=""}})]})})}function be({image:i,tags:v,open:w,onOpenChange:j}){const[f,N]=l.useState(i.name),[t,u]=l.useState(i.tagId??""),g=pe();l.useEffect(()=>{N(i.name),u(i.tagId??"")},[i]);const c=async()=>{try{await g.mutateAsync({id:i.id,data:{name:f.trim(),tagId:t||null}}),h.success("Image updated"),j(!1)}catch{h.error("Failed to update image")}};return e.jsx(K,{open:w,onOpenChange:j,children:e.jsxs(W,{children:[e.jsx(X,{children:e.jsx(J,{children:"Edit Image"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"flex justify-center",children:e.jsx("img",{src:i.url,alt:i.name,className:"max-h-48 rounded-lg border object-contain"})}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{children:"Name"}),e.jsx(A,{value:f,onChange:r=>N(r.target.value),placeholder:"Image name"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(k,{children:"Tag"}),e.jsxs(V,{value:t||"_none",onValueChange:r=>u(r==="_none"?"":r),children:[e.jsx(q,{children:e.jsx(B,{placeholder:"No tag"})}
1),e.jsxs(H,{children:[e.jsx(F,{value:"_none",children:"No tag"}),v.map(r=>e.jsx(F,{value:r.id,children:r.name},r.id))]})]})]})]}),e.jsxs(ne,{children:[e.jsx(o,{variant:"outline",onClick:()=>j(!1),children:"Cancel"}),e.jsxs(o,{disabled:!f.trim()||g.isPending,onClick:c,children:[g.isPending&&e.jsx($,{className:"mr-2 h-4 w-4 animate-spin"}),"Save"]})]})]})})}function we({open:i,onOpenChange:v}){const{data:w,isLoading:j}=ie(),f=je(),N=fe(),t=ve(),[u,g]=l.useState(""),[c,r]=l.useState(null),p=async()=>{if(u.trim())try{await f.mutateAsync({name:u.trim()}),g(""),h.success("Tag created")}catch{h.error("Failed to create tag")}},b=async()=>{if(!(!c||!c.name.trim()))try{await N.mutateAsync({id:c.id,data:{name:c.name.trim()}}),r(null),h.success("Tag updated")}catch{h.error("Failed to update tag")}},C=async n=>{try{await t.mutateAsync(n),h.success("Tag deleted")}catch{h.error("Failed to delete tag")}};return e.jsx(K,{open:i,onOpenChange:v,children:e.jsxs(W,{children:[e.jsx(X,{children:e.jsx(J,{children:"Manage Tags"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx(A,{value:u,onChange:n=>g(n.target.value),placeholder:"New tag name",onKeyDown:n=>{n.key==="Enter"&&p()}}),e.jsx(o,{size:"sm",disabled:!u.trim()||f.isPending,onClick:p,children:f.isPending?e.jsx($,{className:"h-4 w-4 animate-spin"}):e.jsx(ae,{className:"h-4 w-4"})})]}),e.jsx("div",{className:"max-h-64 space-y-2 overflow-y-auto",children:j?Array.from({length:3}).map((n,x)=>e.jsx(Z,{className:"h-10 rounded-lg"},x)):w?.length?w.map(n=>e.jsx("div",{className:"flex items-center gap-2 rounded-lg border p-2",children:c?.id===n.id?e.jsxs(e.Fragment,{children:[e.jsx(A,{value:c.name,onChange:x=>r({...c,name:x.target.value}),className:"h-8",onKeyDown:x=>{x.key==="Enter"&&b(),x.key==="Escape"&&r(null)},autoFocus:!0}),e.jsx(o,{size:"sm",variant:"ghost",onClick:b,children:"Save"}),e.jsx(o,{size:"sm",variant:"ghost",onClick:()=>r(null),children:"Cancel"})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"flex-1 text-sm",children:n.name}),e.jsx(ee,{variant:"secondary",className:"text-xs",children:n._count?.images??0}),e.jsx(o,{size:"icon",variant:"ghost",className:"h-7 w-7",onClick:()=>r({id:n.id,name:n.name}),children:e.jsx(ce,{className:"h-3.5 w-3.5"})}),e.jsx(re,{trigger:e.jsx(o,{size:"icon",variant:"ghost",className:"h-7 w-7 text-destructive",children:e.jsx(se,{className:"h-3.5 w-3.5"})}),title:"Delete Tag",description:`Delete "${n.name}"? Images with this tag will be untagged.`,onConfirm:()=>C(n.id)})]})},n.id)):e.jsx("p",{className:"py-4 text-center text-sm text-muted-foreground",children:"No tags yet"})})]})]})})}export{Me as GalleryPage};
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.