@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.
Files changed (83) hide show
  1. package/dist/housingvista/HousingVistaRoutes.d.ts.map +1 -1
  2. package/dist/housingvista/HousingVistaRoutes.js +136 -37
  3. package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
  4. package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts +1 -1
  5. package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts.map +1 -1
  6. package/dist/housingvista/hooks/useHousingVistaAnalytics.js +4 -4
  7. package/dist/housingvista/hooks/useHousingVistaAnalytics.js.map +1 -1
  8. package/dist/housingvista/pages/amc/AMCManagementPage.d.ts.map +1 -1
  9. package/dist/housingvista/pages/amc/AMCManagementPage.js +62 -60
  10. package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
  11. package/dist/housingvista/pages/assets/AssetDetailPage.d.ts.map +1 -1
  12. package/dist/housingvista/pages/assets/AssetDetailPage.js +141 -138
  13. package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
  14. package/dist/housingvista/pages/assets/AssetManagementPage.d.ts.map +1 -1
  15. package/dist/housingvista/pages/assets/AssetManagementPage.js +193 -191
  16. package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
  17. package/dist/housingvista/pages/chat/ChatPage.d.ts.map +1 -1
  18. package/dist/housingvista/pages/chat/ChatPage.js +115 -113
  19. package/dist/housingvista/pages/chat/ChatPage.js.map +1 -1
  20. package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts.map +1 -1
  21. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +152 -149
  22. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
  23. package/dist/housingvista/pages/finance/HomeLoansPage.d.ts.map +1 -1
  24. package/dist/housingvista/pages/finance/HomeLoansPage.js +141 -139
  25. package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
  26. package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts.map +1 -1
  27. package/dist/housingvista/pages/investments/InvestmentDetailPage.js +290 -287
  28. package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
  29. package/dist/housingvista/pages/investments/InvestmentsPage.d.ts.map +1 -1
  30. package/dist/housingvista/pages/investments/InvestmentsPage.js +64 -62
  31. package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
  32. package/dist/housingvista/pages/legal/LegalPage.d.ts.map +1 -1
  33. package/dist/housingvista/pages/legal/LegalPage.js +95 -93
  34. package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
  35. package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts.map +1 -1
  36. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +129 -126
  37. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
  38. package/dist/housingvista/pages/market/AreaInsightsPage.d.ts.map +1 -1
  39. package/dist/housingvista/pages/market/AreaInsightsPage.js +99 -97
  40. package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
  41. package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts.map +1 -1
  42. package/dist/housingvista/pages/market/MarketAnalyticsPage.js +138 -136
  43. package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
  44. package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts.map +1 -1
  45. package/dist/housingvista/pages/marketplace/MarketplacePage.js +99 -97
  46. package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
  47. package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts.map +1 -1
  48. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +137 -134
  49. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
  50. package/dist/housingvista/pages/offers/OffersPage.d.ts.map +1 -1
  51. package/dist/housingvista/pages/offers/OffersPage.js +94 -92
  52. package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
  53. package/dist/housingvista/pages/properties/AddPropertyPage.d.ts.map +1 -1
  54. package/dist/housingvista/pages/properties/AddPropertyPage.js +280 -279
  55. package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
  56. package/dist/housingvista/pages/rental/RentalManagementPage.d.ts.map +1 -1
  57. package/dist/housingvista/pages/rental/RentalManagementPage.js +153 -151
  58. package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
  59. package/dist/housingvista/pages/settings/ProfilePage.d.ts.map +1 -1
  60. package/dist/housingvista/pages/settings/ProfilePage.js +52 -50
  61. package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
  62. package/dist/housingvista/pages/settings/SettingsPage.d.ts.map +1 -1
  63. package/dist/housingvista/pages/settings/SettingsPage.js +54 -52
  64. package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
  65. package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts.map +1 -1
  66. package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -41
  67. package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
  68. package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts.map +1 -1
  69. package/dist/housingvista/pages/transactions/TransactionDetailPage.js +211 -208
  70. package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
  71. package/dist/housingvista/pages/transactions/TransactionsPage.d.ts.map +1 -1
  72. package/dist/housingvista/pages/transactions/TransactionsPage.js +85 -83
  73. package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
  74. package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts.map +1 -1
  75. package/dist/housingvista/pages/verification/VerificationDetailPage.js +25 -22
  76. package/dist/housingvista/pages/verification/VerificationDetailPage.js.map +1 -1
  77. package/dist/housingvista/pages/verification/VerificationPage.d.ts.map +1 -1
  78. package/dist/housingvista/pages/verification/VerificationPage.js +123 -121
  79. package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
  80. package/dist/housingvista/pages/viewings/ViewingsPage.d.ts.map +1 -1
  81. package/dist/housingvista/pages/viewings/ViewingsPage.js +128 -126
  82. package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
  83. 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 { useAreaInsights as a } from "../../hooks/index.js";
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 o } from "../../hooks/useServerPagination.js";
7
- import { useMemo as s, useState as c } from "react";
8
- import { ArrowUpRight as l, Building as u, Check as d, GitCompare as f, GraduationCap as p, Heart as m, MapPin as h, TrendingUp as g, Users as _ } from "lucide-react";
9
- import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
10
- import { EmphasisPanel as x, Pagination as S } from "@burdenoff/fe-libs/ui";
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 C(e) {
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 w({ score: t, label: n, suffix: r = "", max: i = 100 }) {
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__ */ b("div", {
18
+ return /* @__PURE__ */ x("div", {
18
19
  className: "flex flex-col items-center",
19
- children: [/* @__PURE__ */ b("div", {
20
+ children: [/* @__PURE__ */ x("div", {
20
21
  className: "relative",
21
- children: [/* @__PURE__ */ b("svg", {
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__ */ y("path", {
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__ */ y("path", {
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]", C(a))
41
+ className: e("transition-[stroke-dashoffset]", w(a))
41
42
  })]
42
- }), /* @__PURE__ */ b("span", {
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__ */ y("span", {
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 T({ area: r, isComparing: i, isSelected: a, isTopPick: o, onToggleCompare: s }) {
53
- let c = Math.round((r.safetyScore + r.connectivityScore + r.amenitiesScore) / 3), v = c / 100;
54
- return /* @__PURE__ */ b("div", {
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__ */ b("div", {
58
+ /* @__PURE__ */ x("div", {
58
59
  className: "mb-4 flex items-start justify-between gap-3",
59
- children: [/* @__PURE__ */ b("div", {
60
+ children: [/* @__PURE__ */ x("div", {
60
61
  className: "min-w-0",
61
62
  children: [
62
- /* @__PURE__ */ b("div", {
63
+ /* @__PURE__ */ x("div", {
63
64
  className: "flex flex-wrap items-center gap-2",
64
- children: [/* @__PURE__ */ y("h3", {
65
+ children: [/* @__PURE__ */ b("h3", {
65
66
  className: "text-base font-semibold text-text-primary",
66
67
  children: r.areaName
67
- }), o && /* @__PURE__ */ y("span", {
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__ */ b("p", {
73
+ /* @__PURE__ */ x("p", {
73
74
  className: "flex items-center gap-1 text-xs text-text-secondary",
74
- children: [/* @__PURE__ */ y(h, { className: "h-3 w-3" }), r.city]
75
+ children: [/* @__PURE__ */ b(g, { className: "h-3 w-3" }), r.city]
75
76
  }),
76
- /* @__PURE__ */ b("p", {
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__ */ b("span", {
82
- className: e("font-semibold", C(v)),
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__ */ y("div", {
89
+ }), /* @__PURE__ */ b("div", {
89
90
  className: "flex items-center gap-2",
90
- children: i && /* @__PURE__ */ y("button", {
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: y(a ? d : f, { className: "h-3.5 w-3.5" })
96
+ children: b(a ? f : p, { className: "h-3.5 w-3.5" })
96
97
  })
97
98
  })]
98
99
  }),
99
- /* @__PURE__ */ b("div", {
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__ */ y(w, {
103
+ /* @__PURE__ */ b(T, {
103
104
  score: r.safetyScore,
104
105
  label: "Safety"
105
106
  }),
106
- /* @__PURE__ */ y(w, {
107
+ /* @__PURE__ */ b(T, {
107
108
  score: r.connectivityScore,
108
109
  label: "Transport"
109
110
  }),
110
- /* @__PURE__ */ y(w, {
111
+ /* @__PURE__ */ b(T, {
111
112
  score: r.amenitiesScore,
112
113
  label: "Amenities"
113
114
  }),
114
- /* @__PURE__ */ y(w, {
115
+ /* @__PURE__ */ b(T, {
115
116
  score: r.greenCoverPercent,
116
117
  label: "Green",
117
118
  suffix: "%"
118
119
  })
119
120
  ]
120
121
  }),
121
- /* @__PURE__ */ b("div", {
122
+ /* @__PURE__ */ x("div", {
122
123
  className: "mb-4 grid grid-cols-2 gap-2",
123
124
  children: [
124
- /* @__PURE__ */ b("div", {
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__ */ y(p, { className: "h-3.5 w-3.5 text-text-secondary" }),
128
- /* @__PURE__ */ y("span", {
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__ */ y("span", {
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__ */ b("div", {
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__ */ y(m, { className: "h-3.5 w-3.5 text-text-secondary" }),
142
- /* @__PURE__ */ y("span", {
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__ */ y("span", {
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__ */ b("div", {
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__ */ y(_, { className: "h-3.5 w-3.5 text-text-secondary" }),
156
- /* @__PURE__ */ y("span", {
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__ */ y("span", {
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__ */ b("div", {
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__ */ y(g, { className: "h-3.5 w-3.5 text-text-secondary" }),
170
- /* @__PURE__ */ y("span", {
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__ */ b("span", {
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__ */ b("div", {
183
+ /* @__PURE__ */ x("div", {
183
184
  className: "flex items-center justify-between rounded-md bg-bg-sunken/50 p-3",
184
- children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
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__ */ y("p", {
188
+ }), /* @__PURE__ */ b("p", {
188
189
  className: "text-sm font-bold text-text-primary",
189
190
  children: t(r.avgPropertyPrice)
190
- })] }), /* @__PURE__ */ b("div", {
191
+ })] }), /* @__PURE__ */ x("div", {
191
192
  className: "text-right",
192
- children: [/* @__PURE__ */ y("p", {
193
+ children: [/* @__PURE__ */ b("p", {
193
194
  className: "text-xs text-text-secondary",
194
195
  children: "Appreciation"
195
- }), /* @__PURE__ */ b("p", {
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__ */ y(l, { className: "h-3.5 w-3.5" }),
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__ */ b("div", {
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__ */ y(u, { className: "h-3 w-3" }),
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 E() {
218
- let n = o(10), { data: l, loading: u } = a(n.pagination), [d, p] = c(!1), [m, g] = c(/* @__PURE__ */ new Set()), _ = (e) => {
219
- g((t) => {
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
- }, C = s(() => l.filter((e) => m.has(e.id)), [l, m]), w = s(() => {
224
- if (l.length === 0) return null;
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 l.reduce((t, n) => e(n) > e(t) ? n : t).id;
227
- }, [l]);
228
- return /* @__PURE__ */ b(r, {
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__ */ b("button", {
234
+ actions: /* @__PURE__ */ x("button", {
233
235
  onClick: () => {
234
- p(!d), d && g(/* @__PURE__ */ new Set());
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", d ? "bg-action-primary-bg text-action-primary-text" : "border border-border-subtle text-text-primary hover:bg-bg-sunken"),
237
- children: [/* @__PURE__ */ y(f, { className: "h-3.5 w-3.5" }), d ? `Comparing (${m.size})` : "Compare Areas"]
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: [d && C.length >= 2 && /* @__PURE__ */ b(x, {
241
+ children: [f && w.length >= 2 && /* @__PURE__ */ x(S, {
240
242
  className: "p-4",
241
- children: [/* @__PURE__ */ y("h3", {
243
+ children: [/* @__PURE__ */ b("h3", {
242
244
  className: "mb-3 text-sm font-semibold text-text-primary",
243
245
  children: "Comparison Summary"
244
- }), /* @__PURE__ */ y("div", {
246
+ }), /* @__PURE__ */ b("div", {
245
247
  className: "overflow-x-auto",
246
- children: /* @__PURE__ */ b("table", {
248
+ children: /* @__PURE__ */ x("table", {
247
249
  className: "w-full text-xs",
248
- children: [/* @__PURE__ */ y("thead", { children: /* @__PURE__ */ b("tr", {
250
+ children: [/* @__PURE__ */ b("thead", { children: /* @__PURE__ */ x("tr", {
249
251
  className: "border-b border-border-subtle",
250
- children: [/* @__PURE__ */ y("th", {
252
+ children: [/* @__PURE__ */ b("th", {
251
253
  className: "pb-2 pr-4 text-left text-text-secondary",
252
254
  children: "Metric"
253
- }), C.map((e) => /* @__PURE__ */ y("th", {
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__ */ y("tbody", {
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__ */ b("tr", { children: [/* @__PURE__ */ y("td", {
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
- }), C.map((t) => /* @__PURE__ */ y("td", {
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
- }), l.length > 0 ? /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y("div", {
296
+ }), u.length > 0 ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("div", {
295
297
  className: "grid gap-4 sm:grid-cols-2",
296
- children: l.map((e) => /* @__PURE__ */ y(T, {
298
+ children: u.map((e) => /* @__PURE__ */ b(E, {
297
299
  area: e,
298
- isComparing: d,
299
- isSelected: m.has(e.id),
300
- isTopPick: e.id === w,
301
- onToggleCompare: () => _(e.id)
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__ */ y(S, {
305
+ }), /* @__PURE__ */ b(C, {
304
306
  page: n.page,
305
307
  pageSize: n.pageSize,
306
- hasNextPage: l.length >= n.pageSize,
308
+ hasNextPage: u.length >= n.pageSize,
307
309
  hasPreviousPage: n.page > 1,
308
- loading: u,
310
+ loading: d,
309
311
  onPageChange: n.setPage,
310
312
  onPageSizeChange: n.setPageSize
311
- })] }) : /* @__PURE__ */ y(i, {
313
+ })] }) : /* @__PURE__ */ b(i, {
312
314
  illustration: "empty-data",
313
- icon: /* @__PURE__ */ y(h, { className: "h-12 w-12" }),
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 { E as AreaInsightsPage };
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":"AA0CA,wBAAgB,mBAAmB,gCA+TlC"}
1
+ {"version":3,"file":"MarketAnalyticsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/market/MarketAnalyticsPage.tsx"],"names":[],"mappings":"AA2CA,wBAAgB,mBAAmB,gCAgUlC"}