PageSourceSearch

https://doghealthy.netlify.app/_nuxt/U9Jxyxzf.js

js doghealthy.netlify.app collected 2026-10-03 10:40:00 UTC 12,960 bytes, 1 lines download raw bytes

1import{f as ne,u as ie,g as oe,p as ae,r as h,q as M,h as re,c as r,a as n,t as c,j as o,b as V,w as A,F as U,k as B,i as v,d as I,l as le,m as R,v as F,s as O,x as de,e as ue,o as l,y as S}from"#entry";import{u as ce}from"./Dy9pVEbO.js";import"./DKLWY9DJ.js";const pe={class:"min-h-screen bg-gray-50"},ge={class:"max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8"},me={class:"mb-8 flex flex-col sm:flex-row sm:items-end sm:justify-between gap-4"},fe={class:"flex flex-wrap gap-2 text-sm"},_e={class:"inline-flex items-center gap-1.5 rounded-full bg-blue-600 text-white px-3 py-1 font-semibold"},xe={class:"inline-flex items-center gap-1.5 rounded-full bg-gray-200 text-gray-800 px-3 py-1 font-medium"},ye={key:0,class:"text-center py-16 text-gray-500"},be={key:1,class:"bg-white rounded-xl border border-gray-200 p-12 text-center"},he={key:2,class:"grid lg:grid-cols-5 gap-6"},ve={class:"lg:col-span-2 bg-white rounded-xl border border-gray-200 overflow-hidden"},we=["onClick"],ke={class:"flex items-start justify-between gap-2"},Ce={class:"min-w-0"},Ie={class:"text-xs text-gray-500 truncate"},Se={class:"shrink-0 flex flex-col items-end gap-1"},De={key:0,class:"inline-flex items-center justify-center min-w-[1.25rem] h-5 px-1.5 rounded-full bg-blue-600 text-white text-xs font-bold"},Te={class:"text-[10px] text-gray-400"},Ue={class:"flex items-center justify-between mt-1 gap-2"},Ee={class:"text-xs text-gray-400"},$e={class:"text-xs text-gray-500"},Ne={key:0,class:"inline-block mt-1 text-[11px] font-semibold uppercase tracking-wide text-amber-800 bg-amber-50 border border-amber-200 rounded px-1.5 py-0.5"},qe={class:"lg:col-span-3 bg-white rounded-xl border border-gray-200 flex flex-col min-h-[28rem]"},Ge={key:0,class:"flex-1 flex items-center justify-center text-gray-500 p-8"},Me={class:"p-4 border-b border-gray-100"},Pe={class:"flex items-start justify-between gap-3"},je={class:"font-semibold text-gray-900"},Le={class:"text-sm text-gray-500"},Ve={class:"text-xs text-gray-500 mt-1"},Ae={key:0,class:"mt-3 text-sm bg-amber-50 border border-amber-200 rounded-lg p-3 text-amber-950"},Be={key:0},Re=["href"],Fe={key:1},Oe=["href"],We={class:"flex gap-2 mt-2"},He=["onClick"],Ke={class:"whitespace-pre-wrap"},ze={class:"text-[11px] mt-1 opacity-75"},Ye={key:0},Je={key:1},Qe=["onClick"],Xe=["onClick"],Ze={key:0,class:"p-4 border-t border-gray-100"},et=["disabled"],tt=["disabled"],st={key:1,class:"p-4 border-t border-gray-100 text-sm text-gray-600"},rt=ne({__name:"inbox",setup(nt){ce({title:"Inbox",description:"Your DogHealthy classifieds message inbox.",path:"/inbox",index:!1});const x=ie(),f=oe(),{refreshUnreadCount:P}=ae(),$=h(!0),p=h([]),_=h(null),b=h(""),D=h(!1),E=h(null),N=h(null),w=h(""),a=M(()=>p.value.find(s=>s.key===_.value)||null),W=M(()=>p.value.reduce((s,e)=>s+e.unreadCount,0)),H=M(()=>p.value.reduce((s,e)=>s+e.messageCount,0)),k=s=>s.sender_id===f.userId,K=(s,e)=>s.sender_id===e?!s.sender_deleted_at:s.recipient_id===e?!s.recipient_deleted_at:!1,z=s=>{const e=new Date(s),i=new Date;return e.toDateString()===i.toDateString()?e.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}):e.toLocaleDateString("en-GB",{day:"numeric",month:"short"})},Y=s=>new Date(s).toLocaleString("en-GB",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"}),J=(s,e)=>{if(!s.sender_id)return`guest:${s.listing_id}:${(s.guest_email||"").toLowerCase()}`;const i=s.sender_id===e?s.recipient_id:s.sender_id;return`user:${s.listing_id}:${i}`},Q=(s,e)=>{const i=new Map;for(const t of s){if(!K(t,e))continue;const u=J(t,e),d=t.doghealthy_listings?.title||"Listing",y=!t.sender_id;let m="User",C=null,j=null,L=null;y?(m=t.guest_name||"Guest",j=t.guest_email,L=t.guest_phone):(C=t.sender_id===e?t.recipient_id:t.sender_id,m="Message"),i.has(u)||i.set(u,{key:u,listingId:t.listing_id,listingTitle:d,counterpartName:m,counterpartUserId:C,guestEmail:j,guestPhone:L,isGuest:y,preview:t.content,lastAt:t.created_at,unreadCount:0,readCount:0,messageCount:0,messages:[]});const g=i.get(u);g.messages.push(t),g.messageCount+=1,t.created_at>=g.lastAt&&(g.lastAt=t.created_at,g.preview=t.content,y&&(g.counterpartName=t.guest_name||g.counterpartName,g.guestEmail=t.guest_email||g.guestEmail,g.guestPhone=t.guest_phone||g.guestPhone)),t.recipient_id===e?t.is_read?g.readCount+=1:g.unreadCount+=1:t.sender_id===e&&(g.readCount+=1)}return[...i.values()].map(t=>({...t,messages:t.messages.sort((u,d)=>new Date(u.created_at).getTime()-new Date(d.created_at).getTime())})).sort((t,u)=>new Date(u.lastAt).getTime()-new Date(t.lastAt).getTime())},T=async s=>{$.value=!0;try{const e=f.userId;if(!e)return;const{data:i,error:t}=await x.from("doghealthy_messages").select("*, doghealthy_listings(id, title)").or(`sender_id.eq.${e},recipient_id.eq.${e}`).order("created_at",{ascending:!0});if(t)throw t;p.value=Q(i||[],e);const u=[...new Set(p.value.filter(d=>d.counterpartUserId).map(d=>d.counterpartUserId))];if(u.length){const{data:d}=await x.from("doghealthy_users").select("id, full_name, email").in("id",u),y=new Map((d||[]).map(m=>[m.id,m]));p.value=p.value.map(m=>{if(!m.counterpartUserId)return m;const C=y.get(m.counterpartUserId);return C?{...m,counterpartName:C.full_name||C.email||"User"}:m})}if(s?.keepSelection)_.value&&(p.value.find(y=>y.key===_.value)||(_.value=p.value[0]?.key||null));else if(!_.value&&p.value.length)await q(p.value[0]);else if(_.value){const d=p.value.find(y=>y.key===_.value);d?await q(d):_.value=p.value[0]?.key||null}await P()}catch(e){console.error("loadInbox",e)}finally{$.value=!1}},q=async s=>{_.value=s.key,b.value="",G();const e=s.messages.filter(i=>!i.is_read&&i.recipient_id===f.userId).map(i=>i.id);e.length&&(await x.from("doghealthy_messages").update({is_read:!0}).in("id",e),s.unreadCount=0,s.readCount=s.messageCount,s.messages=s.messages.map(i=>e.includes(i.id)?{...i,is_read:!0}:i),await P()),await de(),E.value&&(E.value.scrollTop=E.value.scrollHeight)},X=s=>{k(s)&&(N.value=s.id,w.value=s.content)},G=()=>{N.value=null,w.value=""},Z=async s=>{if(!k(s)||!w.value.trim())return;const e=w.value.trim(),{error:i}=await x.from("doghealthy_messages").update({content:e,edited_at:new Date().toISOString()}).eq("id",s.id).eq("sender_id",f.userId);if(i){console.error(i),alert("Could not edit message.");return}G(),await T({keepSelection:!0}
1)},ee=async s=>{const e=f.userId;if(e){if(k(s)){if(!confirm("Delete this message? It will be removed for both people."))return;const{error:i}=await x.from("doghealthy_messages").delete().eq("id",s.id).eq("sender_id",e);if(i){console.error(i),alert("Could not delete message.");return}}else{if(!confirm("Remove this message from your inbox?"))return;const{error:i}=await x.from("doghealthy_messages").update({recipient_deleted_at:new Date().toISOString()}).eq("id",s.id).eq("recipient_id",e);if(i){console.error(i),alert("Could not delete message.");return}}await T({keepSelection:!0})}},te=async s=>{const e=f.userId;if(!e||!confirm("Remove this whole conversation from your inbox?"))return;const i=new Date().toISOString(),t=s.messages.filter(d=>d.sender_id===e).map(d=>d.id),u=s.messages.filter(d=>d.recipient_id===e).map(d=>d.id);t.length&&await x.from("doghealthy_messages").update({sender_deleted_at:i}).in("id",t),u.length&&await x.from("doghealthy_messages").update({recipient_deleted_at:i}).in("id",u),_.value=null,await T()},se=async()=>{if(!(!a.value||a.value.isGuest||!f.userId)&&!(!b.value.trim()||!a.value.counterpartUserId)){D.value=!0;try{const s=b.value.trim(),{error:e}=await x.from("doghealthy_messages").insert({listing_id:a.value.listingId,sender_id:f.userId,recipient_id:a.value.counterpartUserId,content:s});if(e)throw e;await x.from("doghealthy_notifications").insert({user_id:a.value.counterpartUserId,type:"message",reference_id:a.value.listingId,title:"New Message",message:s.slice(0,280),is_read:!1}),b.value="",await T({keepSelection:!0})}catch(s){console.error("sendReply",s),alert("Could not send reply. Please try again.")}finally{D.value=!1}}};return re(async()=>{f.loading&&await new Promise(s=>{const e=()=>{f.loading?setTimeout(e,40):s()};e()}),await T()}),(s,e)=>{const i=ue;return l(),r("div",pe,[n("div",ge,[n("div",me,[e[3]||(e[3]=n("div",null,[n("h1",{class:"text-3xl font-bold text-gray-900"},"Inbox"),n("p",{class:"text-gray-600 mt-1"}," Messages about your classifieds listings — including guest enquiries. ")],-1)),n("div",fe,[n("span",_e,c(o(W))+" unread ",1),n("span",xe,c(o(H))+" in inbox ",1)])]),o($)?(l(),r("div",ye,"Loading messages…")):o(p).length===0?(l(),r("div",be,[e[5]||(e[5]=n("div",{class:"text-5xl mb-4"},"📭",-1)),e[6]||(e[6]=n("h2",{class:"text-xl font-semibold text-gray-900 mb-2"},"No messages yet",-1)),e[7]||(e[7]=n("p",{class:"text-gray-600 mb-6"},"When someone contacts you about a listing, it will show up here.",-1)),V(i,{to:"/classifieds",class:"text-blue-600 font-medium hover:underline"},{default:A(()=>[...e[4]||(e[4]=[I("Browse classifieds",-1)])]),_:1})])):(l(),r("div",he,[n("div",ve,[(l(!0),r(U,null,B(o(p),t=>(l(),r("button",{key:t.key,type:"button",class:S(["w-full text-left px-4 py-3 border-b border-gray-100 hover:bg-gray-50 transition-colors",o(_)===t.key?"bg-blue-50 border-l-4 border-l-blue-600":""]),onClick:u=>q(t)},[n("div",ke,[n("div",Ce,[n("p",{class:S(["font-semibold text-gray-900 truncate",t.unreadCount?"text-blue-900":""])},c(t.counterpartName),3),n("p",Ie,c(t.listingTitle),1)]),n("div",Se,[t.unreadCount>0?(l(),r("span",De,c(t.unreadCount),1)):v("",!0),n("span",Te,c(t.messageCount)+" msg",1)])]),n("p",{class:S(["text-sm mt-1 line-clamp-2",t.unreadCount?"font-medium text-gray-900":"text-gray-600"])},c(t.preview),3),n("div",Ue,[n("p",Ee,c(z(t.lastAt)),1),n("p",$e,c(t.unreadCount)+" unread · "+c(t.readCount)+" read ",1)]),t.isGuest?(l(),r("span",Ne," Guest enquiry ")):v("",!0)],10,we))),128))]),n("div",qe,[o(a)?(l(),r(U,{key:1},[n("div",Me,[n("div",Pe,[n("div",null,[n("h2",je,c(o(a).counterpartName),1),n("p",Le,[e[8]||(e[8]=I(" Re: ",-1)),V(i,{to:`/classifieds/${o(a).listingId}`,class:"text-blue-600 hover:underline"},{default:A(()=>[I(c(o(a).listingTitle),1)]),_:1},8,["to"])]),n("p",Ve,c(o(a).unreadCount)+" unread · "+c(o(a).readCount)+" read · "+c(o(a).messageCount)+" total ",1)]),n("button",{type:"button",class:"text-xs text-red-600 hover:text-red-800 font-medium",onClick:e[0]||(e[0]=t=>te(o(a)))}," Clear from inbox ")]),o(a).isGuest?(l(),r("div",Ae,[e[11]||(e[11]=n("p",{class:"font-medium mb-1"},"Guest contact details",-1)),o(a).guestEmail?(l(),r("p",Be,[e[9]||(e[9]=I(" Email: ",-1)),n("a",{href:`mailto:${o(a).guestEmail}`,class:"underline"},c(o(a).guestEmail),9,Re)])):v("",!0),o(a).guestPhone?(l(),r("p",Fe,[e[10]||(e[10]=I(" Phone: ",-1)),n("a",{href:`tel:${o(a).guestPhone}`,class:"underline"},c(o(a).guestPhone),9,Oe)])):v("",!0),e[12]||(e[12]=n("p",{class:"text-xs mt-2 text-amber-800"}," This person isn’t registered — reply by email or phone. ",-1))])):v("",!0)]),n("div",{ref_key:"messagesEl",ref:E,class:"flex-1 overflow-y-auto p-4 space-y-3"},[(l(!0),r(U,null,B(o(a).messages,t=>(l(),r("div",{key:t.id,class:S(["flex",k(t)?"justify-end":"justify-start"])},[n("div",{class:S(["max-w-[85%] rounded-lg px-3 py-2 text-sm group relative",k(t)?"bg-blue-600 text-white":"bg-gray-100 text-gray-900"])},[o(N)===t.id?(l(),r(U,{key:0},[R(n("textarea",{"onUpdate:modelValue":e[1]||(e[1]=u=>O(w)?w.value=u:null),rows:"3",class:"w-full text-gray-900 rounded border border-gray-300 px-2 py-1 text-sm"},null,512),[[F,o(w)]]),n("div",We,[n("button",{type:"button",class:"text-xs font-semibold underline",onClick:u=>Z(t)},"Save",8,He),n("button",{type:"button",class:"text-xs opacity-80 underline",onClick:G},"Cancel")])],64)):(l(),r(U,{key:1},[n("p",Ke,c(t.content),1),n("p",ze,[I(c(Y(t.created_at))+" ",1),t.edited_at?(l(),r("span",Ye," · edited")):v("",!0),!t.is_read&&t.recipient_id===o(f).userId?(l(),r("span",Je," · unread")):v("",!0)]),n("div",{class:S(["flex gap-2 mt-1 text-[11px]",k(t)?"text-blue-100":"text-gray-500"])}
1,[k(t)?(l(),r("button",{key:0,type:"button",class:"underline opacity-80 hover:opacity-100",onClick:u=>X(t)}," Edit ",8,Qe)):v("",!0),n("button",{type:"button",class:"underline opacity-80 hover:opacity-100",onClick:u=>ee(t)}," Delete ",8,Xe)],2)],64))],2)],2))),128))],512),o(a).isGuest?(l(),r("div",st," Use the email or phone above to continue this conversation with the guest. ")):(l(),r("div",Ze,[n("form",{class:"flex gap-2",onSubmit:le(se,["prevent"])},[R(n("input",{"onUpdate:modelValue":e[2]||(e[2]=t=>O(b)?b.value=t:null),type:"text",required:"",placeholder:"Write a reply…",class:"flex-1 border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500",disabled:o(D)},null,8,et),[[F,o(b)]]),n("button",{type:"submit",disabled:o(D)||!o(b).trim(),class:"bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-semibold disabled:opacity-50"},c(o(D)?"…":"Send"),9,tt)],32)]))],64)):(l(),r("div",Ge," Select a conversation "))])]))])])}}});export{rt 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.