1import{j as e}from"./vendor-grid-ClmSNH6q.js";import{c as W,o as g,$ as J,aW as j,l as q,X as R,aT as H,aU as K,a8 as X}from"./index-Cab6mplo.js";import{r as o}from"./vendor-charts-B2bLUVVL.js";import{b as v,C as Z,a as Q,c as V}from"./Card-BUL_z2x0.js";import{C as Y}from"./camera-BDrnICbm.js";import{I as ee}from"./image-DiIDUDrc.js";/** 2 * @license lucide-react v0.563.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const te=[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]],se=W("zoom-in",te),f=" https://reamintell.com";function ce({propertyId:h}){const[r,w]=o.useState([]),[B,N]=o.useState(!0),[k,c]=o.useState(null),[C,D]=o.useState(!1),[P,U]=o.useState(null),[L,y]=o.useState(!1),[n,d]=o.useState(null),[O,b]=o.useState(null),[u,E]=o.useState(""),[m,$]=o.useState({}),p=o.useRef(null);o.useEffect(()=>{S()},[h]),o.useEffect(()=>{if(r.length===0)return;const t=g();if(!t)return;let a=!1;const s={};return(async()=>{await Promise.all(r.map(async l=>{if(m[l.key]){s[l.key]=m[l.key];return}try{const i=await fetch(`${f}${l.url}`,{headers:{"x-api-key":t}});if(i.ok){const M=await i.blob();a||(s[l.key]=URL.createObjectURL(M))}}catch(i){console.error("Failed to load photo blob:",l.key,i)}})),a||$(l=>({...l,...s}))})(),()=>{a=!0}},[r]),o.useEffect(()=>()=>{Object.values(m).forEach(t=>URL.revokeObjectURL(t))},[]),o.useEffect(()=>{if(n===null)return;const t=a=>{a.key==="Escape"&&d(null),a.key==="ArrowLeft"&&d(s=>s!==null&&s>0?s-1:s),a.key==="ArrowRight"&&d(s=>s!==null&&s<r.length-1?s+1:s)};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[n,r.length]);const S=async()=>{const t=g();if(t){N(!0),c(null);try{const s=await(await fetch(`${f}/api/properties/${h}/photos`,{headers:{"x-api-key":t}})).json();s.success?w(s.photos||[]):c(s.error||"Failed to load photos")}catch(a){console.error("Failed to load photos:",a),c(a.message||"Network error")}finally{N(!1)}}},z=async t=>{const a=g();if(!a)return;if(!["image/jpeg","image/png","image/webp","image/gif"].includes(t.type)){c("Invalid file type. Allowed: JPEG, PNG, WebP, GIF");return}if(t.size>15*1024*1024){c("File size exceeds 15MB limit");return}D(!0),U(`Uploading ${t.name}...`),c(null);try{const x=new FormData;x.append("file",t),u.trim()&&x.append("caption",u.trim());const i=await(await fetch(`${f}/api/properties/${h}/photos`,{method:"POST",headers:{"x-api-key":a},body:x})).json();i.success?(E(""),await S()):c(i.error||"Upload failed")}catch(x){console.error("Upload failed:",x),c(x.message||"Upload failed")}finally{D(!1),U(null)}},T=t=>{const a=t.target.files;a&&a.length>0&&z(a[0]),p.current&&(p.current.value="")},I=o.useCallback(t=>{t.preventDefault(),y(!1);const a=t.dataTransfer.files;a&&a.length>0&&z(a[0])},[h,u]),A=t=>{t.preventDefault(),y(!0)},G=t=>{t.preventDefault(),y(!1)},_=async t=>{const a=g();if(a)try{const x=await(await fetch(`${f}/api/properties/${h}/photos?key=${encodeURIComponent(t)}`,{method:"DELETE",headers:{"x-api-key":a}})).json();if(x.success){if(m[t]&&(URL.revokeObjectURL(m[t]),$(l=>{const i={...l};return delete i[t],i})),w(l=>l.filter(i=>i.key!==t)),b(null),n!==null){const l=r.filter(i=>i.key!==t);l.length===0?d(null):n>=l.length&&d(l.length-1)}}else c(x.error||"Delete failed")}catch(s){console.error("Delete failed:",s),c(s.message||"Delete failed")}},F=t=>t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`;return B?e.jsx(v,{children:e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin rounded-full h-10 w-10 border-b-2 border-brand-navy mx-auto mb-3"}),e.jsx("p",{className:"text-sm text-gray-500",children:"Loading photos..."})]})})}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs(v,{children:[e.jsxs(Z,{children:[e.jsx(Q,{children:"Property Photos"}),e.jsx(V,{children:"Upload and manage property images"})]}),e.jsxs("div",{className:"px-6 pb-6",children:[e.jsxs("div",{onDrop:I,onDragOver:A,onDragLeave:G,className:`border-2 border-dashed rounded-lg p-6 text-center transition-colors ${L?"border-brand-navy bg-brand-navy
6/5":"border-gray-300 hover:border-gray-400"}`,children:[e.jsx(J,{className:`w-8 h-8 mx-auto mb-2 ${L?"text-brand-navy":"text-gray-400"}`}),e.jsx("p",{className:"text-sm text-gray-600 mb-1",children:"Drag and drop an image here, or click to browse"}),e.jsx("p",{className:"text-xs text-gray-400",children:"JPEG, PNG, WebP, GIF up to 15MB"}),e.jsxs("div",{className:"flex items-center justify-center gap-3 mt-4",children:[e.jsx("input",{type:"text",value:u,onChange:t=>E(t.target.value),placeholder:"Optional caption...",className:"px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-navy/20 focus:border-brand-navy w-64"}),e.jsx(j,{variant:"primary",size:"sm",icon:e.jsx(Y,{className:"w-4 h-4"}),disabled:C,onClick:()=>{var t;return(t=p.current)==null?void 0:t.click()},children:C?"Uploading...":"Upload Photo"})]}),e.jsx("input",{ref:p,type:"file",accept:"image/jpeg,image/png,image/webp,image/gif",onChange:T,className:"hidden"})]}),P&&e.jsxs("div",{className:"mt-3 flex items-center gap-2 text-sm text-brand-navy",children:[e.jsx("div",{className:"animate-spin rounded-full h-4 w-4 border-b-2 border-brand-navy"}),P]}),k&&e.jsxs("div",{className:"mt-3 p-3 bg-red-50 border border-red-200 text-red-700 rounded-lg text-sm flex items-center gap-2",children:[e.jsx(q,{className:"w-4 h-4 shrink-0"}),k,e.jsx("button",{onClick:()=>c(null),className:"ml-auto text-red-400 hover:text-red-600",children:e.jsx(R,{className:"w-4 h-4"})})]})]})]}),r.length===0?e.jsx(v,{children:e.jsxs("div",{className:"text-center py-12",children:[e.jsx(ee,{className:"w-12 h-12 text-gray-400 mx-auto mb-3"}),e.jsx("p",{className:"text-gray-600",children:"No photos uploaded yet"}),e.jsx("p",{className:"text-xs text-gray-400 mt-1",children:"Upload photos to showcase this property"})]})}):e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4",children:r.map((t,a)=>e.jsxs("div",{className:"group relative bg-white rounded-lg border border-gray-200 overflow-hidden shadow-sm hover:shadow-md transition-shadow",children:[e.jsxs("div",{className:"aspect-square cursor-pointer overflow-hidden",onClick:()=>d(a),children:[e.jsx("img",{src:m[t.key]||"",alt:t.caption||t.filename,className:`w-full h-full object-cover group-hover:scale-105 transition-transform duration-200 ${m[t.key]?"":"bg-gray-100"}`,loading:"lazy"}),e.jsx("div",{className:"absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors flex items-center justify-center",children:e.jsx(se,{className:"w-6 h-6 text-white opacity-0 group-hover:opacity-100 transition-opacity"})})]}),e.jsxs("div",{className:"p-2",children:[e.jsx("p",{className:"text-xs font-medium text-gray-900 truncate",children:t.caption||t.filename}),e.jsxs("div",{className:"flex items-center justify-between mt-1",children:[e.jsx("span",{className:"text-[10px] text-gray-400",children:F(t.size)}),e.jsx("button",{onClick:s=>{s.stopPropagation(),b(t.key)},className:"p-1 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors opacity-0 group-hover:opacity-100",title:"Delete photo",children:e.jsx(H,{className:"w-3.5 h-3.5"})})]})]}),O===t.key&&e.jsxs("div",{className:"absolute inset-0 bg-white/95 flex flex-col items-center justify-center p-4 z-10",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900 text-center mb-3",children:"Delete this photo?"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(j,{variant:"outline",size:"sm",onClick:s=>{s.stopPropagation(),b(null)},children:"Cancel"}),e.jsx(j,{variant:"danger",size:"sm",onClick:s=>{s.stopPropagation(),_(t.key)},children:"Delete"})]})]})]},t.key))}),r.length>0&&e.jsx("div",{className:"text-center",children:e.jsxs("p",{className:"text-xs text-gray-400",children:[r.length," photo",r.length!==1?"s":""]})}),n!==null&&r[n]&&e.jsxs("div",{className:"fixed inset-0 bg-black/90 z-50 flex items-center justify-center",onClick:()=>d(null),children:[e.jsx("button",{onClick:()=>d(null),className:"absolute top-4 right-4 p-2 text-white/70 hover:text-white hover:bg-white/10 rounded-lg z-10",children:e.jsx(R,{className:"w-6 h-6"})}),e.jsxs("div",{className:"absolute top-4 left-4 text-white/70 text-sm",children:[n+1," / ",r.length]}),n>0&&e.jsx("button",{onClick:t=>{t.stopPropagation(),d(n-1)},className:"absolute left-4 top-1/2 -translate-y-1/2 p-2 text-white/70 hover:text-white hover:bg-white/10 rounded-lg",children:e.jsx(K,{className:"w-8 h-8"})}),e.jsxs("div",{className:"max-w-[90vw] max-h-[85vh] flex flex-col items-center",onClick:t=>t.stopPropagation(),children:[e.jsx("img",{src:m[r[n].key]||"",alt:r[n].caption||r[n].filename,className:"max-w-full max-h-[80vh] object-contain rounded-lg"}),e.jsxs("div",{className:"mt-3 text-center",children:[r[n].caption&&e.jsx("p",{className:"text-white text-sm",children:r[n].caption}),e.jsxs("p",{className:"text-white/50 text-xs mt-1",children:[r[n].filename," ·"," ",F(r[n].size)," ·"," ",new Date(r[n].uploaded).toLocaleDateString(),r[n].uploaded_by&&e.jsxs(e.Fragment,{children:[" · Uploaded by ",r[n].uploaded_by]})]})]})]}),n<r.length-1&&e.jsx("button",{onClick:t=>{t.stopPropagation(),d(n+1)},className:"absolute right-4 top-1/2 -translate-y-1/2 p-2 text-white/70 hover:text-white hover:bg-white/10 rounded-lg",children:e.jsx(X,{className:"w-8 h-8"})})]})]})}export{ce 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.