@burdenoff/microfe-housingvista 2026.709.2 → 2026.709.3
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.d.ts.map +1 -1
- package/dist/housingvista/HousingVistaRoutes.js +136 -37
- package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts.map +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js +4 -4
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.js +62 -60
- package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.js +141 -138
- package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/assets/AssetManagementPage.js +193 -191
- package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.d.ts.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.js +115 -113
- package/dist/housingvista/pages/chat/ChatPage.js.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +152 -149
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoansPage.d.ts.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoansPage.js +141 -139
- package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js +290 -287
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentsPage.js +64 -62
- package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.d.ts.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.js +95 -93
- package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +129 -126
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/market/AreaInsightsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/market/AreaInsightsPage.js +99 -97
- package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
- package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js +138 -136
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts.map +1 -1
- package/dist/housingvista/pages/marketplace/MarketplacePage.js +99 -97
- package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +137 -134
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/offers/OffersPage.d.ts.map +1 -1
- package/dist/housingvista/pages/offers/OffersPage.js +94 -92
- package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
- package/dist/housingvista/pages/properties/AddPropertyPage.d.ts.map +1 -1
- package/dist/housingvista/pages/properties/AddPropertyPage.js +280 -279
- package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.js +153 -151
- package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
- package/dist/housingvista/pages/settings/ProfilePage.d.ts.map +1 -1
- package/dist/housingvista/pages/settings/ProfilePage.js +52 -50
- package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
- package/dist/housingvista/pages/settings/SettingsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/settings/SettingsPage.js +54 -52
- package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
- package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts.map +1 -1
- package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -41
- package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js +211 -208
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionsPage.js +85 -83
- package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
- package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/verification/VerificationDetailPage.js +25 -22
- package/dist/housingvista/pages/verification/VerificationDetailPage.js.map +1 -1
- package/dist/housingvista/pages/verification/VerificationPage.d.ts.map +1 -1
- package/dist/housingvista/pages/verification/VerificationPage.js +123 -121
- package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
- package/dist/housingvista/pages/viewings/ViewingsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/viewings/ViewingsPage.js +128 -126
- package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
import { cn as e, formatINRCompact as t, formatNumber as n } from "../../utils/helpers.js";
|
|
2
2
|
import { PageLayout as r } from "../../components/PageLayout.js";
|
|
3
3
|
import { EmptyState as i } from "../../components/EmptyState.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useTrackPageView as a } from "../../hooks/useHousingVistaAnalytics.js";
|
|
5
|
+
import { useAreaInsights as o } from "../../hooks/index.js";
|
|
5
6
|
import "../../components/index.js";
|
|
6
|
-
import { useServerPagination as
|
|
7
|
-
import { useMemo as
|
|
8
|
-
import { ArrowUpRight as
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { EmphasisPanel as
|
|
7
|
+
import { useServerPagination as s } from "../../hooks/useServerPagination.js";
|
|
8
|
+
import { useMemo as c, useState as l } from "react";
|
|
9
|
+
import { ArrowUpRight as u, Building as d, Check as f, GitCompare as p, GraduationCap as m, Heart as h, MapPin as g, TrendingUp as _, Users as v } from "lucide-react";
|
|
10
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
11
|
+
import { EmphasisPanel as S, Pagination as C } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
//#region src/housingvista/pages/market/AreaInsightsPage.tsx
|
|
12
|
-
function
|
|
13
|
+
function w(e) {
|
|
13
14
|
return e >= .8 ? "text-status-success-text" : e >= .6 ? "text-status-info-text" : e >= .4 ? "text-status-warning-text" : "text-status-error-text";
|
|
14
15
|
}
|
|
15
|
-
function
|
|
16
|
+
function T({ score: t, label: n, suffix: r = "", max: i = 100 }) {
|
|
16
17
|
let a = Math.max(0, Math.min(t / i, 1)), o = "M5 46 A41 41 0 0 1 87 46";
|
|
17
|
-
return /* @__PURE__ */
|
|
18
|
+
return /* @__PURE__ */ x("div", {
|
|
18
19
|
className: "flex flex-col items-center",
|
|
19
|
-
children: [/* @__PURE__ */
|
|
20
|
+
children: [/* @__PURE__ */ x("div", {
|
|
20
21
|
className: "relative",
|
|
21
|
-
children: [/* @__PURE__ */
|
|
22
|
+
children: [/* @__PURE__ */ x("svg", {
|
|
22
23
|
viewBox: "0 0 92 50",
|
|
23
24
|
className: "h-11 w-[64px]",
|
|
24
25
|
"aria-hidden": "true",
|
|
25
|
-
children: [/* @__PURE__ */
|
|
26
|
+
children: [/* @__PURE__ */ b("path", {
|
|
26
27
|
d: o,
|
|
27
28
|
fill: "none",
|
|
28
29
|
strokeWidth: 8,
|
|
29
30
|
strokeLinecap: "round",
|
|
30
31
|
className: "stroke-bg-sunken"
|
|
31
|
-
}), /* @__PURE__ */
|
|
32
|
+
}), /* @__PURE__ */ b("path", {
|
|
32
33
|
d: o,
|
|
33
34
|
fill: "none",
|
|
34
35
|
strokeWidth: 8,
|
|
@@ -37,141 +38,141 @@ function w({ score: t, label: n, suffix: r = "", max: i = 100 }) {
|
|
|
37
38
|
pathLength: 100,
|
|
38
39
|
strokeDasharray: 100,
|
|
39
40
|
strokeDashoffset: 100 * (1 - a),
|
|
40
|
-
className: e("transition-[stroke-dashoffset]",
|
|
41
|
+
className: e("transition-[stroke-dashoffset]", w(a))
|
|
41
42
|
})]
|
|
42
|
-
}), /* @__PURE__ */
|
|
43
|
+
}), /* @__PURE__ */ x("span", {
|
|
43
44
|
className: "absolute inset-x-0 bottom-0 text-center text-sm font-bold tabular-nums text-text-primary",
|
|
44
45
|
children: [t, r]
|
|
45
46
|
})]
|
|
46
|
-
}), /* @__PURE__ */
|
|
47
|
+
}), /* @__PURE__ */ b("span", {
|
|
47
48
|
className: "mt-1 text-[10px] font-medium text-text-secondary",
|
|
48
49
|
children: n
|
|
49
50
|
})]
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
function
|
|
53
|
-
let c = Math.round((r.safetyScore + r.connectivityScore + r.amenitiesScore) / 3),
|
|
54
|
-
return /* @__PURE__ */
|
|
53
|
+
function E({ area: r, isComparing: i, isSelected: a, isTopPick: o, onToggleCompare: s }) {
|
|
54
|
+
let c = Math.round((r.safetyScore + r.connectivityScore + r.amenitiesScore) / 3), l = c / 100;
|
|
55
|
+
return /* @__PURE__ */ x("div", {
|
|
55
56
|
className: e("rounded-card border bg-bg-surface p-5 shadow-elevation-1 transition-[box-shadow,border-color]", a ? "border-action-primary-border ring-2 ring-action-primary-border/20" : "border-border-seam hover:border-border-strong hover:shadow-elevation-2"),
|
|
56
57
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ x("div", {
|
|
58
59
|
className: "mb-4 flex items-start justify-between gap-3",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ x("div", {
|
|
60
61
|
className: "min-w-0",
|
|
61
62
|
children: [
|
|
62
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ x("div", {
|
|
63
64
|
className: "flex flex-wrap items-center gap-2",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
65
|
+
children: [/* @__PURE__ */ b("h3", {
|
|
65
66
|
className: "text-base font-semibold text-text-primary",
|
|
66
67
|
children: r.areaName
|
|
67
|
-
}), o && /* @__PURE__ */
|
|
68
|
+
}), o && /* @__PURE__ */ b("span", {
|
|
68
69
|
className: "rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-status-success-text",
|
|
69
70
|
children: "Top Pick"
|
|
70
71
|
})]
|
|
71
72
|
}),
|
|
72
|
-
/* @__PURE__ */
|
|
73
|
+
/* @__PURE__ */ x("p", {
|
|
73
74
|
className: "flex items-center gap-1 text-xs text-text-secondary",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
+
children: [/* @__PURE__ */ b(g, { className: "h-3 w-3" }), r.city]
|
|
75
76
|
}),
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
+
/* @__PURE__ */ x("p", {
|
|
77
78
|
className: "mt-1 text-xs text-text-secondary",
|
|
78
79
|
children: [
|
|
79
80
|
"Overall score",
|
|
80
81
|
" ",
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
className: e("font-semibold",
|
|
82
|
+
/* @__PURE__ */ x("span", {
|
|
83
|
+
className: e("font-semibold", w(l)),
|
|
83
84
|
children: [(c / 10).toFixed(1), "/10"]
|
|
84
85
|
})
|
|
85
86
|
]
|
|
86
87
|
})
|
|
87
88
|
]
|
|
88
|
-
}), /* @__PURE__ */
|
|
89
|
+
}), /* @__PURE__ */ b("div", {
|
|
89
90
|
className: "flex items-center gap-2",
|
|
90
|
-
children: i && /* @__PURE__ */
|
|
91
|
+
children: i && /* @__PURE__ */ b("button", {
|
|
91
92
|
onClick: s,
|
|
92
93
|
"aria-pressed": a,
|
|
93
94
|
"aria-label": a ? `Remove ${r.areaName} from comparison` : `Add ${r.areaName} to comparison`,
|
|
94
95
|
className: e("flex h-7 w-7 items-center justify-center rounded-md border transition-colors", a ? "border-action-primary-border bg-action-primary-bg text-action-primary-text" : "border-border-subtle text-text-secondary hover:bg-bg-sunken"),
|
|
95
|
-
children:
|
|
96
|
+
children: b(a ? f : p, { className: "h-3.5 w-3.5" })
|
|
96
97
|
})
|
|
97
98
|
})]
|
|
98
99
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ x("div", {
|
|
100
101
|
className: "mb-4 grid grid-cols-4 gap-1 rounded-lg bg-bg-sunken/40 py-3",
|
|
101
102
|
children: [
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ b(T, {
|
|
103
104
|
score: r.safetyScore,
|
|
104
105
|
label: "Safety"
|
|
105
106
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ b(T, {
|
|
107
108
|
score: r.connectivityScore,
|
|
108
109
|
label: "Transport"
|
|
109
110
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
111
|
+
/* @__PURE__ */ b(T, {
|
|
111
112
|
score: r.amenitiesScore,
|
|
112
113
|
label: "Amenities"
|
|
113
114
|
}),
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ b(T, {
|
|
115
116
|
score: r.greenCoverPercent,
|
|
116
117
|
label: "Green",
|
|
117
118
|
suffix: "%"
|
|
118
119
|
})
|
|
119
120
|
]
|
|
120
121
|
}),
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ x("div", {
|
|
122
123
|
className: "mb-4 grid grid-cols-2 gap-2",
|
|
123
124
|
children: [
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ x("div", {
|
|
125
126
|
className: "flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs",
|
|
126
127
|
children: [
|
|
127
|
-
/* @__PURE__ */
|
|
128
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ b(m, { className: "h-3.5 w-3.5 text-text-secondary" }),
|
|
129
|
+
/* @__PURE__ */ b("span", {
|
|
129
130
|
className: "text-text-secondary",
|
|
130
131
|
children: "Schools:"
|
|
131
132
|
}),
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ b("span", {
|
|
133
134
|
className: "font-semibold text-text-primary",
|
|
134
135
|
children: r.schoolsNearby
|
|
135
136
|
})
|
|
136
137
|
]
|
|
137
138
|
}),
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ x("div", {
|
|
139
140
|
className: "flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs",
|
|
140
141
|
children: [
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
142
|
+
/* @__PURE__ */ b(h, { className: "h-3.5 w-3.5 text-text-secondary" }),
|
|
143
|
+
/* @__PURE__ */ b("span", {
|
|
143
144
|
className: "text-text-secondary",
|
|
144
145
|
children: "Hospitals:"
|
|
145
146
|
}),
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
+
/* @__PURE__ */ b("span", {
|
|
147
148
|
className: "font-semibold text-text-primary",
|
|
148
149
|
children: r.hospitalsNearby
|
|
149
150
|
})
|
|
150
151
|
]
|
|
151
152
|
}),
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
+
/* @__PURE__ */ x("div", {
|
|
153
154
|
className: "flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs",
|
|
154
155
|
children: [
|
|
155
|
-
/* @__PURE__ */
|
|
156
|
-
/* @__PURE__ */
|
|
156
|
+
/* @__PURE__ */ b(v, { className: "h-3.5 w-3.5 text-text-secondary" }),
|
|
157
|
+
/* @__PURE__ */ b("span", {
|
|
157
158
|
className: "text-text-secondary",
|
|
158
159
|
children: "Population:"
|
|
159
160
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
161
|
+
/* @__PURE__ */ b("span", {
|
|
161
162
|
className: "font-semibold text-text-primary",
|
|
162
163
|
children: n(r.population)
|
|
163
164
|
})
|
|
164
165
|
]
|
|
165
166
|
}),
|
|
166
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ x("div", {
|
|
167
168
|
className: "flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs",
|
|
168
169
|
children: [
|
|
169
|
-
/* @__PURE__ */
|
|
170
|
-
/* @__PURE__ */
|
|
170
|
+
/* @__PURE__ */ b(_, { className: "h-3.5 w-3.5 text-text-secondary" }),
|
|
171
|
+
/* @__PURE__ */ b("span", {
|
|
171
172
|
className: "text-text-secondary",
|
|
172
173
|
children: "Yield:"
|
|
173
174
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ x("span", {
|
|
175
176
|
className: "font-semibold text-text-primary",
|
|
176
177
|
children: [r.avgRentalYield, "%"]
|
|
177
178
|
})
|
|
@@ -179,33 +180,33 @@ function T({ area: r, isComparing: i, isSelected: a, isTopPick: o, onToggleCompa
|
|
|
179
180
|
})
|
|
180
181
|
]
|
|
181
182
|
}),
|
|
182
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ x("div", {
|
|
183
184
|
className: "flex items-center justify-between rounded-md bg-bg-sunken/50 p-3",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
185
|
+
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("p", {
|
|
185
186
|
className: "text-xs text-text-secondary",
|
|
186
187
|
children: "Avg Property Price"
|
|
187
|
-
}), /* @__PURE__ */
|
|
188
|
+
}), /* @__PURE__ */ b("p", {
|
|
188
189
|
className: "text-sm font-bold text-text-primary",
|
|
189
190
|
children: t(r.avgPropertyPrice)
|
|
190
|
-
})] }), /* @__PURE__ */
|
|
191
|
+
})] }), /* @__PURE__ */ x("div", {
|
|
191
192
|
className: "text-right",
|
|
192
|
-
children: [/* @__PURE__ */
|
|
193
|
+
children: [/* @__PURE__ */ b("p", {
|
|
193
194
|
className: "text-xs text-text-secondary",
|
|
194
195
|
children: "Appreciation"
|
|
195
|
-
}), /* @__PURE__ */
|
|
196
|
+
}), /* @__PURE__ */ x("p", {
|
|
196
197
|
className: "flex items-center justify-end gap-0.5 text-sm font-bold text-status-success-text",
|
|
197
198
|
children: [
|
|
198
|
-
/* @__PURE__ */
|
|
199
|
+
/* @__PURE__ */ b(u, { className: "h-3.5 w-3.5" }),
|
|
199
200
|
r.appreciationRate,
|
|
200
201
|
"% YoY"
|
|
201
202
|
]
|
|
202
203
|
})]
|
|
203
204
|
})]
|
|
204
205
|
}),
|
|
205
|
-
r.upcomingProjects > 0 && /* @__PURE__ */
|
|
206
|
+
r.upcomingProjects > 0 && /* @__PURE__ */ x("div", {
|
|
206
207
|
className: "mt-3 flex items-center gap-1.5 text-xs text-text-secondary",
|
|
207
208
|
children: [
|
|
208
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ b(d, { className: "h-3 w-3" }),
|
|
209
210
|
r.upcomingProjects,
|
|
210
211
|
" upcoming project",
|
|
211
212
|
r.upcomingProjects > 1 ? "s" : ""
|
|
@@ -214,47 +215,48 @@ function T({ area: r, isComparing: i, isSelected: a, isTopPick: o, onToggleCompa
|
|
|
214
215
|
]
|
|
215
216
|
});
|
|
216
217
|
}
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
function D() {
|
|
219
|
+
a("housingvista.market_analytics.area_viewed");
|
|
220
|
+
let n = s(10), { data: u, loading: d } = o(n.pagination), [f, m] = l(!1), [h, _] = l(/* @__PURE__ */ new Set()), v = (e) => {
|
|
221
|
+
_((t) => {
|
|
220
222
|
let n = new Set(t);
|
|
221
223
|
return n.has(e) ? n.delete(e) : n.size < 3 && n.add(e), n;
|
|
222
224
|
});
|
|
223
|
-
},
|
|
224
|
-
if (
|
|
225
|
+
}, w = c(() => u.filter((e) => h.has(e.id)), [u, h]), T = c(() => {
|
|
226
|
+
if (u.length === 0) return null;
|
|
225
227
|
let e = (e) => e.safetyScore + e.connectivityScore + e.amenitiesScore;
|
|
226
|
-
return
|
|
227
|
-
}, [
|
|
228
|
-
return /* @__PURE__ */
|
|
228
|
+
return u.reduce((t, n) => e(n) > e(t) ? n : t).id;
|
|
229
|
+
}, [u]);
|
|
230
|
+
return /* @__PURE__ */ x(r, {
|
|
229
231
|
title: "Area Insights",
|
|
230
232
|
description: "Explore neighborhoods, compare areas, and make informed decisions",
|
|
231
233
|
purpose: "Decide WHERE to buy or rent, not just what. Compare neighborhoods on safety, connectivity, amenities, schools, hospitals, green cover, prices, and appreciation — then pick up to three areas to compare side by side before you commit.",
|
|
232
|
-
actions: /* @__PURE__ */
|
|
234
|
+
actions: /* @__PURE__ */ x("button", {
|
|
233
235
|
onClick: () => {
|
|
234
|
-
|
|
236
|
+
m(!f), f && _(/* @__PURE__ */ new Set());
|
|
235
237
|
},
|
|
236
|
-
className: e("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
|
|
237
|
-
children: [/* @__PURE__ */
|
|
238
|
+
className: e("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", f ? "bg-action-primary-bg text-action-primary-text" : "border border-border-subtle text-text-primary hover:bg-bg-sunken"),
|
|
239
|
+
children: [/* @__PURE__ */ b(p, { className: "h-3.5 w-3.5" }), f ? `Comparing (${h.size})` : "Compare Areas"]
|
|
238
240
|
}),
|
|
239
|
-
children: [
|
|
241
|
+
children: [f && w.length >= 2 && /* @__PURE__ */ x(S, {
|
|
240
242
|
className: "p-4",
|
|
241
|
-
children: [/* @__PURE__ */
|
|
243
|
+
children: [/* @__PURE__ */ b("h3", {
|
|
242
244
|
className: "mb-3 text-sm font-semibold text-text-primary",
|
|
243
245
|
children: "Comparison Summary"
|
|
244
|
-
}), /* @__PURE__ */
|
|
246
|
+
}), /* @__PURE__ */ b("div", {
|
|
245
247
|
className: "overflow-x-auto",
|
|
246
|
-
children: /* @__PURE__ */
|
|
248
|
+
children: /* @__PURE__ */ x("table", {
|
|
247
249
|
className: "w-full text-xs",
|
|
248
|
-
children: [/* @__PURE__ */
|
|
250
|
+
children: [/* @__PURE__ */ b("thead", { children: /* @__PURE__ */ x("tr", {
|
|
249
251
|
className: "border-b border-border-subtle",
|
|
250
|
-
children: [/* @__PURE__ */
|
|
252
|
+
children: [/* @__PURE__ */ b("th", {
|
|
251
253
|
className: "pb-2 pr-4 text-left text-text-secondary",
|
|
252
254
|
children: "Metric"
|
|
253
|
-
}),
|
|
255
|
+
}), w.map((e) => /* @__PURE__ */ b("th", {
|
|
254
256
|
className: "pb-2 pr-4 text-left font-semibold text-text-primary",
|
|
255
257
|
children: e.areaName
|
|
256
258
|
}, e.id))]
|
|
257
|
-
}) }), /* @__PURE__ */
|
|
259
|
+
}) }), /* @__PURE__ */ b("tbody", {
|
|
258
260
|
className: "divide-y divide-border",
|
|
259
261
|
children: [
|
|
260
262
|
{
|
|
@@ -281,42 +283,42 @@ function E() {
|
|
|
281
283
|
label: "Amenities",
|
|
282
284
|
render: (e) => `${e.amenitiesScore}/100`
|
|
283
285
|
}
|
|
284
|
-
].map((e) => /* @__PURE__ */
|
|
286
|
+
].map((e) => /* @__PURE__ */ x("tr", { children: [/* @__PURE__ */ b("td", {
|
|
285
287
|
className: "py-2 pr-4 text-text-secondary",
|
|
286
288
|
children: e.label
|
|
287
|
-
}),
|
|
289
|
+
}), w.map((t) => /* @__PURE__ */ b("td", {
|
|
288
290
|
className: "py-2 pr-4 font-medium text-text-primary",
|
|
289
291
|
children: e.render(t)
|
|
290
292
|
}, t.id))] }, e.label))
|
|
291
293
|
})]
|
|
292
294
|
})
|
|
293
295
|
})]
|
|
294
|
-
}),
|
|
296
|
+
}), u.length > 0 ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("div", {
|
|
295
297
|
className: "grid gap-4 sm:grid-cols-2",
|
|
296
|
-
children:
|
|
298
|
+
children: u.map((e) => /* @__PURE__ */ b(E, {
|
|
297
299
|
area: e,
|
|
298
|
-
isComparing:
|
|
299
|
-
isSelected:
|
|
300
|
-
isTopPick: e.id ===
|
|
301
|
-
onToggleCompare: () =>
|
|
300
|
+
isComparing: f,
|
|
301
|
+
isSelected: h.has(e.id),
|
|
302
|
+
isTopPick: e.id === T,
|
|
303
|
+
onToggleCompare: () => v(e.id)
|
|
302
304
|
}, e.id))
|
|
303
|
-
}), /* @__PURE__ */
|
|
305
|
+
}), /* @__PURE__ */ b(C, {
|
|
304
306
|
page: n.page,
|
|
305
307
|
pageSize: n.pageSize,
|
|
306
|
-
hasNextPage:
|
|
308
|
+
hasNextPage: u.length >= n.pageSize,
|
|
307
309
|
hasPreviousPage: n.page > 1,
|
|
308
|
-
loading:
|
|
310
|
+
loading: d,
|
|
309
311
|
onPageChange: n.setPage,
|
|
310
312
|
onPageSizeChange: n.setPageSize
|
|
311
|
-
})] }) : /* @__PURE__ */
|
|
313
|
+
})] }) : /* @__PURE__ */ b(i, {
|
|
312
314
|
illustration: "empty-data",
|
|
313
|
-
icon: /* @__PURE__ */
|
|
315
|
+
icon: /* @__PURE__ */ b(g, { className: "h-12 w-12" }),
|
|
314
316
|
title: "No area insights available",
|
|
315
317
|
description: "Area insight data will appear here once available."
|
|
316
318
|
})]
|
|
317
319
|
});
|
|
318
320
|
}
|
|
319
321
|
//#endregion
|
|
320
|
-
export {
|
|
322
|
+
export { D as AreaInsightsPage };
|
|
321
323
|
|
|
322
324
|
//# sourceMappingURL=AreaInsightsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AreaInsightsPage.js","names":[],"sources":["../../../../src/housingvista/pages/market/AreaInsightsPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n MapPin,\n GraduationCap,\n Heart,\n Users,\n TrendingUp,\n Building,\n ArrowUpRight,\n GitCompare,\n Check,\n} from 'lucide-react';\nimport { EmphasisPanel, Pagination } from '@burdenoff/fe-libs/ui';\nimport { PageLayout, EmptyState } from '../../components';\nimport { useAreaInsights } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { cn, formatINRCompact, formatNumber } from '../../utils/helpers';\nimport type { AreaInsight } from '../../types';\n\nfunction gaugeColor(pct: number): string {\n if (pct >= 0.8) return 'text-status-success-text';\n if (pct >= 0.6) return 'text-status-info-text';\n if (pct >= 0.4) return 'text-status-warning-text';\n return 'text-status-error-text';\n}\n\n/**\n * Semicircle score gauge (0–max) — the arc is normalised via `pathLength=100`\n * so the fill is radius-independent. Matches the concept's gauge cluster.\n */\nfunction ScoreGauge({\n score,\n label,\n suffix = '',\n max = 100,\n}: {\n score: number;\n label: string;\n suffix?: string;\n max?: number;\n}) {\n const pct = Math.max(0, Math.min(score / max, 1));\n const arc = 'M5 46 A41 41 0 0 1 87 46';\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"relative\">\n <svg viewBox=\"0 0 92 50\" className=\"h-11 w-[64px]\" aria-hidden=\"true\">\n <path d={arc} fill=\"none\" strokeWidth={8} strokeLinecap=\"round\" className=\"stroke-bg-sunken\" />\n <path\n d={arc}\n fill=\"none\"\n strokeWidth={8}\n strokeLinecap=\"round\"\n stroke=\"currentColor\"\n pathLength={100}\n strokeDasharray={100}\n strokeDashoffset={100 * (1 - pct)}\n className={cn('transition-[stroke-dashoffset]', gaugeColor(pct))}\n />\n </svg>\n <span className=\"absolute inset-x-0 bottom-0 text-center text-sm font-bold tabular-nums text-text-primary\">\n {score}\n {suffix}\n </span>\n </div>\n <span className=\"mt-1 text-[10px] font-medium text-text-secondary\">{label}</span>\n </div>\n );\n}\n\nfunction AreaCard({\n area,\n isComparing,\n isSelected,\n isTopPick,\n onToggleCompare,\n}: {\n area: AreaInsight;\n isComparing: boolean;\n isSelected: boolean;\n isTopPick: boolean;\n onToggleCompare: () => void;\n}) {\n const overallScore = Math.round((area.safetyScore + area.connectivityScore + area.amenitiesScore) / 3);\n const overallPct = overallScore / 100;\n\n return (\n <div\n className={cn(\n 'rounded-card border bg-bg-surface p-5 shadow-elevation-1 transition-[box-shadow,border-color]',\n isSelected\n ? 'border-action-primary-border ring-2 ring-action-primary-border/20'\n : 'border-border-seam hover:border-border-strong hover:shadow-elevation-2'\n )}\n >\n {/* Header */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">{area.areaName}</h3>\n {isTopPick && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-status-success-text\">\n Top Pick\n </span>\n )}\n </div>\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <MapPin className=\"h-3 w-3\" />\n {area.city}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n Overall score{' '}\n <span className={cn('font-semibold', gaugeColor(overallPct))}>{(overallScore / 10).toFixed(1)}/10</span>\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {isComparing && (\n <button\n onClick={onToggleCompare}\n aria-pressed={isSelected}\n aria-label={isSelected ? `Remove ${area.areaName} from comparison` : `Add ${area.areaName} to comparison`}\n className={cn(\n 'flex h-7 w-7 items-center justify-center rounded-md border transition-colors',\n isSelected\n ? 'border-action-primary-border bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-bg-sunken'\n )}\n >\n {isSelected ? <Check className=\"h-3.5 w-3.5\" /> : <GitCompare className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n </div>\n </div>\n\n {/* Score Gauges (mock parity) */}\n <div className=\"mb-4 grid grid-cols-4 gap-1 rounded-lg bg-bg-sunken/40 py-3\">\n <ScoreGauge score={area.safetyScore} label=\"Safety\" />\n <ScoreGauge score={area.connectivityScore} label=\"Transport\" />\n <ScoreGauge score={area.amenitiesScore} label=\"Amenities\" />\n <ScoreGauge score={area.greenCoverPercent} label=\"Green\" suffix=\"%\" />\n </div>\n\n {/* Nearby Counts */}\n <div className=\"mb-4 grid grid-cols-2 gap-2\">\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <GraduationCap className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Schools:</span>\n <span className=\"font-semibold text-text-primary\">{area.schoolsNearby}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <Heart className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Hospitals:</span>\n <span className=\"font-semibold text-text-primary\">{area.hospitalsNearby}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <Users className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Population:</span>\n <span className=\"font-semibold text-text-primary\">{formatNumber(area.population)}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <TrendingUp className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Yield:</span>\n <span className=\"font-semibold text-text-primary\">{area.avgRentalYield}%</span>\n </div>\n </div>\n\n {/* Price + Growth */}\n <div className=\"flex items-center justify-between rounded-md bg-bg-sunken/50 p-3\">\n <div>\n <p className=\"text-xs text-text-secondary\">Avg Property Price</p>\n <p className=\"text-sm font-bold text-text-primary\">{formatINRCompact(area.avgPropertyPrice)}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-xs text-text-secondary\">Appreciation</p>\n <p className=\"flex items-center justify-end gap-0.5 text-sm font-bold text-status-success-text\">\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n {area.appreciationRate}% YoY\n </p>\n </div>\n </div>\n\n {/* Upcoming Projects */}\n {area.upcomingProjects > 0 && (\n <div className=\"mt-3 flex items-center gap-1.5 text-xs text-text-secondary\">\n <Building className=\"h-3 w-3\" />\n {area.upcomingProjects} upcoming project{area.upcomingProjects > 1 ? 's' : ''}\n </div>\n )}\n </div>\n );\n}\n\nexport function AreaInsightsPage() {\n const pagination = useServerPagination(10);\n const { data: areas, loading } = useAreaInsights(pagination.pagination);\n const [isComparing, setIsComparing] = useState(false);\n const [selectedForCompare, setSelectedForCompare] = useState<Set<string>>(new Set());\n\n const toggleCompare = (id: string) => {\n setSelectedForCompare((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else if (next.size < 3) {\n next.add(id);\n }\n return next;\n });\n };\n\n const comparedAreas = useMemo(() => {\n return areas.filter((a) => selectedForCompare.has(a.id));\n }, [areas, selectedForCompare]);\n\n // Highlight the highest-scoring area on this page as the \"Top Pick\".\n const topPickId = useMemo(() => {\n if (areas.length === 0) return null;\n const scoreOf = (a: AreaInsight) => a.safetyScore + a.connectivityScore + a.amenitiesScore;\n return areas.reduce((best, a) => (scoreOf(a) > scoreOf(best) ? a : best)).id;\n }, [areas]);\n\n return (\n <PageLayout\n title=\"Area Insights\"\n description=\"Explore neighborhoods, compare areas, and make informed decisions\"\n purpose=\"Decide WHERE to buy or rent, not just what. Compare neighborhoods on safety, connectivity, amenities, schools, hospitals, green cover, prices, and appreciation — then pick up to three areas to compare side by side before you commit.\"\n actions={\n <button\n onClick={() => {\n setIsComparing(!isComparing);\n if (isComparing) setSelectedForCompare(new Set());\n }}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors',\n isComparing\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'border border-border-subtle text-text-primary hover:bg-bg-sunken'\n )}\n >\n <GitCompare className=\"h-3.5 w-3.5\" />\n {isComparing ? `Comparing (${selectedForCompare.size})` : 'Compare Areas'}\n </button>\n }\n >\n {/* Comparison Summary — primary emphasis zone when comparing (one per page) */}\n {isComparing && comparedAreas.length >= 2 && (\n <EmphasisPanel className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">Comparison Summary</h3>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"border-b border-border-subtle\">\n <th className=\"pb-2 pr-4 text-left text-text-secondary\">Metric</th>\n {comparedAreas.map((a) => (\n <th key={a.id} className=\"pb-2 pr-4 text-left font-semibold text-text-primary\">\n {a.areaName}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {[\n { label: 'Avg Price', render: (a: AreaInsight) => formatINRCompact(a.avgPropertyPrice) },\n { label: 'Rental Yield', render: (a: AreaInsight) => `${a.avgRentalYield}%` },\n { label: 'Appreciation', render: (a: AreaInsight) => `${a.appreciationRate}%` },\n { label: 'Safety Score', render: (a: AreaInsight) => `${a.safetyScore}/100` },\n { label: 'Connectivity', render: (a: AreaInsight) => `${a.connectivityScore}/100` },\n { label: 'Amenities', render: (a: AreaInsight) => `${a.amenitiesScore}/100` },\n ].map((row) => (\n <tr key={row.label}>\n <td className=\"py-2 pr-4 text-text-secondary\">{row.label}</td>\n {comparedAreas.map((a) => (\n <td key={a.id} className=\"py-2 pr-4 font-medium text-text-primary\">\n {row.render(a)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </EmphasisPanel>\n )}\n\n {/* Area Cards */}\n {areas.length > 0 ? (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {areas.map((area) => (\n <AreaCard\n key={area.id}\n area={area}\n isComparing={isComparing}\n isSelected={selectedForCompare.has(area.id)}\n isTopPick={area.id === topPickId}\n onToggleCompare={() => toggleCompare(area.id)}\n />\n ))}\n </div>\n\n {/* Pagination (server-side): working prev/next + page-size, no silent truncation */}\n <Pagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n hasNextPage={areas.length >= pagination.pageSize}\n hasPreviousPage={pagination.page > 1}\n loading={loading}\n onPageChange={pagination.setPage}\n onPageSizeChange={pagination.setPageSize}\n />\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<MapPin className=\"h-12 w-12\" />}\n title=\"No area insights available\"\n description=\"Area insight data will appear here once available.\"\n />\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AreaInsightsPage.js","names":[],"sources":["../../../../src/housingvista/pages/market/AreaInsightsPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n MapPin,\n GraduationCap,\n Heart,\n Users,\n TrendingUp,\n Building,\n ArrowUpRight,\n GitCompare,\n Check,\n} from 'lucide-react';\nimport { EmphasisPanel, Pagination } from '@burdenoff/fe-libs/ui';\nimport { PageLayout, EmptyState } from '../../components';\nimport { useAreaInsights } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { cn, formatINRCompact, formatNumber } from '../../utils/helpers';\nimport type { AreaInsight } from '../../types';\nimport { useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\n\nfunction gaugeColor(pct: number): string {\n if (pct >= 0.8) return 'text-status-success-text';\n if (pct >= 0.6) return 'text-status-info-text';\n if (pct >= 0.4) return 'text-status-warning-text';\n return 'text-status-error-text';\n}\n\n/**\n * Semicircle score gauge (0–max) — the arc is normalised via `pathLength=100`\n * so the fill is radius-independent. Matches the concept's gauge cluster.\n */\nfunction ScoreGauge({\n score,\n label,\n suffix = '',\n max = 100,\n}: {\n score: number;\n label: string;\n suffix?: string;\n max?: number;\n}) {\n const pct = Math.max(0, Math.min(score / max, 1));\n const arc = 'M5 46 A41 41 0 0 1 87 46';\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"relative\">\n <svg viewBox=\"0 0 92 50\" className=\"h-11 w-[64px]\" aria-hidden=\"true\">\n <path d={arc} fill=\"none\" strokeWidth={8} strokeLinecap=\"round\" className=\"stroke-bg-sunken\" />\n <path\n d={arc}\n fill=\"none\"\n strokeWidth={8}\n strokeLinecap=\"round\"\n stroke=\"currentColor\"\n pathLength={100}\n strokeDasharray={100}\n strokeDashoffset={100 * (1 - pct)}\n className={cn('transition-[stroke-dashoffset]', gaugeColor(pct))}\n />\n </svg>\n <span className=\"absolute inset-x-0 bottom-0 text-center text-sm font-bold tabular-nums text-text-primary\">\n {score}\n {suffix}\n </span>\n </div>\n <span className=\"mt-1 text-[10px] font-medium text-text-secondary\">{label}</span>\n </div>\n );\n}\n\nfunction AreaCard({\n area,\n isComparing,\n isSelected,\n isTopPick,\n onToggleCompare,\n}: {\n area: AreaInsight;\n isComparing: boolean;\n isSelected: boolean;\n isTopPick: boolean;\n onToggleCompare: () => void;\n}) {\n const overallScore = Math.round((area.safetyScore + area.connectivityScore + area.amenitiesScore) / 3);\n const overallPct = overallScore / 100;\n\n return (\n <div\n className={cn(\n 'rounded-card border bg-bg-surface p-5 shadow-elevation-1 transition-[box-shadow,border-color]',\n isSelected\n ? 'border-action-primary-border ring-2 ring-action-primary-border/20'\n : 'border-border-seam hover:border-border-strong hover:shadow-elevation-2'\n )}\n >\n {/* Header */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">{area.areaName}</h3>\n {isTopPick && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-status-success-text\">\n Top Pick\n </span>\n )}\n </div>\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <MapPin className=\"h-3 w-3\" />\n {area.city}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n Overall score{' '}\n <span className={cn('font-semibold', gaugeColor(overallPct))}>{(overallScore / 10).toFixed(1)}/10</span>\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {isComparing && (\n <button\n onClick={onToggleCompare}\n aria-pressed={isSelected}\n aria-label={isSelected ? `Remove ${area.areaName} from comparison` : `Add ${area.areaName} to comparison`}\n className={cn(\n 'flex h-7 w-7 items-center justify-center rounded-md border transition-colors',\n isSelected\n ? 'border-action-primary-border bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-bg-sunken'\n )}\n >\n {isSelected ? <Check className=\"h-3.5 w-3.5\" /> : <GitCompare className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n </div>\n </div>\n\n {/* Score Gauges (mock parity) */}\n <div className=\"mb-4 grid grid-cols-4 gap-1 rounded-lg bg-bg-sunken/40 py-3\">\n <ScoreGauge score={area.safetyScore} label=\"Safety\" />\n <ScoreGauge score={area.connectivityScore} label=\"Transport\" />\n <ScoreGauge score={area.amenitiesScore} label=\"Amenities\" />\n <ScoreGauge score={area.greenCoverPercent} label=\"Green\" suffix=\"%\" />\n </div>\n\n {/* Nearby Counts */}\n <div className=\"mb-4 grid grid-cols-2 gap-2\">\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <GraduationCap className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Schools:</span>\n <span className=\"font-semibold text-text-primary\">{area.schoolsNearby}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <Heart className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Hospitals:</span>\n <span className=\"font-semibold text-text-primary\">{area.hospitalsNearby}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <Users className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Population:</span>\n <span className=\"font-semibold text-text-primary\">{formatNumber(area.population)}</span>\n </div>\n <div className=\"flex items-center gap-2 rounded-md bg-bg-sunken/50 p-2 text-xs\">\n <TrendingUp className=\"h-3.5 w-3.5 text-text-secondary\" />\n <span className=\"text-text-secondary\">Yield:</span>\n <span className=\"font-semibold text-text-primary\">{area.avgRentalYield}%</span>\n </div>\n </div>\n\n {/* Price + Growth */}\n <div className=\"flex items-center justify-between rounded-md bg-bg-sunken/50 p-3\">\n <div>\n <p className=\"text-xs text-text-secondary\">Avg Property Price</p>\n <p className=\"text-sm font-bold text-text-primary\">{formatINRCompact(area.avgPropertyPrice)}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-xs text-text-secondary\">Appreciation</p>\n <p className=\"flex items-center justify-end gap-0.5 text-sm font-bold text-status-success-text\">\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n {area.appreciationRate}% YoY\n </p>\n </div>\n </div>\n\n {/* Upcoming Projects */}\n {area.upcomingProjects > 0 && (\n <div className=\"mt-3 flex items-center gap-1.5 text-xs text-text-secondary\">\n <Building className=\"h-3 w-3\" />\n {area.upcomingProjects} upcoming project{area.upcomingProjects > 1 ? 's' : ''}\n </div>\n )}\n </div>\n );\n}\n\nexport function AreaInsightsPage() {\n useTrackPageView('housingvista.market_analytics.area_viewed');\n const pagination = useServerPagination(10);\n const { data: areas, loading } = useAreaInsights(pagination.pagination);\n const [isComparing, setIsComparing] = useState(false);\n const [selectedForCompare, setSelectedForCompare] = useState<Set<string>>(new Set());\n\n const toggleCompare = (id: string) => {\n setSelectedForCompare((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else if (next.size < 3) {\n next.add(id);\n }\n return next;\n });\n };\n\n const comparedAreas = useMemo(() => {\n return areas.filter((a) => selectedForCompare.has(a.id));\n }, [areas, selectedForCompare]);\n\n // Highlight the highest-scoring area on this page as the \"Top Pick\".\n const topPickId = useMemo(() => {\n if (areas.length === 0) return null;\n const scoreOf = (a: AreaInsight) => a.safetyScore + a.connectivityScore + a.amenitiesScore;\n return areas.reduce((best, a) => (scoreOf(a) > scoreOf(best) ? a : best)).id;\n }, [areas]);\n\n return (\n <PageLayout\n title=\"Area Insights\"\n description=\"Explore neighborhoods, compare areas, and make informed decisions\"\n purpose=\"Decide WHERE to buy or rent, not just what. Compare neighborhoods on safety, connectivity, amenities, schools, hospitals, green cover, prices, and appreciation — then pick up to three areas to compare side by side before you commit.\"\n actions={\n <button\n onClick={() => {\n setIsComparing(!isComparing);\n if (isComparing) setSelectedForCompare(new Set());\n }}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors',\n isComparing\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'border border-border-subtle text-text-primary hover:bg-bg-sunken'\n )}\n >\n <GitCompare className=\"h-3.5 w-3.5\" />\n {isComparing ? `Comparing (${selectedForCompare.size})` : 'Compare Areas'}\n </button>\n }\n >\n {/* Comparison Summary — primary emphasis zone when comparing (one per page) */}\n {isComparing && comparedAreas.length >= 2 && (\n <EmphasisPanel className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">Comparison Summary</h3>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"border-b border-border-subtle\">\n <th className=\"pb-2 pr-4 text-left text-text-secondary\">Metric</th>\n {comparedAreas.map((a) => (\n <th key={a.id} className=\"pb-2 pr-4 text-left font-semibold text-text-primary\">\n {a.areaName}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {[\n { label: 'Avg Price', render: (a: AreaInsight) => formatINRCompact(a.avgPropertyPrice) },\n { label: 'Rental Yield', render: (a: AreaInsight) => `${a.avgRentalYield}%` },\n { label: 'Appreciation', render: (a: AreaInsight) => `${a.appreciationRate}%` },\n { label: 'Safety Score', render: (a: AreaInsight) => `${a.safetyScore}/100` },\n { label: 'Connectivity', render: (a: AreaInsight) => `${a.connectivityScore}/100` },\n { label: 'Amenities', render: (a: AreaInsight) => `${a.amenitiesScore}/100` },\n ].map((row) => (\n <tr key={row.label}>\n <td className=\"py-2 pr-4 text-text-secondary\">{row.label}</td>\n {comparedAreas.map((a) => (\n <td key={a.id} className=\"py-2 pr-4 font-medium text-text-primary\">\n {row.render(a)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </EmphasisPanel>\n )}\n\n {/* Area Cards */}\n {areas.length > 0 ? (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {areas.map((area) => (\n <AreaCard\n key={area.id}\n area={area}\n isComparing={isComparing}\n isSelected={selectedForCompare.has(area.id)}\n isTopPick={area.id === topPickId}\n onToggleCompare={() => toggleCompare(area.id)}\n />\n ))}\n </div>\n\n {/* Pagination (server-side): working prev/next + page-size, no silent truncation */}\n <Pagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n hasNextPage={areas.length >= pagination.pageSize}\n hasPreviousPage={pagination.page > 1}\n loading={loading}\n onPageChange={pagination.setPage}\n onPageSizeChange={pagination.setPageSize}\n />\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<MapPin className=\"h-12 w-12\" />}\n title=\"No area insights available\"\n description=\"Area insight data will appear here once available.\"\n />\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarketAnalyticsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/market/MarketAnalyticsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MarketAnalyticsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/market/MarketAnalyticsPage.tsx"],"names":[],"mappings":"AA2CA,wBAAgB,mBAAmB,gCAgUlC"}
|