@burdenoff/microfe-housingvista 2026.625.1 → 2026.626.1

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 (49) hide show
  1. package/dist/housingvista/components/DataTable.js +62 -59
  2. package/dist/housingvista/components/DataTable.js.map +1 -1
  3. package/dist/housingvista/components/PageLayout.js +21 -15
  4. package/dist/housingvista/components/PageLayout.js.map +1 -1
  5. package/dist/housingvista/pages/HomePage.js +66 -39
  6. package/dist/housingvista/pages/HomePage.js.map +1 -1
  7. package/dist/housingvista/pages/amc/AMCManagementPage.js +127 -90
  8. package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
  9. package/dist/housingvista/pages/analytics/AnalyticsPage.js +113 -90
  10. package/dist/housingvista/pages/analytics/AnalyticsPage.js.map +1 -1
  11. package/dist/housingvista/pages/assets/AssetManagementPage.js +90 -59
  12. package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
  13. package/dist/housingvista/pages/chat/ChatPage.js +59 -58
  14. package/dist/housingvista/pages/chat/ChatPage.js.map +1 -1
  15. package/dist/housingvista/pages/finance/HomeLoansPage.js +191 -161
  16. package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
  17. package/dist/housingvista/pages/investments/InvestmentDetailPage.js +112 -81
  18. package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
  19. package/dist/housingvista/pages/investments/InvestmentsPage.js +90 -59
  20. package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
  21. package/dist/housingvista/pages/legal/LegalPage.js +39 -14
  22. package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
  23. package/dist/housingvista/pages/market/AreaInsightsPage.js +12 -10
  24. package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
  25. package/dist/housingvista/pages/market/MarketAnalyticsPage.js +155 -123
  26. package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
  27. package/dist/housingvista/pages/marketplace/MarketplacePage.js +39 -12
  28. package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
  29. package/dist/housingvista/pages/notifications/NotificationsPage.js +23 -21
  30. package/dist/housingvista/pages/notifications/NotificationsPage.js.map +1 -1
  31. package/dist/housingvista/pages/properties/AddPropertyPage.js +73 -71
  32. package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
  33. package/dist/housingvista/pages/properties/PropertiesPage.js +140 -135
  34. package/dist/housingvista/pages/properties/PropertiesPage.js.map +1 -1
  35. package/dist/housingvista/pages/properties/PropertyDetailPage.js +191 -154
  36. package/dist/housingvista/pages/properties/PropertyDetailPage.js.map +1 -1
  37. package/dist/housingvista/pages/rental/RentalManagementPage.js +185 -161
  38. package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
  39. package/dist/housingvista/pages/settings/ProfilePage.js +51 -49
  40. package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
  41. package/dist/housingvista/pages/settings/SettingsPage.js +56 -54
  42. package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
  43. package/dist/housingvista/pages/transactions/TransactionDetailPage.js +182 -142
  44. package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
  45. package/dist/housingvista/pages/transactions/TransactionsPage.js +114 -83
  46. package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
  47. package/dist/housingvista/pages/verification/VerificationPage.js +49 -42
  48. package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
  49. package/package.json +2 -2
@@ -2,80 +2,83 @@ import { cn as e } from "../utils/helpers.js";
2
2
  import { useCallback as t, useMemo as n, useState as r } from "react";
3
3
  import { ChevronDown as i, ChevronLeft as a, ChevronRight as o, ChevronUp as s, ChevronsUpDown as c } from "lucide-react";
4
4
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import { IllustratedEmptyState as d } from "@burdenoff/fe-libs/ui";
5
6
  //#region src/housingvista/components/DataTable.tsx
