@burdenoff/microfe-housingvista 2026.703.11 → 2026.703.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/housingvista/HousingVistaRoutes.js +31 -20
  2. package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
  3. package/dist/housingvista/components/ContactOwnerDialog.js +74 -58
  4. package/dist/housingvista/components/ContactOwnerDialog.js.map +1 -1
  5. package/dist/housingvista/components/PropertyCard.js +92 -67
  6. package/dist/housingvista/components/PropertyCard.js.map +1 -1
  7. package/dist/housingvista/hooks/messages.js +66 -0
  8. package/dist/housingvista/hooks/messages.js.map +1 -0
  9. package/dist/housingvista/pages/HomePage.js +182 -146
  10. package/dist/housingvista/pages/HomePage.js.map +1 -1
  11. package/dist/housingvista/pages/amc/AMCManagementPage.js +212 -217
  12. package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
  13. package/dist/housingvista/pages/analytics/AnalyticsPage.js +377 -213
  14. package/dist/housingvista/pages/analytics/AnalyticsPage.js.map +1 -1
  15. package/dist/housingvista/pages/assets/AssetDetailPage.js +237 -144
  16. package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
  17. package/dist/housingvista/pages/assets/AssetManagementPage.js +357 -233
  18. package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
  19. package/dist/housingvista/pages/chat/ChatPage.js +260 -0
  20. package/dist/housingvista/pages/chat/ChatPage.js.map +1 -0
  21. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +157 -154
  22. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
  23. package/dist/housingvista/pages/finance/HomeLoansPage.js +162 -161
  24. package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
  25. package/dist/housingvista/pages/investments/InvestmentDetailPage.js +3 -3
  26. package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
  27. package/dist/housingvista/pages/investments/InvestmentsPage.js +347 -234
  28. package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
  29. package/dist/housingvista/pages/legal/LegalPage.js +146 -119
  30. package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
  31. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +132 -132
  32. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
  33. package/dist/housingvista/pages/market/AreaInsightsPage.js +150 -115
  34. package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
  35. package/dist/housingvista/pages/market/MarketAnalyticsPage.js +321 -203
  36. package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
  37. package/dist/housingvista/pages/marketplace/MarketplacePage.js +89 -77
  38. package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
  39. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +2 -2
  40. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
  41. package/dist/housingvista/pages/offers/OffersPage.js +297 -172
  42. package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
  43. package/dist/housingvista/pages/properties/AddPropertyPage.js +37 -13
  44. package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
  45. package/dist/housingvista/pages/properties/PropertiesPage.js +1 -0
  46. package/dist/housingvista/pages/properties/PropertiesPage.js.map +1 -1
  47. package/dist/housingvista/pages/properties/PropertyDetailPage.js +803 -583
  48. package/dist/housingvista/pages/properties/PropertyDetailPage.js.map +1 -1
  49. package/dist/housingvista/pages/rental/RentalManagementPage.js +513 -418
  50. package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
  51. package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -30
  52. package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
  53. package/dist/housingvista/pages/transactions/TransactionDetailPage.js +207 -199
  54. package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
  55. package/dist/housingvista/pages/transactions/TransactionsPage.js +204 -84
  56. package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
  57. package/dist/housingvista/pages/transactions/milestones.js +68 -0
  58. package/dist/housingvista/pages/transactions/milestones.js.map +1 -0
  59. package/dist/housingvista/pages/verification/VerificationPage.js +175 -125
  60. package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
  61. package/dist/housingvista/pages/viewings/ViewingsPage.js +241 -136
  62. package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
  63. package/dist/housingvista/utils/helpers.js +26 -7
  64. package/dist/housingvista/utils/helpers.js.map +1 -1
  65. package/dist/node_modules/lodash/maxBy.js +17 -0
  66. package/dist/node_modules/lodash/maxBy.js.map +1 -0
  67. package/dist/node_modules/lodash/minBy.js +17 -0
  68. package/dist/node_modules/lodash/minBy.js.map +1 -0
  69. package/dist/node_modules/recharts/es6/chart/BarChart.js +24 -0
  70. package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -0
  71. package/dist/node_modules/recharts/es6/chart/PieChart.js +34 -0
  72. package/dist/node_modules/recharts/es6/chart/PieChart.js.map +1 -0
  73. package/dist/node_modules/recharts/es6/polar/Pie.js +435 -0
  74. package/dist/node_modules/recharts/es6/polar/Pie.js.map +1 -0
  75. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +215 -0
  76. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js.map +1 -0
  77. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +268 -0
  78. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js.map +1 -0
  79. package/dist/node_modules/recharts/es6/shape/Polygon.js +112 -0
  80. package/dist/node_modules/recharts/es6/shape/Polygon.js.map +1 -0
  81. package/dist/node_modules/recharts/es6/util/PolarUtils.js +133 -51
  82. package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
  83. package/package.json +1 -1
@@ -9,8 +9,8 @@ var c = () => /* @__PURE__ */ o("div", {
9
9
  className: "text-sm text-text-secondary",
10
10
  children: "Loading..."
11
11
  })
