@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.
- package/dist/housingvista/HousingVistaRoutes.js +31 -20
- package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
- package/dist/housingvista/components/ContactOwnerDialog.js +74 -58
- package/dist/housingvista/components/ContactOwnerDialog.js.map +1 -1
- package/dist/housingvista/components/PropertyCard.js +92 -67
- package/dist/housingvista/components/PropertyCard.js.map +1 -1
- package/dist/housingvista/hooks/messages.js +66 -0
- package/dist/housingvista/hooks/messages.js.map +1 -0
- package/dist/housingvista/pages/HomePage.js +182 -146
- package/dist/housingvista/pages/HomePage.js.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.js +212 -217
- package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
- package/dist/housingvista/pages/analytics/AnalyticsPage.js +377 -213
- package/dist/housingvista/pages/analytics/AnalyticsPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.js +237 -144
- package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetManagementPage.js +357 -233
- package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.js +260 -0
- package/dist/housingvista/pages/chat/ChatPage.js.map +1 -0
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +157 -154
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoansPage.js +162 -161
- package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js +3 -3
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentsPage.js +347 -234
- package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.js +146 -119
- package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +132 -132
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/market/AreaInsightsPage.js +150 -115
- package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js +321 -203
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/MarketplacePage.js +89 -77
- package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +2 -2
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/offers/OffersPage.js +297 -172
- package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
- package/dist/housingvista/pages/properties/AddPropertyPage.js +37 -13
- package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
- package/dist/housingvista/pages/properties/PropertiesPage.js +1 -0
- package/dist/housingvista/pages/properties/PropertiesPage.js.map +1 -1
- package/dist/housingvista/pages/properties/PropertyDetailPage.js +803 -583
- package/dist/housingvista/pages/properties/PropertyDetailPage.js.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.js +513 -418
- package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
- package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -30
- package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js +207 -199
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionsPage.js +204 -84
- package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/milestones.js +68 -0
- package/dist/housingvista/pages/transactions/milestones.js.map +1 -0
- package/dist/housingvista/pages/verification/VerificationPage.js +175 -125
- package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
- package/dist/housingvista/pages/viewings/ViewingsPage.js +241 -136
- package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
- package/dist/housingvista/utils/helpers.js +26 -7
- package/dist/housingvista/utils/helpers.js.map +1 -1
- package/dist/node_modules/lodash/maxBy.js +17 -0
- package/dist/node_modules/lodash/maxBy.js.map +1 -0
- package/dist/node_modules/lodash/minBy.js +17 -0
- package/dist/node_modules/lodash/minBy.js.map +1 -0
- package/dist/node_modules/recharts/es6/chart/BarChart.js +24 -0
- package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -0
- package/dist/node_modules/recharts/es6/chart/PieChart.js +34 -0
- package/dist/node_modules/recharts/es6/chart/PieChart.js.map +1 -0
- package/dist/node_modules/recharts/es6/polar/Pie.js +435 -0
- package/dist/node_modules/recharts/es6/polar/Pie.js.map +1 -0
- package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +215 -0
- package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js.map +1 -0
- package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +268 -0
- package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js.map +1 -0
- package/dist/node_modules/recharts/es6/shape/Polygon.js +112 -0
- package/dist/node_modules/recharts/es6/shape/Polygon.js.map +1 -0
- package/dist/node_modules/recharts/es6/util/PolarUtils.js +133 -51
- package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
- 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 }))),
|
|
13
|
-
function
|
|
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: "
|
|
62
|
+
path: "chat",
|
|
63
63
|
element: /* @__PURE__ */ o(y, {})
|
|
64
64
|
}),
|
|
65
65
|
/* @__PURE__ */ o(i, {
|
|
66
|
-
path: "
|
|
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: "
|
|
77
|
+
path: "rental",
|
|
71
78
|
element: /* @__PURE__ */ o(x, {})
|
|
72
79
|
}),
|
|
73
80
|
/* @__PURE__ */ o(i, {
|
|
74
|
-
path: "assets
|
|
81
|
+
path: "assets",
|
|
75
82
|
element: /* @__PURE__ */ o(S, {})
|
|
76
83
|
}),
|
|
77
84
|
/* @__PURE__ */ o(i, {
|
|
78
|
-
path: "
|
|
85
|
+
path: "assets/:id",
|
|
79
86
|
element: /* @__PURE__ */ o(C, {})
|
|
80
87
|
}),
|
|
81
88
|
/* @__PURE__ */ o(i, {
|
|
82
|
-
path: "
|
|
89
|
+
path: "amc",
|
|
83
90
|
element: /* @__PURE__ */ o(w, {})
|
|
84
91
|
}),
|
|
85
92
|
/* @__PURE__ */ o(i, {
|
|
86
|
-
path: "marketplace
|
|
93
|
+
path: "marketplace",
|
|
87
94
|
element: /* @__PURE__ */ o(T, {})
|
|
88
95
|
}),
|
|
89
96
|
/* @__PURE__ */ o(i, {
|
|
90
|
-
path: "
|
|
97
|
+
path: "marketplace/:id",
|
|
91
98
|
element: /* @__PURE__ */ o(E, {})
|
|
92
99
|
}),
|
|
93
100
|
/* @__PURE__ */ o(i, {
|
|
94
|
-
path: "verification
|
|
101
|
+
path: "verification",
|
|
95
102
|
element: /* @__PURE__ */ o(D, {})
|
|
96
103
|
}),
|
|
97
104
|
/* @__PURE__ */ o(i, {
|
|
98
|
-
path: "
|
|
105
|
+
path: "verification/:id",
|
|
99
106
|
element: /* @__PURE__ */ o(O, {})
|
|
100
107
|
}),
|
|
101
108
|
/* @__PURE__ */ o(i, {
|
|
102
|
-
path: "legal
|
|
109
|
+
path: "legal",
|
|
103
110
|
element: /* @__PURE__ */ o(k, {})
|
|
104
111
|
}),
|
|
105
112
|
/* @__PURE__ */ o(i, {
|
|
106
|
-
path: "
|
|
113
|
+
path: "legal/:id",
|
|
107
114
|
element: /* @__PURE__ */ o(A, {})
|
|
108
115
|
}),
|
|
109
116
|
/* @__PURE__ */ o(i, {
|
|
110
|
-
path: "home-loans
|
|
117
|
+
path: "home-loans",
|
|
111
118
|
element: /* @__PURE__ */ o(j, {})
|
|
112
119
|
}),
|
|
113
120
|
/* @__PURE__ */ o(i, {
|
|
114
|
-
path: "
|
|
121
|
+
path: "home-loans/:id/apply",
|
|
115
122
|
element: /* @__PURE__ */ o(M, {})
|
|
116
123
|
}),
|
|
117
124
|
/* @__PURE__ */ o(i, {
|
|
118
|
-
path: "
|
|
125
|
+
path: "market-analytics",
|
|
119
126
|
element: /* @__PURE__ */ o(N, {})
|
|
120
127
|
}),
|
|
121
128
|
/* @__PURE__ */ o(i, {
|
|
122
|
-
path: "
|
|
129
|
+
path: "area-insights",
|
|
123
130
|
element: /* @__PURE__ */ o(P, {})
|
|
124
131
|
}),
|
|
125
132
|
/* @__PURE__ */ o(i, {
|
|
126
|
-
path: "
|
|
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 {
|
|
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 {
|
|
8
|
-
import { Fragment as
|
|
9
|
-
import { Button as
|
|
10
|
-
import { createPortal as
|
|
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
|
-
|
|
13
|
-
let
|
|
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 (!
|
|
22
|
+
if (!V || U) return;
|
|
16
23
|
let e = !1;
|
|
17
|
-
return
|
|
18
|
-
entityId:
|
|
19
|
-
entityType:
|
|
20
|
-
title:
|
|
21
|
-
contextHref:
|
|
22
|
-
pagePath:
|
|
24
|
+
return P({
|
|
25
|
+
entityId: S,
|
|
26
|
+
entityType: C,
|
|
27
|
+
title: w,
|
|
28
|
+
contextHref: T,
|
|
29
|
+
pagePath: T
|
|
23
30
|
}).then((t) => {
|
|
24
|
-
e ||
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
x,
|
|
37
|
+
U,
|
|
38
|
+
P,
|
|
34
39
|
S,
|
|
35
|
-
C
|
|
40
|
+
C,
|
|
41
|
+
w,
|
|
42
|
+
T
|
|
36
43
|
]), o(() => {
|
|
37
|
-
|
|
38
|
-
}, [
|
|
39
|
-
let
|
|
40
|
-
let e =
|
|
41
|
-
if (!(!e || !
|
|
42
|
-
await
|
|
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
|
-
},
|
|
47
|
-
return /* @__PURE__ */
|
|
53
|
+
}, Z = N?.id ?? "";
|
|
54
|
+
return /* @__PURE__ */ p(d, { children: [!R && /* @__PURE__ */ f(m, {
|
|
48
55
|
type: "button",
|
|
49
|
-
variant:
|
|
50
|
-
className:
|
|
51
|
-
onClick: () =>
|
|
52
|
-
children:
|
|
53
|
-
}),
|
|
54
|
-
open:
|
|
55
|
-
onOpenChange:
|
|
56
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
-
ref:
|
|
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:
|
|
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
|
-
}) :
|
|
67
|
-
className: "
|
|
68
|
-
children:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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__ */
|
|
74
|
-
className: t("max-w-[80%]
|
|
75
|
-
children:
|
|
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__ */
|
|
96
|
+
/* @__PURE__ */ p("div", {
|
|
81
97
|
className: "mt-3 flex items-end gap-2",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
83
|
-
value:
|
|
84
|
-
onChange: (e) =>
|
|
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(),
|
|
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__ */
|
|
107
|
+
}), /* @__PURE__ */ p(m, {
|
|
92
108
|
type: "button",
|
|
93
|
-
onClick:
|
|
94
|
-
disabled: !
|
|
95
|
-
children: [/* @__PURE__ */
|
|
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 {
|
|
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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"}
|