6
- function d({ columns: d, data: f, keyField: p, onRowClick: m, emptyMessage: h = "No data available", className: g, pageSize: _ = 10, selectable: v = !1, selectedKeys: y, onSelectionChange: b, serverPagination: x }) {
7
- let [S, C] = r(null), [w, T] = r(null), [E, D] = r(0), O = t((e) => {
8
- S === e ? w === "asc" ? T("desc") : w === "desc" ? (C(null), T(null)) : T("asc") : (C(e), T("asc")), D(0);
9
- }, [S, w]), k = n(() => !S || !w ? f : [...f].sort((e, t) => {
10
- let n = e[S], r = t[S];
7
+ function f({ columns: f, data: p, keyField: m, onRowClick: h, emptyMessage: g = "No data available", emptyDescription: _, emptyIllustration: v = "empty-data", emptyAction: y, className: b, pageSize: x = 10, selectable: S = !1, selectedKeys: C, onSelectionChange: w, serverPagination: T }) {
8
+ let [E, D] = r(null), [O, k] = r(null), [A, j] = r(0), M = t((e) => {
9
+ E === e ? O === "asc" ? k("desc") : O === "desc" ? (D(null), k(null)) : k("asc") : (D(e), k("asc")), j(0);
10
+ }, [E, O]), N = n(() => !E || !O ? p : [...p].sort((e, t) => {
11
+ let n = e[E], r = t[E];
11
12
  if (n == null && r == null) return 0;
12
13
  if (n == null) return 1;
13
14
  if (r == null) return -1;
14
15
  let i = typeof n == "number" && typeof r == "number" ? n - r : String(n).localeCompare(String(r));
15
- return w === "asc" ? i : -i;
16
+ return O === "asc" ? i : -i;
16
17
  }), [
17
- f,
18
- S,
19
- w
20
- ]), A = x?.pageSize ?? _, j = Math.max(1, Math.ceil(k.length / A)), M = x ? k : k.slice(E * A, (E + 1) * A), N = v && y ? M.every((e) => y.has(String(e[p]))) : !1, P = () => {
21
- if (!b || !y) return;
22
- let e = new Set(y);
23
- N ? M.forEach((t) => e.delete(String(t[p]))) : M.forEach((t) => e.add(String(t[p]))), b(e);
24
- }, F = (e) => {
25
- if (!b || !y) return;
26
- let t = String(e[p]), n = new Set(y);
27
- n.has(t) ? n.delete(t) : n.add(t), b(n);
18
+ p,
19
+ E,
20
+ O
21
+ ]), P = T?.pageSize ?? x, F = Math.max(1, Math.ceil(N.length / P)), I = T ? N : N.slice(A * P, (A + 1) * P), L = S && C ? I.every((e) => C.has(String(e[m]))) : !1, R = () => {
22
+ if (!w || !C) return;
23
+ let e = new Set(C);
24
+ L ? I.forEach((t) => e.delete(String(t[m]))) : I.forEach((t) => e.add(String(t[m]))), w(e);
25
+ }, z = (e) => {
26
+ if (!w || !C) return;
27
+ let t = String(e[m]), n = new Set(C);
28
+ n.has(t) ? n.delete(t) : n.add(t), w(n);
28
29
  };
29
- return f.length === 0 ? /* @__PURE__ */ l("div", {
30
- className: "flex items-center justify-center rounded-lg border border-border-subtle bg-bg-surface p-12",
31
- children: /* @__PURE__ */ l("p", {
32
- className: "text-sm text-text-secondary",
33
- children: h
30
+ return p.length === 0 ? /* @__PURE__ */ l("div", {
31
+ className: "rounded-card border border-dashed border-border-seam bg-bg-surface/50",
32
+ children: /* @__PURE__ */ l(d, {
33
+ illustration: v,
34
+ title: g,
35
+ description: _,
36
+ action: y
34
37
  })
35
38
  }) : /* @__PURE__ */ u("div", {
36
- className: e("space-y-3", g),
39
+ className: e("space-y-3", b),
37
40
  children: [/* @__PURE__ */ l("div", {
38
41
  className: "overflow-x-auto rounded-card border border-border-seam bg-bg-surface shadow-elevation-1",
39
42
  children: /* @__PURE__ */ u("table", {
40
43
  className: "w-full",
41
44
  children: [/* @__PURE__ */ l("thead", { children: /* @__PURE__ */ u("tr", {
42
45
  className: "border-b border-border-subtle bg-bg-sunken/50",
43
- children: [v && /* @__PURE__ */ l("th", {
46
+ children: [S && /* @__PURE__ */ l("th", {
44
47
  className: "w-10 px-3 py-3",
45
48
  children: /* @__PURE__ */ l("input", {
46
49
  type: "checkbox",
47
- checked: N && M.length > 0,
48
- onChange: P,
50
+ checked: L && I.length > 0,
51
+ onChange: R,
49
52
  className: "h-4 w-4 rounded border-border-subtle"
50
53
  })
51
- }), d.map((t) => {
52
- let n = t.sortable !== !1, r = S === t.key;
54
+ }), f.map((t) => {
55
+ let n = t.sortable !== !1, r = E === t.key;
53
56
  return /* @__PURE__ */ l("th", {
54
57
  className: e("px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary", n && "cursor-pointer select-none hover:text-text-primary", t.className),
55
- onClick: n ? () => O(t.key) : void 0,
58
+ onClick: n ? () => M(t.key) : void 0,
56
59
  children: /* @__PURE__ */ u("span", {
57
60
  className: "inline-flex items-center gap-1",
58
- children: [t.header, n && (r ? l(w === "asc" ? s : i, { className: "h-3 w-3" }) : /* @__PURE__ */ l(c, { className: "h-3 w-3 opacity-30" }))]
61
+ children: [t.header, n && (r ? l(O === "asc" ? s : i, { className: "h-3 w-3" }) : /* @__PURE__ */ l(c, { className: "h-3 w-3 opacity-30" }))]
59
62
  })
60
63
  }, t.key);
61
64
  })]
62
65
  }) }), /* @__PURE__ */ l("tbody", {
63
66
  className: "divide-y divide-border bg-bg-surface",
64
- children: M.map((t) => {
65
- let n = String(t[p]), r = v && y?.has(n);
67
+ children: I.map((t) => {
68
+ let n = String(t[m]), r = S && C?.has(n);
66
69
  return /* @__PURE__ */ u("tr", {
67
- className: e("transition-colors", m && "cursor-pointer hover:bg-bg-sunken/50", r && "bg-action-primary-bg/5"),
68
- onClick: () => m?.(t),
69
- children: [v && /* @__PURE__ */ l("td", {
70
+ className: e("transition-colors", h && "cursor-pointer hover:bg-bg-sunken/50", r && "bg-action-primary-bg/5"),
71
+ onClick: () => h?.(t),
72
+ children: [S && /* @__PURE__ */ l("td", {
70
73
  className: "w-10 px-3 py-3",
71
74
  onClick: (e) => e.stopPropagation(),
72
75
  children: /* @__PURE__ */ l("input", {
73
76
  type: "checkbox",
74
77
  checked: r ?? !1,
75
- onChange: () => F(t),
78
+ onChange: () => z(t),
76
79
  className: "h-4 w-4 rounded border-border-subtle"
77
80
  })
78
- }), d.map((n) => /* @__PURE__ */ l("td", {
81
+ }), f.map((n) => /* @__PURE__ */ l("td", {
79
82
  className: e("px-4 py-3 text-sm text-text-primary", n.className),
80
83
  children: n.render ? n.render(t) : String(t[n.key] ?? "")
81
84
  }, n.key))]
@@ -83,18 +86,18 @@ function d({ columns: d, data: f, keyField: p, onRowClick: m, emptyMessage: h =
83
86
  })
84
87
  })]
85
88
  })
86
- }), x ? /* @__PURE__ */ u("div", {
89
+ }), T ? /* @__PURE__ */ u("div", {
87
90
  className: "flex flex-col gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3 text-sm sm:flex-row sm:items-center sm:justify-between",
88
91
  children: [/* @__PURE__ */ u("span", {
89
92
  className: "text-text-secondary",
90
- children: ["Page ", x.page]
93
+ children: ["Page ", T.page]
91
94
  }), /* @__PURE__ */ u("div", {
92
95
  className: "flex flex-wrap items-center gap-2",
93
96
  children: [
94
- x.onPageSizeChange ? /* @__PURE__ */ l("select", {
95
- value: x.pageSize,
96
- onChange: (e) => x.onPageSizeChange?.(Number(e.target.value)),
97
- disabled: x.loading,
97
+ T.onPageSizeChange ? /* @__PURE__ */ l("select", {
98
+ value: T.pageSize,
99
+ onChange: (e) => T.onPageSizeChange?.(Number(e.target.value)),
100
+ disabled: T.loading,
98
101
  className: "h-8 rounded-md border border-border-subtle bg-bg-surface px-2 text-sm text-text-primary disabled:opacity-50",
99
102
  "aria-label": "Rows per page",
100
103
  children: [
@@ -109,49 +112,49 @@ function d({ columns: d, data: f, keyField: p, onRowClick: m, emptyMessage: h =
109
112
  }) : null,
110
113
  /* @__PURE__ */ u("button", {
111
114
  type: "button",
112
- onClick: () => x.onPageChange(x.page - 1),
113
- disabled: x.loading || x.page <= 1,
115
+ onClick: () => T.onPageChange(T.page - 1),
116
+ disabled: T.loading || T.page <= 1,
114
117
  className: "inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40",
115
118
  children: [/* @__PURE__ */ l(a, { className: "h-4 w-4" }), "Previous"]
116
119
  }),
117
120
  /* @__PURE__ */ u("button", {
118
121
  type: "button",
119
- onClick: () => x.onPageChange(x.page + 1),
120
- disabled: x.loading || !(x.hasNextPage ?? k.length >= x.pageSize),
122
+ onClick: () => T.onPageChange(T.page + 1),
123
+ disabled: T.loading || !(T.hasNextPage ?? N.length >= T.pageSize),
121
124
  className: "inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40",
122
125
  children: ["Next", /* @__PURE__ */ l(o, { className: "h-4 w-4" })]
123
126
  })
124
127
  ]
125
128
  })]
126
- }) : k.length > _ ? /* @__PURE__ */ u("div", {
129
+ }) : N.length > x ? /* @__PURE__ */ u("div", {
127
130
  className: "flex items-center justify-between text-sm",
128
131
  children: [/* @__PURE__ */ u("span", {
129
132
  className: "text-text-secondary",
130
133
  children: [
131
134
  "Showing ",
132
- E * _ + 1,
135
+ A * x + 1,
133
136
  "-",
134
- Math.min((E + 1) * _, k.length),
137
+ Math.min((A + 1) * x, N.length),
135
138
  " of ",
136
- k.length
139
+ N.length
137
140
  ]
138
141
  }), /* @__PURE__ */ u("div", {
139
142
  className: "flex items-center gap-1",
140
143
  children: [
141
144
  /* @__PURE__ */ l("button", {
142
- onClick: () => D((e) => Math.max(0, e - 1)),
143
- disabled: E === 0,
145
+ onClick: () => j((e) => Math.max(0, e - 1)),
146
+ disabled: A === 0,
144
147
  className: "rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40",
145
148
  children: /* @__PURE__ */ l(a, { className: "h-4 w-4" })
146
149
  }),
147
- Array.from({ length: j }).map((t, n) => /* @__PURE__ */ l("button", {
148
- onClick: () => D(n),
149
- className: e("h-8 w-8 rounded-md text-xs font-medium transition-colors", n === E ? "bg-foreground text-background" : "text-text-secondary hover:bg-bg-sunken"),
150
+ Array.from({ length: F }).map((t, n) => /* @__PURE__ */ l("button", {
151
+ onClick: () => j(n),
152
+ className: e("h-8 w-8 rounded-md text-xs font-medium transition-colors", n === A ? "bg-foreground text-background" : "text-text-secondary hover:bg-bg-sunken"),
150
153
  children: n + 1
151
154
  }, n)),
152
155
  /* @__PURE__ */ l("button", {
153
- onClick: () => D((e) => Math.min(j - 1, e + 1)),
154
- disabled: E >= j - 1,
156
+ onClick: () => j((e) => Math.min(F - 1, e + 1)),
157
+ disabled: A >= F - 1,
155
158
  className: "rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40",
156
159
  children: /* @__PURE__ */ l(o, { className: "h-4 w-4" })
157
160
  })
@@ -161,6 +164,6 @@ function d({ columns: d, data: f, keyField: p, onRowClick: m, emptyMessage: h =
161
164
  });
162
165
  }
163
166
  //#endregion
164
- export { d as DataTable };
167
+ export { f as DataTable };
165
168
 
166
169
  //# sourceMappingURL=DataTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/housingvista/components/DataTable.tsx"],"sourcesContent":["import { useState, useMemo, useCallback, type ReactNode } from 'react';\nimport { ChevronUp, ChevronDown, ChevronsUpDown, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { cn } from '../utils/helpers';\n\nexport interface Column<T> {\n key: string;\n header: string;\n render?: (item: T) => ReactNode;\n className?: string;\n sortable?: boolean;\n}\n\ntype SortDirection = 'asc' | 'desc' | null;\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n data: T[];\n keyField: string;\n onRowClick?: (item: T) => void;\n emptyMessage?: string;\n className?: string;\n pageSize?: number;\n selectable?: boolean;\n selectedKeys?: Set<string>;\n onSelectionChange?: (keys: Set<string>) => void;\n serverPagination?: {\n page: number;\n pageSize: number;\n hasNextPage?: boolean;\n loading?: boolean;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n };\n}\n\nexport function DataTable<T extends object>({\n columns,\n data,\n keyField,\n onRowClick,\n emptyMessage = 'No data available',\n className,\n pageSize = 10,\n selectable = false,\n selectedKeys,\n onSelectionChange,\n serverPagination,\n}: DataTableProps<T>) {\n const [sortKey, setSortKey] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDirection>(null);\n const [page, setPage] = useState(0);\n\n const handleSort = useCallback(\n (key: string) => {\n if (sortKey === key) {\n if (sortDir === 'asc') setSortDir('desc');\n else if (sortDir === 'desc') {\n setSortKey(null);\n setSortDir(null);\n } else setSortDir('asc');\n } else {\n setSortKey(key);\n setSortDir('asc');\n }\n setPage(0);\n },\n [sortKey, sortDir]\n );\n\n const sorted = useMemo(() => {\n if (!sortKey || !sortDir) return data;\n return [...data].sort((a, b) => {\n const av = (a as Record<string, unknown>)[sortKey];\n const bv = (b as Record<string, unknown>)[sortKey];\n if (av == null && bv == null) return 0;\n if (av == null) return 1;\n if (bv == null) return -1;\n const cmp = typeof av === 'number' && typeof bv === 'number' ? av - bv : String(av).localeCompare(String(bv));\n return sortDir === 'asc' ? cmp : -cmp;\n });\n }, [data, sortKey, sortDir]);\n\n const effectivePageSize = serverPagination?.pageSize ?? pageSize;\n const totalPages = Math.max(1, Math.ceil(sorted.length / effectivePageSize));\n const paged = serverPagination ? sorted : sorted.slice(page * effectivePageSize, (page + 1) * effectivePageSize);\n\n const allPageKeysSelected =\n selectable && selectedKeys\n ? paged.every((item) => selectedKeys.has(String((item as Record<string, unknown>)[keyField])))\n : false;\n\n const handleSelectAll = () => {\n if (!onSelectionChange || !selectedKeys) return;\n const keys = new Set(selectedKeys);\n if (allPageKeysSelected) {\n paged.forEach((item) => keys.delete(String((item as Record<string, unknown>)[keyField])));\n } else {\n paged.forEach((item) => keys.add(String((item as Record<string, unknown>)[keyField])));\n }\n onSelectionChange(keys);\n };\n\n const handleSelectRow = (item: T) => {\n if (!onSelectionChange || !selectedKeys) return;\n const key = String((item as Record<string, unknown>)[keyField]);\n const keys = new Set(selectedKeys);\n if (keys.has(key)) keys.delete(key);\n else keys.add(key);\n onSelectionChange(keys);\n };\n\n if (data.length === 0) {\n return (\n <div className=\"flex items-center justify-center rounded-lg border border-border-subtle bg-bg-surface p-12\">\n <p className=\"text-sm text-text-secondary\">{emptyMessage}</p>\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-3', className)}>\n <div className=\"overflow-x-auto rounded-card border border-border-seam bg-bg-surface shadow-elevation-1\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n {selectable && (\n <th className=\"w-10 px-3 py-3\">\n <input\n type=\"checkbox\"\n checked={allPageKeysSelected && paged.length > 0}\n onChange={handleSelectAll}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </th>\n )}\n {columns.map((col) => {\n const isSortable = col.sortable !== false;\n const isActive = sortKey === col.key;\n return (\n <th\n key={col.key}\n className={cn(\n 'px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary',\n isSortable && 'cursor-pointer select-none hover:text-text-primary',\n col.className\n )}\n onClick={isSortable ? () => handleSort(col.key) : undefined}\n >\n <span className=\"inline-flex items-center gap-1\">\n {col.header}\n {isSortable &&\n (isActive ? (\n sortDir === 'asc' ? (\n <ChevronUp className=\"h-3 w-3\" />\n ) : (\n <ChevronDown className=\"h-3 w-3\" />\n )\n ) : (\n <ChevronsUpDown className=\"h-3 w-3 opacity-30\" />\n ))}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border bg-bg-surface\">\n {paged.map((item) => {\n const rowKey = String((item as Record<string, unknown>)[keyField]);\n const isSelected = selectable && selectedKeys?.has(rowKey);\n return (\n <tr\n key={rowKey}\n className={cn(\n 'transition-colors',\n onRowClick && 'cursor-pointer hover:bg-bg-sunken/50',\n isSelected && 'bg-action-primary-bg/5'\n )}\n onClick={() => onRowClick?.(item)}\n >\n {selectable && (\n <td className=\"w-10 px-3 py-3\" onClick={(e) => e.stopPropagation()}>\n <input\n type=\"checkbox\"\n checked={isSelected ?? false}\n onChange={() => handleSelectRow(item)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </td>\n )}\n {columns.map((col) => (\n <td key={col.key} className={cn('px-4 py-3 text-sm text-text-primary', col.className)}>\n {col.render ? col.render(item) : String((item as Record<string, unknown>)[col.key] ?? '')}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {serverPagination ? (\n <div className=\"flex flex-col gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3 text-sm sm:flex-row sm:items-center sm:justify-between\">\n <span className=\"text-text-secondary\">Page {serverPagination.page}</span>\n <div className=\"flex flex-wrap items-center gap-2\">\n {serverPagination.onPageSizeChange ? (\n <select\n value={serverPagination.pageSize}\n onChange={(event) => serverPagination.onPageSizeChange?.(Number(event.target.value))}\n disabled={serverPagination.loading}\n className=\"h-8 rounded-md border border-border-subtle bg-bg-surface px-2 text-sm text-text-primary disabled:opacity-50\"\n aria-label=\"Rows per page\"\n >\n {[10, 25, 50, 100].map((option) => (\n <option key={option} value={option}>\n {option} / page\n </option>\n ))}\n </select>\n ) : null}\n <button\n type=\"button\"\n onClick={() => serverPagination.onPageChange(serverPagination.page - 1)}\n disabled={serverPagination.loading || serverPagination.page <= 1}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n Previous\n </button>\n <button\n type=\"button\"\n onClick={() => serverPagination.onPageChange(serverPagination.page + 1)}\n disabled={\n serverPagination.loading ||\n !(serverPagination.hasNextPage ?? sorted.length >= serverPagination.pageSize)\n }\n className=\"inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ) : sorted.length > pageSize ? (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n Showing {page * pageSize + 1}-{Math.min((page + 1) * pageSize, sorted.length)} of {sorted.length}\n </span>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => setPage((p) => Math.max(0, p - 1))}\n disabled={page === 0}\n className=\"rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setPage(i)}\n className={cn(\n 'h-8 w-8 rounded-md text-xs font-medium transition-colors',\n i === page ? 'bg-foreground text-background' : 'text-text-secondary hover:bg-bg-sunken'\n )}\n >\n {i + 1}\n </button>\n ))}\n <button\n onClick={() => setPage((p) => Math.min(totalPages - 1, p + 1))}\n disabled={page >= totalPages - 1}\n className=\"rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/housingvista/components/DataTable.tsx"],"sourcesContent":["import { useState, useMemo, useCallback, type ReactNode } from 'react';\nimport { ChevronUp, ChevronDown, ChevronsUpDown, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/helpers';\n\nexport interface Column<T> {\n key: string;\n header: string;\n render?: (item: T) => ReactNode;\n className?: string;\n sortable?: boolean;\n}\n\ntype SortDirection = 'asc' | 'desc' | null;\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n data: T[];\n keyField: string;\n onRowClick?: (item: T) => void;\n emptyMessage?: string;\n /** Optional secondary line under the empty title. */\n emptyDescription?: string;\n /**\n * Boff UI 2.0 — on-brand illustration name (served from `/illustrations/<name>.webp`)\n * shown in the zero state. Standard names: empty-data, empty-search, empty-files,\n * empty-people, empty-notifications, empty-generic. Defaults to `empty-data`.\n */\n emptyIllustration?: string;\n /** Optional action rendered in the empty state (e.g. a create button). */\n emptyAction?: ReactNode;\n className?: string;\n pageSize?: number;\n selectable?: boolean;\n selectedKeys?: Set<string>;\n onSelectionChange?: (keys: Set<string>) => void;\n serverPagination?: {\n page: number;\n pageSize: number;\n hasNextPage?: boolean;\n loading?: boolean;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n };\n}\n\nexport function DataTable<T extends object>({\n columns,\n data,\n keyField,\n onRowClick,\n emptyMessage = 'No data available',\n emptyDescription,\n emptyIllustration = 'empty-data',\n emptyAction,\n className,\n pageSize = 10,\n selectable = false,\n selectedKeys,\n onSelectionChange,\n serverPagination,\n}: DataTableProps<T>) {\n const [sortKey, setSortKey] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDirection>(null);\n const [page, setPage] = useState(0);\n\n const handleSort = useCallback(\n (key: string) => {\n if (sortKey === key) {\n if (sortDir === 'asc') setSortDir('desc');\n else if (sortDir === 'desc') {\n setSortKey(null);\n setSortDir(null);\n } else setSortDir('asc');\n } else {\n setSortKey(key);\n setSortDir('asc');\n }\n setPage(0);\n },\n [sortKey, sortDir]\n );\n\n const sorted = useMemo(() => {\n if (!sortKey || !sortDir) return data;\n return [...data].sort((a, b) => {\n const av = (a as Record<string, unknown>)[sortKey];\n const bv = (b as Record<string, unknown>)[sortKey];\n if (av == null && bv == null) return 0;\n if (av == null) return 1;\n if (bv == null) return -1;\n const cmp = typeof av === 'number' && typeof bv === 'number' ? av - bv : String(av).localeCompare(String(bv));\n return sortDir === 'asc' ? cmp : -cmp;\n });\n }, [data, sortKey, sortDir]);\n\n const effectivePageSize = serverPagination?.pageSize ?? pageSize;\n const totalPages = Math.max(1, Math.ceil(sorted.length / effectivePageSize));\n const paged = serverPagination ? sorted : sorted.slice(page * effectivePageSize, (page + 1) * effectivePageSize);\n\n const allPageKeysSelected =\n selectable && selectedKeys\n ? paged.every((item) => selectedKeys.has(String((item as Record<string, unknown>)[keyField])))\n : false;\n\n const handleSelectAll = () => {\n if (!onSelectionChange || !selectedKeys) return;\n const keys = new Set(selectedKeys);\n if (allPageKeysSelected) {\n paged.forEach((item) => keys.delete(String((item as Record<string, unknown>)[keyField])));\n } else {\n paged.forEach((item) => keys.add(String((item as Record<string, unknown>)[keyField])));\n }\n onSelectionChange(keys);\n };\n\n const handleSelectRow = (item: T) => {\n if (!onSelectionChange || !selectedKeys) return;\n const key = String((item as Record<string, unknown>)[keyField]);\n const keys = new Set(selectedKeys);\n if (keys.has(key)) keys.delete(key);\n else keys.add(key);\n onSelectionChange(keys);\n };\n\n if (data.length === 0) {\n return (\n <div className=\"rounded-card border border-dashed border-border-seam bg-bg-surface/50\">\n <IllustratedEmptyState\n illustration={emptyIllustration}\n title={emptyMessage}\n description={emptyDescription}\n action={emptyAction}\n />\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-3', className)}>\n <div className=\"overflow-x-auto rounded-card border border-border-seam bg-bg-surface shadow-elevation-1\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n {selectable && (\n <th className=\"w-10 px-3 py-3\">\n <input\n type=\"checkbox\"\n checked={allPageKeysSelected && paged.length > 0}\n onChange={handleSelectAll}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </th>\n )}\n {columns.map((col) => {\n const isSortable = col.sortable !== false;\n const isActive = sortKey === col.key;\n return (\n <th\n key={col.key}\n className={cn(\n 'px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary',\n isSortable && 'cursor-pointer select-none hover:text-text-primary',\n col.className\n )}\n onClick={isSortable ? () => handleSort(col.key) : undefined}\n >\n <span className=\"inline-flex items-center gap-1\">\n {col.header}\n {isSortable &&\n (isActive ? (\n sortDir === 'asc' ? (\n <ChevronUp className=\"h-3 w-3\" />\n ) : (\n <ChevronDown className=\"h-3 w-3\" />\n )\n ) : (\n <ChevronsUpDown className=\"h-3 w-3 opacity-30\" />\n ))}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border bg-bg-surface\">\n {paged.map((item) => {\n const rowKey = String((item as Record<string, unknown>)[keyField]);\n const isSelected = selectable && selectedKeys?.has(rowKey);\n return (\n <tr\n key={rowKey}\n className={cn(\n 'transition-colors',\n onRowClick && 'cursor-pointer hover:bg-bg-sunken/50',\n isSelected && 'bg-action-primary-bg/5'\n )}\n onClick={() => onRowClick?.(item)}\n >\n {selectable && (\n <td className=\"w-10 px-3 py-3\" onClick={(e) => e.stopPropagation()}>\n <input\n type=\"checkbox\"\n checked={isSelected ?? false}\n onChange={() => handleSelectRow(item)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </td>\n )}\n {columns.map((col) => (\n <td key={col.key} className={cn('px-4 py-3 text-sm text-text-primary', col.className)}>\n {col.render ? col.render(item) : String((item as Record<string, unknown>)[col.key] ?? '')}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {serverPagination ? (\n <div className=\"flex flex-col gap-3 rounded-lg border border-border-subtle bg-bg-surface p-3 text-sm sm:flex-row sm:items-center sm:justify-between\">\n <span className=\"text-text-secondary\">Page {serverPagination.page}</span>\n <div className=\"flex flex-wrap items-center gap-2\">\n {serverPagination.onPageSizeChange ? (\n <select\n value={serverPagination.pageSize}\n onChange={(event) => serverPagination.onPageSizeChange?.(Number(event.target.value))}\n disabled={serverPagination.loading}\n className=\"h-8 rounded-md border border-border-subtle bg-bg-surface px-2 text-sm text-text-primary disabled:opacity-50\"\n aria-label=\"Rows per page\"\n >\n {[10, 25, 50, 100].map((option) => (\n <option key={option} value={option}>\n {option} / page\n </option>\n ))}\n </select>\n ) : null}\n <button\n type=\"button\"\n onClick={() => serverPagination.onPageChange(serverPagination.page - 1)}\n disabled={serverPagination.loading || serverPagination.page <= 1}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n Previous\n </button>\n <button\n type=\"button\"\n onClick={() => serverPagination.onPageChange(serverPagination.page + 1)}\n disabled={\n serverPagination.loading ||\n !(serverPagination.hasNextPage ?? sorted.length >= serverPagination.pageSize)\n }\n className=\"inline-flex items-center gap-1 rounded-md border border-border-subtle px-3 py-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ) : sorted.length > pageSize ? (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n Showing {page * pageSize + 1}-{Math.min((page + 1) * pageSize, sorted.length)} of {sorted.length}\n </span>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => setPage((p) => Math.max(0, p - 1))}\n disabled={page === 0}\n className=\"rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n {Array.from({ length: totalPages }).map((_, i) => (\n <button\n key={i}\n onClick={() => setPage(i)}\n className={cn(\n 'h-8 w-8 rounded-md text-xs font-medium transition-colors',\n i === page ? 'bg-foreground text-background' : 'text-text-secondary hover:bg-bg-sunken'\n )}\n >\n {i + 1}\n </button>\n ))}\n <button\n onClick={() => setPage((p) => Math.min(totalPages - 1, p + 1))}\n disabled={page >= totalPages - 1}\n className=\"rounded-md border border-border-subtle p-1.5 text-text-secondary transition-colors hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AA8CA,SAAgB,EAA4B,EAC1C,YACA,SACA,aACA,eACA,kBAAe,qBACf,qBACA,uBAAoB,cACpB,gBACA,cACA,cAAW,IACX,gBAAa,IACb,iBACA,sBACA,uBACoB;CACpB,IAAM,CAAC,GAAS,KAAc,EAAwB,KAAK,EACrD,CAAC,GAAS,KAAc,EAAwB,KAAK,EACrD,CAAC,GAAM,KAAW,EAAS,EAAE,EAE7B,IAAa,GAChB,MAAgB;AAWf,EAVI,MAAY,IACV,MAAY,QAAO,EAAW,OAAO,GAChC,MAAY,UACnB,EAAW,KAAK,EAChB,EAAW,KAAK,IACX,EAAW,MAAM,IAExB,EAAW,EAAI,EACf,EAAW,MAAM,GAEnB,EAAQ,EAAE;IAEZ,CAAC,GAAS,EAAQ,CACnB,EAEK,IAAS,QACT,CAAC,KAAW,CAAC,IAAgB,IAC1B,CAAC,GAAG,EAAK,CAAC,MAAM,GAAG,MAAM;EAC9B,IAAM,IAAM,EAA8B,IACpC,IAAM,EAA8B;AAC1C,MAAI,KAAM,QAAQ,KAAM,KAAM,QAAO;AACrC,MAAI,KAAM,KAAM,QAAO;AACvB,MAAI,KAAM,KAAM,QAAO;EACvB,IAAM,IAAM,OAAO,KAAO,YAAY,OAAO,KAAO,WAAW,IAAK,IAAK,OAAO,EAAG,CAAC,cAAc,OAAO,EAAG,CAAC;AAC7G,SAAO,MAAY,QAAQ,IAAM,CAAC;GAClC,EACD;EAAC;EAAM;EAAS;EAAQ,CAAC,EAEtB,IAAoB,GAAkB,YAAY,GAClD,IAAa,KAAK,IAAI,GAAG,KAAK,KAAK,EAAO,SAAS,EAAkB,CAAC,EACtE,IAAQ,IAAmB,IAAS,EAAO,MAAM,IAAO,IAAoB,IAAO,KAAK,EAAkB,EAE1G,IACJ,KAAc,IACV,EAAM,OAAO,MAAS,EAAa,IAAI,OAAQ,EAAiC,GAAU,CAAC,CAAC,GAC5F,IAEA,UAAwB;AAC5B,MAAI,CAAC,KAAqB,CAAC,EAAc;EACzC,IAAM,IAAO,IAAI,IAAI,EAAa;AAMlC,EALI,IACF,EAAM,SAAS,MAAS,EAAK,OAAO,OAAQ,EAAiC,GAAU,CAAC,CAAC,GAEzF,EAAM,SAAS,MAAS,EAAK,IAAI,OAAQ,EAAiC,GAAU,CAAC,CAAC,EAExF,EAAkB,EAAK;IAGnB,KAAmB,MAAY;AACnC,MAAI,CAAC,KAAqB,CAAC,EAAc;EACzC,IAAM,IAAM,OAAQ,EAAiC,GAAU,EACzD,IAAO,IAAI,IAAI,EAAa;AAGlC,EAFI,EAAK,IAAI,EAAI,GAAE,EAAK,OAAO,EAAI,GAC9B,EAAK,IAAI,EAAI,EAClB,EAAkB,EAAK;;AAgBzB,QAbI,EAAK,WAAW,IAEhB,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GACE,cAAc;GACd,OAAO;GACP,aAAa;GACb,QAAQ;GACR,CAAA;EACE,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAW,EAAG,aAAa,EAAU;YAA1C,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;KAAI,WAAU;eAAd,CACG,KACC,kBAAC,MAAD;MAAI,WAAU;gBACZ,kBAAC,SAAD;OACE,MAAK;OACL,SAAS,KAAuB,EAAM,SAAS;OAC/C,UAAU;OACV,WAAU;OACV,CAAA;MACC,CAAA,EAEN,EAAQ,KAAK,MAAQ;MACpB,IAAM,IAAa,EAAI,aAAa,IAC9B,IAAW,MAAY,EAAI;AACjC,aACE,kBAAC,MAAD;OAEE,WAAW,EACT,wFACA,KAAc,sDACd,EAAI,UACL;OACD,SAAS,UAAmB,EAAW,EAAI,IAAI,GAAG,KAAA;iBAElD,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACG,EAAI,QACJ,MACE,IAEG,EADF,MAAY,QACT,IAEA,GAFD,EAAW,WAAU,WAAY,CAEE,GAGrC,kBAAC,GAAD,EAAgB,WAAU,sBAAuB,CAAA,EAEhD;;OACJ,EArBE,EAAI,IAqBN;OAEP,CACC;QACC,CAAA,EACR,kBAAC,SAAD;KAAO,WAAU;eACd,EAAM,KAAK,MAAS;MACnB,IAAM,IAAS,OAAQ,EAAiC,GAAU,EAC5D,IAAa,KAAc,GAAc,IAAI,EAAO;AAC1D,aACE,kBAAC,MAAD;OAEE,WAAW,EACT,qBACA,KAAc,wCACd,KAAc,yBACf;OACD,eAAe,IAAa,EAAK;iBAPnC,CASG,KACC,kBAAC,MAAD;QAAI,WAAU;QAAiB,UAAU,MAAM,EAAE,iBAAiB;kBAChE,kBAAC,SAAD;SACE,MAAK;SACL,SAAS,KAAc;SACvB,gBAAgB,EAAgB,EAAK;SACrC,WAAU;SACV,CAAA;QACC,CAAA,EAEN,EAAQ,KAAK,MACZ,kBAAC,MAAD;QAAkB,WAAW,EAAG,uCAAuC,EAAI,UAAU;kBAClF,EAAI,SAAS,EAAI,OAAO,EAAK,GAAG,OAAQ,EAAiC,EAAI,QAAQ,GAAG;QACtF,EAFI,EAAI,IAER,CACL,CACC;SAvBE,EAuBF;OAEP;KACI,CAAA,CACF;;GACJ,CAAA,EAEL,IACC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD;IAAM,WAAU;cAAhB,CAAsC,SAAM,EAAiB,KAAY;OACzE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,EAAiB,mBAChB,kBAAC,UAAD;MACE,OAAO,EAAiB;MACxB,WAAW,MAAU,EAAiB,mBAAmB,OAAO,EAAM,OAAO,MAAM,CAAC;MACpF,UAAU,EAAiB;MAC3B,WAAU;MACV,cAAW;gBAEV;OAAC;OAAI;OAAI;OAAI;OAAI,CAAC,KAAK,MACtB,kBAAC,UAAD;OAAqB,OAAO;iBAA5B,CACG,GAAO,UACD;SAFI,EAEJ,CACT;MACK,CAAA,GACP;KACJ,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAiB,aAAa,EAAiB,OAAO,EAAE;MACvE,UAAU,EAAiB,WAAW,EAAiB,QAAQ;MAC/D,WAAU;gBAJZ,CAME,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA,EAAA,WAE5B;;KACT,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAiB,aAAa,EAAiB,OAAO,EAAE;MACvE,UACE,EAAiB,WACjB,EAAE,EAAiB,eAAe,EAAO,UAAU,EAAiB;MAEtE,WAAU;gBAPZ,CAQC,QAEC,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA,CAC7B;;KACL;MACF;OACJ,EAAO,SAAS,IAClB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD;IAAM,WAAU;cAAhB;KAAsC;KAC3B,IAAO,IAAW;KAAE;KAAE,KAAK,KAAK,IAAO,KAAK,GAAU,EAAO,OAAO;KAAC;KAAK,EAAO;KACrF;OACP,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,UAAD;MACE,eAAe,GAAS,MAAM,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC;MACjD,UAAU,MAAS;MACnB,WAAU;gBAEV,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;MAC5B,CAAA;KACR,MAAM,KAAK,EAAE,QAAQ,GAAY,CAAC,CAAC,KAAK,GAAG,MAC1C,kBAAC,UAAD;MAEE,eAAe,EAAQ,EAAE;MACzB,WAAW,EACT,4DACA,MAAM,IAAO,kCAAkC,yCAChD;gBAEA,IAAI;MACE,EARF,EAQE,CACT;KACF,kBAAC,UAAD;MACE,eAAe,GAAS,MAAM,KAAK,IAAI,IAAa,GAAG,IAAI,EAAE,CAAC;MAC9D,UAAU,KAAQ,IAAa;MAC/B,WAAU;gBAEV,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA;MAC7B,CAAA;KACL;MACF;OACJ,KACA"}
@@ -1,24 +1,30 @@
1
1
  import { cn as e } from "../utils/helpers.js";
2
2
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
- import { GradientText as r } from "@burdenoff/fe-libs/ui";
3
+ import { GradientText as r, PagePurpose as i } from "@burdenoff/fe-libs/ui";
4
4
  //#region src/housingvista/components/PageLayout.tsx
5
- var i = ({ title: i, description: a, actions: o, children: s, className: c }) => /* @__PURE__ */ n("div", {
6
- className: e("flex flex-col gap-6 p-6", c),
5
+ var a = ({ title: a, description: o, actions: s, children: c, className: l, purpose: u }) => /* @__PURE__ */ n("div", {
6
+ className: e("flex flex-col gap-6 p-6", l),
7
7
  children: [/* @__PURE__ */ n("div", {
8
- className: "flex items-start justify-between gap-4",
9
- children: [/* @__PURE__ */ n("div", { children: [/* @__PURE__ */ t("h1", {
10
- className: "text-2xl font-semibold text-text-primary",
11
- children: /* @__PURE__ */ t(r, { children: i })
12
- }), a && /* @__PURE__ */ t("p", {
13
- className: "mt-1 text-sm text-text-secondary",
14
- children: a
15
- })] }), o && /* @__PURE__ */ t("div", {
16
- className: "flex items-center gap-2 shrink-0",
17
- children: o
8
+ className: "flex flex-col gap-2",
9
+ children: [/* @__PURE__ */ n("div", {
10
+ className: "flex items-start justify-between gap-4",
11
+ children: [/* @__PURE__ */ n("div", { children: [/* @__PURE__ */ t("h1", {
12
+ className: "text-2xl font-semibold text-text-primary",
13
+ children: /* @__PURE__ */ t(r, { children: a })
14
+ }), o && /* @__PURE__ */ t("p", {
15
+ className: "mt-1 text-sm text-text-secondary",
16
+ children: o
17
+ })] }), s && /* @__PURE__ */ t("div", {
18
+ className: "flex items-center gap-2 shrink-0",
19
+ children: s
20
+ })]
21
+ }), u && /* @__PURE__ */ t(i, {
22
+ className: "max-w-3xl",
23
+ children: u
18
24
  })]
19
- }), s]
25
+ }), c]
20
26
  });
21
27
  //#endregion
22
- export { i as PageLayout };
28
+ export { a as PageLayout };
23
29
 
24
30
  //# sourceMappingURL=PageLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/housingvista/components/PageLayout.tsx"],"sourcesContent":["import type { FC, ReactNode } from 'react';\nimport { GradientText } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/helpers';\n\ninterface PageLayoutProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const PageLayout: FC<PageLayoutProps> = ({ title, description, actions, children, className }) => {\n return (\n <div className={cn('flex flex-col gap-6 p-6', className)}>\n <div className=\"flex items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-semibold text-text-primary\">\n <GradientText>{title}</GradientText>\n </h1>\n {description && <p className=\"mt-1 text-sm text-text-secondary\">{description}</p>}\n </div>\n {actions && <div className=\"flex items-center gap-2 shrink-0\">{actions}</div>}\n </div>\n {children}\n </div>\n );\n};\n"],"mappings":";;;;AAYA,IAAa,KAAmC,EAAE,UAAO,gBAAa,YAAS,aAAU,mBAErF,kBAAC,OAAD;CAAK,WAAW,EAAG,2BAA2B,EAAU;WAAxD,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aACZ,kBAAC,GAAD,EAAA,UAAe,GAAqB,CAAA;GACjC,CAAA,EACJ,KAAe,kBAAC,KAAD;GAAG,WAAU;aAAoC;GAAgB,CAAA,CAC7E,EAAA,CAAA,EACL,KAAW,kBAAC,OAAD;GAAK,WAAU;aAAoC;GAAc,CAAA,CACzE;KACL,EACG"}
1
+ {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/housingvista/components/PageLayout.tsx"],"sourcesContent":["import type { FC, ReactNode } from 'react';\nimport { GradientText, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/helpers';\n\ninterface PageLayoutProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n children: ReactNode;\n className?: string;\n /**\n * Boff UI 2.0 — a calm one/two-line \"story\" explaining WHAT this page is for\n * and the use-case, so a new user understands it at a glance. Rendered with\n * the {@link PagePurpose} primitive directly under the title.\n */\n purpose?: ReactNode;\n}\n\nexport const PageLayout: FC<PageLayoutProps> = ({\n title,\n description,\n actions,\n children,\n className,\n purpose,\n}) => {\n return (\n <div className={cn('flex flex-col gap-6 p-6', className)}>\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-start justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-semibold text-text-primary\">\n <GradientText>{title}</GradientText>\n </h1>\n {description && <p className=\"mt-1 text-sm text-text-secondary\">{description}</p>}\n </div>\n {actions && <div className=\"flex items-center gap-2 shrink-0\">{actions}</div>}\n </div>\n {purpose && <PagePurpose className=\"max-w-3xl\">{purpose}</PagePurpose>}\n </div>\n {children}\n </div>\n );\n};\n"],"mappings":";;;;AAkBA,IAAa,KAAmC,EAC9C,UACA,gBACA,YACA,aACA,cACA,iBAGE,kBAAC,OAAD;CAAK,WAAW,EAAG,2BAA2B,EAAU;WAAxD,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACZ,kBAAC,GAAD,EAAA,UAAe,GAAqB,CAAA;IACjC,CAAA,EACJ,KAAe,kBAAC,KAAD;IAAG,WAAU;cAAoC;IAAgB,CAAA,CAC7E,EAAA,CAAA,EACL,KAAW,kBAAC,OAAD;IAAK,WAAU;cAAoC;IAAc,CAAA,CACzE;MACL,KAAW,kBAAC,GAAD;GAAa,WAAU;aAAa;GAAsB,CAAA,CAClE;KACL,EACG"}
@@ -8,9 +8,9 @@ import { ArrowRight as l, BarChart3 as u, Building as d, DollarSign as f, Eye as
8
8
  import { useNavigate as v } from "react-router-dom";
9
9
  import { jsx as y, jsxs as b } from "react/jsx-runtime";
10
10
  import { useI18n as x } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
- import { AuroraBackground as S, Button as C, EmphasisPanel as w, GlassCard as T, GradientText as E, IllustratedEmptyState as D } from "@burdenoff/fe-libs/ui";
11
+ import { AuroraBackground as S, Button as C, EmphasisPanel as w, GlassCard as T, GradientText as E, IllustratedEmptyState as D, NextSteps as O, PagePurpose as k } from "@burdenoff/fe-libs/ui";
12
12
  //#region src/housingvista/pages/HomePage.tsx
13
- var O = {
13
+ var A = {
14
14
  property_listed: h,
15
15
  transaction_update: m,
16
16
  payment_received: f,
@@ -19,7 +19,7 @@ var O = {
19
19
  document_uploaded: m,
20
20
  offer_received: _,
21
21
  lease_signed: m
22
- }, k = {
22
+ }, j = {
23
23
  property_listed: "text-purple-600 dark:text-purple-400",
24
24
  transaction_update: "text-blue-600 dark:text-blue-400",
25
25
  payment_received: "text-emerald-600 dark:text-emerald-400",
@@ -28,36 +28,36 @@ var O = {
28
28
  document_uploaded: "text-indigo-600 dark:text-indigo-400",
29
29
  offer_received: "text-emerald-600 dark:text-emerald-400",
30
30
  lease_signed: "text-teal-600 dark:text-teal-400"
31
- }, A = () => {
32
- let h = v(), { t: A } = x(), { data: j } = a(), { data: M } = s(), { data: N } = o(), P = (e, t) => {
33
- let n = A(e);
31
+ }, M = () => {
32
+ let h = v(), { t: M } = x(), { data: N } = a(), { data: P } = s(), { data: F } = o(), I = (e, t) => {
33
+ let n = M(e);
34
34
  return n === e ? t : n;
35
- }, F = [
35
+ }, L = [
36
36
  {
37
- title: P("housingvista.home.quickActions.addProperty.title", "Add Property"),
38
- description: P("housingvista.home.quickActions.addProperty.description", "List a new property"),
37
+ title: I("housingvista.home.quickActions.addProperty.title", "Add Property"),
38
+ description: I("housingvista.home.quickActions.addProperty.description", "List a new property"),
39
39
  icon: g,
40
40
  path: "properties/new"
41
41
  },
42
42
  {
43
- title: P("housingvista.home.quickActions.viewAnalytics.title", "View Analytics"),
44
- description: P("housingvista.home.quickActions.viewAnalytics.description", "Check performance metrics"),
43
+ title: I("housingvista.home.quickActions.viewAnalytics.title", "View Analytics"),
44
+ description: I("housingvista.home.quickActions.viewAnalytics.description", "Check performance metrics"),
45
45
  icon: u,
46
46
  path: "analytics"
47
47
  },
48
48
  {
49
- title: P("housingvista.home.quickActions.manageTransactions.title", "Manage Transactions"),
50
- description: P("housingvista.home.quickActions.manageTransactions.description", "Handle ongoing deals"),
49
+ title: I("housingvista.home.quickActions.manageTransactions.title", "Manage Transactions"),
50
+ description: I("housingvista.home.quickActions.manageTransactions.description", "Handle ongoing deals"),
51
51
  icon: m,
52
52
  path: "transactions"
53
53
  },
54
54
  {
55
- title: P("housingvista.home.quickActions.browseProperties.title", "Browse Properties"),
56
- description: P("housingvista.home.quickActions.browseProperties.description", "Explore listings"),
55
+ title: I("housingvista.home.quickActions.browseProperties.title", "Browse Properties"),
56
+ description: I("housingvista.home.quickActions.browseProperties.description", "Explore listings"),
57
57
  icon: d,
58
58
  path: "properties"
59
59
  }
60
- ], I = c(() => N.slice(0, 6), [N]);
60
+ ], R = c(() => F.slice(0, 6), [F]);
61
61
  return /* @__PURE__ */ b("div", {
62
62
  className: "space-y-6 p-6",
63
63
  children: [
@@ -67,45 +67,72 @@ var O = {
67
67
  className: "relative flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between",
68
68
  children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h1", {
69
69
  className: "text-3xl font-bold text-text-primary",
70
- children: /* @__PURE__ */ y(E, { children: P("housingvista.home.header.title", "Welcome back!") })
70
+ children: /* @__PURE__ */ y(E, { children: I("housingvista.home.header.title", "Welcome back!") })
71
71
  }), /* @__PURE__ */ y("p", {
72
72
  className: "mt-1 text-text-secondary",
73
- children: P("housingvista.home.header.description", "Here's what's happening with your real estate portfolio today.")
73
+ children: I("housingvista.home.header.description", "Here's what's happening with your real estate portfolio today.")
74
74
  })] }), /* @__PURE__ */ b(C, {
75
75
  onClick: () => h("properties/new"),
76
76
  className: "gap-2 self-start lg:self-auto",
77
- children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), P("housingvista.home.header.quickAdd", "Quick Add")]
77
+ children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), I("housingvista.home.header.quickAdd", "Quick Add")]
78
78
  })]
79
79
  })]
80
80
  }),
81
+ /* @__PURE__ */ y(k, {
82
+ className: "max-w-3xl",
83
+ children: I("housingvista.home.purpose", "Your real-estate command center. See your portfolio at a glance, jump to the things you do most, and pick up where you left off — from listing a property to tracking deals and analytics.")
84
+ }),
85
+ /* @__PURE__ */ y(O, {
86
+ storageKey: "housingvista-home",
87
+ steps: [
88
+ {
89
+ id: "add-property",
90
+ label: I("housingvista.home.nextSteps.addProperty", "List your first property"),
91
+ description: I("housingvista.home.nextSteps.addPropertyDesc", "Create a market-ready listing in a few guided steps."),
92
+ onClick: () => h("properties/new")
93
+ },
94
+ {
95
+ id: "browse",
96
+ label: I("housingvista.home.nextSteps.browse", "Browse properties"),
97
+ description: I("housingvista.home.nextSteps.browseDesc", "Explore listings and open one for full details."),
98
+ onClick: () => h("properties")
99
+ },
100
+ {
101
+ id: "analytics",
102
+ label: I("housingvista.home.nextSteps.analytics", "Review your analytics"),
103
+ description: I("housingvista.home.nextSteps.analyticsDesc", "Check portfolio performance and market insights."),
104
+ onClick: () => h("analytics")
105
+ }
106
+ ]
107
+ }),
81
108
  /* @__PURE__ */ b("div", {
82
109
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
83
110
  children: [
84
111
  /* @__PURE__ */ y(r, {
85
- label: P("housingvista.home.stats.totalProperties", "Total Properties"),
86
- value: j.totalProperties,
112
+ label: I("housingvista.home.stats.totalProperties", "Total Properties"),
113
+ value: N.totalProperties,
87
114
  icon: /* @__PURE__ */ y(d, { className: "h-5 w-5" }),
88
115
  trend: "up",
89
116
  change: 12,
90
117
  featured: !0
91
118
  }),
92
119
  /* @__PURE__ */ y(r, {
93
- label: P("housingvista.home.stats.activeListings", "Active Listings"),
94
- value: j.activeTransactions,
120
+ label: I("housingvista.home.stats.activeListings", "Active Listings"),
121
+ value: N.activeTransactions,
95
122
  icon: /* @__PURE__ */ y(_, { className: "h-5 w-5" }),
96
123
  trend: "up",
97
124
  change: 8
98
125
  }),
99
126
  /* @__PURE__ */ y(r, {
100
- label: P("housingvista.home.stats.totalViews", "Total Views"),
127
+ label: I("housingvista.home.stats.totalViews", "Total Views"),
101
128
  value: t(12540),
102
129
  icon: /* @__PURE__ */ y(p, { className: "h-5 w-5" }),
103
130
  trend: "down",
104
131
  change: -2
105
132
  }),
106
133
  /* @__PURE__ */ y(r, {
107
- label: P("housingvista.home.stats.monthlyRevenue", "Monthly Revenue"),
108
- value: j.monthlyRevenue,
134
+ label: I("housingvista.home.stats.monthlyRevenue", "Monthly Revenue"),
135
+ value: N.monthlyRevenue,
109
136
  prefix: "$",
110
137
  icon: /* @__PURE__ */ y(f, { className: "h-5 w-5" }),
111
138
  trend: "up",
@@ -124,11 +151,11 @@ var O = {
124
151
  className: "border-b border-border-seam px-5 py-4",
125
152
  children: /* @__PURE__ */ y("h2", {
126
153
  className: "text-base font-semibold text-text-primary",
127
- children: P("housingvista.home.quickActions.title", "Quick Actions")
154
+ children: I("housingvista.home.quickActions.title", "Quick Actions")
128
155
  })
129
156
  }), /* @__PURE__ */ y("div", {
130
157
  className: "space-y-2 p-4",
131
- children: F.map((e) => {
158
+ children: L.map((e) => {
132
159
  let t = e.icon;
133
160
  return /* @__PURE__ */ b("button", {
134
161
  onClick: () => h(e.path),
@@ -158,15 +185,15 @@ var O = {
158
185
  className: "border-b border-border-seam px-5 py-4",
159
186
  children: /* @__PURE__ */ y("h2", {
160
187
  className: "text-base font-semibold text-text-primary",
161
- children: P("housingvista.home.recentActivity.title", "Recent Activity")
188
+ children: I("housingvista.home.recentActivity.title", "Recent Activity")
162
189
  })
163
190
  }), /* @__PURE__ */ y("div", {
164
191
  className: "space-y-2 p-4",
165
- children: M.slice(0, 6).map((t) => /* @__PURE__ */ b("div", {
192
+ children: P.slice(0, 6).map((t) => /* @__PURE__ */ b("div", {
166
193
  className: "flex items-start gap-4 rounded-lg border border-border-seam bg-bg-surface/60 p-4 transition-colors hover:bg-bg-sunken/50",
167
194
  children: [/* @__PURE__ */ y("div", {
168
195
  className: "rounded-lg bg-bg-sunken p-2",
169
- children: /* @__PURE__ */ y(O[t.type] ?? p, { className: e("h-5 w-5", k[t.type] ?? "text-text-secondary") })
196
+ children: /* @__PURE__ */ y(A[t.type] ?? p, { className: e("h-5 w-5", j[t.type] ?? "text-text-secondary") })
170
197
  }), /* @__PURE__ */ b("div", {
171
198
  className: "flex-1 min-w-0",
172
199
  children: [
@@ -196,27 +223,27 @@ var O = {
196
223
  className: "flex items-center justify-between border-b border-border-seam px-5 py-4",
197
224
  children: [/* @__PURE__ */ y("h2", {
198
225
  className: "text-base font-semibold text-text-primary",
199
- children: P("housingvista.home.recentProperties.title", "Recent Properties")
226
+ children: I("housingvista.home.recentProperties.title", "Recent Properties")
200
227
  }), /* @__PURE__ */ b("button", {
201
228
  onClick: () => h("properties"),
202
229
  className: "inline-flex min-h-[44px] items-center gap-1 text-sm font-medium text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] rounded-md px-1",
203
- children: [P("housingvista.home.recentProperties.viewAll", "View All"), /* @__PURE__ */ y(l, { className: "h-4 w-4" })]
230
+ children: [I("housingvista.home.recentProperties.viewAll", "View All"), /* @__PURE__ */ y(l, { className: "h-4 w-4" })]
204
231
  })]
205
- }), I.length === 0 ? /* @__PURE__ */ y("div", {
232
+ }), R.length === 0 ? /* @__PURE__ */ y("div", {
206
233
  className: "p-4",
207
234
  children: /* @__PURE__ */ y(D, {
208
235
  illustration: "empty-data",
209
- title: P("housingvista.home.recentProperties.empty.title", "No properties yet"),
210
- description: P("housingvista.home.recentProperties.empty.description", "List your first property to see it appear here."),
236
+ title: I("housingvista.home.recentProperties.empty.title", "No properties yet"),
237
+ description: I("housingvista.home.recentProperties.empty.description", "List your first property to see it appear here."),
211
238
  action: /* @__PURE__ */ b(C, {
212
239
  onClick: () => h("properties/new"),
213
240
  className: "gap-2",
214
- children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), P("housingvista.home.header.quickAdd", "Quick Add")]
241
+ children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), I("housingvista.home.header.quickAdd", "Quick Add")]
215
242
  })
216
243
  })
217
244
  }) : /* @__PURE__ */ y("div", {
218
245
  className: "grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 lg:grid-cols-3",
219
- children: I.map((e) => /* @__PURE__ */ y(i, {
246
+ children: R.map((e) => /* @__PURE__ */ y(i, {
220
247
  id: e.id,
221
248
  title: e.title,
222
249
  price: e.price.amount,
@@ -237,6 +264,6 @@ var O = {
237
264
  });
238
265
  };
239
266
  //#endregion
240
- export { A as HomePage };
267
+ export { M as HomePage };
241
268
 
242
269
  //# sourceMappingURL=HomePage.js.map