12
- }), l = n(() => import("./pages/properties/PropertiesPage.js").then((e) => ({ default: e.PropertiesPage }))), u = n(() => import("./pages/properties/AddPropertyPage.js").then((e) => ({ default: e.AddPropertyPage }))), d = n(() => import("./pages/properties/PropertyDetailPage.js").then((e) => ({ default: e.PropertyDetailPage }))), f = n(() => import("./pages/shortlist/ShortlistPage.js").then((e) => ({ default: e.ShortlistPage }))), p = n(() => import("./pages/transactions/TransactionsPage.js").then((e) => ({ default: e.TransactionsPage }))), m = n(() => import("./pages/transactions/TransactionDetailPage.js").then((e) => ({ default: e.TransactionDetailPage }))), h = n(() => import("./pages/investments/InvestmentsPage.js").then((e) => ({ default: e.InvestmentsPage }))), g = n(() => import("./pages/investments/InvestmentDetailPage.js").then((e) => ({ default: e.InvestmentDetailPage }))), _ = n(() => import("./pages/offers/OffersPage.js").then((e) => ({ default: e.OffersPage }))), v = n(() => import("./pages/viewings/ViewingsPage.js").then((e) => ({ default: e.ViewingsPage }))), y = n(() => import("./pages/analytics/AnalyticsPage.js").then((e) => ({ default: e.AnalyticsPage }))), b = n(() => import("./pages/rental/RentalManagementPage.js").then((e) => ({ default: e.RentalManagementPage }))), x = n(() => import("./pages/assets/AssetManagementPage.js").then((e) => ({ default: e.AssetManagementPage }))), S = n(() => import("./pages/assets/AssetDetailPage.js").then((e) => ({ default: e.AssetDetailPage }))), C = n(() => import("./pages/amc/AMCManagementPage.js").then((e) => ({ default: e.AMCManagementPage }))), w = n(() => import("./pages/marketplace/MarketplacePage.js").then((e) => ({ default: e.MarketplacePage }))), T = n(() => import("./pages/marketplace/ServiceDetailPage.js").then((e) => ({ default: e.ServiceDetailPage }))), E = n(() => import("./pages/verification/VerificationPage.js").then((e) => ({ default: e.VerificationPage }))), D = n(() => import("./pages/verification/VerificationDetailPage.js").then((e) => ({ default: e.VerificationDetailPage }))), O = n(() => import("./pages/legal/LegalPage.js").then((e) => ({ default: e.LegalPage }))), k = n(() => import("./pages/legal/LegalServiceDetailPage.js").then((e) => ({ default: e.LegalServiceDetailPage }))), A = n(() => import("./pages/finance/HomeLoansPage.js").then((e) => ({ default: e.HomeLoansPage }))), j = n(() => import("./pages/finance/HomeLoanDetailPage.js").then((e) => ({ default: e.HomeLoanDetailPage }))), M = n(() => import("./pages/market/MarketAnalyticsPage.js").then((e) => ({ default: e.MarketAnalyticsPage }))), N = n(() => import("./pages/market/AreaInsightsPage.js").then((e) => ({ default: e.AreaInsightsPage }))), P = n(() => import("./pages/settings/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), F = n(() => import("./pages/settings/ProfilePage.js").then((e) => ({ default: e.ProfilePage })));
13
- function I() {
12
+ }), l = n(() => import("./pages/properties/PropertiesPage.js").then((e) => ({ default: e.PropertiesPage }))), u = n(() => import("./pages/properties/AddPropertyPage.js").then((e) => ({ default: e.AddPropertyPage }))), d = n(() => import("./pages/properties/PropertyDetailPage.js").then((e) => ({ default: e.PropertyDetailPage }))), f = n(() => import("./pages/shortlist/ShortlistPage.js").then((e) => ({ default: e.ShortlistPage }))), p = n(() => import("./pages/transactions/TransactionsPage.js").then((e) => ({ default: e.TransactionsPage }))), m = n(() => import("./pages/transactions/TransactionDetailPage.js").then((e) => ({ default: e.TransactionDetailPage }))), h = n(() => import("./pages/investments/InvestmentsPage.js").then((e) => ({ default: e.InvestmentsPage }))), g = n(() => import("./pages/investments/InvestmentDetailPage.js").then((e) => ({ default: e.InvestmentDetailPage }))), _ = n(() => import("./pages/offers/OffersPage.js").then((e) => ({ default: e.OffersPage }))), v = n(() => import("./pages/viewings/ViewingsPage.js").then((e) => ({ default: e.ViewingsPage }))), y = n(() => import("./pages/chat/ChatPage.js").then((e) => ({ default: e.ChatPage }))), b = n(() => import("./pages/analytics/AnalyticsPage.js").then((e) => ({ default: e.AnalyticsPage }))), x = n(() => import("./pages/rental/RentalManagementPage.js").then((e) => ({ default: e.RentalManagementPage }))), S = n(() => import("./pages/assets/AssetManagementPage.js").then((e) => ({ default: e.AssetManagementPage }))), C = n(() => import("./pages/assets/AssetDetailPage.js").then((e) => ({ default: e.AssetDetailPage }))), w = n(() => import("./pages/amc/AMCManagementPage.js").then((e) => ({ default: e.AMCManagementPage }))), T = n(() => import("./pages/marketplace/MarketplacePage.js").then((e) => ({ default: e.MarketplacePage }))), E = n(() => import("./pages/marketplace/ServiceDetailPage.js").then((e) => ({ default: e.ServiceDetailPage }))), D = n(() => import("./pages/verification/VerificationPage.js").then((e) => ({ default: e.VerificationPage }))), O = n(() => import("./pages/verification/VerificationDetailPage.js").then((e) => ({ default: e.VerificationDetailPage }))), k = n(() => import("./pages/legal/LegalPage.js").then((e) => ({ default: e.LegalPage }))), A = n(() => import("./pages/legal/LegalServiceDetailPage.js").then((e) => ({ default: e.LegalServiceDetailPage }))), j = n(() => import("./pages/finance/HomeLoansPage.js").then((e) => ({ default: e.HomeLoansPage }))), M = n(() => import("./pages/finance/HomeLoanDetailPage.js").then((e) => ({ default: e.HomeLoanDetailPage }))), N = n(() => import("./pages/market/MarketAnalyticsPage.js").then((e) => ({ default: e.MarketAnalyticsPage }))), P = n(() => import("./pages/market/AreaInsightsPage.js").then((e) => ({ default: e.AreaInsightsPage }))), F = n(() => import("./pages/settings/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), I = n(() => import("./pages/settings/ProfilePage.js").then((e) => ({ default: e.ProfilePage })));
13
+ function L() {
14
14
  return /* @__PURE__ */ o(t, {
15
15
  fallback: /* @__PURE__ */ o(c, {}),
16
16
  children: /* @__PURE__ */ s(a, { children: [
@@ -59,73 +59,84 @@ function I() {
59
59
  element: /* @__PURE__ */ o(v, {})
60
60
  }),
61
61
  /* @__PURE__ */ o(i, {
62
- path: "analytics",
62
+ path: "chat",
63
63
  element: /* @__PURE__ */ o(y, {})
64
64
  }),
65
65
  /* @__PURE__ */ o(i, {
66
- path: "rental",
66
+ path: "messages",
67
+ element: /* @__PURE__ */ o(r, {
68
+ to: "../chat",
69
+ replace: !0
70
+ })
71
+ }),
72
+ /* @__PURE__ */ o(i, {
73
+ path: "analytics",
67
74
  element: /* @__PURE__ */ o(b, {})
68
75
  }),
69
76
  /* @__PURE__ */ o(i, {
70
- path: "assets",
77
+ path: "rental",
71
78
  element: /* @__PURE__ */ o(x, {})
72
79
  }),
73
80
  /* @__PURE__ */ o(i, {
74
- path: "assets/:id",
81
+ path: "assets",
75
82
  element: /* @__PURE__ */ o(S, {})
76
83
  }),
77
84
  /* @__PURE__ */ o(i, {
78
- path: "amc",
85
+ path: "assets/:id",
79
86
  element: /* @__PURE__ */ o(C, {})
80
87
  }),
81
88
  /* @__PURE__ */ o(i, {
82
- path: "marketplace",
89
+ path: "amc",
83
90
  element: /* @__PURE__ */ o(w, {})
84
91
  }),
85
92
  /* @__PURE__ */ o(i, {
86
- path: "marketplace/:id",
93
+ path: "marketplace",
87
94
  element: /* @__PURE__ */ o(T, {})
88
95
  }),
89
96
  /* @__PURE__ */ o(i, {
90
- path: "verification",
97
+ path: "marketplace/:id",
91
98
  element: /* @__PURE__ */ o(E, {})
92
99
  }),
93
100
  /* @__PURE__ */ o(i, {
94
- path: "verification/:id",
101
+ path: "verification",
95
102
  element: /* @__PURE__ */ o(D, {})
96
103
  }),
97
104
  /* @__PURE__ */ o(i, {
98
- path: "legal",
105
+ path: "verification/:id",
99
106
  element: /* @__PURE__ */ o(O, {})
100
107
  }),
101
108
  /* @__PURE__ */ o(i, {
102
- path: "legal/:id",
109
+ path: "legal",
103
110
  element: /* @__PURE__ */ o(k, {})
104
111
  }),
105
112
  /* @__PURE__ */ o(i, {
106
- path: "home-loans",
113
+ path: "legal/:id",
107
114
  element: /* @__PURE__ */ o(A, {})
108
115
  }),
109
116
  /* @__PURE__ */ o(i, {
110
- path: "home-loans/:id/apply",
117
+ path: "home-loans",
111
118
  element: /* @__PURE__ */ o(j, {})
112
119
  }),
113
120
  /* @__PURE__ */ o(i, {
114
- path: "market-analytics",
121
+ path: "home-loans/:id/apply",
115
122
  element: /* @__PURE__ */ o(M, {})
116
123
  }),
117
124
  /* @__PURE__ */ o(i, {
118
- path: "area-insights",
125
+ path: "market-analytics",
119
126
  element: /* @__PURE__ */ o(N, {})
120
127
  }),
121
128
  /* @__PURE__ */ o(i, {
122
- path: "settings",
129
+ path: "area-insights",
123
130
  element: /* @__PURE__ */ o(P, {})
124
131
  }),
125
132
  /* @__PURE__ */ o(i, {
126
- path: "profile",
133
+ path: "settings",
127
134
  element: /* @__PURE__ */ o(F, {})
128
135
  }),
136
+ /* @__PURE__ */ o(i, {
137
+ path: "profile",
138
+ element: /* @__PURE__ */ o(I, {})
139
+ }),
129
140
  /* @__PURE__ */ o(i, {
130
141
  path: "*",
131
142
  element: /* @__PURE__ */ o(r, {
@@ -137,6 +148,6 @@ function I() {
137
148
  });
138
149
  }
139
150
  //#endregion
140
- export { I as HousingVistaRoutes };
151
+ export { L as HousingVistaRoutes };
141
152
 
142
153
  //# sourceMappingURL=HousingVistaRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HousingVistaRoutes.js","names":[],"sources":["../../src/housingvista/HousingVistaRoutes.tsx"],"sourcesContent":["/**\n * HousingVista Routes\n * All route definitions with lazy loading.\n * @module housingvista\n */\n\nimport { lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\n\n// Eagerly load the home page\nimport { HomePage } from './pages/HomePage';\n\n// Loading fallback\nconst PageLoader = () => (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"text-sm text-text-secondary\">Loading...</div>\n </div>\n);\n\n// ── Properties ──────────────────────────────────────────────────────────────\nconst PropertiesPage = lazy(() =>\n import('./pages/properties/PropertiesPage').then((m) => ({ default: m.PropertiesPage }))\n);\nconst AddPropertyPage = lazy(() =>\n import('./pages/properties/AddPropertyPage').then((m) => ({ default: m.AddPropertyPage }))\n);\nconst PropertyDetailPage = lazy(() =>\n import('./pages/properties/PropertyDetailPage').then((m) => ({ default: m.PropertyDetailPage }))\n);\nconst ShortlistPage = lazy(() => import('./pages/shortlist/ShortlistPage').then((m) => ({ default: m.ShortlistPage })));\n\n// ── Transactions ────────────────────────────────────────────────────────────\nconst TransactionsPage = lazy(() =>\n import('./pages/transactions/TransactionsPage').then((m) => ({ default: m.TransactionsPage }))\n);\nconst TransactionDetailPage = lazy(() =>\n import('./pages/transactions/TransactionDetailPage').then((m) => ({ default: m.TransactionDetailPage }))\n);\n\n// ── Investments ─────────────────────────────────────────────────────────────\nconst InvestmentsPage = lazy(() =>\n import('./pages/investments/InvestmentsPage').then((m) => ({ default: m.InvestmentsPage }))\n);\nconst InvestmentDetailPage = lazy(() =>\n import('./pages/investments/InvestmentDetailPage').then((m) => ({ default: m.InvestmentDetailPage }))\n);\n\n// ── Offers ──────────────────────────────────────────────────────────────────\nconst OffersPage = lazy(() => import('./pages/offers/OffersPage').then((m) => ({ default: m.OffersPage })));\n\n// ── Viewings ────────────────────────────────────────────────────────────────\nconst ViewingsPage = lazy(() => import('./pages/viewings/ViewingsPage').then((m) => ({ default: m.ViewingsPage })));\n\n// ── Analytics ───────────────────────────────────────────────────────────────\nconst AnalyticsPage = lazy(() => import('./pages/analytics/AnalyticsPage').then((m) => ({ default: m.AnalyticsPage })));\n\n// ── Rental Management ───────────────────────────────────────────────────────\nconst RentalManagementPage = lazy(() =>\n import('./pages/rental/RentalManagementPage').then((m) => ({ default: m.RentalManagementPage }))\n);\n\n// ── Asset Management ────────────────────────────────────────────────────────\nconst AssetManagementPage = lazy(() =>\n import('./pages/assets/AssetManagementPage').then((m) => ({ default: m.AssetManagementPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\n\n// ── AMC Management ──────────────────────────────────────────────────────────\nconst AMCManagementPage = lazy(() =>\n import('./pages/amc/AMCManagementPage').then((m) => ({ default: m.AMCManagementPage }))\n);\n\n// ── Marketplace ─────────────────────────────────────────────────────────────\nconst MarketplacePage = lazy(() =>\n import('./pages/marketplace/MarketplacePage').then((m) => ({ default: m.MarketplacePage }))\n);\nconst ServiceDetailPage = lazy(() =>\n import('./pages/marketplace/ServiceDetailPage').then((m) => ({ default: m.ServiceDetailPage }))\n);\n\n// ── Verification ────────────────────────────────────────────────────────────\nconst VerificationPage = lazy(() =>\n import('./pages/verification/VerificationPage').then((m) => ({ default: m.VerificationPage }))\n);\nconst VerificationDetailPage = lazy(() =>\n import('./pages/verification/VerificationDetailPage').then((m) => ({ default: m.VerificationDetailPage }))\n);\n\n// ── Legal ───────────────────────────────────────────────────────────────────\nconst LegalPage = lazy(() => import('./pages/legal/LegalPage').then((m) => ({ default: m.LegalPage })));\nconst LegalServiceDetailPage = lazy(() =>\n import('./pages/legal/LegalServiceDetailPage').then((m) => ({ default: m.LegalServiceDetailPage }))\n);\n\n// ── Finance ─────────────────────────────────────────────────────────────────\nconst HomeLoansPage = lazy(() => import('./pages/finance/HomeLoansPage').then((m) => ({ default: m.HomeLoansPage })));\nconst HomeLoanDetailPage = lazy(() =>\n import('./pages/finance/HomeLoanDetailPage').then((m) => ({ default: m.HomeLoanDetailPage }))\n);\n\n// ── Market ──────────────────────────────────────────────────────────────────\nconst MarketAnalyticsPage = lazy(() =>\n import('./pages/market/MarketAnalyticsPage').then((m) => ({ default: m.MarketAnalyticsPage }))\n);\nconst AreaInsightsPage = lazy(() =>\n import('./pages/market/AreaInsightsPage').then((m) => ({ default: m.AreaInsightsPage }))\n);\n\n// ── Settings ────────────────────────────────────────────────────────────────\nconst SettingsPage = lazy(() => import('./pages/settings/SettingsPage').then((m) => ({ default: m.SettingsPage })));\nconst ProfilePage = lazy(() => import('./pages/settings/ProfilePage').then((m) => ({ default: m.ProfilePage })));\n\n// ============================================================================\n// Routes\n// ============================================================================\n\nexport function HousingVistaRoutes() {\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Dashboard */}\n <Route index element={<HomePage />} />\n\n {/* Properties */}\n <Route path=\"properties\" element={<PropertiesPage />} />\n <Route path=\"properties/new\" element={<AddPropertyPage />} />\n <Route path=\"properties/:id\" element={<PropertyDetailPage />} />\n\n {/* Shortlist */}\n <Route path=\"shortlist\" element={<ShortlistPage />} />\n\n {/* Transactions */}\n <Route path=\"transactions\" element={<TransactionsPage />} />\n <Route path=\"transactions/:id\" element={<TransactionDetailPage />} />\n\n {/* Investments */}\n <Route path=\"investments\" element={<InvestmentsPage />} />\n <Route path=\"investments/:id\" element={<InvestmentDetailPage />} />\n\n {/* Offers */}\n <Route path=\"offers\" element={<OffersPage />} />\n\n {/* Viewings */}\n <Route path=\"viewings\" element={<ViewingsPage />} />\n\n {/* Analytics */}\n <Route path=\"analytics\" element={<AnalyticsPage />} />\n\n {/* Rental Management */}\n <Route path=\"rental\" element={<RentalManagementPage />} />\n\n {/* Asset Management */}\n <Route path=\"assets\" element={<AssetManagementPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n {/* AMC Management */}\n <Route path=\"amc\" element={<AMCManagementPage />} />\n\n {/* Marketplace */}\n <Route path=\"marketplace\" element={<MarketplacePage />} />\n <Route path=\"marketplace/:id\" element={<ServiceDetailPage />} />\n\n {/* Verification */}\n <Route path=\"verification\" element={<VerificationPage />} />\n <Route path=\"verification/:id\" element={<VerificationDetailPage />} />\n\n {/* Legal */}\n <Route path=\"legal\" element={<LegalPage />} />\n <Route path=\"legal/:id\" element={<LegalServiceDetailPage />} />\n\n {/* Home Loans */}\n <Route path=\"home-loans\" element={<HomeLoansPage />} />\n <Route path=\"home-loans/:id/apply\" element={<HomeLoanDetailPage />} />\n\n {/* Market Analytics */}\n <Route path=\"market-analytics\" element={<MarketAnalyticsPage />} />\n <Route path=\"area-insights\" element={<AreaInsightsPage />} />\n\n {/* Settings & Profile */}\n <Route path=\"settings\" element={<SettingsPage />} />\n <Route path=\"profile\" element={<ProfilePage />} />\n\n {/* Catch-all: redirect to dashboard */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"HousingVistaRoutes.js","names":[],"sources":["../../src/housingvista/HousingVistaRoutes.tsx"],"sourcesContent":["/**\n * HousingVista Routes\n * All route definitions with lazy loading.\n * @module housingvista\n */\n\nimport { lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\n\n// Eagerly load the home page\nimport { HomePage } from './pages/HomePage';\n\n// Loading fallback\nconst PageLoader = () => (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"text-sm text-text-secondary\">Loading...</div>\n </div>\n);\n\n// ── Properties ──────────────────────────────────────────────────────────────\nconst PropertiesPage = lazy(() =>\n import('./pages/properties/PropertiesPage').then((m) => ({ default: m.PropertiesPage }))\n);\nconst AddPropertyPage = lazy(() =>\n import('./pages/properties/AddPropertyPage').then((m) => ({ default: m.AddPropertyPage }))\n);\nconst PropertyDetailPage = lazy(() =>\n import('./pages/properties/PropertyDetailPage').then((m) => ({ default: m.PropertyDetailPage }))\n);\nconst ShortlistPage = lazy(() => import('./pages/shortlist/ShortlistPage').then((m) => ({ default: m.ShortlistPage })));\n\n// ── Transactions ────────────────────────────────────────────────────────────\nconst TransactionsPage = lazy(() =>\n import('./pages/transactions/TransactionsPage').then((m) => ({ default: m.TransactionsPage }))\n);\nconst TransactionDetailPage = lazy(() =>\n import('./pages/transactions/TransactionDetailPage').then((m) => ({ default: m.TransactionDetailPage }))\n);\n\n// ── Investments ─────────────────────────────────────────────────────────────\nconst InvestmentsPage = lazy(() =>\n import('./pages/investments/InvestmentsPage').then((m) => ({ default: m.InvestmentsPage }))\n);\nconst InvestmentDetailPage = lazy(() =>\n import('./pages/investments/InvestmentDetailPage').then((m) => ({ default: m.InvestmentDetailPage }))\n);\n\n// ── Offers ──────────────────────────────────────────────────────────────────\nconst OffersPage = lazy(() => import('./pages/offers/OffersPage').then((m) => ({ default: m.OffersPage })));\n\n// ── Viewings ────────────────────────────────────────────────────────────────\nconst ViewingsPage = lazy(() => import('./pages/viewings/ViewingsPage').then((m) => ({ default: m.ViewingsPage })));\n\n// ── Messages / Chat ───────────────────────────────────────────────────────────\nconst ChatPage = lazy(() => import('./pages/chat/ChatPage').then((m) => ({ default: m.ChatPage })));\n\n// ── Analytics ───────────────────────────────────────────────────────────────\nconst AnalyticsPage = lazy(() => import('./pages/analytics/AnalyticsPage').then((m) => ({ default: m.AnalyticsPage })));\n\n// ── Rental Management ───────────────────────────────────────────────────────\nconst RentalManagementPage = lazy(() =>\n import('./pages/rental/RentalManagementPage').then((m) => ({ default: m.RentalManagementPage }))\n);\n\n// ── Asset Management ────────────────────────────────────────────────────────\nconst AssetManagementPage = lazy(() =>\n import('./pages/assets/AssetManagementPage').then((m) => ({ default: m.AssetManagementPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\n\n// ── AMC Management ──────────────────────────────────────────────────────────\nconst AMCManagementPage = lazy(() =>\n import('./pages/amc/AMCManagementPage').then((m) => ({ default: m.AMCManagementPage }))\n);\n\n// ── Marketplace ─────────────────────────────────────────────────────────────\nconst MarketplacePage = lazy(() =>\n import('./pages/marketplace/MarketplacePage').then((m) => ({ default: m.MarketplacePage }))\n);\nconst ServiceDetailPage = lazy(() =>\n import('./pages/marketplace/ServiceDetailPage').then((m) => ({ default: m.ServiceDetailPage }))\n);\n\n// ── Verification ────────────────────────────────────────────────────────────\nconst VerificationPage = lazy(() =>\n import('./pages/verification/VerificationPage').then((m) => ({ default: m.VerificationPage }))\n);\nconst VerificationDetailPage = lazy(() =>\n import('./pages/verification/VerificationDetailPage').then((m) => ({ default: m.VerificationDetailPage }))\n);\n\n// ── Legal ───────────────────────────────────────────────────────────────────\nconst LegalPage = lazy(() => import('./pages/legal/LegalPage').then((m) => ({ default: m.LegalPage })));\nconst LegalServiceDetailPage = lazy(() =>\n import('./pages/legal/LegalServiceDetailPage').then((m) => ({ default: m.LegalServiceDetailPage }))\n);\n\n// ── Finance ─────────────────────────────────────────────────────────────────\nconst HomeLoansPage = lazy(() => import('./pages/finance/HomeLoansPage').then((m) => ({ default: m.HomeLoansPage })));\nconst HomeLoanDetailPage = lazy(() =>\n import('./pages/finance/HomeLoanDetailPage').then((m) => ({ default: m.HomeLoanDetailPage }))\n);\n\n// ── Market ──────────────────────────────────────────────────────────────────\nconst MarketAnalyticsPage = lazy(() =>\n import('./pages/market/MarketAnalyticsPage').then((m) => ({ default: m.MarketAnalyticsPage }))\n);\nconst AreaInsightsPage = lazy(() =>\n import('./pages/market/AreaInsightsPage').then((m) => ({ default: m.AreaInsightsPage }))\n);\n\n// ── Settings ────────────────────────────────────────────────────────────────\nconst SettingsPage = lazy(() => import('./pages/settings/SettingsPage').then((m) => ({ default: m.SettingsPage })));\nconst ProfilePage = lazy(() => import('./pages/settings/ProfilePage').then((m) => ({ default: m.ProfilePage })));\n\n// ============================================================================\n// Routes\n// ============================================================================\n\nexport function HousingVistaRoutes() {\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Dashboard */}\n <Route index element={<HomePage />} />\n\n {/* Properties */}\n <Route path=\"properties\" element={<PropertiesPage />} />\n <Route path=\"properties/new\" element={<AddPropertyPage />} />\n <Route path=\"properties/:id\" element={<PropertyDetailPage />} />\n\n {/* Shortlist */}\n <Route path=\"shortlist\" element={<ShortlistPage />} />\n\n {/* Transactions */}\n <Route path=\"transactions\" element={<TransactionsPage />} />\n <Route path=\"transactions/:id\" element={<TransactionDetailPage />} />\n\n {/* Investments */}\n <Route path=\"investments\" element={<InvestmentsPage />} />\n <Route path=\"investments/:id\" element={<InvestmentDetailPage />} />\n\n {/* Offers */}\n <Route path=\"offers\" element={<OffersPage />} />\n\n {/* Viewings */}\n <Route path=\"viewings\" element={<ViewingsPage />} />\n\n {/* Messages / Chat */}\n <Route path=\"chat\" element={<ChatPage />} />\n <Route path=\"messages\" element={<Navigate to=\"../chat\" replace />} />\n\n {/* Analytics */}\n <Route path=\"analytics\" element={<AnalyticsPage />} />\n\n {/* Rental Management */}\n <Route path=\"rental\" element={<RentalManagementPage />} />\n\n {/* Asset Management */}\n <Route path=\"assets\" element={<AssetManagementPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n {/* AMC Management */}\n <Route path=\"amc\" element={<AMCManagementPage />} />\n\n {/* Marketplace */}\n <Route path=\"marketplace\" element={<MarketplacePage />} />\n <Route path=\"marketplace/:id\" element={<ServiceDetailPage />} />\n\n {/* Verification */}\n <Route path=\"verification\" element={<VerificationPage />} />\n <Route path=\"verification/:id\" element={<VerificationDetailPage />} />\n\n {/* Legal */}\n <Route path=\"legal\" element={<LegalPage />} />\n <Route path=\"legal/:id\" element={<LegalServiceDetailPage />} />\n\n {/* Home Loans */}\n <Route path=\"home-loans\" element={<HomeLoansPage />} />\n <Route path=\"home-loans/:id/apply\" element={<HomeLoanDetailPage />} />\n\n {/* Market Analytics */}\n <Route path=\"market-analytics\" element={<MarketAnalyticsPage />} />\n <Route path=\"area-insights\" element={<AreaInsightsPage />} />\n\n {/* Settings & Profile */}\n <Route path=\"settings\" element={<SettingsPage />} />\n <Route path=\"profile\" element={<ProfilePage />} />\n\n {/* Catch-all: redirect to dashboard */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
@@ -4,95 +4,111 @@ import { useContactConversation as n, useConversationMessages as r, useSendMessa
4
4
  import "../hooks/index.js";
5
5
  import { notify as a } from "../lib/toast.js";
6
6
  import { useEffect as o, useRef as s, useState as c } from "react";
7
- import { Send as l } from "lucide-react";
8
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
9
- import { Button as p, ResponsiveDialog as m, ResponsiveDialogContent as h, ResponsiveDialogDescription as g, ResponsiveDialogHeader as _, ResponsiveDialogTitle as v } from "@burdenoff/fe-libs/ui";
10
- import { createPortal as y } from "react-dom";
7
+ import { MessageSquare as l, Send as u } from "lucide-react";
8
+ import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
9
+ import { Button as m, ResponsiveDialog as h, ResponsiveDialogContent as g, ResponsiveDialogDescription as _, ResponsiveDialogHeader as v, ResponsiveDialogTitle as y } from "@burdenoff/fe-libs/ui";
10
+ import { createPortal as b } from "react-dom";
11
11
  //#region src/housingvista/components/ContactOwnerDialog.tsx
12
- var b = ({ entityId: b, entityType: x, title: S, pagePath: C, triggerContent: w, triggerVariant: T = "outline", triggerClassName: E, heading: D = "Contact", description: O, open: k, onOpenChange: A }) => {
13
- let { currentUser: j } = e(), { openConversation: M, loading: N } = n(), { sendMessage: P, loading: F } = i(), I = k !== void 0, [L, R] = c(!1), z = I ? k : L, B = (e) => I ? A?.(e) : R(e), [V, H] = c(), [U, W] = c(""), { data: G, loading: K } = r(V), q = s(null);
12
+ function x(e) {
13
+ let t = new Date(e);
14
+ return Number.isNaN(t.getTime()) ? "" : t.toLocaleTimeString("en-US", {
15
+ hour: "numeric",
16
+ minute: "2-digit"
17
+ });
18
+ }
19
+ var S = ({ entityId: S, entityType: C, title: w, pagePath: T, triggerContent: E, triggerVariant: D = "outline", triggerClassName: O, heading: k = "Contact", description: A, open: j, onOpenChange: M }) => {
20
+ let { currentUser: N } = e(), { openConversation: P, loading: F } = n(), { sendMessage: I, loading: L } = i(), R = j !== void 0, [z, B] = c(!1), V = R ? j : z, H = (e) => R ? M?.(e) : B(e), [U, W] = c(), [G, K] = c(""), { data: q, loading: J } = r(U), Y = s(null);
14
21
  o(() => {
15
- if (!z || V) return;
22
+ if (!V || U) return;
16
23
  let e = !1;
17
- return M({
18
- entityId: b,
19
- entityType: x,
20
- title: S,
21
- contextHref: C,
22
- pagePath: C
24
+ return P({
25
+ entityId: S,
26
+ entityType: C,
27
+ title: w,
28
+ contextHref: T,
29
+ pagePath: T
23
30
  }).then((t) => {
24
- e || H(t.id);
31
+ e || W(t.id);
25
32
  }).catch((e) => a.error("Could not open the conversation", e.message)), () => {
26
33
  e = !0;
27
34
  };
28
35
  }, [
29
- z,
30
36
  V,
31
- M,
32
- b,
33
- x,
37
+ U,
38
+ P,
34
39
  S,
35
- C
40
+ C,
41
+ w,
42
+ T
36
43
  ]), o(() => {
37
- q.current?.scrollTo({ top: q.current.scrollHeight });
38
- }, [G]);
39
- let J = async () => {
40
- let e = U.trim();
41
- if (!(!e || !V)) try {
42
- await P(V, e), W("");
44
+ Y.current?.scrollTo({ top: Y.current.scrollHeight });
45
+ }, [q]);
46
+ let X = async () => {
47
+ let e = G.trim();
48
+ if (!(!e || !U)) try {
49
+ await I(U, e), K("");
43
50
  } catch (e) {
44
51
  a.error("Message not sent", e.message);
45
52
  }
46
- }, Y = j?.id ?? "";
47
- return /* @__PURE__ */ f(u, { children: [!I && /* @__PURE__ */ d(p, {
53
+ }, Z = N?.id ?? "";
54
+ return /* @__PURE__ */ p(d, { children: [!R && /* @__PURE__ */ f(m, {
48
55
  type: "button",
49
- variant: T,
50
- className: E,
51
- onClick: () => B(!0),
52
- children: w
53
- }), y(/* @__PURE__ */ d(m, {
54
- open: z,
55
- onOpenChange: B,
56
- children: /* @__PURE__ */ f(h, {
56
+ variant: D,
57
+ className: O,
58
+ onClick: () => H(!0),
59
+ children: E
60
+ }), b(/* @__PURE__ */ f(h, {
61
+ open: V,
62
+ onOpenChange: H,
63
+ children: /* @__PURE__ */ p(g, {
57
64
  className: "sm:max-w-lg",
58
65
  children: [
59
- /* @__PURE__ */ f(_, { children: [/* @__PURE__ */ d(v, { children: D }), /* @__PURE__ */ d(g, { children: O ?? `Start a conversation about ${S}. Messages are saved and delivered in your inbox.` })] }),
60
- /* @__PURE__ */ d("div", {
61
- ref: q,
66
+ /* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: k }), /* @__PURE__ */ f(_, { children: A ?? `Start a conversation about ${w}. Messages are saved and delivered in your inbox.` })] }),
67
+ /* @__PURE__ */ f("div", {
68
+ ref: Y,
62
69
  className: "max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3",
63
- children: N || K ? /* @__PURE__ */ d("p", {
70
+ children: F || J ? /* @__PURE__ */ f("p", {
64
71
  className: "py-8 text-center text-sm text-text-secondary",
65
72
  children: "Loading conversation…"
66
- }) : G.length === 0 ? /* @__PURE__ */ d("p", {
67
- className: "py-8 text-center text-sm text-text-secondary",
68
- children: "No messages yet. Say hello to get the conversation started."
69
- }) : G.map((e) => {
70
- let n = e.authorId === Y;
71
- return /* @__PURE__ */ d("div", {
73
+ }) : q.length === 0 ? /* @__PURE__ */ p("div", {
74
+ className: "flex flex-col items-center gap-2 py-8 text-center",
75
+ children: [/* @__PURE__ */ f(l, { className: "h-8 w-8 text-text-secondary" }), /* @__PURE__ */ f("p", {
76
+ className: "text-sm text-text-secondary",
77
+ children: "No messages yet. Say hello to get the conversation started."
78
+ })]
79
+ }) : q.map((e) => {
80
+ let n = e.authorId === Z;
81
+ return /* @__PURE__ */ f("div", {
72
82
  className: t("flex", n ? "justify-end" : "justify-start"),
73
- children: /* @__PURE__ */ d("div", {
74
- className: t("max-w-[80%] rounded-lg px-3 py-2 text-sm", n ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary border border-border-subtle"),
75
- children: e.text
83
+ children: /* @__PURE__ */ p("div", {
84
+ className: t("max-w-[80%]", n ? "items-end" : "items-start"),
85
+ children: [/* @__PURE__ */ f("div", {
86
+ className: t("rounded-2xl px-3.5 py-2 text-sm", n ? "rounded-br-sm bg-action-primary-bg text-action-primary-text" : "rounded-bl-sm border border-border-subtle bg-bg-surface text-text-primary"),
87
+ children: e.text
88
+ }), /* @__PURE__ */ f("div", {
89
+ className: t("mt-1 px-1 text-[0.65rem] text-text-secondary", n && "text-right"),
90
+ children: x(e.createdAt)
91
+ })]
76
92
  })
77
93
  }, e.id);
78
94
  })
79
95
  }),
80
- /* @__PURE__ */ f("div", {
96
+ /* @__PURE__ */ p("div", {
81
97
  className: "mt-3 flex items-end gap-2",
82
- children: [/* @__PURE__ */ d("textarea", {
83
- value: U,
84
- onChange: (e) => W(e.target.value),
98
+ children: [/* @__PURE__ */ f("textarea", {
99
+ value: G,
100
+ onChange: (e) => K(e.target.value),
85
101
  onKeyDown: (e) => {
86
- e.key === "Enter" && !e.shiftKey && (e.preventDefault(), J());
102
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), X());
87
103
  },
88
104
  rows: 2,
89
105
  placeholder: "Write a message…",
90
106
  className: "min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
91
- }), /* @__PURE__ */ f(p, {
107
+ }), /* @__PURE__ */ p(m, {
92
108
  type: "button",
93
- onClick: J,
94
- disabled: !U.trim() || !V || F,
95
- children: [/* @__PURE__ */ d(l, { className: "h-4 w-4" }), /* @__PURE__ */ d("span", {
109
+ onClick: X,
110
+ disabled: !G.trim() || !U || L,
111
+ children: [/* @__PURE__ */ f(u, { className: "h-4 w-4" }), /* @__PURE__ */ f("span", {
96
112
  className: "ml-1",
97
113
  children: "Send"
98
114
  })]
@@ -103,6 +119,6 @@ var b = ({ entityId: b, entityType: x, title: S, pagePath: C, triggerContent: w,
103
119
  }), document.body)] });
104
120
  };
105
121
  //#endregion
106
- export { b as ContactOwnerDialog };
122
+ export { S as ContactOwnerDialog };
107
123
 
108
124
  //# sourceMappingURL=ContactOwnerDialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContactOwnerDialog.js","names":[],"sources":["../../../src/housingvista/components/ContactOwnerDialog.tsx"],"sourcesContent":["/**\n * Real messaging surface backed by wspace-conversations-svc. Any \"Contact /\n * Message / Apply / Contact Owner\" CTA renders this: it resolves (get-or-create)\n * the entity's conversation, shows the persisted thread, and posts messages via\n * `sendMessage`. No stub, no dead-end — everything is persisted server-side.\n * @module housingvista\n */\n\nimport { useEffect, useRef, useState, type FC, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Send } from 'lucide-react';\nimport {\n Button,\n type ButtonProps,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n} from '@burdenoff/fe-libs/ui';\nimport { useContactConversation, useConversationMessages, useSendMessage } from '../hooks';\nimport { useHousingVista } from '../context/HousingVistaContext';\nimport { notify } from '../lib/toast';\nimport { cn } from '../utils/helpers';\n\ninterface ContactOwnerDialogProps {\n /** Stable id of the thing being discussed (property/service/listing id). */\n entityId: string;\n /** e.g. `housingvista-property`, `housingvista-marketplace-service`. */\n entityType: string;\n /** Title used when the conversation is first created. */\n title: string;\n /** Router path back into this surface (deep link). */\n pagePath: string;\n /** Inner content of the trigger button (icon + label). Omit in controlled mode. */\n triggerContent?: ReactNode;\n /** Trigger button variant (defaults to `outline`). */\n triggerVariant?: ButtonProps['variant'];\n /** Extra classes for the trigger button. */\n triggerClassName?: string;\n /** Dialog heading, defaults to \"Contact\". */\n heading?: string;\n description?: string;\n /**\n * Controlled-open mode. When `open`/`onOpenChange` are provided the parent\n * owns the state and the internal trigger button is not rendered — the\n * caller renders its own trigger. This is the pattern the in-page dialogs\n * (e.g. Make Offer) use, and it renders the dialog reliably at page root.\n */\n open?: boolean;\n onOpenChange?: (next: boolean) => void;\n}\n\nexport const ContactOwnerDialog: FC<ContactOwnerDialogProps> = ({\n entityId,\n entityType,\n title,\n pagePath,\n triggerContent,\n triggerVariant = 'outline',\n triggerClassName,\n heading = 'Contact',\n description,\n open: openProp,\n onOpenChange,\n}) => {\n const { currentUser } = useHousingVista();\n const { openConversation, loading: opening } = useContactConversation();\n const { sendMessage, loading: sending } = useSendMessage();\n const controlled = openProp !== undefined;\n const [internalOpen, setInternalOpen] = useState(false);\n const open = controlled ? openProp : internalOpen;\n const setOpen = (next: boolean) => (controlled ? onOpenChange?.(next) : setInternalOpen(next));\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [draft, setDraft] = useState('');\n const { data: messages, loading: loadingMessages } = useConversationMessages(conversationId);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resolve the conversation the first time the dialog opens.\n useEffect(() => {\n if (!open || conversationId) return;\n let cancelled = false;\n openConversation({\n entityId,\n entityType,\n title,\n contextHref: pagePath,\n pagePath,\n })\n .then((res) => {\n if (!cancelled) setConversationId(res.id);\n })\n .catch((err: Error) => notify.error('Could not open the conversation', err.message));\n return () => {\n cancelled = true;\n };\n }, [open, conversationId, openConversation, entityId, entityType, title, pagePath]);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages]);\n\n const handleSend = async () => {\n const text = draft.trim();\n if (!text || !conversationId) return;\n try {\n await sendMessage(conversationId, text);\n setDraft('');\n } catch (err) {\n notify.error('Message not sent', (err as Error).message);\n }\n };\n\n const currentUserId = currentUser?.id ?? '';\n\n // Render the trigger as a real Button with a direct onClick — the exact\n // controlled-open pattern the in-page dialogs (e.g. Make Offer) use. Passing a\n // pre-built element through ResponsiveDialogTrigger asChild / cloneElement /\n // a display:contents wrapper all failed to forward the click in production.\n return (\n <>\n {!controlled && (\n <Button type=\"button\" variant={triggerVariant} className={triggerClassName} onClick={() => setOpen(true)}>\n {triggerContent}\n </Button>\n )}\n {createPortal(\n <ResponsiveDialog open={open} onOpenChange={setOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{heading}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {description ?? `Start a conversation about ${title}. Messages are saved and delivered in your inbox.`}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div\n ref={scrollRef}\n className=\"max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3\"\n >\n {opening || loadingMessages ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">Loading conversation…</p>\n ) : messages.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">\n No messages yet. Say hello to get the conversation started.\n </p>\n ) : (\n messages.map((message) => {\n const mine = message.authorId === currentUserId;\n return (\n <div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>\n <div\n className={cn(\n 'max-w-[80%] rounded-lg px-3 py-2 text-sm',\n mine\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary border border-border-subtle'\n )}\n >\n {message.text}\n </div>\n </div>\n );\n })\n )}\n </div>\n\n <div className=\"mt-3 flex items-end gap-2\">\n <textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n void handleSend();\n }\n }}\n rows={2}\n placeholder=\"Write a message…\"\n className=\"min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <Button type=\"button\" onClick={handleSend} disabled={!draft.trim() || !conversationId || sending}>\n <Send className=\"h-4 w-4\" />\n <span className=\"ml-1\">Send</span>\n </Button>\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>,\n document.body\n )}\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ContactOwnerDialog.js","names":[],"sources":["../../../src/housingvista/components/ContactOwnerDialog.tsx"],"sourcesContent":["/**\n * Real messaging surface backed by wspace-conversations-svc. Any \"Contact /\n * Message / Apply / Contact Owner\" CTA renders this: it resolves (get-or-create)\n * the entity's conversation, shows the persisted thread, and posts messages via\n * `sendMessage`. No stub, no dead-end — everything is persisted server-side.\n * @module housingvista\n */\n\nimport { useEffect, useRef, useState, type FC, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { MessageSquare, Send } from 'lucide-react';\nimport {\n Button,\n type ButtonProps,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n} from '@burdenoff/fe-libs/ui';\nimport { useContactConversation, useConversationMessages, useSendMessage } from '../hooks';\nimport { useHousingVista } from '../context/HousingVistaContext';\nimport { notify } from '../lib/toast';\nimport { cn } from '../utils/helpers';\n\n/** Short local time (e.g. \"2:30 PM\") for a message bubble timestamp. */\nfunction formatMessageTime(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return '';\n return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });\n}\n\ninterface ContactOwnerDialogProps {\n /** Stable id of the thing being discussed (property/service/listing id). */\n entityId: string;\n /** e.g. `housingvista-property`, `housingvista-marketplace-service`. */\n entityType: string;\n /** Title used when the conversation is first created. */\n title: string;\n /** Router path back into this surface (deep link). */\n pagePath: string;\n /** Inner content of the trigger button (icon + label). Omit in controlled mode. */\n triggerContent?: ReactNode;\n /** Trigger button variant (defaults to `outline`). */\n triggerVariant?: ButtonProps['variant'];\n /** Extra classes for the trigger button. */\n triggerClassName?: string;\n /** Dialog heading, defaults to \"Contact\". */\n heading?: string;\n description?: string;\n /**\n * Controlled-open mode. When `open`/`onOpenChange` are provided the parent\n * owns the state and the internal trigger button is not rendered — the\n * caller renders its own trigger. This is the pattern the in-page dialogs\n * (e.g. Make Offer) use, and it renders the dialog reliably at page root.\n */\n open?: boolean;\n onOpenChange?: (next: boolean) => void;\n}\n\nexport const ContactOwnerDialog: FC<ContactOwnerDialogProps> = ({\n entityId,\n entityType,\n title,\n pagePath,\n triggerContent,\n triggerVariant = 'outline',\n triggerClassName,\n heading = 'Contact',\n description,\n open: openProp,\n onOpenChange,\n}) => {\n const { currentUser } = useHousingVista();\n const { openConversation, loading: opening } = useContactConversation();\n const { sendMessage, loading: sending } = useSendMessage();\n const controlled = openProp !== undefined;\n const [internalOpen, setInternalOpen] = useState(false);\n const open = controlled ? openProp : internalOpen;\n const setOpen = (next: boolean) => (controlled ? onOpenChange?.(next) : setInternalOpen(next));\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [draft, setDraft] = useState('');\n const { data: messages, loading: loadingMessages } = useConversationMessages(conversationId);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resolve the conversation the first time the dialog opens.\n useEffect(() => {\n if (!open || conversationId) return;\n let cancelled = false;\n openConversation({\n entityId,\n entityType,\n title,\n contextHref: pagePath,\n pagePath,\n })\n .then((res) => {\n if (!cancelled) setConversationId(res.id);\n })\n .catch((err: Error) => notify.error('Could not open the conversation', err.message));\n return () => {\n cancelled = true;\n };\n }, [open, conversationId, openConversation, entityId, entityType, title, pagePath]);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages]);\n\n const handleSend = async () => {\n const text = draft.trim();\n if (!text || !conversationId) return;\n try {\n await sendMessage(conversationId, text);\n setDraft('');\n } catch (err) {\n notify.error('Message not sent', (err as Error).message);\n }\n };\n\n const currentUserId = currentUser?.id ?? '';\n\n // Render the trigger as a real Button with a direct onClick — the exact\n // controlled-open pattern the in-page dialogs (e.g. Make Offer) use. Passing a\n // pre-built element through ResponsiveDialogTrigger asChild / cloneElement /\n // a display:contents wrapper all failed to forward the click in production.\n return (\n <>\n {!controlled && (\n <Button type=\"button\" variant={triggerVariant} className={triggerClassName} onClick={() => setOpen(true)}>\n {triggerContent}\n </Button>\n )}\n {createPortal(\n <ResponsiveDialog open={open} onOpenChange={setOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{heading}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {description ?? `Start a conversation about ${title}. Messages are saved and delivered in your inbox.`}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div\n ref={scrollRef}\n className=\"max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3\"\n >\n {opening || loadingMessages ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">Loading conversation…</p>\n ) : messages.length === 0 ? (\n <div className=\"flex flex-col items-center gap-2 py-8 text-center\">\n <MessageSquare className=\"h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n No messages yet. Say hello to get the conversation started.\n </p>\n </div>\n ) : (\n messages.map((message) => {\n const mine = message.authorId === currentUserId;\n return (\n <div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>\n <div className={cn('max-w-[80%]', mine ? 'items-end' : 'items-start')}>\n <div\n className={cn(\n 'rounded-2xl px-3.5 py-2 text-sm',\n mine\n ? 'rounded-br-sm bg-action-primary-bg text-action-primary-text'\n : 'rounded-bl-sm border border-border-subtle bg-bg-surface text-text-primary'\n )}\n >\n {message.text}\n </div>\n <div className={cn('mt-1 px-1 text-[0.65rem] text-text-secondary', mine && 'text-right')}>\n {formatMessageTime(message.createdAt)}\n </div>\n </div>\n </div>\n );\n })\n )}\n </div>\n\n <div className=\"mt-3 flex items-end gap-2\">\n <textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n void handleSend();\n }\n }}\n rows={2}\n placeholder=\"Write a message…\"\n className=\"min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <Button type=\"button\" onClick={handleSend} disabled={!draft.trim() || !conversationId || sending}>\n <Send className=\"h-4 w-4\" />\n <span className=\"ml-1\">Send</span>\n </Button>\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>,\n document.body\n )}\n </>\n );\n};\n"],"mappings":"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"}