PageSourceSearch

https://housekings.com/assets/AdminProperties-DsBtLfzg.js

js housekings.com collected 2026-10-08 20:58:00 UTC 13,330 bytes, 1 lines download raw bytes

1import{w as ce,r as d,o as pe,v as i,j as t,at as me,I as K,a as H,B as A,C as ue,X as fe}from"./index-C9ARtntu.js";import{P as ge}from"./PortalLayout-B5jEVFlc.js";import{C as D,d as E}from"./card-CvV5FR2v.js";import{T as he}from"./textarea-TXdTqvcY.js";import{A as X,b as Q,c as W,d as Y,e as Z,f as ee,g as te,h as re}from"./alert-dialog-CU9JAI4D.js";import{h as xe,P as ve}from"./psaGate-C5maepMW.js";import{S as se,e as $,a as x}from"./constants-BOzeTIYf.js";import{S as ye}from"./StageMetricBadge-BblV9FfW.js";import{f as be}from"./dates-B12sT4ak.js";import{S as _e}from"./ShareListingLink--cE0awRK.js";import{S as je}from"./search-CBq_P0_e.js";import{T as we}from"./trash-2-Bp-ZIwxN.js";import"./sheet-CiYIa4Mm.js";import"./index-BNKmmuc7.js";import"./Combination-DXLXaj1V.js";import"./NoIndexMeta-BnydGd9z.js";import"./crown-SMOcZKdJ.js";import"./log-out-DVVsyEEz.js";import"./layout-dashboard-ZXDEqVhJ.js";import"./plus-CjYtSx2x.js";import"./calculator-Bfef4nZm.js";import"./settings-gRWYiS4A.js";import"./file-text-DqKYCTRV.js";import"./inbox-Bvt2HvSL.js";import"./trending-up-DaXFQrvB.js";import"./differenceInCalendarDays-BV5Kr9EH.js";import"./copy-B68x3O_w.js";import"./external-link-D5NSgPBF.js";import"./link-2-Bicw9jOS.js";const et=()=>{const[v,k]=ce(),h=(v.get("filter")??"")==="under_review",[y,ae]=d.useState("awaiting"),[u,m]=d.useState([]),[q,ie]=d.useState(""),[b,_]=d.useState(!0),[j,F]=d.useState(null),[T,c]=d.useState(null),[f,R]=d.useState(null),[M,w]=d.useState(""),[g,L]=d.useState(null),[P,N]=d.useState(""),C=v.get("stage")??"",{toast:p}=pe();d.useEffect(()=>{(async()=>{_(!0),F(null);const{data:e,error:r}=await i.from("properties").select("*").order("created_at",{ascending:!1});if(r){console.error("AdminProperties: failed to load properties",r),F(r.message),m([]),_(!1);return}if(!e||e.length===0){m([]),_(!1);return}const s=Array.from(new Set(e.map(o=>o.jv_user_id).filter(Boolean)));let a=new Map;if(s.length>0){const{data:o,error:n}=await i.from("profiles").select("user_id, full_name, email").in("user_id",s);n&&console.warn("AdminProperties: profile lookup failed",n),a=new Map((o??[]).map(l=>[l.user_id,l]))}m(e.map(o=>({...o,profiles:a.get(o.jv_user_id)??null}))),_(!1)})()},[]),d.useEffect(()=>{const e=i.channel("admin-properties-feed").on("postgres_changes",{event:"*",schema:"public",table:"properties"},()=>{S()}).subscribe();return()=>{i.removeChannel(e)}},[]);const S=async()=>{const{data:e}=await i.from("properties").select("*").order("created_at",{ascending:!1});if(!e)return;const r=Array.from(new Set(e.map(a=>a.jv_user_id).filter(Boolean)));let s=new Map;if(r.length>0){const{data:a}=await i.from("profiles").select("user_id, full_name, email").in("user_id",r);s=new Map((a??[]).map(o=>[o.user_id,o]))}m(e.map(a=>({...a,profiles:s.get(a.jv_user_id)??null})))},B=(e,r,s)=>{var l,G;if(!((l=e.profiles)!=null&&l.email))return;const a=r==="property_approved",o=a?"property-stage-approved":"property-status-change",n={partnerName:(G=e.profiles.full_name)==null?void 0:G.split(" ")[0],propertyAddress:e.street_address,city:e.city,state:e.state,zip:e.zip,notes:s||void 0};a||(n.fromStageLabel=x[e.stage],n.toStageLabel=x[r]),i.functions.invoke("send-app-email",{body:{templateName:o,recipientEmail:e.profiles.email,idempotencyKey:`quick-${r}-${e.id}-${Date.now()}`,templateData:n}}).catch(()=>{})},oe=async e=>{if(e.stage==="property_approved")return;if(c(e.id),!await xe(e.id))return c(null),p({title:"Purchase & Sale Agreement required",description:ve,variant:"destructive"});const r=e.stage;m(o=>o.map(n=>n.id===e.id?{...n,stage:"property_approved"}:n));const{error:s}=await i.from("properties").update({stage:"property_approved"}).eq("id",e.id);if(s)return c(null),m(o=>o.map(n=>n.id===e.id?{...n,stage:r}:n)),p({title:"Failed to approve",description:s.message,variant:"destructive"});const{data:{user:a}}=await i.auth.getUser();a&&await i.from("property_status_history").insert({property_id:e.id,changed_by:a.id,from_stage:r,to_stage:"property_approved",notes:"Approved from properties list"}),B(e,"property_approved"),p({title:"Property approved",description:"JV partner has been notified by email."}),c(null),S()},ne=async()=>
1{if(!g)return;if(P.trim().toUpperCase()!=="DELETE")return p({title:"Type DELETE to confirm",variant:"destructive"});const e=g;c(e.id),await i.from("property_status_history").delete().eq("property_id",e.id),await i.from("property_field_history").delete().eq("property_id",e.id),await i.from("property_critical_dates").delete().eq("property_id",e.id),await i.from("property_documents").delete().eq("property_id",e.id),await i.from("jv_agreements").delete().eq("property_id",e.id),await i.from("investor_email_campaigns").update({property_id:null}).eq("property_id",e.id);const{error:r}=await i.from("properties").delete().eq("id",e.id);if(r)return c(null),p({title:"Failed to delete",description:r.message,variant:"destructive"});p({title:"Property deleted",description:`${e.street_address} removed.`}),L(null),N(""),await S(),c(null)},le=async()=>{if(!f)return;const e=M.trim();if(!e)return p({title:"Reason required",description:"Please add a short note explaining why.",variant:"destructive"});const r=f;c(r.id);const s=r.stage;m(n=>n.map(l=>l.id===r.id?{...l,stage:"dead"}:l));const{error:a}=await i.from("properties").update({stage:"dead"}).eq("id",r.id);if(a)return c(null),m(n=>n.map(l=>l.id===r.id?{...l,stage:s}:l)),p({title:"Failed to reject",description:a.message,variant:"destructive"});const{data:{user:o}}=await i.auth.getUser();o&&await i.from("property_status_history").insert({property_id:r.id,changed_by:o.id,from_stage:s,to_stage:"dead",notes:e}),B(r,"dead",e),p({title:"Property rejected",description:"Marked as Dead Deal and JV notified."}),R(null),w(""),c(null),S()},U=e=>e==="under_review"||e==="new_submitted",V=u.filter(e=>{var r;if(h){const s=!!e.review_completed_at||e.stage==="property_approved";if(!U(e.stage)&&!(y==="completed"&&s)||y==="awaiting"&&e.review_completed_at||y==="completed"&&!s)return!1}return C&&e.stage!==C?!1:`${e.street_address} ${e.city} ${((r=e.profiles)==null?void 0:r.full_name)||""}`.toLowerCase().includes(q.toLowerCase())}),I=(()=>{const e={};return se.forEach((r,s)=>{e[r]=s}),e.new_submitted=-2,e.under_review=-1,e.dead=90,e.seller_backed_out=91,e.draft=99,e})(),de=[...V].sort((e,r)=>{const s=I[e.stage]??50,a=I[r.stage]??50;return s!==a?s-a:(r.created_at||"").localeCompare(e.created_at||"")}),J=u.reduce((e,r)=>(e[r.stage]=(e[r.stage]??0)+1,e),{}),O=["new_submitted","under_review",...se.filter(e=>e!=="new_submitted"),"dead","seller_backed_out","draft"].filter((e,r,s)=>s.indexOf(e)===r&&(J[e]??0)>0),z={awaiting:u.filter(r=>U(r.stage)).filter(r=>!r.review_completed_at).length,completed:u.filter(r=>r.review_completed_at||r.stage==="property_approved").length};return t.jsxs(ge,{children:[t.jsxs("div",{className:"max-w-6xl",children:[t.jsxs("h1",{className:"text-2xl md:text-3xl font-display mb-4 flex items-center gap-2",children:[h&&t.jsx(me,{className:"w-6 h-6 text-primary"}),h?"Properties Under Review":"All Properties"]}),h&&t.jsxs("div",{className:"flex gap-2 mb-4 border-b",role:"tablist","aria-label":"Review status filter",children:[[{key:"awaiting",label:"Awaiting",count:z.awaiting},{key:"completed",label:"Completed",count:z.completed}].map(e=>{const r=y===e.key;return t.jsxs("button",{type:"button",role:"tab","aria-selected":r,onClick:()=>ae(e.key),className:`px-3 py-2 text-sm font-semibold border-b-2 -mb-px transition-colors ${r?"border-primary text-primary":"border-transparent text-muted-foreground hover:text-foreground"}`,children:[e.label,t.jsx("span",{className:`ml-1.5 text-[11px] rounded-full px-1.5 py-0.5 ${e.key==="awaiting"?"bg-amber-100 text-amber-900":"bg-emerald-100 text-emerald-900"}`,children:e.count})]},e.key)}),t.jsx("button",{type:"button",onClick:()=>k({}),className:"ml-auto px-3 py-2 text-xs text-muted-foreground hover:text-foreground",children:"View all properties →"})]}),!h&&O.length>0&&t.jsxs("div",{className:"mb-4",children:[t.jsx("div",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground mb-2",children:"Filter by stage"}),t.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[t.jsxs("button",{type:"button",onClick:()=>{const e=new URLSearchParams(v);e.delete("stage"),k(e)},className:`text-xs px-2.5 py-1 rounded-full border font-semibold whitespace-nowrap transition-colors ${C?"bg-background hover:bg-muted border-border text-foreground":"bg-primary text-primary-foreground border-primary"}`,children:["All ",t.jsxs("span",{className:"opacity-70",children:["(",u.length,")"]})]}),O.map(e=>{const r=C===e;return t.jsxs("button",{type:"button",onClick:()=>{const s=new URLSearchParams(v);r?s.delete("stage"):s.set("stage",e),k(s)},className:`text-xs px-2.5 py-1 rounded-full border font-semibold whitespace-nowrap transition-all ${r?`${$[e]} ring-2 ring-primary ring-offset-1`:`${$[e]} opacity-70 hover:opacity-100`}`,title:`Show only ${x[e]}`,children:[x[e]," ",t.jsxs("span",{className:"opacity-70",children:["(",J[e],")"]})]},e)})]})]}),t.jsxs("div",{className:"relative mb-4",children:[t.jsx(je,{className:"w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"}),t.jsx(K,{value:q,onChange:e=>ie(e.target.value),className:"pl-9 h-11"})]}),b&&t.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading properties…"}),j&&!b&&t.jsx(D,{className:"border-destructive/40",children:t.jsxs(E,{className:"p-4 text-sm text-destructive",children:["Failed to load properties: ",j]})}),!b&&!j&&u.length===0&&t.jsx(D,{children:t.jsx(E,{className:"p-4 text-sm text-muted-foreground",children:"No properties have been submitted yet."})}),!b&&!j&&u.length>0&&V.length===0&&t.jsx(D,{children:t.jsx(E,{className:"p-4 text-sm text-muted-foreground",children:"No properties match your search."})}),t.jsx("div",{className:"grid gap-2",children:de.map(e=>{var r;return t.jsx(D,{className:"hover:border-primary/40",children:t.jsxs(E,{className:"p-3 flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3",children:[t.jsxs(H,{to:`/jv/admin/properties/${e.id}`,className:"min-w-0 flex-1 block",children:[t.jsxs("div",{className:"font-semibold break-words",children:[e.street_address,", ",e.city]}),t.jsxs("div",{className:"text-xs text-muted-foreground break-words",children:["JV: ",((r=e.profiles)==null?void 0:r.full_name)||"—"," • ",be(e.created_at)]})]}),t.jsxs("div",{className:"flex items-center gap-2 flex-wrap self-start sm:self-auto",children:[t.jsx("span",{className:`text-xs px-2 py-1 rounded-full border font-semibold whitespace-nowrap ${$[e.stage]}`,children:x[e.stage]}),t.jsx(ye,{stage:e.stage,hideDefault:!0}),t.jsx(A,{asChild:!0,size:"sm",variant:"outline",children:t.jsx(H,{to:`/jv/admin/properties/${e.id}#edit`,children:"Edit"})}),t.jsx(_e,{propertyId:e.id,stage:e.stage,isDraft:e.is_draft,variant:"inline"}),e.stage==="new_submitted"&&!e.is_draft&&t.jsxs(t.Fragment,{children:[t.jsxs(A,{size:"sm",variant:"default",disabled:T===e.id,onClick:s=>{s.preventDefault(),oe(e)},className:"h-8 bg-emerald-600 hover:bg-emerald-700 text-white",children:[t.jsx(ue,{className:"w-3.5 h-3.5 mr-1"})," Approve"]}),t.jsxs(A,{size:"sm",variant:"outline",disabled:T===e.id,onClick:s=>{s.preventDefault(),R(e),w("")},className:"h-8 border-destructive/50 text-destructive hover:bg-destructive/10",children:[t.jsx(fe,{className:"w-3.5 h-3.5 mr-1"})," Reject"]})]}),t.jsx(A,{size:"sm",variant:"ghost",disabled:T===e.id,onClick:s=>{s.preventDefault(),L(e),N("")},className:"h-8 text-destructive hover:bg-destructive/10",title:"Delete property",children:t.jsx(we,{className:"w-3.5 h-3.5"})})]})]})},e.id)})})]}),t.jsx(X,{open:!!f,onOpenChange:e=>{e||(R(null),w(""))},children:t.jsxs(Q,{children:[t.jsxs(W,{children:[t.jsx(Y,{children:"Reject this property?"}),t.jsxs(Z,{children:[f&&t.jsxs(t.Fragment,{children:[t.jsxs("strong",{children:[f.street_address,", ",f.city]}),t.jsx("br",{})]}),"This will mark it as a Dead Deal and email the JV partner your reason."]})]}),t.jsxs("div",{className:"space-y-2",children:[t.jsx("label",{className:"text-sm font-semibold",children:"Reason (sent to JV partner)"}),t.jsx(he,{rows:4,value:M,onChange:e=>w(e.target.value)})]}),t.jsxs(ee,{children:[t.jsx(te,{children:"Cancel"}),t.jsx(re,{onClick:le,className:"bg-destructive hover:bg-destructive/90",children:"Reject & notify JV"})]})]})}),t.jsx(X,{open:!!g,onOpenChange:e=>{e||(L(null),N(""))},children:t.jsxs(Q,{children:[t.jsxs(W,{children:[t.jsx(Y,{children:"Delete this property permanently?"}),t.jsxs(Z,{children:[g&&t.jsxs(t.Fragment,{children:[t.jsxs("strong",{children:[g.street_address,", ",g.city]}),t.jsx("br",{})]}),"This permanently removes the property, its agreement, dates, documents, and history. The JV partner is ",t.jsx("strong",{children:"not"})," notified. This cannot be undone."]})]}),t.jsxs("div",{className:"space-y-2",children:[t.jsxs("label",{className:"text-sm font-semibold",children:["Type ",t.jsx("span",{className:"font-mono",children:"DELETE"})," to confirm"]}),t.jsx(K,{value:P,onChange:e=>N(e.target.value),autoFocus:!0})]}),t.jsxs(ee,{children:[t.jsx(te,{children:"Cancel"}),t.jsx(re,{onClick:ne,disabled:P.trim().toUpperCase()!=="DELETE",className:"bg-destructive hover:bg-destructive/90",children:"Delete forever"})]})]})})]})};export{et 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.