1import{c as Oe,u as Te,r as h,j as e,X as Ae,C as ue,E as H,w as Ee,J as Fe,B as $e,L as Le,N as _e}from"./index-C1bzktH2.js";import{u as qe,F as Me,a as y,b,c as w,d as N,e as oe,t as Re}from"./form-pmsNHfvk.js";import{U as Be,L as Ie,T as ze}from"./layout-shell-BWZOnZXL.js";import{a as de}from"./format-DJ6ii0ek.js";import{LOAN_LEDGER_ENABLED as le}from"./loans-page-BmWl5dKz.js";import{a as Ve,r as Ye,P as Y,s as Ue,t as he,i as Ge,v as He}from"./use-data-DJpvhWJo.js";import{S as Ke}from"./switch-CoI0Qndb.js";import{B as k}from"./button-wsGvj0vi.js";import{I as A}from"./input-B7MIbfY8.js";import{B as Ze}from"./bounded-date-picker-CKhoUmZu.js";import{B as K}from"./badge-DT60eL2O.js";import{C as ce}from"./checkbox-BY5bL0OC.js";import{T as Je}from"./textarea-CjZcEkUU.js";import{A as pe,b as xe,a as ge}from"./alert-PAq-m9Tl.js";import{D as fe,a as je,b as ye,c as be,d as we,e as Qe}from"./dialog-B6Jn0O56.js";import{A as We,a as Xe,b as et,c as tt,d as st,e as at,f as nt,g as rt}from"./alert-dialog-6fleYcIt.js";import{S as ot}from"./skeleton-RPXo7oo1.js";import{S as X,a as ee,b as te,c as se,d as V}from"./select-BmLmhL5s.js";import{H as lt}from"./house-dz5qMHEg.js";import{P as Ne}from"./plus-BOoEZTL7.js";import{C as ae}from"./circle-alert-Cfx85ov1.js";import{S as it}from"./search-DJ3N5aHD.js";import{C as dt}from"./chevron-down-sna3Fr62.js";import{A as ct}from"./arrow-up-down-tx8VihV6.js";import{B as mt}from"./banknote-BgS0s31g.js";import{A as ut}from"./arrow-left-Cft0ZNMu.js";import{P as ht}from"./pencil-07Lm6QZy.js";import{M as ie}
1from"./map-pin-Dns3vErB.js";import{C as pt}from"./circle-check-BThC6yWv.js";import{o as xt,s as S,b as gt,e as ft}from"./types-BJVkoEHY.js";import"./label-Cl_2e4hg.js";import"./landmark-BWVyZpRz.js";import"./receipt-Dv3DfI7M.js";import"./upload-BTIO5mLb.js";import"./file-text-FO0uNq0t.js";import"./log-out-LV8XNMo5.js";import"./account-display-UOtJtySJ.js";import"./rate-format-BUCU8cp9.js";import"./card-DMLjyOE0.js";import"./table-CMTj595R.js";import"./rotate-ccw-hMjC8HuR.js";import"./archive-0yxrBbeV.js";import"./invalidate-ledger-reports-BJYy4ign.js";import"./en-US-B2t2PTQ7.js";import"./endOfMonth-BdYOBJlA.js";import"./format-CPoXbVrY.js";import"./popover-DfmOnfds.js";import"./calendar-8hVef9xC.js";import"./index-BsvUWKEV.js";const jt=Oe("Key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]]),R={owned:{label:"Owned",blurb:"You own this property and rent it out.",Icon:lt,badgeClass:"bg-emerald-50 text-emerald-700 border-emerald-200"},leased:{label:"Leased",blurb:"You lease this property and sublet / operate it.",Icon:jt,badgeClass:"bg-sky-50 text-sky-700 border-sky-200"},managed:{label:"Managed",blurb:"You manage this property on behalf of an owner.",Icon:Be,badgeClass:"bg-violet-50 text-violet-700 border-violet-200"}};function yt({value:t,onChange:r,placeholder:o,testId:x}){const[D,l]=h.useState([]),[g,v]=h.useState(!1),[p,n]=h.useState(!1),[i,O]=h.useState("idle"),d=h.useRef(null),P=h.useRef(0),s=h.useRef(null);h.useEffect(()=>{const j=_=>{s.current&&!s.current.contains(_.target)&&v(!1)};return document.addEventListener("mousedown",j),()=>document.removeEventListener("mousedown",j)},[]);const m=j=>{if(r(j),d.current&&clearTimeout(d.current),j.trim().length<3){l([]),O("idle"),v(!1);return}d.current=setTimeout(async()=>{const _=++P.current;n(!0),v(!0);try{const Z=await fetch("/api/geocode/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:j})});if(_!==P.current)return;if(!Z.ok){l([]),O("unavailable");return}const E=await Z.json();if(_!==P.current)return;if(E.status==="error"){l([]),O("unavailable");return}const M=E.results??[];l(M),O(M.length>0?"results":"empty")}catch{if(_!==P.current)return;l([]),O("unavailable")}finally{_===P.current&&n(!1)}},400)},I=j=>{r(j.display_name),l([]),O("idle"),v(!1)},z=g&&(p||i==="results"||i==="empty"||i==="unavailable");return e.jsxs("div",{className:"relative",ref:s,children:[e.jsxs("div",{className:"relative",children:[e.jsx(ie,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground pointer-events-none"}),p&&e.jsx(H,{className:"absolute right-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 animate-spin text-muted-foreground"}),e.jsx(A,{className:"pl-9",placeholder:o??"Start typing an addressâ¦",value:t,onChange:j=>m(j.target.value),onFocus:()=>(D.length>0||i!=="idle")&&v(!0),autoComplete:"off","data-testid":x})]}),z&&e.jsxs("div",{className:"absolute z-50 top-full mt-1 left-0 right-0 bg-white border rounded-xl shadow-lg overflow-hidden",children:[i==="results"&&D.map(j=>e.jsxs("button",{type:"button",className:"w-full text-left px-4 py-2.5 text-sm hover:bg-neutral-50 border-b last:border-b-0 truncate",onMouseDown:()=>I(j),"data-testid":x?`${x}-suggestion`:void 0,children:[e.jsx(ie,{className:"inline w-3.5 h-3.5 mr-1.5 text-muted-foreground shrink-0"}),j.display_name]},j.place_id)),p&&i!=="results"&&e.jsxs("div",{className:"px-4 py-2.5 text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(H,{className:"w-3.5 h-3.5 animate-spin shrink-0"}),"Searching addressesâ¦"]}),!p&&i==="empty"&&e.jsx("div",{className:"px-4 py-2.5 text-sm text-muted-foreground","data-testid":x?`${x}-empty`:void 0,children:"No matching address found. Try a shorter address or enter it manually."}),!p&&i==="unavailable"&&e.jsx("div",{className:"px-4 py-2.5 text-sm text-muted-foreground","data-testid":x?`${x}-unavailable`:void 0,children:"Address lookup is unavailable right now â you can enter the address manually and continue."}),(i==="results"||i==="empty")&&!p&&e.jsx("div",{className:"px-4 py-2 text-xs text-muted-foreground bg-neutral-50 border-t","data-testid":x?`${x}-manual-hint`:void 0,children:"Canât find the address? You can enter it manually and continue."})]})]})}const bt=xt({name:S().min(2,"Name must be at least 2 characters"),address:S().optional(),propertyType:ft(Y),ownedAcquisitionDate:S().optional(),ownedPurchasePrice:S().optional(),ownedOwnershipPercent:S().optional(),leasedStartDate:S().optional(),leasedEndDate:S().optional(),leasedMonthlyRent:S().optional(),leasedSecurityDeposit:S().optional(),managedOwnerName:S().optional(),managedOwnerContact:S().optional(),managedFeePercent:S().optional(),managedFeeBasis:S().optional(),managedPayoutSchedule:S().optional(),managedOwnerStatementsEnabled:gt().optional(),managedDefaultCleaningFee:S().optional(),managedOwnerStatementNotes:S().optional(),managedOwnerEmail:S().optional()});function Q(t){if(!t||t.trim()==="")return;const r=Number(t.replace(/[,$ ]/g,""));if(!Number.isNaN(r))return Math.round(r*100)}function wt(t){const r={name:t.name,address:t.address||null,propertyType:t.propertyType};return t.propertyType==="owned"?r.ownedDetails={acquisitionDate:t.ownedAcquisitionDate||null,purchasePriceCents:Q(t.ownedPurchasePrice)??null,ownershipPercent:t.ownedOwnershipPercent||null}:t.propertyType==="leased"?r.leasedDetails={leaseStartDate:t.leasedStartDate||null,leaseEndDate:t.leasedEndDate||null,monthlyRentCents:Q(t.leasedMonthlyRent)??null,securityDepositCents:Q(t.leasedSecurityDeposit)??null}
1:r.managedDetails={ownerName:t.managedOwnerName||null,ownerContact:t.managedOwnerContact||null,mgmtFeePercent:t.managedFeePercent||null,mgmtFeeBasis:t.managedFeeBasis||"gross_rent",payoutSchedule:t.managedPayoutSchedule||null,ownerStatementsEnabled:t.managedOwnerStatementsEnabled??!1,defaultCleaningFeeCents:Q(t.managedDefaultCleaningFee)??0,ownerStatementNotes:t.managedOwnerStatementNotes||null,ownerEmail:t.managedOwnerEmail||null},r}function W(t){return t==null?"":(t/100).toFixed(2)}function Nt({propertyId:t,legacyLenderName:r,legacyMortgageBalanceCents:o}){const[,x]=Ee(),D=r!=null&&r!==""||o!=null,{data:l,isLoading:g}=Fe({queryKey:["/api/loans",{propertyId:t}],enabled:le&&t!=null,queryFn:async()=>(await _e("GET",`/api/loans?propertyId=${t}`)).json()}),v=()=>x(t!=null?`/loans?propertyId=${t}&new=1`:"/loans?new=1"),p=()=>x(t!=null?`/loans?propertyId=${t}`:"/loans"),n=l??[];return e.jsxs("div",{className:"rounded-lg border p-3 space-y-3","data-testid":"section-financing",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium",children:[e.jsx(mt,{className:"w-4 h-4"})," Financing"]}),le&&t!=null&&n.length>0&&e.jsx(k,{type:"button",variant:"outline",size:"sm",onClick:p,"data-testid":"button-manage-loans",children:"Manage Loans"})]}),le?t==null?e.jsx("p",{className:"text-sm text-muted-foreground","data-testid":"text-financing-save-first",children:"Save this property first, then attach loans to track financing."}):g?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Loadingâ¦"}):n.length===0?e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground","data-testid":"text-financing-empty",children:"No loans attached."}),e.jsxs(k,{type:"button",variant:"outline",size:"sm",onClick:v,"data-testid":"button-add-loan",children:[e.jsx(Ne,{className:"w-4 h-4 mr-1.5"})," Add Loan"]})]}):e.jsx("ul",{className:"divide-y",children:n.map(i=>e.jsxs("li",{className:"py-2 flex items-center justify-between text-sm","data-testid":`row-financing-loan-${i.id}`,children:[e.jsx("span",{className:"font-medium",children:i.name}),e.jsx("span",{className:"tabular-nums","data-testid":`text-financing-balance-${i.id}`,children:de(i.currentPrincipalCents)})]},i.id))}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loan tracking is currently disabled."}),D&&n.length===0&&e.jsxs(pe,{"data-testid":"alert-legacy-financing",children:[e.jsx(ae,{className:"h-4 w-4"}),e.jsx(xe,{children:"Legacy financing (from old property form)"}),e.jsxs(ge,{children:[r?e.jsxs("div",{children:["Lender: ",r]}):null,o!=null?e.jsxs("div",{children:["Mortgage balance: ",de(o)]}):null,e.jsx("div",{className:"mt-1",children:"Create a loan to start tracking this financing in the Loans module."})]})]})]})}function me({open:t,onOpenChange:r,property:o}){const x=Ue(),D=he(),l=!!o,{data:g}=Ge(l?o.id:null),[v,p]=h.useState(l?2:1);h.useEffect(()=>{p(l?2:1)},[l,t]);const n=qe({resolver:Re(bt),defaultValues:{name:o?.name||"",address:o?.address||"",propertyType:o?.propertyType||"owned",ownedAcquisitionDate:"",ownedPurchasePrice:"",ownedOwnershipPercent:"",leasedStartDate:"",leasedEndDate:"",leasedMonthlyRent:"",leasedSecurityDeposit:"",managedOwnerName:"",managedOwnerContact:"",managedFeePercent:"",managedFeeBasis:"gross_rent",managedPayoutSchedule:"",managedOwnerStatementsEnabled:!1,managedDefaultCleaningFee:"",managedOwnerStatementNotes:"",managedOwnerEmail:""}});h.useEffect(()=>{if(!g||!l)return;const s=g.details??{},m=g.propertyType;n.reset({name:g.name,address:g.address??"",propertyType:m,ownedAcquisitionDate:s.acquisitionDate??"",ownedPurchasePrice:m==="owned"?W(s.purchasePriceCents):"",ownedOwnershipPercent:s.ownershipPercent??"",leasedStartDate:s.leaseStartDate??"",leasedEndDate:s.leaseEndDate??"",leasedMonthlyRent:m==="leased"?W(s.monthlyRentCents):"",leasedSecurityDeposit:m==="leased"?W(s.securityDepositCents):"",managedOwnerName:s.ownerName??"",managedOwnerContact:s.ownerContact??"",managedFeePercent:s.mgmtFeePercent??"",managedFeeBasis:(m==="managed"?s.mgmtFeeBasis:"")||"gross_rent",managedPayoutSchedule:s.payoutSchedule??"",managedOwnerStatementsEnabled:m==="managed"?!!s.ownerStatementsEnabled:!1,managedDefaultCleaningFee:m==="managed"?W(s.defaultCleaningFeeCents):"",managedOwnerStatementNotes:s.ownerStatementNotes??"",managedOwnerEmail:s.ownerEmail??""})},[g,l]);const i=n.watch("propertyType"),O=R[i].Icon,d=async s=>{const m=wt(s);try{l?await D.mutateAsync({id:o.id,...m,typeConfirmed:!0}):await x.mutateAsync({...m,typeConfirmed:!0}),r(!1),n.reset()}catch{}},P=l?D.isPending:x.isPending;return e.jsx(fe,{open:t,onOpenChange:r,children:e.jsxs(je,{className:"max-w-lg",children:[e.jsxs(ye,{children:[e.jsx(be,{children:l?"Edit Property":"Add New Property"}),e.jsx(we,{children:v===1?"First, tell us what kind of property this is. You can change this later.":l?"Update the details of your property.":"Enter the details of your property."})]}),v===1?e.jsxs("div",{className:"space-y-3 py-2",children:[Y.map(s=>{const m=R[s],I=m.Icon,z=i===s;return e.jsxs("button",{type:"button",onClick:()=>n.setValue("propertyType",s),className:`w-full text-left p-4 rounded-xl border-2 transition-all flex items-start gap-3 ${z?"border-primary bg-primary/5":"border-neutral-200 hover:border-neutral-300"}`,"data-testid":`button-type-${s}`,children:[e.jsx("div",{className:`w-10 h-10 rounded-lg flex items-center justify-center shrink-0 ${m.badgeClass}`,children:e.jsx(I,{className:"w-5 h-5"})}),e.jsxs("div",{className:"space-y-0.5",children:[e.jsx("div",{className:"font-medium",children:m.label}),e.jsx("div",{className:"text-sm text-muted-foreground",children:m.blurb})]})]},s)}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx(k,{type:"button",variant:"ghost",onClick:()=>r(!1),"data-testid":"button-cancel-step1",children:"Cancel"}),e.jsx(k,{type:"button",onClick:()=>p(2),"data-testid":"button-next-step1",children:"Next"})]})]}):e.jsx(Me,{...n,children:e.jsxs("form",{onSubmit:n.handleSubmit(d),className:"space-y-4 max-h-[60vh] overflow-y-auto pr-1",children:[l&&e.jsx(y,{control:n.control,name:"propertyType",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Property Type"}),e.jsxs(X,{onValueChange:s.onChange,value:s.value,children:[e.jsx(N,{children:e.jsx(ee,{"data-testid":"select-property-type",children:e.jsx(te,{})})}),e.jsx(se,{children:Y.map(m=>e.jsx(V,{value:m,"data-testid":`select-item-type-${m}`,children:R[m].label},m))})]}),e.jsx(oe,{})]})}),e.jsx(y,{control:n.control,name:"name",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Property Name"}),e.jsx(N,{children:e.jsx(A,{placeholder:"e.g. Seaside Villa",...s,"data-testid":"input-property-name"})}),e.jsx(oe,{})]})}),e.jsx(y,{control:n.control,name:"address",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Address"}),e.jsx(N,{children:e.jsx(yt,{value:s.value??"",onChange:s.onChange,placeholder:"123 Ocean Drive",testId:"input-property-address"})}),e.jsx(oe,{})]})}),e.jsxs("div",{className:"rounded-lg border bg-neutral-50/50 p-3 flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(O,{className:"w-4 h-4"}),e.jsxs("span",{children:[R[i].label," â optional details below."]})]}),i==="owned"&&e.jsxs("div",{className:"space-y-3 border-l-2 border-emerald-200 pl-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(y,{control:n.control,name:"ownedAcquisitionDate",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Acquisition Date"}),e.jsx(N,{children:e.jsx(Ze,{className:"max-w-none",value:s.value??"",onChange:s.onChange,"data-testid":"input-owned-acquisition"})})]})}),e.jsx(y,{control:n.control,name:"ownedPurchasePrice",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Purchase Price ($)"}),e.jsx(N,{children:e.jsx(A,{placeholder:"350000",...s,"data-testid":"input-owned-price"})})]})})]}),e.jsx(y,{control:n.control,name:"ownedOwnershipPercent",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Ownership %"}),e.jsx(N,{children:e.jsx(A,{placeholder:"100",...s,"data-testid":"input-owned-percent"})})]})}),e.jsx(Nt,{propertyId:l&&o?o.id:null,legacyLenderName:g?.details?.lenderName??null,legacyMortgageBalanceCents:g?.details?.mortgageBalanceCents??null})]}),i==="leased"&&e.jsxs("div",{className:"space-y-3 border-l-2 border-sky-200 pl-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(y,{control:n.control,name:"leasedStartDate",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Lease Start"}),e.jsx(N,{children:e.jsx(A,{type:"date",...s,"data-testid":"input-leased-start"})})]})}),e.jsx(y,{control:n.control,name:"leasedEndDate",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Lease End"}),e.jsx(N,{children:e.jsx(A,{type:"date",...s,"data-testid":"input-leased-end"})})]})})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(y,{control:n.control,name:"leasedMonthlyRent",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Monthly Rent ($)"}),e.jsx(N,{children:e.jsx(A,{placeholder:"2400",...s,"data-testid":"input-leased-rent"})})]})}),e.jsx(y,{control:n.control,name:"leasedSecurityDeposit",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Security Deposit ($)"}),e.jsx(N,{children:e.jsx(A,{placeholder:"2400",...s,"data-testid":"input-leased-deposit"})})]})})]})]}),i==="managed"&&e.jsxs("div",{className:"space-y-3 border-l-2 border-violet-200 pl-4",children:[e.jsx(y,{control:n.control,name:"managedOwnerContact",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Owner Contact"}),e.jsx(N,{children:e.jsx(A,{placeholder:"[email protected]",...s,"data-testid":"input-managed-owner-contact"})})]})}),e.jsx(y,{control:n.control,name:"managedPayoutSchedule",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Payout Schedule"}),e.jsxs(X,{onValueChange:s.onChange,value:s.value||"",children:[e.jsx(N,{children:e.jsx(ee,{"data-testid":"select-managed-payout",children:e.jsx(te,{placeholder:"Choose"})})}),e.jsxs(se,{children:[e.jsx(V,{value:"monthly",children:"Monthly"}),e.jsx(V,{value:"weekly",children:"Weekly"}),e.jsx(V,{value:"on_booking",children:"On Booking"})]})]})]})}),e.jsxs("div",{className:"rounded-lg border p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("div",{className:"text-sm font-medium",children:"Owner Statements"}),e.jsx(y,{control:n.control,name:"managedOwnerStatementsEnabled",render:({field:s})=>e.jsxs(b,{className:"flex items-center gap-2 space-y-0",children:[e.jsx(w,{className:"text-sm text-muted-foreground",children:"Enable"}),e.jsx(N,{children:e.jsx(Ke,{checked:!!s.value,onCheckedChange:s.onChange,"data-testid":"checkbox-owner-statements-enabled"})})]})})]}),e.jsx(y,{control:n.control,name:"managedOwnerName",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Owner Name"}),e.jsx(N,{children:e.jsx(A,{placeholder:"Jane Smith",...s,"data-testid":"input-managed-owner-name"})})]})}),e.jsx(y,{control:n.control,name:"managedOwnerEmail",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Owner Email"}),e.jsx(N,{children:e.jsx(A,{type:"email",placeholder:"[email protected]",...s,"data-testid":"input-managed-owner-email"})})]})}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(y,{control:n.control,name:"managedFeePercent",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Management Fee %"}),e.jsx(N,{children:e.jsx(A,{placeholder:"10",...s,"data-testid":"input-managed-fee"})})]})}),e.jsx(y,{control:n.control,name:"managedDefaultCleaningFee",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Default Cleaning Fee ($)"}),e.jsx(N,{children:e.jsx(A,{placeholder:"120",...s,"data-testid":"input-managed-cleaning-fee"})})]})})]}),e.jsx(y,{control:n.control,name:"managedFeeBasis",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Management Fee Formula"}),e.jsxs(X,{onValueChange:s.onChange,value:s.value||"gross_rent",children:[e.jsx(N,{children:e.jsx(ee,{"data-testid":"select-managed-fee-basis",children:e.jsx(te,{placeholder:"Choose"})})}),e.jsxs(se,{children:[e.jsx(V,{value:"gross_rent",children:"Commission on Gross Rent"}),e.jsx(V,{value:"gross_rent_less_cleaning",children:"Commission on Gross Rent less Cleaning Fee"})]})]})]})}),e.jsx(y,{control:n.control,name:"managedOwnerStatementNotes",render:({field:s})=>e.jsxs(b,{children:[e.jsx(w,{children:"Statement Notes"}),e.jsx(N,{children:e.jsx(Je,{placeholder:"Notes shown on the owner statement (optional)",rows:2,...s,"data-testid":"input-owner-statement-notes"})})]})})]})]}),e.jsxs("div",{className:"flex justify-between gap-3 pt-4 sticky bottom-0 bg-white",children:[l?e.jsx("span",{}):e.jsxs(k,{type:"button",variant:"ghost",onClick:()=>p(1),"data-testid":"button-back-step2",children:[e.jsx(ut,{className:"w-4 h-4 mr-2"})," Back"]}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx(k,{type:"button",variant:"ghost",onClick:()=>r(!1),"data-testid":"button-cancel-property",children:"Cancel"}),e.jsxs(k,{type:"submit",disabled:P,"data-testid":"button-save-property",children:[P&&e.jsx(H,{className:"w-4 h-4 animate-spin mr-2"}),l?"Save Changes":"Add Property"]})]})]})]})})]})})}function ve({type:t}){const r=R[t],o=r.Icon;return e.jsxs(K,{variant:"outline",className:`${r.badgeClass} font-normal`,"data-testid":`badge-property-type-${t}`,children:[e.jsx(o,{className:"w-3 h-3 mr-1"}),r.label]})}function vt(t){const r=t.details??{};return t.propertyType==="owned"?[["Acquired",r.acquisitionDate||"â"],["Lender",r.lenderName||"â"]]:t.propertyType==="leased"?[["Lease end",r.leaseEndDate||"â"],["Lease start",r.leaseStartDate||"â"]]:[["Owner",r.ownerName||"â"],["Payout",r.payoutSchedule||"â"]]}function Ct({open:t,onOpenChange:r,properties:o}){const x=he(),[D,l]=h.useState({}),[g,v]=h.useState(!1);h.useEffect(()=>{if(t){const d={};for(const P of o)d[P.id]=!0;l(d)}},[t,o]);const p=o.length>0&&o.every(d=>D[d.id]),n=o.filter(d=>D[d.id]).map(d=>d.id),i=()=>
1{if(p)l({});else{const d={};for(const P of o)d[P.id]=!0;l(d)}},O=async()=>{v(!0);try{for(const d of n)await x.mutateAsync({id:d,typeConfirmed:!0});r(!1)}finally{v(!1)}};return e.jsx(fe,{open:t,onOpenChange:r,children:e.jsxs(je,{className:"max-w-lg",children:[e.jsxs(ye,{children:[e.jsx(be,{children:"Review unconfirmed properties"}),e.jsx(we,{children:"These properties were set to âOwnedâ by default. Confirm the ones whose type is correct, or close this and open a single property to change its type."})]}),e.jsx("div",{className:"max-h-[50vh] overflow-y-auto space-y-2 py-2",children:o.length===0?e.jsx("div",{className:"text-sm text-muted-foreground text-center py-4",children:"Nothing left to confirm."}):e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-neutral-50 cursor-pointer",children:[e.jsx(ce,{checked:p,onCheckedChange:i,"data-testid":"checkbox-bulk-confirm-all"}),e.jsx("span",{className:"text-sm font-medium",children:"Select all"})]}),o.map(d=>{const P=d.propertyType;return e.jsxs("label",{className:"flex items-center gap-3 px-3 py-2 rounded-lg border hover:bg-neutral-50 cursor-pointer","data-testid":`row-bulk-confirm-${d.id}`,children:[e.jsx(ce,{checked:!!D[d.id],onCheckedChange:s=>l(m=>({...m,[d.id]:!!s})),"data-testid":`checkbox-bulk-confirm-${d.id}`}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm font-medium truncate",children:d.name}),e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:d.address||"No address listed"})]}),e.jsx(ve,{type:P})]},d.id)})]})}),e.jsxs(Qe,{children:[e.jsx(k,{variant:"ghost",onClick:()=>r(!1),"data-testid":"button-bulk-cancel",children:"Cancel"}),e.jsxs(k,{onClick:O,disabled:g||n.length===0,"data-testid":"button-bulk-confirm",children:[g&&e.jsx(H,{className:"w-4 h-4 animate-spin mr-2"}),"Confirm ",n.length," ",n.length===1?"property":"properties"]})]})]})})}function St({propertyId:t}){const{data:r}=He(),o=r?.find(x=>x.propertyId===t);return o?o.ready?e.jsxs(K,{variant:"outline",className:"bg-green-50 text-green-700 border-green-200 font-normal gap-1","data-testid":`badge-onboarding-ready-${t}`,children:[e.jsx(pt,{className:"w-3 h-3"})," Ready"]}):e.jsxs(K,{variant:"outline",className:"bg-amber-50 text-amber-700 border-amber-200 font-normal gap-1","data-testid":`badge-onboarding-steps-${t}`,children:[e.jsx(ae,{className:"w-3 h-3"}),o.warnCount," setup ",o.warnCount===1?"step":"steps"]}):null}function Dt({property:t,onEdit:r,onDelete:o,canDelete:x}){const D=t.propertyType,l=R[D],g=l.Icon,v=vt(t);return e.jsxs("div",{className:"group p-6 rounded-2xl border bg-white hover:border-primary/50 hover:shadow-lg transition-all duration-300","data-testid":`card-property-${t.id}`,children:[e.jsxs("div",{className:"flex items-start justify-between mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary group-hover:bg-primary group-hover:text-white transition-colors",children:e.jsx($e,{className:"w-5 h-5"})}),e.jsx(ve,{type:D}),!t.typeConfirmed&&e.jsx(K,{variant:"outline",className:"bg-amber-50 text-amber-700 border-amber-200 font-normal","data-testid":`badge-unconfirmed-${t.id}`,children:"Unconfirmed"}),e.jsx(St,{propertyId:t.id})]}),e.jsxs("div",{className:"flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx(k,{variant:"ghost",size:"icon",className:"h-8 w-8",onClick:()=>r(t),"data-testid":`button-edit-property-${t.id}`,children:e.jsx(ht,{className:"w-3.5 h-3.5"})}),x&&e.jsx(k,{variant:"ghost",size:"icon",className:"h-8 w-8 hover:text-destructive",onClick:()=>o(t),"data-testid":`button-delete-property-${t.id}`,children:e.jsx(ze,{className:"w-3.5 h-3.5"})})]})]}),e.jsx(Le,{href:`/properties/${t.id}`,children:e.jsxs("a",{className:"block","data-testid":`link-property-${t.id}`,children:[e.jsx("h3",{className:"text-xl font-semibold mb-1 hover:text-primary transition-colors","data-testid":`text-property-name-${t.id}`,children:t.name}),e.jsxs("div",{className:"flex items-center text-sm text-muted-foreground",children:[e.jsx(ie,{className:"w-3.5 h-3.5 mr-1.5"}),e.jsx("span",{"data-testid":`text-property-address-${t.id}`,children:t.address||"No address listed"})]}),e.jsx("dl",{className:"mt-4 grid grid-cols-2 gap-x-3 gap-y-1.5",children:v.map(([p,n])=>e.jsxs("div",{className:"flex flex-col",children:[e.jsx("dt",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:p}),e.jsx("dd",{className:"text-sm font-medium truncate","data-testid":`card-meta-${t.id}-${p.toLowerCase().replace(/\s+/g,"-")}`,children:n})]},p))}),e.jsxs("div",{className:"mt-3 flex items-center text-xs text-muted-foreground gap-1.5",children:[e.jsx(g,{className:"w-3 h-3"}),e.jsx("span",{children:l.blurb})]}),e.jsxs("div",{className:"mt-4 flex items-center justify-end gap-1 text-sm font-medium text-primary","data-testid":`link-view-property-${t.id}`,children:[e.jsx("span",{children:"View property"}),e.jsx(ue,{className:"w-4 h-4"})]})]})})]})}function Ns(){const{data:t,isLoading:r}=Ve(),o=Ye(),{isSofiaStaff:x}=Te(),[D,l]=h.useState(!1),[g,v]=h.useState(null),[p,n]=h.useState(null),[i,O]=h.useState(new Set),[d,P]=h.useState(new Set),[s,m]=h.useState(!1),[I,z]=h.useState(""),j=h.useDeferredValue(I),[_,Z]=h.useState({owned:"acquisition_desc",leased:"lease_end_asc",managed:"owner_asc"}),E=t??[],M=h.useMemo(()=>E.filter(a=>!a.typeConfirmed),[E]),Ce=h.useMemo(()=>{const a={owned:0,leased:0,managed:0};for(const u of E)a[u.propertyType]=(a[u.propertyType]??0)+1;return a},[E]),J=h.useMemo(()=>{const a=j.trim().toLowerCase();return E.filter(u=>{if(i.size>0&&!i.has(u.propertyType))return!1;if(a.length===0)return!0;const f=(u.name??"").toLowerCase(),T=(u.address??"").toLowerCase();return f.includes(a)||T.includes(a)})},[E,i,j]),Se=h.useMemo(()=>{const a={owned:[],leased:[],managed:[]};for(const c of J)a[c.propertyType].push(c);const u=(c,C)=>(c.name??"").localeCompare(C.name??"",void 0,{sensitivity:"base"}),f=c=>{if(typeof c!="string"||!c)return NaN;const C=Date.parse(c);return Number.isNaN(C)?NaN:C},T=(c,C,G)=>{const F=f(c),$=f(C),L=Number.isNaN(F),B=Number.isNaN($);return L&&B?0:L?1:B?-1:G==="asc"?F-$:$-F},U=(c,C)=>{const G=typeof c=="string"?c:"",F=typeof C=="string"?C:"",$=G.trim()==="",L=F.trim()==="";return $&&L?0:$?1:L?-1:G.localeCompare(F,void 0,{sensitivity:"base"})};for(const c of Y){const C=_[c];a[c].sort((F,$)=>{const L=F.details??{},B=$.details??{};let q=0;return c==="owned"?C==="acquisition_desc"?q=T(L.acquisitionDate,B.acquisitionDate,"desc"):C==="acquisition_asc"?q=T(L.acquisitionDate,B.acquisitionDate,"asc"):q=u(F,$):c==="leased"?C==="lease_end_asc"?q=T(L.leaseEndDate,B.leaseEndDate,"asc"):C==="lease_end_desc"?q=T(L.leaseEndDate,B.leaseEndDate,"desc"):q=u(F,$):C==="owner_asc"?q=U(L.ownerName,B.ownerName):q=u(F,$),q!==0?q:u(F,$)})}return a},[J,_]),De={owned:[{value:"acquisition_desc",label:"Acquisition date (newest)"},{value:"acquisition_asc",label:"Acquisition date (oldest)"},{value:"name",label:"Name (AâZ)"}],leased:[{value:"lease_end_asc",label:"Lease end (soonest)"},{value:"lease_end_desc",label:"Lease end (latest)"},{value:"name",label:"Name (AâZ)"}],managed:[{value:"owner_asc",label:"Owner name (AâZ)"},{value:"name",label:"Property name (AâZ)"}]},ne=j.trim().length>0,re=i.size>0,Pe=a=>{O(u=>{const f=new Set(u);return f.has(a)?f.delete(a):f.add(a),f})},ke=a=>{P(u=>{const f=new Set(u);return f.has(a)?f.delete(a):f.add(a),f})};return e.jsxs(Ie,{children:[e.jsxs("div",{className:"max-w-5xl mx-auto
1space-y-6",children:[e.jsxs("div",{className:"flex flex-col md:flex-row md:items-center justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("h1",{className:"text-3xl font-serif text-primary",children:"Properties"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage your rental units and homes."})]}),e.jsxs(k,{size:"lg",className:"shadow-lg shadow-primary/20",onClick:()=>l(!0),"data-testid":"button-add-property",children:[e.jsx(Ne,{className:"w-4 h-4 mr-2"}),"Add Property"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-2 px-4 py-3 rounded-xl border bg-white","data-testid":"strip-portfolio-glance",children:[e.jsx("span",{className:"text-xs uppercase tracking-wide text-muted-foreground font-medium",children:"Portfolio at a glance"}),Y.map(a=>{const u=R[a],f=u.Icon;return e.jsxs("span",{className:"flex items-center gap-1.5 text-sm","data-testid":`stat-count-${a}`,children:[e.jsx(f,{className:"w-3.5 h-3.5 text-muted-foreground"}),e.jsx("span",{className:"font-semibold",children:Ce[a]}),e.jsx("span",{className:"text-muted-foreground",children:u.label.toLowerCase()})]},a)}),M.length>0&&e.jsxs("span",{className:"flex items-center gap-1.5 text-sm","data-testid":"stat-count-unconfirmed",children:[e.jsx(ae,{className:"w-3.5 h-3.5 text-amber-600"}),e.jsx("span",{className:"font-semibold",children:M.length}),e.jsx("span",{className:"text-muted-foreground",children:"unconfirmed"})]})]}),M.length>0&&e.jsxs(pe,{"data-testid":"alert-confirm-types",children:[e.jsx(ae,{className:"h-4 w-4"}),e.jsx(xe,{children:"Confirm your property types"}),e.jsxs(ge,{className:"flex flex-col md:flex-row md:items-center md:justify-between gap-3 mt-1",children:[e.jsx("span",{children:M.length===1?"1 property was set to âOwnedâ by default. Open it to confirm or change the type.":`${M.length} properties were set to âOwnedâ by default. Open each one to confirm or change the type.`}),e.jsx(k,{variant:"outline",size:"sm",onClick:()=>m(!0),"data-testid":"button-review-unconfirmed",children:"Review all unconfirmed"})]})]}),e.jsxs("div",{className:"relative",children:[e.jsx(it,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground pointer-events-none"}),e.jsx(A,{value:I,onChange:a=>z(a.target.value),placeholder:"Search by name or addressâ¦",className:"pl-9 pr-9","data-testid":"input-property-search","aria-label":"Search properties"}),I&&e.jsx("button",{type:"button",onClick:()=>z(""),className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded-md text-muted-foreground hover:text-foreground hover:bg-neutral-100","aria-label":"Clear search","data-testid":"button-clear-search",children:e.jsx(Ae,{className:"w-3.5 h-3.5"})})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:"Filter by type:"}),Y.map(a=>{const u=R[a],f=u.Icon,T=i.has(a);return e.jsxs("button",{type:"button",onClick:()=>Pe(a),className:`inline-flex items-center gap-1.5 px-3 py-1 rounded-full border text-sm transition-all ${T?`${u.badgeClass} border-current`:"bg-white text-muted-foreground border-neutral-200 hover:border-neutral-400"}`,"data-testid":`chip-filter-${a}`,"aria-pressed":T,children:[e.jsx(f,{className:"w-3.5 h-3.5"}),u.label]},a)}),i.size>0&&e.jsx("button",{type:"button",onClick:()=>O(new Set),className:"text-xs text-muted-foreground underline hover:text-foreground ml-1","data-testid":"button-clear-filter",children:"Clear"}),(ne||re)&&E.length>0&&e.jsxs("span",{className:"text-xs text-muted-foreground ml-auto","data-testid":"text-result-count",children:["Showing ",J.length," of ",E.length]})]}),r?e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:Array.from({length:4}).map((a,u)=>e.jsx(ot,{className:"h-44 rounded-xl"},u))}):E.length===0?e.jsx("div",{className:"py-12 text-center text-muted-foreground bg-neutral-50 rounded-xl border border-dashed",children:"No properties found. Add one to get started."}):J.length===0?e.jsxs("div",{className:"py-12 text-center text-muted-foreground bg-neutral-50 rounded-xl border border-dashed space-y-3","data-testid":"empty-state-no-matches",children:[e.jsx("div",{children:ne?e.jsxs(e.Fragment,{children:["No properties match ",e.jsxs("span",{className:"font-medium text-foreground",children:['"',j,'"']}),re?" with the current type filter.":"."]}):"No properties match this filter."}),e.jsxs("div",{className:"flex items-center justify-center gap-2",children:[ne&&e.jsx(k,{variant:"outline",size:"sm",onClick:()=>z(""),"data-testid":"button-clear-search-empty",children:"Clear search"}),re&&e.jsx(k,{variant:"outline",size:"sm",onClick:()=>O(new Set),"data-testid":"button-clear-filter-empty",children:"Clear filter"})]})]}):e.jsx("div",{className:"space-y-6",children:Y.map(a=>{const u=R[a],f=u.Icon,T=Se[a];if(T.length===0)return null;const U=d.has(a);return e.jsxs("section",{"data-testid":`section-${a}`,children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 mb-3",children:[e.jsxs("button",{type:"button",onClick:()=>ke(a),className:"flex items-center gap-2 group","data-testid":`button-toggle-section-${a}`,"aria-expanded":!U,children:[U?e.jsx(ue,{className:"w-4 h-4 text-muted-foreground group-hover:text-foreground"}):e.jsx(dt,{className:"w-4 h-4 text-muted-foreground group-hover:text-foreground"}),e.jsx(f,{className:"w-4 h-4 text-muted-foreground"}),e.jsx("h2",{className:"text-lg font-semibold",children:u.label}),e.jsx(K,{variant:"outline",className:"font-normal","data-testid":`badge-section-count-${a}`,children:T.length})]}),!U&&T.length>1&&e.jsxs("div",{className:"flex items-center gap-1.5 text-sm text-muted-foreground",children:[e.jsx(ct,{className:"w-3.5 h-3.5"}),e.jsxs(X,{value:_[a],onValueChange:c=>Z(C=>({...C,[a]:c})),children:[e.jsx(ee,{className:"h-8 w-[200px] text-sm","data-testid":`select-sort-${a}`,children:e.jsx(te,{})}),e.jsx(se,{children:De[a].map(c=>e.jsx(V,{value:c.value,"data-testid":`select-sort-${a}-${c.value}`,children:c.label},c.value))})]})]})]}),!U&&e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:T.map(c=>e.jsx(Dt,{property:c,onEdit:v,onDelete:n,canDelete:!x},c.id))})]},a)})})]}),e.jsx(me,{open:D,onOpenChange:l}),g&&e.jsx(me,{open:!0,onOpenChange:a=>{a||v(null)},property:g},g.id),e.jsx(Ct,{open:s,onOpenChange:m,properties:M}),e.jsx(We,{open:!!p,onOpenChange:a=>{a||n(null)},children:e.jsxs(Xe,{children:[e.jsxs(et,{children:[e.jsx(tt,{children:"Delete Property"}),e.jsxs(st,{children:['Are you sure you want to delete "',p?.name,'"? This cannot be undone. Transactions linked to this property will not be deleted, but they will lose their property assignment.']})]}),e.jsxs(at,{children:[e.jsx(nt,{"data-testid":"button-cancel-delete",children:"Cancel"}),e.jsxs(rt,{className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",disabled:o.isPending,onClick:()=>{p&&o.mutate(p.id,{onSettled:()=>n(null)})},"data-testid":"button-confirm-delete",children:[o.isPending&&e.jsx(H,{className:"w-4 h-4 animate-spin mr-2"}),"Delete"]})]})]})})]})}export{R as PROPERTY_TYPE_META,Nt as PropertyFinancingSummary,me as PropertyFormDialog,ve as PropertyTypeBadge,Ns 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.