@burdenoff/microfe-brainyrich 2026.705.1 → 2026.706.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.
- package/dist/brainyrich/BrainyRichRoot.js +13 -13
- package/dist/brainyrich/components/ActorName.js +38 -0
- package/dist/brainyrich/components/ActorName.js.map +1 -0
- package/dist/brainyrich/components/ConfirmDialog.js +25 -0
- package/dist/brainyrich/components/ConfirmDialog.js.map +1 -0
- package/dist/brainyrich/components/LoadMore.js +24 -0
- package/dist/brainyrich/components/LoadMore.js.map +1 -0
- package/dist/brainyrich/components/index.js +5 -0
- package/dist/brainyrich/components/notify.js +38 -0
- package/dist/brainyrich/components/notify.js.map +1 -0
- package/dist/brainyrich/components/pickers.js +232 -0
- package/dist/brainyrich/components/pickers.js.map +1 -0
- package/dist/brainyrich/components/reuse/CommentThread.js +208 -0
- package/dist/brainyrich/components/reuse/CommentThread.js.map +1 -0
- package/dist/brainyrich/components/reuse/DocumentsPanel.js +237 -0
- package/dist/brainyrich/components/reuse/DocumentsPanel.js.map +1 -0
- package/dist/brainyrich/components/reuse/TagField.js +206 -0
- package/dist/brainyrich/components/reuse/TagField.js.map +1 -0
- package/dist/brainyrich/components/reuse/transport.js +24 -0
- package/dist/brainyrich/components/reuse/transport.js.map +1 -0
- package/dist/brainyrich/hooks/useBrainyRichApi.js +644 -372
- package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -1
- package/dist/brainyrich/pages/AccountsPage.js +346 -293
- package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js +339 -320
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js +178 -164
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js +195 -169
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js +247 -198
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js +478 -442
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js +438 -396
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +246 -213
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +321 -173
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/TaxPage.js +258 -225
- package/dist/brainyrich/pages/TaxPage.js.map +1 -1
- package/dist/brainyrich/pages/_shared.js.map +1 -1
- package/dist/node_modules/sonner/dist/index.js +163 -0
- package/dist/node_modules/sonner/dist/index.js.map +1 -0
- package/package.json +3 -2
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n,
|
|
2
|
-
import {
|
|
1
|
+
import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n, usePagedInsights as r, usePortfolios as i, useRebalanceProposals as ee, useResolveInsight as te, useTransitionRebalanceProposal as ne } from "../hooks/useBrainyRichApi.js";
|
|
2
|
+
import { LoadMore as re } from "../components/LoadMore.js";
|
|
3
|
+
import { ConfirmDialog as ie } from "../components/ConfirmDialog.js";
|
|
4
|
+
import { ActorName as a } from "../components/ActorName.js";
|
|
5
|
+
import "../components/index.js";
|
|
6
|
+
import { EmptyState as o, ErrorState as ae, KpiGrid as oe, LoadingState as se, SectionShell as ce, formatDate as s, formatPct as c, statusBadgeVariant as l } from "./_shared.js";
|
|
7
|
+
import { CommentThread as u } from "../components/reuse/CommentThread.js";
|
|
3
8
|
import { useMemo as d, useState as f } from "react";
|
|
4
|
-
import { AlertTriangle as
|
|
5
|
-
import { jsx as
|
|
6
|
-
import { Badge as
|
|
9
|
+
import { AlertTriangle as le, ArrowRight as ue, Check as de, Eye as fe, MoreHorizontal as pe, Plus as me, Scale as p, ShieldAlert as he, ShieldCheck as ge, X as _e } from "lucide-react";
|
|
10
|
+
import { Fragment as ve, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
11
|
+
import { Badge as g, Button as _, Card as v, CardContent as y, CardDescription as b, CardHeader as x, CardTitle as S, Dialog as C, DialogClose as ye, DialogContent as w, DialogDescription as T, DialogFooter as be, DialogHeader as E, DialogTitle as D, DropdownMenu as O, DropdownMenuContent as k, DropdownMenuItem as A, DropdownMenuLabel as xe, DropdownMenuSeparator as Se, DropdownMenuTrigger as j, Input as Ce, Label as M, Select as we, SelectContent as Te, SelectItem as Ee, SelectTrigger as De, SelectValue as Oe, Table as ke, TableBody as Ae, TableCell as N, TableHead as P, TableHeader as je, TableRow as F, Textarea as I } from "@burdenoff/fe-libs/ui";
|
|
7
12
|
//#region src/brainyrich/pages/RiskPage.tsx
|
|
8
|
-
var
|
|
13
|
+
var Me = {
|
|
9
14
|
DRAFT: ["PROPOSED", "CANCELLED"],
|
|
10
15
|
PROPOSED: [
|
|
11
16
|
"APPROVED",
|
|
@@ -16,17 +21,17 @@ var Oe = {
|
|
|
16
21
|
REJECTED: [],
|
|
17
22
|
EXECUTED: [],
|
|
18
23
|
CANCELLED: []
|
|
19
|
-
},
|
|
24
|
+
}, Ne = new Set([
|
|
20
25
|
"DRIFT",
|
|
21
26
|
"CONCENTRATION_RISK",
|
|
22
27
|
"REBALANCE_DUE",
|
|
23
28
|
"CASH_DRAG",
|
|
24
29
|
"FEE_ANOMALY"
|
|
25
30
|
]);
|
|
26
|
-
function
|
|
31
|
+
function L(e) {
|
|
27
32
|
return e.toLowerCase().split("_").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
|
|
28
33
|
}
|
|
29
|
-
function
|
|
34
|
+
function R(e) {
|
|
30
35
|
if (e == null) return "—";
|
|
31
36
|
if (Array.isArray(e)) return `${e.length} trade${e.length === 1 ? "" : "s"}`;
|
|
32
37
|
if (typeof e == "object") {
|
|
@@ -35,394 +40,537 @@ function Ae(e) {
|
|
|
35
40
|
}
|
|
36
41
|
return String(e);
|
|
37
42
|
}
|
|
38
|
-
var
|
|
43
|
+
var Pe = {
|
|
39
44
|
portfolioId: "",
|
|
40
45
|
driftPct: "",
|
|
41
46
|
rationale: "",
|
|
42
47
|
trades: ""
|
|
43
48
|
};
|
|
44
|
-
function
|
|
49
|
+
function Fe(e) {
|
|
45
50
|
if (e.trim() === "") return;
|
|
46
51
|
let t = Number(e);
|
|
47
52
|
return Number.isFinite(t) ? t : void 0;
|
|
48
53
|
}
|
|
49
|
-
function
|
|
50
|
-
let { data:
|
|
54
|
+
function Ie() {
|
|
55
|
+
let { data: a, isLoading: u, isError: de, refetch: Ie } = ee(), { data: z } = i(), { items: ze, hasMore: Be, loadMore: Ve, isLoading: He, isFetchingNextPage: Ue, isError: We, refetch: Ge } = r(), B = t(), V = ne(), Ke = e(), qe = n(), Je = te(), [Ye, H] = f(!1), [U, W] = f(Pe), [Xe, G] = f(null), [K, Ze] = f(null), [q, J] = f(null), Y = d(() => {
|
|
51
56
|
let e = /* @__PURE__ */ new Map();
|
|
52
|
-
for (let t of
|
|
57
|
+
for (let t of z) e.set(t.id, t);
|
|
53
58
|
return e;
|
|
54
|
-
}, [
|
|
55
|
-
function
|
|
56
|
-
|
|
59
|
+
}, [z]), X = d(() => ze.filter((e) => Ne.has(e.type)), [ze]), Qe = a.filter((e) => e.status === "DRAFT" || e.status === "PROPOSED" || e.status === "APPROVED"), Z = X.filter((e) => e.status === "OPEN"), $e = a.length > 0 ? a.reduce((e, t) => e + (t.driftPct ?? 0), 0) / a.length : null, Q = z.length > 0;
|
|
60
|
+
function $() {
|
|
61
|
+
W(Pe), G(null), H(!0);
|
|
57
62
|
}
|
|
58
|
-
function
|
|
59
|
-
if (!
|
|
63
|
+
function et() {
|
|
64
|
+
if (!U.portfolioId) return;
|
|
60
65
|
let e;
|
|
61
|
-
if (
|
|
62
|
-
e = JSON.parse(
|
|
66
|
+
if (U.trades.trim() !== "") try {
|
|
67
|
+
e = JSON.parse(U.trades);
|
|
63
68
|
} catch {
|
|
64
|
-
|
|
69
|
+
G("Trades must be valid JSON.");
|
|
65
70
|
return;
|
|
66
71
|
}
|
|
67
|
-
let t =
|
|
72
|
+
let t = Y.get(U.portfolioId);
|
|
68
73
|
B.mutate({
|
|
69
|
-
portfolioId:
|
|
74
|
+
portfolioId: U.portfolioId,
|
|
70
75
|
householdId: t?.householdId ?? null,
|
|
71
|
-
driftPct:
|
|
72
|
-
rationale:
|
|
76
|
+
driftPct: Fe(U.driftPct),
|
|
77
|
+
rationale: U.rationale.trim() || null,
|
|
73
78
|
...e === void 0 ? {} : { trades: e }
|
|
74
|
-
}, { onSuccess: () =>
|
|
79
|
+
}, { onSuccess: () => H(!1) });
|
|
75
80
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
81
|
+
function tt(e, t) {
|
|
82
|
+
if (t === "REJECTED" || t === "CANCELLED") {
|
|
83
|
+
J({
|
|
84
|
+
proposal: e,
|
|
85
|
+
status: t
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
V.mutate({
|
|
90
|
+
id: e.id,
|
|
91
|
+
status: t
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function nt(e) {
|
|
95
|
+
let t = Y.get(e.portfolioId)?.driftThresholdPct;
|
|
78
96
|
return t != null && Number.isFinite(t) && e.driftPct >= t;
|
|
79
97
|
}
|
|
80
|
-
return /* @__PURE__ */
|
|
98
|
+
return /* @__PURE__ */ h(ce, {
|
|
81
99
|
title: "Risk & Rebalancing",
|
|
82
100
|
description: "Review drift-driven rebalance proposals and act on portfolio risk insights.",
|
|
83
|
-
badges: [`${
|
|
101
|
+
badges: [`${Qe.length} active`, `${Z.length} open insight${Z.length === 1 ? "" : "s"}`],
|
|
84
102
|
actionLabel: "New proposal",
|
|
85
|
-
onAction:
|
|
103
|
+
onAction: $,
|
|
86
104
|
children: [
|
|
87
|
-
/* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ m(oe, { items: [
|
|
88
106
|
{
|
|
89
107
|
label: "Total proposals",
|
|
90
|
-
value: String(
|
|
108
|
+
value: String(a.length)
|
|
91
109
|
},
|
|
92
110
|
{
|
|
93
111
|
label: "Active proposals",
|
|
94
|
-
value: String(
|
|
112
|
+
value: String(Qe.length)
|
|
95
113
|
},
|
|
96
114
|
{
|
|
97
115
|
label: "Average drift",
|
|
98
|
-
value:
|
|
116
|
+
value: $e === null ? "—" : c($e)
|
|
99
117
|
},
|
|
100
118
|
{
|
|
101
119
|
label: "Open risk insights",
|
|
102
|
-
value: String(
|
|
120
|
+
value: String(Z.length)
|
|
103
121
|
}
|
|
104
122
|
] }),
|
|
105
|
-
/* @__PURE__ */ v
|
|
123
|
+
/* @__PURE__ */ h(v, { children: [/* @__PURE__ */ h(x, { children: [/* @__PURE__ */ h(S, {
|
|
106
124
|
className: "flex items-center gap-2",
|
|
107
|
-
children: [/* @__PURE__ */
|
|
125
|
+
children: [/* @__PURE__ */ m(p, {
|
|
108
126
|
className: "h-5 w-5",
|
|
109
127
|
"aria-hidden": "true"
|
|
110
128
|
}), "Rebalance proposals"]
|
|
111
|
-
}), /* @__PURE__ */
|
|
112
|
-
icon: /* @__PURE__ */
|
|
129
|
+
}), /* @__PURE__ */ m(b, { children: "Drift against target allocation, with lifecycle actions per proposal." })] }), /* @__PURE__ */ m(y, { children: u ? /* @__PURE__ */ m(se, {}) : de ? /* @__PURE__ */ m(ae, { onRetry: () => Ie() }) : a.length === 0 ? /* @__PURE__ */ m(o, {
|
|
130
|
+
icon: /* @__PURE__ */ m(p, {
|
|
113
131
|
className: "size-6",
|
|
114
132
|
"aria-hidden": "true"
|
|
115
133
|
}),
|
|
116
134
|
title: "No rebalance proposals",
|
|
117
|
-
description:
|
|
118
|
-
action:
|
|
135
|
+
description: Q ? "Create a proposal when a portfolio drifts from its target allocation." : "Create a portfolio first, then propose a rebalance when it drifts.",
|
|
136
|
+
action: Q ? /* @__PURE__ */ h(_, {
|
|
119
137
|
size: "sm",
|
|
120
|
-
onClick:
|
|
121
|
-
children: [/* @__PURE__ */
|
|
138
|
+
onClick: $,
|
|
139
|
+
children: [/* @__PURE__ */ m(me, {
|
|
122
140
|
className: "size-4",
|
|
123
141
|
"aria-hidden": "true"
|
|
124
142
|
}), "New proposal"]
|
|
125
143
|
}) : void 0
|
|
126
|
-
}) : /* @__PURE__ */
|
|
144
|
+
}) : /* @__PURE__ */ m("div", {
|
|
127
145
|
className: "overflow-x-auto",
|
|
128
|
-
children: /* @__PURE__ */
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
/* @__PURE__ */
|
|
146
|
+
children: /* @__PURE__ */ h(ke, { children: [/* @__PURE__ */ m(je, { children: /* @__PURE__ */ h(F, { children: [
|
|
147
|
+
/* @__PURE__ */ m(P, { children: "Portfolio" }),
|
|
148
|
+
/* @__PURE__ */ m(P, {
|
|
131
149
|
className: "text-right",
|
|
132
150
|
children: "Drift"
|
|
133
151
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
/* @__PURE__ */
|
|
138
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ m(P, { children: "Status" }),
|
|
153
|
+
/* @__PURE__ */ m(P, { children: "Rationale" }),
|
|
154
|
+
/* @__PURE__ */ m(P, { children: "Trades" }),
|
|
155
|
+
/* @__PURE__ */ m(P, { children: "Created" }),
|
|
156
|
+
/* @__PURE__ */ m(P, {
|
|
139
157
|
className: "w-12 text-right",
|
|
140
158
|
children: "Actions"
|
|
141
159
|
})
|
|
142
|
-
] }) }), /* @__PURE__ */
|
|
143
|
-
let t =
|
|
144
|
-
return /* @__PURE__ */
|
|
145
|
-
/* @__PURE__ */
|
|
160
|
+
] }) }), /* @__PURE__ */ m(Ae, { children: a.map((e) => {
|
|
161
|
+
let t = Y.get(e.portfolioId), n = nt(e), r = Me[e.status];
|
|
162
|
+
return /* @__PURE__ */ h(F, { children: [
|
|
163
|
+
/* @__PURE__ */ h(N, { children: [/* @__PURE__ */ m("p", {
|
|
146
164
|
className: "font-medium text-text-primary",
|
|
147
165
|
children: t?.name ?? "Unknown portfolio"
|
|
148
|
-
}), /* @__PURE__ */
|
|
166
|
+
}), /* @__PURE__ */ h("p", {
|
|
149
167
|
className: "text-xs text-text-secondary",
|
|
150
|
-
children: [t?.baseCurrency ?? "—", t?.driftThresholdPct == null ? "" : ` · threshold ${
|
|
168
|
+
children: [t?.baseCurrency ?? "—", t?.driftThresholdPct == null ? "" : ` · threshold ${c(t.driftThresholdPct)}`]
|
|
151
169
|
})] }),
|
|
152
|
-
/* @__PURE__ */
|
|
170
|
+
/* @__PURE__ */ h(N, {
|
|
153
171
|
className: "text-right",
|
|
154
|
-
children: [/* @__PURE__ */
|
|
172
|
+
children: [/* @__PURE__ */ h("span", {
|
|
155
173
|
className: `inline-flex items-center justify-end gap-1 font-semibold ${n ? "text-status-error-text" : "text-text-primary"}`,
|
|
156
|
-
children: [n ? /* @__PURE__ */
|
|
174
|
+
children: [n ? /* @__PURE__ */ m(le, {
|
|
157
175
|
className: "size-4",
|
|
158
176
|
"aria-hidden": "true"
|
|
159
|
-
}) : null,
|
|
160
|
-
}), n ? /* @__PURE__ */
|
|
177
|
+
}) : null, c(e.driftPct)]
|
|
178
|
+
}), n ? /* @__PURE__ */ m("p", {
|
|
161
179
|
className: "text-xs text-status-error-text",
|
|
162
180
|
children: "Over threshold"
|
|
163
181
|
}) : null]
|
|
164
182
|
}),
|
|
165
|
-
/* @__PURE__ */
|
|
166
|
-
variant:
|
|
167
|
-
children:
|
|
183
|
+
/* @__PURE__ */ m(N, { children: /* @__PURE__ */ m(g, {
|
|
184
|
+
variant: l(e.status),
|
|
185
|
+
children: L(e.status)
|
|
168
186
|
}) }),
|
|
169
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ m(N, {
|
|
170
188
|
className: "max-w-xs",
|
|
171
|
-
children: /* @__PURE__ */
|
|
189
|
+
children: /* @__PURE__ */ m("p", {
|
|
172
190
|
className: "truncate text-sm text-text-secondary",
|
|
173
191
|
children: e.rationale ?? "—"
|
|
174
192
|
})
|
|
175
193
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ m(N, {
|
|
177
195
|
className: "text-sm text-text-secondary",
|
|
178
|
-
children:
|
|
196
|
+
children: R(e.trades)
|
|
179
197
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ m(N, {
|
|
181
199
|
className: "text-sm text-text-secondary",
|
|
182
|
-
children:
|
|
200
|
+
children: s(e.createdAt)
|
|
183
201
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ m(N, {
|
|
185
203
|
className: "text-right",
|
|
186
|
-
children:
|
|
187
|
-
className: "text-xs text-text-muted",
|
|
188
|
-
children: "—"
|
|
189
|
-
}) : /* @__PURE__ */ v(E, { children: [/* @__PURE__ */ _(k, {
|
|
204
|
+
children: /* @__PURE__ */ h(O, { children: [/* @__PURE__ */ m(j, {
|
|
190
205
|
asChild: !0,
|
|
191
|
-
children: /* @__PURE__ */ _
|
|
206
|
+
children: /* @__PURE__ */ m(_, {
|
|
192
207
|
variant: "ghost",
|
|
193
208
|
size: "sm",
|
|
194
|
-
"aria-label": `
|
|
195
|
-
children: /* @__PURE__ */
|
|
209
|
+
"aria-label": `Actions for ${t?.name ?? "proposal"}`,
|
|
210
|
+
children: /* @__PURE__ */ m(pe, {
|
|
196
211
|
className: "size-4",
|
|
197
212
|
"aria-hidden": "true"
|
|
198
213
|
})
|
|
199
214
|
})
|
|
200
|
-
}), /* @__PURE__ */
|
|
215
|
+
}), /* @__PURE__ */ h(k, {
|
|
201
216
|
align: "end",
|
|
202
|
-
children: [
|
|
203
|
-
|
|
204
|
-
/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ h(A, {
|
|
218
|
+
onClick: () => Ze(e),
|
|
219
|
+
children: [/* @__PURE__ */ m(fe, {
|
|
220
|
+
className: "size-4",
|
|
221
|
+
"aria-hidden": "true"
|
|
222
|
+
}), "View details"]
|
|
223
|
+
}), r.length > 0 ? /* @__PURE__ */ h(ve, { children: [
|
|
224
|
+
/* @__PURE__ */ m(Se, {}),
|
|
225
|
+
/* @__PURE__ */ m(xe, { children: "Advance to" }),
|
|
205
226
|
r.map((t) => {
|
|
206
227
|
let n = t === "REJECTED" || t === "CANCELLED";
|
|
207
|
-
return /* @__PURE__ */
|
|
228
|
+
return /* @__PURE__ */ h(A, {
|
|
208
229
|
disabled: V.isPending,
|
|
209
230
|
className: n ? "text-status-error-text" : void 0,
|
|
210
|
-
onClick: () =>
|
|
211
|
-
|
|
212
|
-
status: t
|
|
213
|
-
}),
|
|
214
|
-
children: [_(n ? le : oe, {
|
|
231
|
+
onClick: () => tt(e, t),
|
|
232
|
+
children: [m(n ? _e : ue, {
|
|
215
233
|
className: "size-4",
|
|
216
234
|
"aria-hidden": "true"
|
|
217
|
-
}),
|
|
235
|
+
}), L(t)]
|
|
218
236
|
}, t);
|
|
219
237
|
})
|
|
220
|
-
]
|
|
238
|
+
] }) : null]
|
|
221
239
|
})] })
|
|
222
240
|
})
|
|
223
241
|
] }, e.id);
|
|
224
242
|
}) })] })
|
|
225
243
|
}) })] }),
|
|
226
|
-
/* @__PURE__ */ v
|
|
244
|
+
/* @__PURE__ */ h(v, { children: [/* @__PURE__ */ h(x, { children: [/* @__PURE__ */ h(S, {
|
|
227
245
|
className: "flex items-center gap-2",
|
|
228
|
-
children: [/* @__PURE__ */
|
|
246
|
+
children: [/* @__PURE__ */ m(he, {
|
|
229
247
|
className: "h-5 w-5",
|
|
230
248
|
"aria-hidden": "true"
|
|
231
249
|
}), "Risk insights"]
|
|
232
|
-
}), /* @__PURE__ */
|
|
233
|
-
icon: /* @__PURE__ */
|
|
250
|
+
}), /* @__PURE__ */ m(b, { children: "Drift, concentration, cash-drag and fee-anomaly signals detected across your portfolios." })] }), /* @__PURE__ */ m(y, { children: He ? /* @__PURE__ */ m(se, {}) : We ? /* @__PURE__ */ m(ae, { onRetry: () => Ge() }) : X.length === 0 ? /* @__PURE__ */ m(o, {
|
|
251
|
+
icon: /* @__PURE__ */ m(ge, {
|
|
234
252
|
className: "size-6",
|
|
235
253
|
"aria-hidden": "true"
|
|
236
254
|
}),
|
|
237
255
|
title: "No risk insights",
|
|
238
256
|
description: "No drift, concentration, cash-drag or fee-anomaly signals are open right now."
|
|
239
|
-
}) : /* @__PURE__ */
|
|
257
|
+
}) : /* @__PURE__ */ h("div", {
|
|
240
258
|
className: "space-y-3",
|
|
241
|
-
children:
|
|
259
|
+
children: [X.map((e) => /* @__PURE__ */ m(Re, {
|
|
242
260
|
insight: e,
|
|
243
|
-
onAcknowledge: () =>
|
|
244
|
-
onResolve: () =>
|
|
245
|
-
onDismiss: () =>
|
|
246
|
-
actionPending:
|
|
247
|
-
}, e.id))
|
|
261
|
+
onAcknowledge: () => Ke.mutate(e.id),
|
|
262
|
+
onResolve: () => Je.mutate(e.id),
|
|
263
|
+
onDismiss: () => qe.mutate(e.id),
|
|
264
|
+
actionPending: Ke.isPending || Je.isPending || qe.isPending
|
|
265
|
+
}, e.id)), /* @__PURE__ */ m(re, {
|
|
266
|
+
hasMore: Be,
|
|
267
|
+
onClick: Ve,
|
|
268
|
+
loading: Ue,
|
|
269
|
+
label: "Load more insights"
|
|
270
|
+
})]
|
|
248
271
|
}) })] }),
|
|
249
|
-
/* @__PURE__ */
|
|
250
|
-
open:
|
|
251
|
-
onOpenChange:
|
|
252
|
-
children: /* @__PURE__ */
|
|
253
|
-
/* @__PURE__ */
|
|
254
|
-
|
|
272
|
+
/* @__PURE__ */ m(C, {
|
|
273
|
+
open: Ye,
|
|
274
|
+
onOpenChange: H,
|
|
275
|
+
children: /* @__PURE__ */ h(w, { children: [
|
|
276
|
+
/* @__PURE__ */ h(E, { children: [/* @__PURE__ */ m(D, { children: "New rebalance proposal" }), /* @__PURE__ */ m(T, { children: "Propose a rebalance for a portfolio that has drifted from its target allocation." })] }),
|
|
277
|
+
Q ? /* @__PURE__ */ h("div", {
|
|
255
278
|
className: "grid gap-4",
|
|
256
279
|
children: [
|
|
257
|
-
/* @__PURE__ */
|
|
280
|
+
/* @__PURE__ */ h("div", {
|
|
258
281
|
className: "space-y-2",
|
|
259
|
-
children: [/* @__PURE__ */
|
|
282
|
+
children: [/* @__PURE__ */ m(M, {
|
|
260
283
|
htmlFor: "prop-portfolio",
|
|
261
284
|
children: "Portfolio"
|
|
262
|
-
}), /* @__PURE__ */
|
|
263
|
-
value:
|
|
264
|
-
onValueChange: (e) =>
|
|
285
|
+
}), /* @__PURE__ */ h(we, {
|
|
286
|
+
value: U.portfolioId,
|
|
287
|
+
onValueChange: (e) => W((t) => ({
|
|
265
288
|
...t,
|
|
266
289
|
portfolioId: e
|
|
267
290
|
})),
|
|
268
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ m(De, {
|
|
269
292
|
id: "prop-portfolio",
|
|
270
|
-
children: /* @__PURE__ */
|
|
271
|
-
}), /* @__PURE__ */
|
|
293
|
+
children: /* @__PURE__ */ m(Oe, { placeholder: "Select a portfolio" })
|
|
294
|
+
}), /* @__PURE__ */ m(Te, { children: z.map((e) => /* @__PURE__ */ m(Ee, {
|
|
272
295
|
value: e.id,
|
|
273
296
|
children: e.name
|
|
274
297
|
}, e.id)) })]
|
|
275
298
|
})]
|
|
276
299
|
}),
|
|
277
|
-
/* @__PURE__ */
|
|
300
|
+
/* @__PURE__ */ h("div", {
|
|
278
301
|
className: "space-y-2",
|
|
279
|
-
children: [/* @__PURE__ */
|
|
302
|
+
children: [/* @__PURE__ */ m(M, {
|
|
280
303
|
htmlFor: "prop-drift",
|
|
281
304
|
children: "Drift %"
|
|
282
|
-
}), /* @__PURE__ */
|
|
305
|
+
}), /* @__PURE__ */ m(Ce, {
|
|
283
306
|
id: "prop-drift",
|
|
284
307
|
type: "number",
|
|
285
|
-
value:
|
|
286
|
-
onChange: (e) =>
|
|
308
|
+
value: U.driftPct,
|
|
309
|
+
onChange: (e) => W((t) => ({
|
|
287
310
|
...t,
|
|
288
311
|
driftPct: e.target.value
|
|
289
312
|
})),
|
|
290
313
|
placeholder: "e.g. 6.5"
|
|
291
314
|
})]
|
|
292
315
|
}),
|
|
293
|
-
/* @__PURE__ */
|
|
316
|
+
/* @__PURE__ */ h("div", {
|
|
294
317
|
className: "space-y-2",
|
|
295
|
-
children: [/* @__PURE__ */
|
|
318
|
+
children: [/* @__PURE__ */ m(M, {
|
|
296
319
|
htmlFor: "prop-rationale",
|
|
297
320
|
children: "Rationale"
|
|
298
|
-
}), /* @__PURE__ */
|
|
321
|
+
}), /* @__PURE__ */ m(I, {
|
|
299
322
|
id: "prop-rationale",
|
|
300
|
-
value:
|
|
301
|
-
onChange: (e) =>
|
|
323
|
+
value: U.rationale,
|
|
324
|
+
onChange: (e) => W((t) => ({
|
|
302
325
|
...t,
|
|
303
326
|
rationale: e.target.value
|
|
304
327
|
})),
|
|
305
328
|
placeholder: "Why is this rebalance needed?"
|
|
306
329
|
})]
|
|
307
330
|
}),
|
|
308
|
-
/* @__PURE__ */
|
|
331
|
+
/* @__PURE__ */ h("div", {
|
|
309
332
|
className: "space-y-2",
|
|
310
333
|
children: [
|
|
311
|
-
/* @__PURE__ */
|
|
334
|
+
/* @__PURE__ */ m(M, {
|
|
312
335
|
htmlFor: "prop-trades",
|
|
313
336
|
children: "Trades (JSON, optional)"
|
|
314
337
|
}),
|
|
315
|
-
/* @__PURE__ */
|
|
338
|
+
/* @__PURE__ */ m(I, {
|
|
316
339
|
id: "prop-trades",
|
|
317
|
-
value:
|
|
340
|
+
value: U.trades,
|
|
318
341
|
onChange: (e) => {
|
|
319
|
-
|
|
342
|
+
G(null), W((t) => ({
|
|
320
343
|
...t,
|
|
321
344
|
trades: e.target.value
|
|
322
345
|
}));
|
|
323
346
|
},
|
|
324
347
|
placeholder: "e.g. [{\"symbol\":\"VOO\",\"action\":\"SELL\",\"quantity\":10}]"
|
|
325
348
|
}),
|
|
326
|
-
|
|
349
|
+
Xe ? /* @__PURE__ */ m("p", {
|
|
327
350
|
className: "text-xs text-status-error-text",
|
|
328
|
-
children:
|
|
351
|
+
children: Xe
|
|
329
352
|
}) : null
|
|
330
353
|
]
|
|
331
354
|
})
|
|
332
355
|
]
|
|
333
|
-
}) : /* @__PURE__ */
|
|
334
|
-
|
|
335
|
-
|
|
356
|
+
}) : /* @__PURE__ */ m(o, {
|
|
357
|
+
icon: /* @__PURE__ */ m(p, {
|
|
358
|
+
className: "size-6",
|
|
359
|
+
"aria-hidden": "true"
|
|
360
|
+
}),
|
|
361
|
+
title: "Create a portfolio first",
|
|
362
|
+
description: "A rebalance proposal targets a portfolio. Add a portfolio on the Portfolios page, then return here to propose a rebalance."
|
|
336
363
|
}),
|
|
337
|
-
/* @__PURE__ */
|
|
364
|
+
/* @__PURE__ */ h(be, { children: [/* @__PURE__ */ m(ye, {
|
|
338
365
|
asChild: !0,
|
|
339
|
-
children: /* @__PURE__ */ _
|
|
366
|
+
children: /* @__PURE__ */ m(_, {
|
|
340
367
|
variant: "outline",
|
|
341
368
|
children: "Cancel"
|
|
342
369
|
})
|
|
343
|
-
}), /* @__PURE__ */ _
|
|
344
|
-
onClick:
|
|
345
|
-
disabled: !
|
|
370
|
+
}), /* @__PURE__ */ m(_, {
|
|
371
|
+
onClick: et,
|
|
372
|
+
disabled: !U.portfolioId || B.isPending,
|
|
346
373
|
children: B.isPending ? "Creating…" : "Create proposal"
|
|
347
374
|
})] })
|
|
348
375
|
] })
|
|
376
|
+
}),
|
|
377
|
+
/* @__PURE__ */ m(Le, {
|
|
378
|
+
proposal: K,
|
|
379
|
+
portfolio: K ? Y.get(K.portfolioId) ?? null : null,
|
|
380
|
+
onOpenChange: (e) => {
|
|
381
|
+
e || Ze(null);
|
|
382
|
+
}
|
|
383
|
+
}),
|
|
384
|
+
/* @__PURE__ */ m(ie, {
|
|
385
|
+
open: q !== null,
|
|
386
|
+
onOpenChange: (e) => {
|
|
387
|
+
e || J(null);
|
|
388
|
+
},
|
|
389
|
+
title: q?.status === "REJECTED" ? "Reject this proposal?" : "Cancel this proposal?",
|
|
390
|
+
description: q ? `This moves the rebalance proposal for ${Y.get(q.proposal.portfolioId)?.name ?? "this portfolio"} to ${L(q.status)}. This cannot be undone.` : void 0,
|
|
391
|
+
confirmLabel: q?.status === "REJECTED" ? "Reject" : "Cancel proposal",
|
|
392
|
+
cancelLabel: "Keep",
|
|
393
|
+
destructive: !0,
|
|
394
|
+
pending: V.isPending,
|
|
395
|
+
onConfirm: () => {
|
|
396
|
+
q && V.mutate({
|
|
397
|
+
id: q.proposal.id,
|
|
398
|
+
status: q.status
|
|
399
|
+
}, { onSuccess: () => J(null) });
|
|
400
|
+
}
|
|
349
401
|
})
|
|
350
402
|
]
|
|
351
403
|
});
|
|
352
404
|
}
|
|
353
|
-
function
|
|
354
|
-
|
|
355
|
-
|
|
405
|
+
function Le({ proposal: e, portfolio: t, onOpenChange: n }) {
|
|
406
|
+
return /* @__PURE__ */ m(C, {
|
|
407
|
+
open: e !== null,
|
|
408
|
+
onOpenChange: n,
|
|
409
|
+
children: /* @__PURE__ */ m(w, {
|
|
410
|
+
className: "max-h-[85vh] overflow-y-auto",
|
|
411
|
+
children: e ? /* @__PURE__ */ h(ve, { children: [
|
|
412
|
+
/* @__PURE__ */ h(E, { children: [/* @__PURE__ */ h(D, {
|
|
413
|
+
className: "flex flex-wrap items-center gap-2",
|
|
414
|
+
children: [t?.name ?? "Rebalance proposal", /* @__PURE__ */ m(g, {
|
|
415
|
+
variant: l(e.status),
|
|
416
|
+
children: L(e.status)
|
|
417
|
+
})]
|
|
418
|
+
}), /* @__PURE__ */ h(T, { children: [
|
|
419
|
+
"Drift ",
|
|
420
|
+
c(e.driftPct),
|
|
421
|
+
t?.driftThresholdPct == null ? "" : ` · threshold ${c(t.driftThresholdPct)}`,
|
|
422
|
+
" · created ",
|
|
423
|
+
s(e.createdAt)
|
|
424
|
+
] })] }),
|
|
425
|
+
/* @__PURE__ */ h("dl", {
|
|
426
|
+
className: "grid grid-cols-2 gap-4 text-sm",
|
|
427
|
+
children: [
|
|
428
|
+
/* @__PURE__ */ h("div", {
|
|
429
|
+
className: "space-y-1",
|
|
430
|
+
children: [/* @__PURE__ */ m("dt", {
|
|
431
|
+
className: "text-xs font-medium text-text-muted",
|
|
432
|
+
children: "Proposed by"
|
|
433
|
+
}), /* @__PURE__ */ m("dd", {
|
|
434
|
+
className: "text-text-primary",
|
|
435
|
+
children: e.proposedById ? /* @__PURE__ */ m(a, { id: e.proposedById }) : /* @__PURE__ */ m("span", {
|
|
436
|
+
className: "text-text-muted",
|
|
437
|
+
children: "—"
|
|
438
|
+
})
|
|
439
|
+
})]
|
|
440
|
+
}),
|
|
441
|
+
/* @__PURE__ */ h("div", {
|
|
442
|
+
className: "space-y-1",
|
|
443
|
+
children: [/* @__PURE__ */ m("dt", {
|
|
444
|
+
className: "text-xs font-medium text-text-muted",
|
|
445
|
+
children: "Approved by"
|
|
446
|
+
}), /* @__PURE__ */ m("dd", {
|
|
447
|
+
className: "text-text-primary",
|
|
448
|
+
children: e.approvedById ? /* @__PURE__ */ m(a, { id: e.approvedById }) : /* @__PURE__ */ m("span", {
|
|
449
|
+
className: "text-text-muted",
|
|
450
|
+
children: "—"
|
|
451
|
+
})
|
|
452
|
+
})]
|
|
453
|
+
}),
|
|
454
|
+
/* @__PURE__ */ h("div", {
|
|
455
|
+
className: "space-y-1",
|
|
456
|
+
children: [/* @__PURE__ */ m("dt", {
|
|
457
|
+
className: "text-xs font-medium text-text-muted",
|
|
458
|
+
children: "Trades"
|
|
459
|
+
}), /* @__PURE__ */ m("dd", {
|
|
460
|
+
className: "text-text-primary",
|
|
461
|
+
children: R(e.trades)
|
|
462
|
+
})]
|
|
463
|
+
}),
|
|
464
|
+
/* @__PURE__ */ h("div", {
|
|
465
|
+
className: "space-y-1",
|
|
466
|
+
children: [/* @__PURE__ */ m("dt", {
|
|
467
|
+
className: "text-xs font-medium text-text-muted",
|
|
468
|
+
children: "Executed"
|
|
469
|
+
}), /* @__PURE__ */ m("dd", {
|
|
470
|
+
className: "text-text-primary",
|
|
471
|
+
children: e.executedAt ? s(e.executedAt) : /* @__PURE__ */ m("span", {
|
|
472
|
+
className: "text-text-muted",
|
|
473
|
+
children: "—"
|
|
474
|
+
})
|
|
475
|
+
})]
|
|
476
|
+
})
|
|
477
|
+
]
|
|
478
|
+
}),
|
|
479
|
+
/* @__PURE__ */ h("div", {
|
|
480
|
+
className: "space-y-1",
|
|
481
|
+
children: [/* @__PURE__ */ m("p", {
|
|
482
|
+
className: "text-xs font-medium text-text-muted",
|
|
483
|
+
children: "Rationale (summary)"
|
|
484
|
+
}), /* @__PURE__ */ m("p", {
|
|
485
|
+
className: "text-sm text-text-secondary",
|
|
486
|
+
children: e.rationale ?? "—"
|
|
487
|
+
})]
|
|
488
|
+
}),
|
|
489
|
+
/* @__PURE__ */ m("div", {
|
|
490
|
+
className: "border-t border-border-subtle pt-4",
|
|
491
|
+
children: /* @__PURE__ */ m(u, {
|
|
492
|
+
entityType: "brainyrich-rebalance",
|
|
493
|
+
entityId: e.id,
|
|
494
|
+
heading: "Discussion"
|
|
495
|
+
})
|
|
496
|
+
})
|
|
497
|
+
] }) : null
|
|
498
|
+
})
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
function Re({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPending: i }) {
|
|
502
|
+
let ee = e.status === "RESOLVED" || e.status === "DISMISSED";
|
|
503
|
+
return /* @__PURE__ */ h("div", {
|
|
356
504
|
className: "flex items-start justify-between gap-4 rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
357
|
-
children: [/* @__PURE__ */
|
|
505
|
+
children: [/* @__PURE__ */ h("div", {
|
|
358
506
|
className: "min-w-0 space-y-1",
|
|
359
507
|
children: [
|
|
360
|
-
/* @__PURE__ */
|
|
508
|
+
/* @__PURE__ */ h("div", {
|
|
361
509
|
className: "flex flex-wrap items-center gap-2",
|
|
362
510
|
children: [
|
|
363
|
-
/* @__PURE__ */
|
|
511
|
+
/* @__PURE__ */ m("p", {
|
|
364
512
|
className: "font-medium text-text-primary",
|
|
365
513
|
children: e.title
|
|
366
514
|
}),
|
|
367
|
-
/* @__PURE__ */
|
|
368
|
-
variant:
|
|
369
|
-
children:
|
|
515
|
+
/* @__PURE__ */ m(g, {
|
|
516
|
+
variant: l(e.severity),
|
|
517
|
+
children: L(e.severity)
|
|
370
518
|
}),
|
|
371
|
-
/* @__PURE__ */
|
|
519
|
+
/* @__PURE__ */ m(g, {
|
|
372
520
|
variant: "outline",
|
|
373
|
-
children:
|
|
521
|
+
children: L(e.type)
|
|
374
522
|
}),
|
|
375
|
-
/* @__PURE__ */
|
|
376
|
-
variant:
|
|
377
|
-
children:
|
|
523
|
+
/* @__PURE__ */ m(g, {
|
|
524
|
+
variant: l(e.status),
|
|
525
|
+
children: L(e.status)
|
|
378
526
|
})
|
|
379
527
|
]
|
|
380
528
|
}),
|
|
381
|
-
e.detail ? /* @__PURE__ */
|
|
529
|
+
e.detail ? /* @__PURE__ */ m("p", {
|
|
382
530
|
className: "text-sm text-text-secondary",
|
|
383
531
|
children: e.detail
|
|
384
532
|
}) : null,
|
|
385
|
-
/* @__PURE__ */
|
|
533
|
+
/* @__PURE__ */ h("p", {
|
|
386
534
|
className: "text-xs text-text-muted",
|
|
387
|
-
children: ["Detected ",
|
|
535
|
+
children: ["Detected ", s(e.createdAt)]
|
|
388
536
|
})
|
|
389
537
|
]
|
|
390
|
-
}),
|
|
538
|
+
}), ee ? /* @__PURE__ */ m("span", {
|
|
391
539
|
className: "mt-1 text-xs text-text-muted",
|
|
392
540
|
children: "Closed"
|
|
393
|
-
}) : /* @__PURE__ */
|
|
541
|
+
}) : /* @__PURE__ */ h(O, { children: [/* @__PURE__ */ m(j, {
|
|
394
542
|
asChild: !0,
|
|
395
|
-
children: /* @__PURE__ */ _
|
|
543
|
+
children: /* @__PURE__ */ m(_, {
|
|
396
544
|
variant: "ghost",
|
|
397
545
|
size: "sm",
|
|
398
546
|
"aria-label": `Actions for ${e.title}`,
|
|
399
547
|
disabled: i,
|
|
400
|
-
children: /* @__PURE__ */
|
|
548
|
+
children: /* @__PURE__ */ m(pe, {
|
|
401
549
|
className: "size-4",
|
|
402
550
|
"aria-hidden": "true"
|
|
403
551
|
})
|
|
404
552
|
})
|
|
405
|
-
}), /* @__PURE__ */
|
|
553
|
+
}), /* @__PURE__ */ h(k, {
|
|
406
554
|
align: "end",
|
|
407
555
|
children: [
|
|
408
|
-
e.status === "OPEN" ? /* @__PURE__ */
|
|
556
|
+
e.status === "OPEN" ? /* @__PURE__ */ h(A, {
|
|
409
557
|
onClick: t,
|
|
410
|
-
children: [/* @__PURE__ */
|
|
558
|
+
children: [/* @__PURE__ */ m(de, {
|
|
411
559
|
className: "size-4",
|
|
412
560
|
"aria-hidden": "true"
|
|
413
561
|
}), "Acknowledge"]
|
|
414
562
|
}) : null,
|
|
415
|
-
/* @__PURE__ */
|
|
563
|
+
/* @__PURE__ */ h(A, {
|
|
416
564
|
onClick: n,
|
|
417
|
-
children: [/* @__PURE__ */
|
|
565
|
+
children: [/* @__PURE__ */ m(ge, {
|
|
418
566
|
className: "size-4",
|
|
419
567
|
"aria-hidden": "true"
|
|
420
568
|
}), "Resolve"]
|
|
421
569
|
}),
|
|
422
|
-
/* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ h(A, {
|
|
423
571
|
className: "text-status-error-text",
|
|
424
572
|
onClick: r,
|
|
425
|
-
children: [/* @__PURE__ */
|
|
573
|
+
children: [/* @__PURE__ */ m(_e, {
|
|
426
574
|
className: "size-4",
|
|
427
575
|
"aria-hidden": "true"
|
|
428
576
|
}), "Dismiss"]
|
|
@@ -432,6 +580,6 @@ function Me({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPe
|
|
|
432
580
|
});
|
|
433
581
|
}
|
|
434
582
|
//#endregion
|
|
435
|
-
export {
|
|
583
|
+
export { Ie as RiskPage };
|
|
436
584
|
|
|
437
585
|
//# sourceMappingURL=RiskPage.js.map
|