@burdenoff/microfe-brainyrich 2026.730.1 → 2026.731.2
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/hooks/useBrainyRichApi.d.ts +16 -1
- package/dist/brainyrich/hooks/useBrainyRichApi.d.ts.map +1 -1
- package/dist/brainyrich/hooks/useBrainyRichApi.js +53 -16
- package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.d.ts.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +536 -405
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/types/bra.d.ts +23 -0
- package/dist/brainyrich/types/bra.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n, useGenerateRiskInsights as r,
|
|
2
|
-
import { LoadMore as
|
|
3
|
-
import { ConfirmDialog as
|
|
4
|
-
import { ActorName as
|
|
5
|
-
import { DonutChart as
|
|
1
|
+
import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n, useGenerateRiskInsights as r, useHarvestTaxLossInsights as i, usePagedInsights as a, usePortfolioRiskSignals as o, usePortfolioRiskSummary as s, usePortfolios as ee, useRebalanceProposals as te, useResolveInsight as ne, useTaxLossOpportunities as re, useTransitionRebalanceProposal as ie } from "../hooks/useBrainyRichApi.js";
|
|
2
|
+
import { LoadMore as ae } from "../components/LoadMore.js";
|
|
3
|
+
import { ConfirmDialog as oe } from "../components/ConfirmDialog.js";
|
|
4
|
+
import { ActorName as c } from "../components/ActorName.js";
|
|
5
|
+
import { DonutChart as se, FadeIn as l, GlassCard as ce, LifecycleStepper as le, StatTile as u } from "../components/viz.js";
|
|
6
6
|
import "../components/index.js";
|
|
7
|
-
import { EmptyState as
|
|
8
|
-
import { CommentThread as
|
|
9
|
-
import { useMemo as
|
|
10
|
-
import { Activity as
|
|
11
|
-
import { Fragment as
|
|
12
|
-
import { Badge as
|
|
7
|
+
import { EmptyState as d, ErrorState as f, LoadingState as p, SectionShell as ue, formatDate as m, formatMoney as h, formatPct as g, statusBadgeVariant as _ } from "./_shared.js";
|
|
8
|
+
import { CommentThread as de } from "../components/reuse/CommentThread.js";
|
|
9
|
+
import { useMemo as v, useState as y } from "react";
|
|
10
|
+
import { Activity as fe, AlertTriangle as pe, ArrowRight as me, Check as he, Eye as ge, Gauge as b, Layers as _e, MoreHorizontal as ve, Plus as ye, RefreshCw as be, Scale as x, Scissors as S, ShieldAlert as C, ShieldCheck as w, Sparkles as xe, TrendingUp as Se, X as T } from "lucide-react";
|
|
11
|
+
import { Fragment as Ce, jsx as E, jsxs as D } from "react/jsx-runtime";
|
|
12
|
+
import { Badge as O, Button as k, Card as A, CardContent as j, CardDescription as M, CardHeader as N, CardTitle as P, Dialog as we, DialogClose as Te, DialogContent as Ee, DialogDescription as De, DialogFooter as Oe, DialogHeader as ke, DialogTitle as Ae, DropdownMenu as je, DropdownMenuContent as Me, DropdownMenuItem as F, DropdownMenuLabel as Ne, DropdownMenuSeparator as Pe, DropdownMenuTrigger as Fe, Input as Ie, Label as I, Select as Le, SelectContent as Re, SelectItem as ze, SelectTrigger as Be, SelectValue as Ve, Table as He, TableBody as Ue, TableCell as L, TableHead as R, TableHeader as We, TableRow as z, Textarea as Ge } from "@burdenoff/fe-libs/ui";
|
|
13
13
|
//#region src/brainyrich/pages/RiskPage.tsx
|
|
14
|
-
var
|
|
14
|
+
var Ke = {
|
|
15
15
|
DRAFT: ["PROPOSED", "CANCELLED"],
|
|
16
16
|
PROPOSED: [
|
|
17
17
|
"APPROVED",
|
|
@@ -22,49 +22,49 @@ var Je = {
|
|
|
22
22
|
REJECTED: [],
|
|
23
23
|
EXECUTED: [],
|
|
24
24
|
CANCELLED: []
|
|
25
|
-
},
|
|
25
|
+
}, qe = new Set([
|
|
26
26
|
"DRIFT",
|
|
27
27
|
"CONCENTRATION_RISK",
|
|
28
28
|
"REBALANCE_DUE",
|
|
29
29
|
"CASH_DRAG",
|
|
30
30
|
"FEE_ANOMALY"
|
|
31
31
|
]);
|
|
32
|
-
function
|
|
32
|
+
function B(e) {
|
|
33
33
|
return e.toLowerCase().split("_").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
|
|
34
34
|
}
|
|
35
|
-
var
|
|
35
|
+
var V = [
|
|
36
36
|
"Draft",
|
|
37
37
|
"Proposed",
|
|
38
38
|
"Approved",
|
|
39
39
|
"Executed"
|
|
40
|
-
],
|
|
40
|
+
], Je = {
|
|
41
41
|
DRAFT: "neutral",
|
|
42
42
|
PROPOSED: "warning",
|
|
43
43
|
APPROVED: "blue",
|
|
44
44
|
EXECUTED: "success",
|
|
45
45
|
REJECTED: "error",
|
|
46
46
|
CANCELLED: "neutral"
|
|
47
|
-
},
|
|
47
|
+
}, Ye = [
|
|
48
48
|
"PROPOSED",
|
|
49
49
|
"DRAFT",
|
|
50
50
|
"APPROVED",
|
|
51
51
|
"EXECUTED",
|
|
52
52
|
"REJECTED",
|
|
53
53
|
"CANCELLED"
|
|
54
|
-
],
|
|
54
|
+
], Xe = {
|
|
55
55
|
CRITICAL: "error",
|
|
56
56
|
HIGH: "warning",
|
|
57
57
|
MEDIUM: "info",
|
|
58
58
|
LOW: "teal",
|
|
59
59
|
INFO: "neutral"
|
|
60
|
-
},
|
|
60
|
+
}, Ze = [
|
|
61
61
|
"CRITICAL",
|
|
62
62
|
"HIGH",
|
|
63
63
|
"MEDIUM",
|
|
64
64
|
"LOW",
|
|
65
65
|
"INFO"
|
|
66
66
|
];
|
|
67
|
-
function
|
|
67
|
+
function Qe(e) {
|
|
68
68
|
if (!Array.isArray(e) || e.length === 0) return null;
|
|
69
69
|
let t = [];
|
|
70
70
|
for (let n of e) {
|
|
@@ -101,14 +101,14 @@ function et(e) {
|
|
|
101
101
|
}
|
|
102
102
|
return t;
|
|
103
103
|
}
|
|
104
|
-
function
|
|
104
|
+
function H(e) {
|
|
105
105
|
return e == null ? "—" : typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : e.toLocaleString(void 0, { maximumFractionDigits: 2 }) : typeof e == "boolean" ? e ? "Yes" : "No" : typeof e == "string" ? e : JSON.stringify(e);
|
|
106
106
|
}
|
|
107
|
-
function
|
|
107
|
+
function U(e) {
|
|
108
108
|
let t = (e ?? "").toUpperCase();
|
|
109
109
|
return t.includes("BUY") || t.includes("ADD") ? "text-status-success-text" : t.includes("SELL") || t.includes("TRIM") || t.includes("REDUCE") ? "text-status-error-text" : "text-text-secondary";
|
|
110
110
|
}
|
|
111
|
-
function
|
|
111
|
+
function $e(e) {
|
|
112
112
|
if (e == null) return "—";
|
|
113
113
|
if (Array.isArray(e)) return `${e.length} trade${e.length === 1 ? "" : "s"}`;
|
|
114
114
|
if (typeof e == "object") {
|
|
@@ -117,133 +117,133 @@ function nt(e) {
|
|
|
117
117
|
}
|
|
118
118
|
return String(e);
|
|
119
119
|
}
|
|
120
|
-
var
|
|
120
|
+
var et = {
|
|
121
121
|
portfolioId: "",
|
|
122
122
|
driftPct: "",
|
|
123
123
|
rationale: "",
|
|
124
124
|
trades: ""
|
|
125
125
|
};
|
|
126
|
-
function
|
|
126
|
+
function tt(e) {
|
|
127
127
|
if (e.trim() === "") return;
|
|
128
128
|
let t = Number(e);
|
|
129
129
|
return Number.isFinite(t) ? t : void 0;
|
|
130
130
|
}
|
|
131
|
-
function
|
|
132
|
-
let { data:
|
|
131
|
+
function W() {
|
|
132
|
+
let { data: c, isLoading: le, isError: de, refetch: he } = te(), { data: V } = ee(), [Qe, H] = y(void 0), U = Qe ?? V[0]?.id ?? "", { data: W, isLoading: ot, isError: st, refetch: ct } = o(U || void 0), G = r(), { data: K, isFetching: lt, refetch: ut } = s(U || void 0), { data: q, isLoading: dt, isError: ft, refetch: pt } = re(U || void 0), mt = i(), { items: ht, hasMore: gt, loadMore: _t, isLoading: vt, isFetchingNextPage: yt, isError: bt, refetch: xt } = a(), St = t(), J = ie(), Ct = e(), wt = n(), Tt = ne(), [Et, Dt] = y(!1), [Y, X] = y(et), [Ot, kt] = y(null), [At, jt] = y(null), [Z, Mt] = y(null), Q = v(() => {
|
|
133
133
|
let e = /* @__PURE__ */ new Map();
|
|
134
|
-
for (let t of
|
|
134
|
+
for (let t of V) e.set(t.id, t);
|
|
135
135
|
return e;
|
|
136
|
-
}, [
|
|
136
|
+
}, [V]), Nt = v(() => ht.filter((e) => qe.has(e.type)), [ht]), Pt = c.filter((e) => e.status === "DRAFT" || e.status === "PROPOSED" || e.status === "APPROVED"), $ = Nt.filter((e) => e.status === "OPEN"), Ft = c.length > 0 ? c.reduce((e, t) => e + (t.driftPct ?? 0), 0) / c.length : null, It = v(() => c.filter((e) => {
|
|
137
137
|
let t = Q.get(e.portfolioId)?.driftThresholdPct;
|
|
138
138
|
return t != null && Number.isFinite(t) && e.driftPct >= t;
|
|
139
|
-
}).length, [
|
|
139
|
+
}).length, [c, Q]), Lt = v(() => [...c].sort((e, t) => new Date(e.createdAt).getTime() - new Date(t.createdAt).getTime()).map((e) => e.driftPct).filter((e) => Number.isFinite(e)), [c]), Rt = v(() => {
|
|
140
140
|
let e = /* @__PURE__ */ new Map();
|
|
141
|
-
for (let t of
|
|
142
|
-
return
|
|
143
|
-
label:
|
|
141
|
+
for (let t of c) e.set(t.status, (e.get(t.status) ?? 0) + 1);
|
|
142
|
+
return Ye.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
|
|
143
|
+
label: B(t),
|
|
144
144
|
value: e.get(t) ?? 0,
|
|
145
|
-
tone:
|
|
145
|
+
tone: Je[t]
|
|
146
146
|
}));
|
|
147
|
-
}, [
|
|
147
|
+
}, [c]), zt = v(() => {
|
|
148
148
|
let e = /* @__PURE__ */ new Map();
|
|
149
149
|
for (let t of $) e.set(t.severity, (e.get(t.severity) ?? 0) + 1);
|
|
150
|
-
return
|
|
151
|
-
label:
|
|
150
|
+
return Ze.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
|
|
151
|
+
label: B(t),
|
|
152
152
|
value: e.get(t) ?? 0,
|
|
153
|
-
tone:
|
|
153
|
+
tone: Xe[t]
|
|
154
154
|
}));
|
|
155
|
-
}, [$]),
|
|
156
|
-
function
|
|
157
|
-
|
|
155
|
+
}, [$]), Bt = V.length > 0;
|
|
156
|
+
function Vt() {
|
|
157
|
+
X(et), kt(null), Dt(!0);
|
|
158
158
|
}
|
|
159
|
-
function
|
|
160
|
-
if (!
|
|
159
|
+
function Ht() {
|
|
160
|
+
if (!Y.portfolioId) return;
|
|
161
161
|
let e;
|
|
162
|
-
if (
|
|
163
|
-
e = JSON.parse(
|
|
162
|
+
if (Y.trades.trim() !== "") try {
|
|
163
|
+
e = JSON.parse(Y.trades);
|
|
164
164
|
} catch {
|
|
165
|
-
|
|
165
|
+
kt("Trades must be valid JSON.");
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
|
-
let t = Q.get(
|
|
169
|
-
|
|
170
|
-
portfolioId:
|
|
168
|
+
let t = Q.get(Y.portfolioId);
|
|
169
|
+
St.mutate({
|
|
170
|
+
portfolioId: Y.portfolioId,
|
|
171
171
|
householdId: t?.householdId ?? null,
|
|
172
|
-
driftPct:
|
|
173
|
-
rationale:
|
|
172
|
+
driftPct: tt(Y.driftPct),
|
|
173
|
+
rationale: Y.rationale.trim() || null,
|
|
174
174
|
...e === void 0 ? {} : { trades: e }
|
|
175
|
-
}, { onSuccess: () =>
|
|
175
|
+
}, { onSuccess: () => Dt(!1) });
|
|
176
176
|
}
|
|
177
|
-
function
|
|
177
|
+
function Ut(e, t) {
|
|
178
178
|
if (t === "REJECTED" || t === "CANCELLED") {
|
|
179
|
-
|
|
179
|
+
Mt({
|
|
180
180
|
proposal: e,
|
|
181
181
|
status: t
|
|
182
182
|
});
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
|
-
|
|
185
|
+
J.mutate({
|
|
186
186
|
id: e.id,
|
|
187
187
|
status: t
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
|
-
function
|
|
190
|
+
function Wt(e) {
|
|
191
191
|
let t = Q.get(e.portfolioId)?.driftThresholdPct;
|
|
192
192
|
return t != null && Number.isFinite(t) && e.driftPct >= t;
|
|
193
193
|
}
|
|
194
|
-
return /* @__PURE__ */
|
|
194
|
+
return /* @__PURE__ */ D(ue, {
|
|
195
195
|
title: "Risk & Rebalancing",
|
|
196
196
|
description: "Review drift-driven rebalance proposals and act on portfolio risk insights.",
|
|
197
|
-
badges: [`${
|
|
197
|
+
badges: [`${Pt.length} active`, `${$.length} open insight${$.length === 1 ? "" : "s"}`],
|
|
198
198
|
actionLabel: "New proposal",
|
|
199
|
-
onAction:
|
|
199
|
+
onAction: Vt,
|
|
200
200
|
children: [
|
|
201
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ D("div", {
|
|
202
202
|
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
|
|
203
203
|
children: [
|
|
204
|
-
/* @__PURE__ */
|
|
204
|
+
/* @__PURE__ */ E(l, {
|
|
205
205
|
index: 0,
|
|
206
|
-
children: /* @__PURE__ */
|
|
206
|
+
children: /* @__PURE__ */ E(u, {
|
|
207
207
|
label: "Average drift",
|
|
208
|
-
value:
|
|
209
|
-
spark:
|
|
210
|
-
sparkTone:
|
|
208
|
+
value: Ft === null ? "—" : g(Ft),
|
|
209
|
+
spark: Lt.length > 1 ? Lt : void 0,
|
|
210
|
+
sparkTone: It > 0 ? "error" : "brand",
|
|
211
211
|
glow: !0,
|
|
212
|
-
icon: /* @__PURE__ */
|
|
212
|
+
icon: /* @__PURE__ */ E(b, {
|
|
213
213
|
className: "size-4",
|
|
214
214
|
"aria-hidden": "true"
|
|
215
215
|
})
|
|
216
216
|
})
|
|
217
217
|
}),
|
|
218
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ E(l, {
|
|
219
219
|
index: 1,
|
|
220
|
-
children: /* @__PURE__ */
|
|
220
|
+
children: /* @__PURE__ */ E(u, {
|
|
221
221
|
label: "Active proposals",
|
|
222
|
-
value: String(
|
|
223
|
-
icon: /* @__PURE__ */
|
|
222
|
+
value: String(Pt.length),
|
|
223
|
+
icon: /* @__PURE__ */ E(fe, {
|
|
224
224
|
className: "size-4",
|
|
225
225
|
"aria-hidden": "true"
|
|
226
226
|
})
|
|
227
227
|
})
|
|
228
228
|
}),
|
|
229
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ E(l, {
|
|
230
230
|
index: 2,
|
|
231
|
-
children: /* @__PURE__ */
|
|
231
|
+
children: /* @__PURE__ */ E(u, {
|
|
232
232
|
label: "Total proposals",
|
|
233
|
-
value: String(
|
|
234
|
-
icon: /* @__PURE__ */
|
|
233
|
+
value: String(c.length),
|
|
234
|
+
icon: /* @__PURE__ */ E(_e, {
|
|
235
235
|
className: "size-4",
|
|
236
236
|
"aria-hidden": "true"
|
|
237
237
|
})
|
|
238
238
|
})
|
|
239
239
|
}),
|
|
240
|
-
/* @__PURE__ */
|
|
240
|
+
/* @__PURE__ */ E(l, {
|
|
241
241
|
index: 3,
|
|
242
|
-
children: /* @__PURE__ */
|
|
242
|
+
children: /* @__PURE__ */ E(u, {
|
|
243
243
|
label: "Open risk insights",
|
|
244
244
|
value: String($.length),
|
|
245
245
|
deltaTone: $.length > 0 ? "negative" : "neutral",
|
|
246
|
-
icon: /* @__PURE__ */
|
|
246
|
+
icon: /* @__PURE__ */ E(C, {
|
|
247
247
|
className: "size-4",
|
|
248
248
|
"aria-hidden": "true"
|
|
249
249
|
})
|
|
@@ -251,53 +251,53 @@ function R() {
|
|
|
251
251
|
})
|
|
252
252
|
]
|
|
253
253
|
}),
|
|
254
|
-
(
|
|
254
|
+
(Rt.length > 0 || zt.length > 0) && !le ? /* @__PURE__ */ D("div", {
|
|
255
255
|
className: "grid gap-4 lg:grid-cols-2",
|
|
256
|
-
children: [/* @__PURE__ */
|
|
256
|
+
children: [/* @__PURE__ */ E(l, {
|
|
257
257
|
index: 0,
|
|
258
|
-
children: /* @__PURE__ */
|
|
258
|
+
children: /* @__PURE__ */ D(ce, {
|
|
259
259
|
glow: !0,
|
|
260
260
|
className: "h-full",
|
|
261
|
-
children: [/* @__PURE__ */
|
|
261
|
+
children: [/* @__PURE__ */ D("div", {
|
|
262
262
|
className: "mb-3 flex items-center gap-2",
|
|
263
|
-
children: [/* @__PURE__ */
|
|
263
|
+
children: [/* @__PURE__ */ E(Se, {
|
|
264
264
|
className: "size-4 text-text-secondary",
|
|
265
265
|
"aria-hidden": "true"
|
|
266
|
-
}), /* @__PURE__ */
|
|
266
|
+
}), /* @__PURE__ */ E("h2", {
|
|
267
267
|
className: "text-sm font-semibold text-text-primary",
|
|
268
268
|
children: "Proposal pipeline"
|
|
269
269
|
})]
|
|
270
|
-
}), /* @__PURE__ */
|
|
271
|
-
data:
|
|
272
|
-
centerValue: String(
|
|
270
|
+
}), /* @__PURE__ */ E(se, {
|
|
271
|
+
data: Rt,
|
|
272
|
+
centerValue: String(c.length),
|
|
273
273
|
centerLabel: "proposals",
|
|
274
274
|
height: 200
|
|
275
275
|
})]
|
|
276
276
|
})
|
|
277
|
-
}), /* @__PURE__ */
|
|
277
|
+
}), /* @__PURE__ */ E(l, {
|
|
278
278
|
index: 1,
|
|
279
|
-
children: /* @__PURE__ */
|
|
279
|
+
children: /* @__PURE__ */ D(ce, {
|
|
280
280
|
className: "h-full",
|
|
281
|
-
children: [/* @__PURE__ */
|
|
281
|
+
children: [/* @__PURE__ */ D("div", {
|
|
282
282
|
className: "mb-3 flex items-center gap-2",
|
|
283
|
-
children: [/* @__PURE__ */
|
|
283
|
+
children: [/* @__PURE__ */ E(C, {
|
|
284
284
|
className: "size-4 text-text-secondary",
|
|
285
285
|
"aria-hidden": "true"
|
|
286
|
-
}), /* @__PURE__ */
|
|
286
|
+
}), /* @__PURE__ */ E("h2", {
|
|
287
287
|
className: "text-sm font-semibold text-text-primary",
|
|
288
288
|
children: "Open risk signals"
|
|
289
289
|
})]
|
|
290
|
-
}),
|
|
291
|
-
data:
|
|
290
|
+
}), zt.length > 0 ? /* @__PURE__ */ E(se, {
|
|
291
|
+
data: zt,
|
|
292
292
|
centerValue: String($.length),
|
|
293
293
|
centerLabel: "open",
|
|
294
294
|
height: 200
|
|
295
|
-
}) : /* @__PURE__ */
|
|
295
|
+
}) : /* @__PURE__ */ D("div", {
|
|
296
296
|
className: "flex h-[200px] flex-col items-center justify-center gap-2 text-center",
|
|
297
|
-
children: [/* @__PURE__ */ w
|
|
297
|
+
children: [/* @__PURE__ */ E(w, {
|
|
298
298
|
className: "size-8 text-status-success-text",
|
|
299
299
|
"aria-hidden": "true"
|
|
300
|
-
}), /* @__PURE__ */
|
|
300
|
+
}), /* @__PURE__ */ E("p", {
|
|
301
301
|
className: "text-sm text-text-secondary",
|
|
302
302
|
children: "No open risk signals."
|
|
303
303
|
})]
|
|
@@ -305,174 +305,174 @@ function R() {
|
|
|
305
305
|
})
|
|
306
306
|
})]
|
|
307
307
|
}) : null,
|
|
308
|
-
/* @__PURE__ */
|
|
308
|
+
/* @__PURE__ */ D(A, { children: [/* @__PURE__ */ D(N, { children: [/* @__PURE__ */ D(P, {
|
|
309
309
|
className: "flex items-center gap-2",
|
|
310
|
-
children: [/* @__PURE__ */
|
|
310
|
+
children: [/* @__PURE__ */ E(b, {
|
|
311
311
|
className: "h-5 w-5",
|
|
312
312
|
"aria-hidden": "true"
|
|
313
313
|
}), "Portfolio risk signals"]
|
|
314
|
-
}), /* @__PURE__ */
|
|
314
|
+
}), /* @__PURE__ */ E(M, { children: "Real, explainable signals computed live from this portfolio's own holdings and target allocation — every signal below shows the real inputs and formula/threshold behind it. Informational only, never a buy/sell recommendation." })] }), /* @__PURE__ */ D(j, {
|
|
315
315
|
className: "space-y-4",
|
|
316
|
-
children: [/* @__PURE__ */
|
|
316
|
+
children: [/* @__PURE__ */ D("div", {
|
|
317
317
|
className: "flex flex-wrap items-center gap-3",
|
|
318
318
|
children: [
|
|
319
|
-
/* @__PURE__ */
|
|
319
|
+
/* @__PURE__ */ D("div", {
|
|
320
320
|
className: "min-w-[220px] space-y-1.5",
|
|
321
|
-
children: [/* @__PURE__ */
|
|
321
|
+
children: [/* @__PURE__ */ E(I, {
|
|
322
322
|
htmlFor: "risk-portfolio",
|
|
323
323
|
children: "Portfolio"
|
|
324
|
-
}), /* @__PURE__ */
|
|
325
|
-
value:
|
|
326
|
-
onValueChange:
|
|
327
|
-
children: [/* @__PURE__ */
|
|
324
|
+
}), /* @__PURE__ */ D(Le, {
|
|
325
|
+
value: U,
|
|
326
|
+
onValueChange: H,
|
|
327
|
+
children: [/* @__PURE__ */ E(Be, {
|
|
328
328
|
id: "risk-portfolio",
|
|
329
|
-
children: /* @__PURE__ */
|
|
330
|
-
}), /* @__PURE__ */
|
|
329
|
+
children: /* @__PURE__ */ E(Ve, { placeholder: "Select a portfolio" })
|
|
330
|
+
}), /* @__PURE__ */ E(Re, { children: V.map((e) => /* @__PURE__ */ E(ze, {
|
|
331
331
|
value: e.id,
|
|
332
332
|
children: e.name
|
|
333
333
|
}, e.id)) })]
|
|
334
334
|
})]
|
|
335
335
|
}),
|
|
336
|
-
/* @__PURE__ */
|
|
336
|
+
/* @__PURE__ */ D(k, {
|
|
337
337
|
variant: "outline",
|
|
338
338
|
size: "sm",
|
|
339
339
|
className: "mt-auto",
|
|
340
|
-
disabled: !
|
|
341
|
-
onClick: () =>
|
|
342
|
-
children: [/* @__PURE__ */
|
|
340
|
+
disabled: !U || ot,
|
|
341
|
+
onClick: () => ct(),
|
|
342
|
+
children: [/* @__PURE__ */ E(be, {
|
|
343
343
|
className: "size-4",
|
|
344
344
|
"aria-hidden": "true"
|
|
345
345
|
}), "Recompute"]
|
|
346
346
|
}),
|
|
347
|
-
/* @__PURE__ */
|
|
347
|
+
/* @__PURE__ */ D(k, {
|
|
348
348
|
variant: "outline",
|
|
349
349
|
size: "sm",
|
|
350
350
|
className: "mt-auto",
|
|
351
|
-
disabled: !
|
|
352
|
-
onClick: () =>
|
|
353
|
-
children: [/* @__PURE__ */
|
|
351
|
+
disabled: !U || (W?.signals.length ?? 0) === 0 || G.isPending,
|
|
352
|
+
onClick: () => G.mutate(U),
|
|
353
|
+
children: [/* @__PURE__ */ E(C, {
|
|
354
354
|
className: "size-4",
|
|
355
355
|
"aria-hidden": "true"
|
|
356
|
-
}),
|
|
356
|
+
}), G.isPending ? "Saving…" : "Save as insights"]
|
|
357
357
|
})
|
|
358
358
|
]
|
|
359
|
-
}),
|
|
360
|
-
icon: /* @__PURE__ */
|
|
359
|
+
}), V.length === 0 ? /* @__PURE__ */ E(d, {
|
|
360
|
+
icon: /* @__PURE__ */ E(b, {
|
|
361
361
|
className: "size-6",
|
|
362
362
|
"aria-hidden": "true"
|
|
363
363
|
}),
|
|
364
364
|
title: "No portfolios yet",
|
|
365
365
|
description: "Create a portfolio to compute real risk signals from its holdings."
|
|
366
|
-
}) :
|
|
366
|
+
}) : ot ? /* @__PURE__ */ E(p, {}) : st ? /* @__PURE__ */ E(f, { onRetry: () => ct() }) : W ? /* @__PURE__ */ D("div", {
|
|
367
367
|
className: "space-y-4",
|
|
368
368
|
children: [
|
|
369
|
-
/* @__PURE__ */
|
|
369
|
+
/* @__PURE__ */ D("div", {
|
|
370
370
|
className: "grid gap-3 sm:grid-cols-3",
|
|
371
371
|
children: [
|
|
372
|
-
/* @__PURE__ */
|
|
372
|
+
/* @__PURE__ */ E(u, {
|
|
373
373
|
label: "Portfolio value",
|
|
374
|
-
value:
|
|
375
|
-
icon: /* @__PURE__ */
|
|
374
|
+
value: h(W.totalValue),
|
|
375
|
+
icon: /* @__PURE__ */ E(_e, {
|
|
376
376
|
className: "size-4",
|
|
377
377
|
"aria-hidden": "true"
|
|
378
378
|
})
|
|
379
379
|
}),
|
|
380
|
-
/* @__PURE__ */
|
|
380
|
+
/* @__PURE__ */ E(u, {
|
|
381
381
|
label: "Holdings considered",
|
|
382
|
-
value: String(
|
|
383
|
-
icon: /* @__PURE__ */
|
|
382
|
+
value: String(W.holdingsConsidered),
|
|
383
|
+
icon: /* @__PURE__ */ E(fe, {
|
|
384
384
|
className: "size-4",
|
|
385
385
|
"aria-hidden": "true"
|
|
386
386
|
})
|
|
387
387
|
}),
|
|
388
|
-
/* @__PURE__ */
|
|
388
|
+
/* @__PURE__ */ E(u, {
|
|
389
389
|
label: "Signals breached",
|
|
390
|
-
value: String(
|
|
391
|
-
deltaTone:
|
|
392
|
-
icon: /* @__PURE__ */
|
|
390
|
+
value: String(W.signals.length),
|
|
391
|
+
deltaTone: W.signals.length > 0 ? "negative" : "neutral",
|
|
392
|
+
icon: /* @__PURE__ */ E(C, {
|
|
393
393
|
className: "size-4",
|
|
394
394
|
"aria-hidden": "true"
|
|
395
395
|
})
|
|
396
396
|
})
|
|
397
397
|
]
|
|
398
398
|
}),
|
|
399
|
-
|
|
400
|
-
icon: /* @__PURE__ */ w
|
|
399
|
+
W.signals.length === 0 ? /* @__PURE__ */ E(d, {
|
|
400
|
+
icon: /* @__PURE__ */ E(w, {
|
|
401
401
|
className: "size-6",
|
|
402
402
|
"aria-hidden": "true"
|
|
403
403
|
}),
|
|
404
404
|
title: "No configured threshold was breached",
|
|
405
405
|
description: "This portfolio's concentration, cash, drift and unrealized-loss metrics are all within their configured thresholds."
|
|
406
|
-
}) : /* @__PURE__ */
|
|
406
|
+
}) : /* @__PURE__ */ E("ul", {
|
|
407
407
|
className: "space-y-3",
|
|
408
|
-
children:
|
|
408
|
+
children: W.signals.map((e, t) => /* @__PURE__ */ E(rt, { signal: e }, `${e.kind}-${t}`))
|
|
409
409
|
}),
|
|
410
|
-
/* @__PURE__ */
|
|
410
|
+
/* @__PURE__ */ D("div", {
|
|
411
411
|
className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
|
|
412
|
-
children: [/* @__PURE__ */
|
|
412
|
+
children: [/* @__PURE__ */ D("div", {
|
|
413
413
|
className: "flex flex-wrap items-center justify-between gap-2",
|
|
414
|
-
children: [/* @__PURE__ */
|
|
414
|
+
children: [/* @__PURE__ */ D("div", {
|
|
415
415
|
className: "flex items-center gap-2",
|
|
416
416
|
children: [
|
|
417
|
-
/* @__PURE__ */
|
|
417
|
+
/* @__PURE__ */ E(xe, {
|
|
418
418
|
className: "size-4 text-text-secondary",
|
|
419
419
|
"aria-hidden": "true"
|
|
420
420
|
}),
|
|
421
|
-
/* @__PURE__ */
|
|
421
|
+
/* @__PURE__ */ E("h3", {
|
|
422
422
|
className: "text-sm font-semibold text-text-primary",
|
|
423
423
|
children: "AI summary"
|
|
424
424
|
}),
|
|
425
|
-
/* @__PURE__ */
|
|
425
|
+
/* @__PURE__ */ E("span", {
|
|
426
426
|
className: "text-xs text-text-muted",
|
|
427
427
|
children: "(optional — plain-language restatement of the signals above; never a source of numbers)"
|
|
428
428
|
})
|
|
429
429
|
]
|
|
430
|
-
}), /* @__PURE__ */
|
|
430
|
+
}), /* @__PURE__ */ D(k, {
|
|
431
431
|
variant: "outline",
|
|
432
432
|
size: "sm",
|
|
433
|
-
disabled: !
|
|
434
|
-
onClick: () =>
|
|
435
|
-
children: [/* @__PURE__ */
|
|
433
|
+
disabled: !U || lt,
|
|
434
|
+
onClick: () => ut(),
|
|
435
|
+
children: [/* @__PURE__ */ E(xe, {
|
|
436
436
|
className: "size-4",
|
|
437
437
|
"aria-hidden": "true"
|
|
438
|
-
}),
|
|
438
|
+
}), lt ? "Generating…" : "Generate AI summary"]
|
|
439
439
|
})]
|
|
440
|
-
}),
|
|
440
|
+
}), lt ? /* @__PURE__ */ E("p", {
|
|
441
441
|
className: "mt-2 text-sm text-text-secondary",
|
|
442
442
|
children: "Asking the AI provider…"
|
|
443
|
-
}) :
|
|
443
|
+
}) : K?.generated ? /* @__PURE__ */ D("div", {
|
|
444
444
|
className: "mt-2 space-y-1",
|
|
445
|
-
children: [/* @__PURE__ */
|
|
445
|
+
children: [/* @__PURE__ */ E("p", {
|
|
446
446
|
className: "text-sm text-text-primary",
|
|
447
|
-
children:
|
|
448
|
-
}), /* @__PURE__ */
|
|
447
|
+
children: K.summary
|
|
448
|
+
}), /* @__PURE__ */ D("p", {
|
|
449
449
|
className: "text-xs text-text-muted",
|
|
450
450
|
children: [
|
|
451
451
|
"AI-generated commentary",
|
|
452
|
-
|
|
452
|
+
K.provider ? ` · ${K.provider}` : "",
|
|
453
453
|
" · based on",
|
|
454
454
|
" ",
|
|
455
|
-
|
|
455
|
+
K.signalsConsidered,
|
|
456
456
|
" computed signal",
|
|
457
|
-
|
|
457
|
+
K.signalsConsidered === 1 ? "" : "s",
|
|
458
458
|
" above"
|
|
459
459
|
]
|
|
460
460
|
})]
|
|
461
|
-
}) :
|
|
461
|
+
}) : K && !K.generated ? /* @__PURE__ */ D("p", {
|
|
462
462
|
className: "mt-2 text-sm text-text-secondary",
|
|
463
463
|
children: [
|
|
464
464
|
"AI summary unavailable — ",
|
|
465
|
-
|
|
465
|
+
K.reason ?? "no provider configured",
|
|
466
466
|
". The deterministic signals above are unaffected."
|
|
467
467
|
]
|
|
468
|
-
}) : /* @__PURE__ */
|
|
468
|
+
}) : /* @__PURE__ */ E("p", {
|
|
469
469
|
className: "mt-2 text-sm text-text-muted",
|
|
470
470
|
children: "Not generated yet. The deterministic signals above always work without this."
|
|
471
471
|
})]
|
|
472
472
|
})
|
|
473
473
|
]
|
|
474
|
-
}) : /* @__PURE__ */
|
|
475
|
-
icon: /* @__PURE__ */
|
|
474
|
+
}) : /* @__PURE__ */ E(d, {
|
|
475
|
+
icon: /* @__PURE__ */ E(b, {
|
|
476
476
|
className: "size-6",
|
|
477
477
|
"aria-hidden": "true"
|
|
478
478
|
}),
|
|
@@ -480,75 +480,143 @@ function R() {
|
|
|
480
480
|
description: "Choose a portfolio above to compute its real risk signals."
|
|
481
481
|
})]
|
|
482
482
|
})] }),
|
|
483
|
-
/* @__PURE__ */
|
|
483
|
+
/* @__PURE__ */ D(A, { children: [/* @__PURE__ */ D(N, { children: [/* @__PURE__ */ D(P, {
|
|
484
|
+
className: "flex items-center gap-2",
|
|
485
|
+
children: [/* @__PURE__ */ E(S, {
|
|
486
|
+
className: "h-5 w-5",
|
|
487
|
+
"aria-hidden": "true"
|
|
488
|
+
}), "Tax-loss-harvesting opportunities"]
|
|
489
|
+
}), /* @__PURE__ */ E(M, { children: "Real unrealized-loss detection for the selected portfolio, using configurable dollar/percent thresholds and a wash-sale caution flag from your recorded transactions. Detection only — this never places a trade, and it is not tax advice." })] }), /* @__PURE__ */ D(j, {
|
|
490
|
+
className: "space-y-4",
|
|
491
|
+
children: [/* @__PURE__ */ D("div", {
|
|
492
|
+
className: "flex flex-wrap items-center gap-3",
|
|
493
|
+
children: [
|
|
494
|
+
/* @__PURE__ */ D(k, {
|
|
495
|
+
variant: "outline",
|
|
496
|
+
size: "sm",
|
|
497
|
+
disabled: !U || dt,
|
|
498
|
+
onClick: () => pt(),
|
|
499
|
+
children: [/* @__PURE__ */ E(be, {
|
|
500
|
+
className: "size-4",
|
|
501
|
+
"aria-hidden": "true"
|
|
502
|
+
}), "Recompute"]
|
|
503
|
+
}),
|
|
504
|
+
/* @__PURE__ */ D(k, {
|
|
505
|
+
variant: "outline",
|
|
506
|
+
size: "sm",
|
|
507
|
+
disabled: !U || (q?.opportunities.length ?? 0) === 0 || mt.isPending,
|
|
508
|
+
onClick: () => mt.mutate({ portfolioId: U }),
|
|
509
|
+
children: [/* @__PURE__ */ E(C, {
|
|
510
|
+
className: "size-4",
|
|
511
|
+
"aria-hidden": "true"
|
|
512
|
+
}), mt.isPending ? "Saving…" : "Save as insights"]
|
|
513
|
+
}),
|
|
514
|
+
q ? /* @__PURE__ */ D("span", {
|
|
515
|
+
className: "text-xs text-text-muted",
|
|
516
|
+
children: [
|
|
517
|
+
"Thresholds: ≥",
|
|
518
|
+
h(q.thresholds.minLossAmount),
|
|
519
|
+
" or ≥",
|
|
520
|
+
g(q.thresholds.minLossPct),
|
|
521
|
+
" of portfolio value"
|
|
522
|
+
]
|
|
523
|
+
}) : null
|
|
524
|
+
]
|
|
525
|
+
}), V.length === 0 ? /* @__PURE__ */ E(d, {
|
|
526
|
+
icon: /* @__PURE__ */ E(S, {
|
|
527
|
+
className: "size-6",
|
|
528
|
+
"aria-hidden": "true"
|
|
529
|
+
}),
|
|
530
|
+
title: "No portfolios yet",
|
|
531
|
+
description: "Create a portfolio to detect real tax-loss-harvesting opportunities from its holdings."
|
|
532
|
+
}) : dt ? /* @__PURE__ */ E(p, {}) : ft ? /* @__PURE__ */ E(f, { onRetry: () => pt() }) : q && q.opportunities.length > 0 ? /* @__PURE__ */ E("ul", {
|
|
533
|
+
className: "space-y-3",
|
|
534
|
+
children: q.opportunities.map((e) => /* @__PURE__ */ E(it, { opportunity: e }, e.symbol))
|
|
535
|
+
}) : q ? /* @__PURE__ */ E(d, {
|
|
536
|
+
icon: /* @__PURE__ */ E(w, {
|
|
537
|
+
className: "size-6",
|
|
538
|
+
"aria-hidden": "true"
|
|
539
|
+
}),
|
|
540
|
+
title: "No opportunities at the current thresholds",
|
|
541
|
+
description: "No symbol's unrealized loss clears the configured dollar/percent thresholds."
|
|
542
|
+
}) : /* @__PURE__ */ E(d, {
|
|
543
|
+
icon: /* @__PURE__ */ E(S, {
|
|
544
|
+
className: "size-6",
|
|
545
|
+
"aria-hidden": "true"
|
|
546
|
+
}),
|
|
547
|
+
title: "Select a portfolio",
|
|
548
|
+
description: "Choose a portfolio above to detect real tax-loss opportunities."
|
|
549
|
+
})]
|
|
550
|
+
})] }),
|
|
551
|
+
/* @__PURE__ */ D(A, { children: [/* @__PURE__ */ D(N, { children: [/* @__PURE__ */ D(P, {
|
|
484
552
|
className: "flex items-center gap-2",
|
|
485
|
-
children: [/* @__PURE__ */
|
|
553
|
+
children: [/* @__PURE__ */ E(x, {
|
|
486
554
|
className: "h-5 w-5",
|
|
487
555
|
"aria-hidden": "true"
|
|
488
556
|
}), "Rebalance proposals"]
|
|
489
|
-
}), /* @__PURE__ */
|
|
490
|
-
icon: /* @__PURE__ */
|
|
557
|
+
}), /* @__PURE__ */ E(M, { children: "Drift against target allocation, with lifecycle actions per proposal." })] }), /* @__PURE__ */ E(j, { children: le ? /* @__PURE__ */ E(p, {}) : de ? /* @__PURE__ */ E(f, { onRetry: () => he() }) : c.length === 0 ? /* @__PURE__ */ E(d, {
|
|
558
|
+
icon: /* @__PURE__ */ E(x, {
|
|
491
559
|
className: "size-6",
|
|
492
560
|
"aria-hidden": "true"
|
|
493
561
|
}),
|
|
494
562
|
title: "No rebalance proposals",
|
|
495
|
-
description:
|
|
496
|
-
action:
|
|
563
|
+
description: Bt ? "Create a proposal when a portfolio drifts from its target allocation." : "Create a portfolio first, then propose a rebalance when it drifts.",
|
|
564
|
+
action: Bt ? /* @__PURE__ */ D(k, {
|
|
497
565
|
size: "sm",
|
|
498
|
-
onClick:
|
|
499
|
-
children: [/* @__PURE__ */
|
|
566
|
+
onClick: Vt,
|
|
567
|
+
children: [/* @__PURE__ */ E(ye, {
|
|
500
568
|
className: "size-4",
|
|
501
569
|
"aria-hidden": "true"
|
|
502
570
|
}), "New proposal"]
|
|
503
571
|
}) : void 0
|
|
504
|
-
}) : /* @__PURE__ */
|
|
572
|
+
}) : /* @__PURE__ */ E("div", {
|
|
505
573
|
className: "overflow-x-auto",
|
|
506
|
-
children: /* @__PURE__ */
|
|
507
|
-
/* @__PURE__ */
|
|
508
|
-
/* @__PURE__ */
|
|
574
|
+
children: /* @__PURE__ */ D(He, { children: [/* @__PURE__ */ E(We, { children: /* @__PURE__ */ D(z, { children: [
|
|
575
|
+
/* @__PURE__ */ E(R, { children: "Portfolio" }),
|
|
576
|
+
/* @__PURE__ */ E(R, {
|
|
509
577
|
className: "text-right",
|
|
510
578
|
children: "Drift"
|
|
511
579
|
}),
|
|
512
|
-
/* @__PURE__ */
|
|
513
|
-
/* @__PURE__ */
|
|
514
|
-
/* @__PURE__ */
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
/* @__PURE__ */
|
|
580
|
+
/* @__PURE__ */ E(R, { children: "Status" }),
|
|
581
|
+
/* @__PURE__ */ E(R, { children: "Rationale" }),
|
|
582
|
+
/* @__PURE__ */ E(R, { children: "Trades" }),
|
|
583
|
+
/* @__PURE__ */ E(R, { children: "Created" }),
|
|
584
|
+
/* @__PURE__ */ E(R, {
|
|
517
585
|
className: "w-12 text-right",
|
|
518
586
|
children: "Actions"
|
|
519
587
|
})
|
|
520
|
-
] }) }), /* @__PURE__ */
|
|
521
|
-
let t = Q.get(e.portfolioId), n =
|
|
522
|
-
return /* @__PURE__ */
|
|
523
|
-
onClick: () =>
|
|
588
|
+
] }) }), /* @__PURE__ */ E(Ue, { children: c.map((e) => {
|
|
589
|
+
let t = Q.get(e.portfolioId), n = Wt(e), r = Ke[e.status], i = t?.driftThresholdPct, a = i != null && i > 0 ? Math.min(100, e.driftPct / i * 100) : null;
|
|
590
|
+
return /* @__PURE__ */ D(z, {
|
|
591
|
+
onClick: () => jt(e),
|
|
524
592
|
className: "cursor-pointer transition-colors motion-safe:hover:bg-bg-elevated",
|
|
525
593
|
children: [
|
|
526
|
-
/* @__PURE__ */
|
|
594
|
+
/* @__PURE__ */ D(L, { children: [/* @__PURE__ */ E("p", {
|
|
527
595
|
className: "font-medium text-text-primary",
|
|
528
596
|
children: t?.name ?? "Unknown portfolio"
|
|
529
|
-
}), /* @__PURE__ */
|
|
597
|
+
}), /* @__PURE__ */ D("p", {
|
|
530
598
|
className: "text-xs text-text-secondary",
|
|
531
|
-
children: [t?.baseCurrency ?? "—", i == null ? "" : ` · threshold ${
|
|
599
|
+
children: [t?.baseCurrency ?? "—", i == null ? "" : ` · threshold ${g(i)}`]
|
|
532
600
|
})] }),
|
|
533
|
-
/* @__PURE__ */
|
|
601
|
+
/* @__PURE__ */ D(L, {
|
|
534
602
|
className: "text-right",
|
|
535
|
-
children: [/* @__PURE__ */
|
|
603
|
+
children: [/* @__PURE__ */ D("span", {
|
|
536
604
|
className: `inline-flex items-center justify-end gap-1 font-semibold tabular-nums ${n ? "text-status-error-text" : "text-text-primary"}`,
|
|
537
|
-
children: [n ? /* @__PURE__ */
|
|
605
|
+
children: [n ? /* @__PURE__ */ E(pe, {
|
|
538
606
|
className: "size-4",
|
|
539
607
|
"aria-hidden": "true"
|
|
540
|
-
}) : null,
|
|
541
|
-
}), a == null ? n ? /* @__PURE__ */
|
|
608
|
+
}) : null, g(e.driftPct)]
|
|
609
|
+
}), a == null ? n ? /* @__PURE__ */ E("p", {
|
|
542
610
|
className: "text-xs text-status-error-text",
|
|
543
611
|
children: "Over threshold"
|
|
544
|
-
}) : null : /* @__PURE__ */
|
|
612
|
+
}) : null : /* @__PURE__ */ E("div", {
|
|
545
613
|
className: "ml-auto mt-1 h-1.5 w-24 overflow-hidden rounded-full bg-bg-sunken",
|
|
546
614
|
role: "progressbar",
|
|
547
615
|
"aria-valuenow": Math.round(a),
|
|
548
616
|
"aria-valuemin": 0,
|
|
549
617
|
"aria-valuemax": 100,
|
|
550
618
|
"aria-label": `Drift vs threshold for ${t?.name ?? "portfolio"}`,
|
|
551
|
-
children: /* @__PURE__ */
|
|
619
|
+
children: /* @__PURE__ */ E("div", {
|
|
552
620
|
className: "h-full rounded-full",
|
|
553
621
|
style: {
|
|
554
622
|
width: `${a}%`,
|
|
@@ -557,60 +625,60 @@ function R() {
|
|
|
557
625
|
})
|
|
558
626
|
})]
|
|
559
627
|
}),
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
variant:
|
|
562
|
-
children:
|
|
628
|
+
/* @__PURE__ */ E(L, { children: /* @__PURE__ */ E(O, {
|
|
629
|
+
variant: _(e.status),
|
|
630
|
+
children: B(e.status)
|
|
563
631
|
}) }),
|
|
564
|
-
/* @__PURE__ */
|
|
632
|
+
/* @__PURE__ */ E(L, {
|
|
565
633
|
className: "max-w-xs",
|
|
566
|
-
children: /* @__PURE__ */
|
|
634
|
+
children: /* @__PURE__ */ E("p", {
|
|
567
635
|
className: "truncate text-sm text-text-secondary",
|
|
568
636
|
children: e.rationale ?? "—"
|
|
569
637
|
})
|
|
570
638
|
}),
|
|
571
|
-
/* @__PURE__ */
|
|
639
|
+
/* @__PURE__ */ E(L, {
|
|
572
640
|
className: "text-sm text-text-secondary",
|
|
573
|
-
children:
|
|
641
|
+
children: $e(e.trades)
|
|
574
642
|
}),
|
|
575
|
-
/* @__PURE__ */
|
|
643
|
+
/* @__PURE__ */ E(L, {
|
|
576
644
|
className: "text-sm text-text-secondary",
|
|
577
645
|
children: m(e.createdAt)
|
|
578
646
|
}),
|
|
579
|
-
/* @__PURE__ */
|
|
647
|
+
/* @__PURE__ */ E(L, {
|
|
580
648
|
className: "text-right",
|
|
581
649
|
onClick: (e) => e.stopPropagation(),
|
|
582
|
-
children: /* @__PURE__ */
|
|
650
|
+
children: /* @__PURE__ */ D(je, { children: [/* @__PURE__ */ E(Fe, {
|
|
583
651
|
asChild: !0,
|
|
584
|
-
children: /* @__PURE__ */
|
|
652
|
+
children: /* @__PURE__ */ E(k, {
|
|
585
653
|
variant: "ghost",
|
|
586
654
|
size: "sm",
|
|
587
655
|
"aria-label": `Actions for ${t?.name ?? "proposal"}`,
|
|
588
|
-
children: /* @__PURE__ */
|
|
656
|
+
children: /* @__PURE__ */ E(ve, {
|
|
589
657
|
className: "size-4",
|
|
590
658
|
"aria-hidden": "true"
|
|
591
659
|
})
|
|
592
660
|
})
|
|
593
|
-
}), /* @__PURE__ */
|
|
661
|
+
}), /* @__PURE__ */ D(Me, {
|
|
594
662
|
align: "end",
|
|
595
|
-
children: [/* @__PURE__ */
|
|
596
|
-
onClick: () =>
|
|
597
|
-
children: [/* @__PURE__ */
|
|
663
|
+
children: [/* @__PURE__ */ D(F, {
|
|
664
|
+
onClick: () => jt(e),
|
|
665
|
+
children: [/* @__PURE__ */ E(ge, {
|
|
598
666
|
className: "size-4",
|
|
599
667
|
"aria-hidden": "true"
|
|
600
668
|
}), "View details"]
|
|
601
|
-
}), r.length > 0 ? /* @__PURE__ */
|
|
602
|
-
/* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
669
|
+
}), r.length > 0 ? /* @__PURE__ */ D(Ce, { children: [
|
|
670
|
+
/* @__PURE__ */ E(Pe, {}),
|
|
671
|
+
/* @__PURE__ */ E(Ne, { children: "Advance to" }),
|
|
604
672
|
r.map((t) => {
|
|
605
673
|
let n = t === "REJECTED" || t === "CANCELLED";
|
|
606
|
-
return /* @__PURE__ */
|
|
607
|
-
disabled:
|
|
674
|
+
return /* @__PURE__ */ D(F, {
|
|
675
|
+
disabled: J.isPending,
|
|
608
676
|
className: n ? "text-status-error-text" : void 0,
|
|
609
|
-
onClick: () =>
|
|
610
|
-
children: [
|
|
677
|
+
onClick: () => Ut(e, t),
|
|
678
|
+
children: [E(n ? T : me, {
|
|
611
679
|
className: "size-4",
|
|
612
680
|
"aria-hidden": "true"
|
|
613
|
-
}),
|
|
681
|
+
}), B(t)]
|
|
614
682
|
}, t);
|
|
615
683
|
})
|
|
616
684
|
] }) : null]
|
|
@@ -620,79 +688,79 @@ function R() {
|
|
|
620
688
|
}, e.id);
|
|
621
689
|
}) })] })
|
|
622
690
|
}) })] }),
|
|
623
|
-
/* @__PURE__ */
|
|
691
|
+
/* @__PURE__ */ D(A, { children: [/* @__PURE__ */ D(N, { children: [/* @__PURE__ */ D(P, {
|
|
624
692
|
className: "flex items-center gap-2",
|
|
625
|
-
children: [/* @__PURE__ */
|
|
693
|
+
children: [/* @__PURE__ */ E(C, {
|
|
626
694
|
className: "h-5 w-5",
|
|
627
695
|
"aria-hidden": "true"
|
|
628
696
|
}), "Risk insights"]
|
|
629
|
-
}), /* @__PURE__ */
|
|
630
|
-
icon: /* @__PURE__ */ w
|
|
697
|
+
}), /* @__PURE__ */ E(M, { children: "Drift, concentration, cash-drag and fee-anomaly signals detected across your portfolios." })] }), /* @__PURE__ */ E(j, { children: vt ? /* @__PURE__ */ E(p, {}) : bt ? /* @__PURE__ */ E(f, { onRetry: () => xt() }) : Nt.length === 0 ? /* @__PURE__ */ E(d, {
|
|
698
|
+
icon: /* @__PURE__ */ E(w, {
|
|
631
699
|
className: "size-6",
|
|
632
700
|
"aria-hidden": "true"
|
|
633
701
|
}),
|
|
634
702
|
title: "No risk insights",
|
|
635
703
|
description: "No drift, concentration, cash-drag or fee-anomaly signals are open right now."
|
|
636
|
-
}) : /* @__PURE__ */
|
|
704
|
+
}) : /* @__PURE__ */ D("div", {
|
|
637
705
|
className: "space-y-3",
|
|
638
|
-
children: [
|
|
706
|
+
children: [Nt.map((e, t) => /* @__PURE__ */ E(l, {
|
|
639
707
|
index: t,
|
|
640
|
-
children: /* @__PURE__ */
|
|
708
|
+
children: /* @__PURE__ */ E(at, {
|
|
641
709
|
insight: e,
|
|
642
|
-
onAcknowledge: () =>
|
|
643
|
-
onResolve: () =>
|
|
644
|
-
onDismiss: () =>
|
|
645
|
-
actionPending:
|
|
710
|
+
onAcknowledge: () => Ct.mutate(e.id),
|
|
711
|
+
onResolve: () => Tt.mutate(e.id),
|
|
712
|
+
onDismiss: () => wt.mutate(e.id),
|
|
713
|
+
actionPending: Ct.isPending || Tt.isPending || wt.isPending
|
|
646
714
|
})
|
|
647
|
-
}, e.id)), /* @__PURE__ */
|
|
648
|
-
hasMore:
|
|
649
|
-
onClick:
|
|
650
|
-
loading:
|
|
715
|
+
}, e.id)), /* @__PURE__ */ E(ae, {
|
|
716
|
+
hasMore: gt,
|
|
717
|
+
onClick: _t,
|
|
718
|
+
loading: yt,
|
|
651
719
|
label: "Load more insights"
|
|
652
720
|
})]
|
|
653
721
|
}) })] }),
|
|
654
|
-
/* @__PURE__ */
|
|
655
|
-
open:
|
|
656
|
-
onOpenChange:
|
|
657
|
-
children: /* @__PURE__ */
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
|
|
722
|
+
/* @__PURE__ */ E(we, {
|
|
723
|
+
open: Et,
|
|
724
|
+
onOpenChange: Dt,
|
|
725
|
+
children: /* @__PURE__ */ D(Ee, { children: [
|
|
726
|
+
/* @__PURE__ */ D(ke, { children: [/* @__PURE__ */ E(Ae, { children: "New rebalance proposal" }), /* @__PURE__ */ E(De, { children: "Propose a rebalance for a portfolio that has drifted from its target allocation." })] }),
|
|
727
|
+
Bt ? /* @__PURE__ */ D("div", {
|
|
660
728
|
className: "grid gap-4",
|
|
661
729
|
children: [
|
|
662
|
-
/* @__PURE__ */
|
|
730
|
+
/* @__PURE__ */ D("div", {
|
|
663
731
|
className: "grid gap-4 sm:grid-cols-2",
|
|
664
|
-
children: [/* @__PURE__ */
|
|
732
|
+
children: [/* @__PURE__ */ D("div", {
|
|
665
733
|
className: "space-y-2",
|
|
666
|
-
children: [/* @__PURE__ */
|
|
734
|
+
children: [/* @__PURE__ */ D(I, {
|
|
667
735
|
htmlFor: "prop-portfolio",
|
|
668
|
-
children: ["Portfolio ", /* @__PURE__ */
|
|
736
|
+
children: ["Portfolio ", /* @__PURE__ */ E("span", {
|
|
669
737
|
className: "text-status-error-text",
|
|
670
738
|
children: "*"
|
|
671
739
|
})]
|
|
672
|
-
}), /* @__PURE__ */
|
|
673
|
-
value:
|
|
674
|
-
onValueChange: (e) =>
|
|
740
|
+
}), /* @__PURE__ */ D(Le, {
|
|
741
|
+
value: Y.portfolioId,
|
|
742
|
+
onValueChange: (e) => X((t) => ({
|
|
675
743
|
...t,
|
|
676
744
|
portfolioId: e
|
|
677
745
|
})),
|
|
678
|
-
children: [/* @__PURE__ */
|
|
746
|
+
children: [/* @__PURE__ */ E(Be, {
|
|
679
747
|
id: "prop-portfolio",
|
|
680
|
-
children: /* @__PURE__ */
|
|
681
|
-
}), /* @__PURE__ */
|
|
748
|
+
children: /* @__PURE__ */ E(Ve, { placeholder: "Select a portfolio" })
|
|
749
|
+
}), /* @__PURE__ */ E(Re, { children: V.map((e) => /* @__PURE__ */ E(ze, {
|
|
682
750
|
value: e.id,
|
|
683
751
|
children: e.name
|
|
684
752
|
}, e.id)) })]
|
|
685
753
|
})]
|
|
686
|
-
}), /* @__PURE__ */
|
|
754
|
+
}), /* @__PURE__ */ D("div", {
|
|
687
755
|
className: "space-y-2",
|
|
688
|
-
children: [/* @__PURE__ */
|
|
756
|
+
children: [/* @__PURE__ */ E(I, {
|
|
689
757
|
htmlFor: "prop-drift",
|
|
690
758
|
children: "Drift %"
|
|
691
|
-
}), /* @__PURE__ */
|
|
759
|
+
}), /* @__PURE__ */ E(Ie, {
|
|
692
760
|
id: "prop-drift",
|
|
693
761
|
type: "number",
|
|
694
|
-
value:
|
|
695
|
-
onChange: (e) =>
|
|
762
|
+
value: Y.driftPct,
|
|
763
|
+
onChange: (e) => X((t) => ({
|
|
696
764
|
...t,
|
|
697
765
|
driftPct: e.target.value
|
|
698
766
|
})),
|
|
@@ -700,294 +768,294 @@ function R() {
|
|
|
700
768
|
})]
|
|
701
769
|
})]
|
|
702
770
|
}),
|
|
703
|
-
/* @__PURE__ */
|
|
771
|
+
/* @__PURE__ */ D("div", {
|
|
704
772
|
className: "space-y-2",
|
|
705
|
-
children: [/* @__PURE__ */
|
|
773
|
+
children: [/* @__PURE__ */ E(I, {
|
|
706
774
|
htmlFor: "prop-rationale",
|
|
707
775
|
children: "Rationale"
|
|
708
|
-
}), /* @__PURE__ */
|
|
776
|
+
}), /* @__PURE__ */ E(Ge, {
|
|
709
777
|
id: "prop-rationale",
|
|
710
|
-
value:
|
|
711
|
-
onChange: (e) =>
|
|
778
|
+
value: Y.rationale,
|
|
779
|
+
onChange: (e) => X((t) => ({
|
|
712
780
|
...t,
|
|
713
781
|
rationale: e.target.value
|
|
714
782
|
})),
|
|
715
783
|
placeholder: "Why is this rebalance needed?"
|
|
716
784
|
})]
|
|
717
785
|
}),
|
|
718
|
-
/* @__PURE__ */
|
|
786
|
+
/* @__PURE__ */ D("div", {
|
|
719
787
|
className: "space-y-2",
|
|
720
788
|
children: [
|
|
721
|
-
/* @__PURE__ */
|
|
789
|
+
/* @__PURE__ */ E(I, {
|
|
722
790
|
htmlFor: "prop-trades",
|
|
723
791
|
children: "Trades (JSON, optional)"
|
|
724
792
|
}),
|
|
725
|
-
/* @__PURE__ */
|
|
793
|
+
/* @__PURE__ */ E(Ge, {
|
|
726
794
|
id: "prop-trades",
|
|
727
795
|
className: "font-mono text-xs",
|
|
728
|
-
value:
|
|
796
|
+
value: Y.trades,
|
|
729
797
|
onChange: (e) => {
|
|
730
|
-
|
|
798
|
+
kt(null), X((t) => ({
|
|
731
799
|
...t,
|
|
732
800
|
trades: e.target.value
|
|
733
801
|
}));
|
|
734
802
|
},
|
|
735
803
|
placeholder: "e.g. [{\"symbol\":\"VOO\",\"action\":\"SELL\",\"quantity\":10}]"
|
|
736
804
|
}),
|
|
737
|
-
|
|
805
|
+
Ot ? /* @__PURE__ */ E("p", {
|
|
738
806
|
className: "text-xs text-status-error-text",
|
|
739
|
-
children:
|
|
807
|
+
children: Ot
|
|
740
808
|
}) : null
|
|
741
809
|
]
|
|
742
810
|
})
|
|
743
811
|
]
|
|
744
|
-
}) : /* @__PURE__ */
|
|
745
|
-
icon: /* @__PURE__ */
|
|
812
|
+
}) : /* @__PURE__ */ E(d, {
|
|
813
|
+
icon: /* @__PURE__ */ E(x, {
|
|
746
814
|
className: "size-6",
|
|
747
815
|
"aria-hidden": "true"
|
|
748
816
|
}),
|
|
749
817
|
title: "Create a portfolio first",
|
|
750
818
|
description: "A rebalance proposal targets a portfolio. Add a portfolio on the Portfolios page, then return here to propose a rebalance."
|
|
751
819
|
}),
|
|
752
|
-
/* @__PURE__ */
|
|
820
|
+
/* @__PURE__ */ D(Oe, { children: [/* @__PURE__ */ E(Te, {
|
|
753
821
|
asChild: !0,
|
|
754
|
-
children: /* @__PURE__ */
|
|
822
|
+
children: /* @__PURE__ */ E(k, {
|
|
755
823
|
variant: "outline",
|
|
756
824
|
children: "Cancel"
|
|
757
825
|
})
|
|
758
|
-
}), /* @__PURE__ */
|
|
759
|
-
onClick:
|
|
760
|
-
disabled: !
|
|
761
|
-
children:
|
|
826
|
+
}), /* @__PURE__ */ E(k, {
|
|
827
|
+
onClick: Ht,
|
|
828
|
+
disabled: !Y.portfolioId || St.isPending,
|
|
829
|
+
children: St.isPending ? "Creating…" : "Create proposal"
|
|
762
830
|
})] })
|
|
763
831
|
] })
|
|
764
832
|
}),
|
|
765
833
|
(() => {
|
|
766
|
-
let e =
|
|
767
|
-
return /* @__PURE__ */
|
|
834
|
+
let e = At ? c.find((e) => e.id === At.id) ?? At : null, t = e ? ht.filter((t) => t.subjectId === e.portfolioId) : [];
|
|
835
|
+
return /* @__PURE__ */ E(nt, {
|
|
768
836
|
proposal: e,
|
|
769
837
|
portfolio: e ? Q.get(e.portfolioId) ?? null : null,
|
|
770
838
|
relatedInsights: t,
|
|
771
|
-
nextStatuses: e ?
|
|
772
|
-
transitionPending:
|
|
839
|
+
nextStatuses: e ? Ke[e.status] : [],
|
|
840
|
+
transitionPending: J.isPending,
|
|
773
841
|
onTransition: (t) => {
|
|
774
|
-
e &&
|
|
842
|
+
e && Ut(e, t);
|
|
775
843
|
},
|
|
776
844
|
onOpenChange: (e) => {
|
|
777
|
-
e ||
|
|
845
|
+
e || jt(null);
|
|
778
846
|
}
|
|
779
847
|
});
|
|
780
848
|
})(),
|
|
781
|
-
/* @__PURE__ */
|
|
782
|
-
open:
|
|
849
|
+
/* @__PURE__ */ E(oe, {
|
|
850
|
+
open: Z !== null,
|
|
783
851
|
onOpenChange: (e) => {
|
|
784
|
-
e ||
|
|
852
|
+
e || Mt(null);
|
|
785
853
|
},
|
|
786
|
-
title:
|
|
787
|
-
description:
|
|
788
|
-
confirmLabel:
|
|
854
|
+
title: Z?.status === "REJECTED" ? "Reject this proposal?" : "Cancel this proposal?",
|
|
855
|
+
description: Z ? `This moves the rebalance proposal for ${Q.get(Z.proposal.portfolioId)?.name ?? "this portfolio"} to ${B(Z.status)}. This cannot be undone.` : void 0,
|
|
856
|
+
confirmLabel: Z?.status === "REJECTED" ? "Reject" : "Cancel proposal",
|
|
789
857
|
cancelLabel: "Keep",
|
|
790
858
|
destructive: !0,
|
|
791
|
-
pending:
|
|
859
|
+
pending: J.isPending,
|
|
792
860
|
onConfirm: () => {
|
|
793
|
-
|
|
794
|
-
id:
|
|
795
|
-
status:
|
|
796
|
-
}, { onSuccess: () =>
|
|
861
|
+
Z && J.mutate({
|
|
862
|
+
id: Z.proposal.id,
|
|
863
|
+
status: Z.status
|
|
864
|
+
}, { onSuccess: () => Mt(null) });
|
|
797
865
|
}
|
|
798
866
|
})
|
|
799
867
|
]
|
|
800
868
|
});
|
|
801
869
|
}
|
|
802
|
-
function
|
|
803
|
-
let s = e ?
|
|
804
|
-
return /* @__PURE__ */
|
|
870
|
+
function nt({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, transitionPending: i, onTransition: a, onOpenChange: o }) {
|
|
871
|
+
let s = e ? Qe(e.trades) : null, ee = e != null && t?.driftThresholdPct != null && Number.isFinite(t.driftThresholdPct) && e.driftPct >= t.driftThresholdPct;
|
|
872
|
+
return /* @__PURE__ */ E(we, {
|
|
805
873
|
open: e !== null,
|
|
806
874
|
onOpenChange: o,
|
|
807
|
-
children: /* @__PURE__ */
|
|
875
|
+
children: /* @__PURE__ */ E(Ee, {
|
|
808
876
|
className: "max-h-[88vh] max-w-3xl overflow-y-auto",
|
|
809
|
-
children: e ? /* @__PURE__ */
|
|
810
|
-
/* @__PURE__ */
|
|
811
|
-
/* @__PURE__ */
|
|
877
|
+
children: e ? /* @__PURE__ */ D(Ce, { children: [
|
|
878
|
+
/* @__PURE__ */ D(ke, { children: [
|
|
879
|
+
/* @__PURE__ */ E("p", {
|
|
812
880
|
className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
813
881
|
children: "Detail"
|
|
814
882
|
}),
|
|
815
|
-
/* @__PURE__ */
|
|
883
|
+
/* @__PURE__ */ D(Ae, {
|
|
816
884
|
className: "flex flex-wrap items-center gap-2 text-xl",
|
|
817
885
|
children: [
|
|
818
886
|
t?.name ?? "Rebalance proposal",
|
|
819
|
-
/* @__PURE__ */
|
|
887
|
+
/* @__PURE__ */ E("span", {
|
|
820
888
|
className: "text-text-secondary",
|
|
821
889
|
children: "— Rebalance proposal"
|
|
822
890
|
}),
|
|
823
|
-
/* @__PURE__ */
|
|
824
|
-
variant:
|
|
825
|
-
children:
|
|
891
|
+
/* @__PURE__ */ E(O, {
|
|
892
|
+
variant: _(e.status),
|
|
893
|
+
children: B(e.status)
|
|
826
894
|
})
|
|
827
895
|
]
|
|
828
896
|
}),
|
|
829
|
-
/* @__PURE__ */
|
|
897
|
+
/* @__PURE__ */ D(De, { children: [
|
|
830
898
|
"Created ",
|
|
831
899
|
m(e.createdAt),
|
|
832
900
|
e.executedAt ? ` · executed ${m(e.executedAt)}` : ""
|
|
833
901
|
] })
|
|
834
902
|
] }),
|
|
835
|
-
/* @__PURE__ */
|
|
903
|
+
/* @__PURE__ */ E("div", {
|
|
836
904
|
className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
|
|
837
|
-
children: /* @__PURE__ */
|
|
838
|
-
steps:
|
|
839
|
-
current:
|
|
905
|
+
children: /* @__PURE__ */ E(le, {
|
|
906
|
+
steps: V,
|
|
907
|
+
current: B(e.status)
|
|
840
908
|
})
|
|
841
909
|
}),
|
|
842
|
-
/* @__PURE__ */
|
|
910
|
+
/* @__PURE__ */ D("div", {
|
|
843
911
|
className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4",
|
|
844
912
|
children: [
|
|
845
|
-
/* @__PURE__ */
|
|
913
|
+
/* @__PURE__ */ E(u, {
|
|
846
914
|
label: "Drift",
|
|
847
|
-
value:
|
|
848
|
-
deltaTone:
|
|
849
|
-
glow:
|
|
850
|
-
icon: /* @__PURE__ */
|
|
915
|
+
value: g(e.driftPct),
|
|
916
|
+
deltaTone: ee ? "negative" : "neutral",
|
|
917
|
+
glow: ee,
|
|
918
|
+
icon: /* @__PURE__ */ E(b, {
|
|
851
919
|
className: "size-4",
|
|
852
920
|
"aria-hidden": "true"
|
|
853
921
|
})
|
|
854
922
|
}),
|
|
855
|
-
/* @__PURE__ */
|
|
923
|
+
/* @__PURE__ */ E(u, {
|
|
856
924
|
label: "Threshold",
|
|
857
|
-
value: t?.driftThresholdPct == null ? "—" :
|
|
925
|
+
value: t?.driftThresholdPct == null ? "—" : g(t.driftThresholdPct)
|
|
858
926
|
}),
|
|
859
|
-
/* @__PURE__ */
|
|
927
|
+
/* @__PURE__ */ D("div", {
|
|
860
928
|
className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
|
|
861
|
-
children: [/* @__PURE__ */
|
|
929
|
+
children: [/* @__PURE__ */ E("p", {
|
|
862
930
|
className: "text-xs text-text-secondary",
|
|
863
931
|
children: "Proposed by"
|
|
864
|
-
}), /* @__PURE__ */
|
|
932
|
+
}), /* @__PURE__ */ E("p", {
|
|
865
933
|
className: "mt-1 truncate text-sm font-medium text-text-primary",
|
|
866
|
-
children: e.proposedById ? /* @__PURE__ */
|
|
934
|
+
children: e.proposedById ? /* @__PURE__ */ E(c, { id: e.proposedById }) : "—"
|
|
867
935
|
})]
|
|
868
936
|
}),
|
|
869
|
-
/* @__PURE__ */
|
|
937
|
+
/* @__PURE__ */ D("div", {
|
|
870
938
|
className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
|
|
871
|
-
children: [/* @__PURE__ */
|
|
939
|
+
children: [/* @__PURE__ */ E("p", {
|
|
872
940
|
className: "text-xs text-text-secondary",
|
|
873
941
|
children: "Approved by"
|
|
874
|
-
}), /* @__PURE__ */
|
|
942
|
+
}), /* @__PURE__ */ E("p", {
|
|
875
943
|
className: "mt-1 truncate text-sm font-medium text-text-primary",
|
|
876
|
-
children: e.approvedById ? /* @__PURE__ */
|
|
944
|
+
children: e.approvedById ? /* @__PURE__ */ E(c, { id: e.approvedById }) : "—"
|
|
877
945
|
})]
|
|
878
946
|
})
|
|
879
947
|
]
|
|
880
948
|
}),
|
|
881
|
-
/* @__PURE__ */
|
|
949
|
+
/* @__PURE__ */ D("div", {
|
|
882
950
|
className: "space-y-2",
|
|
883
|
-
children: [/* @__PURE__ */
|
|
951
|
+
children: [/* @__PURE__ */ E("h3", {
|
|
884
952
|
className: "text-sm font-semibold text-text-primary",
|
|
885
953
|
children: "Proposed trades"
|
|
886
|
-
}), s && s.length > 0 ? /* @__PURE__ */
|
|
954
|
+
}), s && s.length > 0 ? /* @__PURE__ */ E("div", {
|
|
887
955
|
className: "overflow-x-auto rounded-lg border border-border-subtle",
|
|
888
|
-
children: /* @__PURE__ */
|
|
889
|
-
/* @__PURE__ */
|
|
890
|
-
/* @__PURE__ */
|
|
891
|
-
/* @__PURE__ */
|
|
956
|
+
children: /* @__PURE__ */ D(He, { children: [/* @__PURE__ */ E(We, { children: /* @__PURE__ */ D(z, { children: [
|
|
957
|
+
/* @__PURE__ */ E(R, { children: "Action" }),
|
|
958
|
+
/* @__PURE__ */ E(R, { children: "Symbol" }),
|
|
959
|
+
/* @__PURE__ */ E(R, {
|
|
892
960
|
className: "text-right",
|
|
893
961
|
children: "Quantity"
|
|
894
962
|
}),
|
|
895
|
-
/* @__PURE__ */
|
|
963
|
+
/* @__PURE__ */ E(R, {
|
|
896
964
|
className: "text-right",
|
|
897
965
|
children: "Est. value"
|
|
898
966
|
})
|
|
899
|
-
] }) }), /* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
901
|
-
className: `font-semibold ${
|
|
967
|
+
] }) }), /* @__PURE__ */ E(Ue, { children: s.map((e, n) => /* @__PURE__ */ D(z, { children: [
|
|
968
|
+
/* @__PURE__ */ E(L, {
|
|
969
|
+
className: `font-semibold ${U(e.action)}`,
|
|
902
970
|
children: e.action ? e.action.toUpperCase() : "—"
|
|
903
971
|
}),
|
|
904
|
-
/* @__PURE__ */
|
|
972
|
+
/* @__PURE__ */ E(L, {
|
|
905
973
|
className: "font-medium text-text-primary",
|
|
906
974
|
children: e.symbol ?? "—"
|
|
907
975
|
}),
|
|
908
|
-
/* @__PURE__ */
|
|
976
|
+
/* @__PURE__ */ E(L, {
|
|
909
977
|
className: "text-right tabular-nums text-text-secondary",
|
|
910
978
|
children: e.quantity == null ? "—" : e.quantity.toLocaleString()
|
|
911
979
|
}),
|
|
912
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ E(L, {
|
|
913
981
|
className: "text-right tabular-nums text-text-secondary",
|
|
914
|
-
children: e.value == null ? "—" :
|
|
982
|
+
children: e.value == null ? "—" : h(e.value, t?.baseCurrency ?? "USD")
|
|
915
983
|
})
|
|
916
984
|
] }, n)) })] })
|
|
917
|
-
}) : /* @__PURE__ */
|
|
985
|
+
}) : /* @__PURE__ */ D("p", {
|
|
918
986
|
className: "text-sm text-text-secondary",
|
|
919
|
-
children: [
|
|
987
|
+
children: [$e(e.trades), " — no structured trade breakdown available."]
|
|
920
988
|
})]
|
|
921
989
|
}),
|
|
922
|
-
/* @__PURE__ */
|
|
990
|
+
/* @__PURE__ */ D("div", {
|
|
923
991
|
className: "space-y-1",
|
|
924
|
-
children: [/* @__PURE__ */
|
|
992
|
+
children: [/* @__PURE__ */ E("h3", {
|
|
925
993
|
className: "text-sm font-semibold text-text-primary",
|
|
926
994
|
children: "Rationale"
|
|
927
|
-
}), /* @__PURE__ */
|
|
995
|
+
}), /* @__PURE__ */ E("p", {
|
|
928
996
|
className: "text-sm text-text-secondary",
|
|
929
997
|
children: e.rationale ?? "—"
|
|
930
998
|
})]
|
|
931
999
|
}),
|
|
932
|
-
r.length > 0 ? /* @__PURE__ */
|
|
1000
|
+
r.length > 0 ? /* @__PURE__ */ E("div", {
|
|
933
1001
|
className: "flex flex-wrap gap-2",
|
|
934
1002
|
children: r.map((e) => {
|
|
935
1003
|
let t = e === "REJECTED" || e === "CANCELLED";
|
|
936
|
-
return /* @__PURE__ */
|
|
1004
|
+
return /* @__PURE__ */ D(k, {
|
|
937
1005
|
variant: t ? "outline" : "default",
|
|
938
1006
|
size: "sm",
|
|
939
1007
|
disabled: i,
|
|
940
1008
|
className: t ? "text-status-error-text" : void 0,
|
|
941
1009
|
onClick: () => a(e),
|
|
942
|
-
children: [
|
|
1010
|
+
children: [E(t ? T : me, {
|
|
943
1011
|
className: "size-4",
|
|
944
1012
|
"aria-hidden": "true"
|
|
945
|
-
}),
|
|
1013
|
+
}), B(e)]
|
|
946
1014
|
}, e);
|
|
947
1015
|
})
|
|
948
1016
|
}) : null,
|
|
949
|
-
n.length > 0 ? /* @__PURE__ */
|
|
1017
|
+
n.length > 0 ? /* @__PURE__ */ D("div", {
|
|
950
1018
|
className: "space-y-2 border-t border-border-subtle pt-4",
|
|
951
|
-
children: [/* @__PURE__ */
|
|
1019
|
+
children: [/* @__PURE__ */ D("h3", {
|
|
952
1020
|
className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
|
|
953
|
-
children: [/* @__PURE__ */
|
|
1021
|
+
children: [/* @__PURE__ */ E(C, {
|
|
954
1022
|
className: "size-4",
|
|
955
1023
|
"aria-hidden": "true"
|
|
956
1024
|
}), "Risk insights"]
|
|
957
|
-
}), /* @__PURE__ */
|
|
1025
|
+
}), /* @__PURE__ */ E("ul", {
|
|
958
1026
|
className: "space-y-2",
|
|
959
|
-
children: n.map((e) => /* @__PURE__ */
|
|
1027
|
+
children: n.map((e) => /* @__PURE__ */ D("li", {
|
|
960
1028
|
className: "rounded-lg border border-border-subtle bg-bg-surface p-3",
|
|
961
|
-
children: [/* @__PURE__ */
|
|
1029
|
+
children: [/* @__PURE__ */ D("div", {
|
|
962
1030
|
className: "flex flex-wrap items-center gap-2",
|
|
963
1031
|
children: [
|
|
964
|
-
/* @__PURE__ */
|
|
1032
|
+
/* @__PURE__ */ E("span", {
|
|
965
1033
|
className: "text-sm font-medium text-text-primary",
|
|
966
1034
|
children: e.title
|
|
967
1035
|
}),
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
variant:
|
|
970
|
-
children:
|
|
1036
|
+
/* @__PURE__ */ E(O, {
|
|
1037
|
+
variant: _(e.severity),
|
|
1038
|
+
children: B(e.severity)
|
|
971
1039
|
}),
|
|
972
|
-
/* @__PURE__ */
|
|
1040
|
+
/* @__PURE__ */ E(O, {
|
|
973
1041
|
variant: "outline",
|
|
974
|
-
children:
|
|
1042
|
+
children: B(e.type)
|
|
975
1043
|
}),
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
variant:
|
|
978
|
-
children:
|
|
1044
|
+
/* @__PURE__ */ E(O, {
|
|
1045
|
+
variant: _(e.status),
|
|
1046
|
+
children: B(e.status)
|
|
979
1047
|
})
|
|
980
1048
|
]
|
|
981
|
-
}), e.detail ? /* @__PURE__ */
|
|
1049
|
+
}), e.detail ? /* @__PURE__ */ E("p", {
|
|
982
1050
|
className: "mt-1 text-xs text-text-secondary",
|
|
983
1051
|
children: e.detail
|
|
984
1052
|
}) : null]
|
|
985
1053
|
}, e.id))
|
|
986
1054
|
})]
|
|
987
1055
|
}) : null,
|
|
988
|
-
/* @__PURE__ */
|
|
1056
|
+
/* @__PURE__ */ E("div", {
|
|
989
1057
|
className: "border-t border-border-subtle pt-4",
|
|
990
|
-
children: /* @__PURE__ */
|
|
1058
|
+
children: /* @__PURE__ */ E(de, {
|
|
991
1059
|
entityType: "brainyrich-rebalance",
|
|
992
1060
|
entityId: e.id,
|
|
993
1061
|
heading: "Discussion"
|
|
@@ -997,121 +1065,184 @@ function at({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
|
|
|
997
1065
|
})
|
|
998
1066
|
});
|
|
999
1067
|
}
|
|
1000
|
-
function
|
|
1068
|
+
function rt({ signal: e }) {
|
|
1001
1069
|
let t = Object.entries(e.metrics ?? {});
|
|
1002
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ D("li", {
|
|
1003
1071
|
className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
1004
1072
|
children: [
|
|
1005
|
-
/* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ D("div", {
|
|
1006
1074
|
className: "flex flex-wrap items-center gap-2",
|
|
1007
1075
|
children: [
|
|
1008
|
-
/* @__PURE__ */
|
|
1076
|
+
/* @__PURE__ */ E("p", {
|
|
1009
1077
|
className: "font-medium text-text-primary",
|
|
1010
1078
|
children: e.title
|
|
1011
1079
|
}),
|
|
1012
|
-
/* @__PURE__ */
|
|
1013
|
-
variant:
|
|
1014
|
-
children:
|
|
1080
|
+
/* @__PURE__ */ E(O, {
|
|
1081
|
+
variant: _(e.severity),
|
|
1082
|
+
children: B(e.severity)
|
|
1015
1083
|
}),
|
|
1016
|
-
/* @__PURE__ */
|
|
1084
|
+
/* @__PURE__ */ E(O, {
|
|
1017
1085
|
variant: "outline",
|
|
1018
|
-
children:
|
|
1086
|
+
children: B(e.kind)
|
|
1019
1087
|
})
|
|
1020
1088
|
]
|
|
1021
1089
|
}),
|
|
1022
|
-
e.detail ? /* @__PURE__ */
|
|
1090
|
+
e.detail ? /* @__PURE__ */ E("p", {
|
|
1023
1091
|
className: "mt-1 text-sm text-text-secondary",
|
|
1024
1092
|
children: e.detail
|
|
1025
1093
|
}) : null,
|
|
1026
|
-
t.length > 0 ? /* @__PURE__ */
|
|
1094
|
+
t.length > 0 ? /* @__PURE__ */ E("dl", {
|
|
1095
|
+
className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3 lg:grid-cols-4",
|
|
1096
|
+
children: t.map(([e, t]) => /* @__PURE__ */ D("div", {
|
|
1097
|
+
className: "min-w-0",
|
|
1098
|
+
children: [/* @__PURE__ */ E("dt", {
|
|
1099
|
+
className: "truncate text-[11px] uppercase tracking-wide text-text-muted",
|
|
1100
|
+
children: B(e)
|
|
1101
|
+
}), /* @__PURE__ */ E("dd", {
|
|
1102
|
+
className: "truncate text-sm font-medium tabular-nums text-text-primary",
|
|
1103
|
+
children: H(t)
|
|
1104
|
+
})]
|
|
1105
|
+
}, e))
|
|
1106
|
+
}) : null
|
|
1107
|
+
]
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
function it({ opportunity: e }) {
|
|
1111
|
+
let t = Object.entries(e.metrics ?? {});
|
|
1112
|
+
return /* @__PURE__ */ D("li", {
|
|
1113
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
1114
|
+
children: [
|
|
1115
|
+
/* @__PURE__ */ D("div", {
|
|
1116
|
+
className: "flex flex-wrap items-center gap-2",
|
|
1117
|
+
children: [
|
|
1118
|
+
/* @__PURE__ */ D("p", {
|
|
1119
|
+
className: "font-medium text-text-primary",
|
|
1120
|
+
children: [
|
|
1121
|
+
e.symbol,
|
|
1122
|
+
" — unrealized loss ",
|
|
1123
|
+
h(e.unrealizedLoss)
|
|
1124
|
+
]
|
|
1125
|
+
}),
|
|
1126
|
+
/* @__PURE__ */ E(O, {
|
|
1127
|
+
variant: _(e.severity),
|
|
1128
|
+
children: B(e.severity)
|
|
1129
|
+
}),
|
|
1130
|
+
e.washSaleRisk ? /* @__PURE__ */ D(O, {
|
|
1131
|
+
variant: "outline",
|
|
1132
|
+
className: "text-status-error-text",
|
|
1133
|
+
children: [/* @__PURE__ */ E(pe, {
|
|
1134
|
+
className: "mr-1 size-3",
|
|
1135
|
+
"aria-hidden": "true"
|
|
1136
|
+
}), "Wash-sale caution"]
|
|
1137
|
+
}) : null
|
|
1138
|
+
]
|
|
1139
|
+
}),
|
|
1140
|
+
/* @__PURE__ */ D("p", {
|
|
1141
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
1142
|
+
children: [
|
|
1143
|
+
"Market value ",
|
|
1144
|
+
h(e.marketValue),
|
|
1145
|
+
" vs. cost basis",
|
|
1146
|
+
" ",
|
|
1147
|
+
h(e.costBasis),
|
|
1148
|
+
" · ",
|
|
1149
|
+
g(e.lossPctOfPortfolio),
|
|
1150
|
+
" of portfolio value"
|
|
1151
|
+
]
|
|
1152
|
+
}),
|
|
1153
|
+
e.washSaleReason ? /* @__PURE__ */ E("p", {
|
|
1154
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
1155
|
+
children: e.washSaleReason
|
|
1156
|
+
}) : null,
|
|
1157
|
+
t.length > 0 ? /* @__PURE__ */ E("dl", {
|
|
1027
1158
|
className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3 lg:grid-cols-4",
|
|
1028
|
-
children: t.map(([e, t]) => /* @__PURE__ */
|
|
1159
|
+
children: t.filter(([e]) => e !== "formula").map(([e, t]) => /* @__PURE__ */ D("div", {
|
|
1029
1160
|
className: "min-w-0",
|
|
1030
|
-
children: [/* @__PURE__ */
|
|
1161
|
+
children: [/* @__PURE__ */ E("dt", {
|
|
1031
1162
|
className: "truncate text-[11px] uppercase tracking-wide text-text-muted",
|
|
1032
|
-
children:
|
|
1033
|
-
}), /* @__PURE__ */
|
|
1163
|
+
children: B(e)
|
|
1164
|
+
}), /* @__PURE__ */ E("dd", {
|
|
1034
1165
|
className: "truncate text-sm font-medium tabular-nums text-text-primary",
|
|
1035
|
-
children:
|
|
1166
|
+
children: H(t)
|
|
1036
1167
|
})]
|
|
1037
1168
|
}, e))
|
|
1038
1169
|
}) : null
|
|
1039
1170
|
]
|
|
1040
1171
|
});
|
|
1041
1172
|
}
|
|
1042
|
-
function
|
|
1173
|
+
function at({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPending: i }) {
|
|
1043
1174
|
let a = e.status === "RESOLVED" || e.status === "DISMISSED";
|
|
1044
|
-
return /* @__PURE__ */
|
|
1175
|
+
return /* @__PURE__ */ D("div", {
|
|
1045
1176
|
className: "flex items-start justify-between gap-4 rounded-lg border border-border-subtle bg-bg-surface p-4 transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]",
|
|
1046
|
-
children: [/* @__PURE__ */
|
|
1177
|
+
children: [/* @__PURE__ */ D("div", {
|
|
1047
1178
|
className: "min-w-0 space-y-1",
|
|
1048
1179
|
children: [
|
|
1049
|
-
/* @__PURE__ */
|
|
1180
|
+
/* @__PURE__ */ D("div", {
|
|
1050
1181
|
className: "flex flex-wrap items-center gap-2",
|
|
1051
1182
|
children: [
|
|
1052
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ E("p", {
|
|
1053
1184
|
className: "font-medium text-text-primary",
|
|
1054
1185
|
children: e.title
|
|
1055
1186
|
}),
|
|
1056
|
-
/* @__PURE__ */
|
|
1057
|
-
variant:
|
|
1058
|
-
children:
|
|
1187
|
+
/* @__PURE__ */ E(O, {
|
|
1188
|
+
variant: _(e.severity),
|
|
1189
|
+
children: B(e.severity)
|
|
1059
1190
|
}),
|
|
1060
|
-
/* @__PURE__ */
|
|
1191
|
+
/* @__PURE__ */ E(O, {
|
|
1061
1192
|
variant: "outline",
|
|
1062
|
-
children:
|
|
1193
|
+
children: B(e.type)
|
|
1063
1194
|
}),
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
variant:
|
|
1066
|
-
children:
|
|
1195
|
+
/* @__PURE__ */ E(O, {
|
|
1196
|
+
variant: _(e.status),
|
|
1197
|
+
children: B(e.status)
|
|
1067
1198
|
})
|
|
1068
1199
|
]
|
|
1069
1200
|
}),
|
|
1070
|
-
e.detail ? /* @__PURE__ */
|
|
1201
|
+
e.detail ? /* @__PURE__ */ E("p", {
|
|
1071
1202
|
className: "text-sm text-text-secondary",
|
|
1072
1203
|
children: e.detail
|
|
1073
1204
|
}) : null,
|
|
1074
|
-
/* @__PURE__ */
|
|
1205
|
+
/* @__PURE__ */ D("p", {
|
|
1075
1206
|
className: "text-xs text-text-muted",
|
|
1076
1207
|
children: ["Detected ", m(e.createdAt)]
|
|
1077
1208
|
})
|
|
1078
1209
|
]
|
|
1079
|
-
}), a ? /* @__PURE__ */
|
|
1210
|
+
}), a ? /* @__PURE__ */ E("span", {
|
|
1080
1211
|
className: "mt-1 text-xs text-text-muted",
|
|
1081
1212
|
children: "Closed"
|
|
1082
|
-
}) : /* @__PURE__ */
|
|
1213
|
+
}) : /* @__PURE__ */ D(je, { children: [/* @__PURE__ */ E(Fe, {
|
|
1083
1214
|
asChild: !0,
|
|
1084
|
-
children: /* @__PURE__ */
|
|
1215
|
+
children: /* @__PURE__ */ E(k, {
|
|
1085
1216
|
variant: "ghost",
|
|
1086
1217
|
size: "sm",
|
|
1087
1218
|
"aria-label": `Actions for ${e.title}`,
|
|
1088
1219
|
disabled: i,
|
|
1089
|
-
children: /* @__PURE__ */
|
|
1220
|
+
children: /* @__PURE__ */ E(ve, {
|
|
1090
1221
|
className: "size-4",
|
|
1091
1222
|
"aria-hidden": "true"
|
|
1092
1223
|
})
|
|
1093
1224
|
})
|
|
1094
|
-
}), /* @__PURE__ */
|
|
1225
|
+
}), /* @__PURE__ */ D(Me, {
|
|
1095
1226
|
align: "end",
|
|
1096
1227
|
children: [
|
|
1097
|
-
e.status === "OPEN" ? /* @__PURE__ */
|
|
1228
|
+
e.status === "OPEN" ? /* @__PURE__ */ D(F, {
|
|
1098
1229
|
onClick: t,
|
|
1099
|
-
children: [/* @__PURE__ */
|
|
1230
|
+
children: [/* @__PURE__ */ E(he, {
|
|
1100
1231
|
className: "size-4",
|
|
1101
1232
|
"aria-hidden": "true"
|
|
1102
1233
|
}), "Acknowledge"]
|
|
1103
1234
|
}) : null,
|
|
1104
|
-
/* @__PURE__ */
|
|
1235
|
+
/* @__PURE__ */ D(F, {
|
|
1105
1236
|
onClick: n,
|
|
1106
|
-
children: [/* @__PURE__ */ w
|
|
1237
|
+
children: [/* @__PURE__ */ E(w, {
|
|
1107
1238
|
className: "size-4",
|
|
1108
1239
|
"aria-hidden": "true"
|
|
1109
1240
|
}), "Resolve"]
|
|
1110
1241
|
}),
|
|
1111
|
-
/* @__PURE__ */
|
|
1242
|
+
/* @__PURE__ */ D(F, {
|
|
1112
1243
|
className: "text-status-error-text",
|
|
1113
1244
|
onClick: r,
|
|
1114
|
-
children: [/* @__PURE__ */
|
|
1245
|
+
children: [/* @__PURE__ */ E(T, {
|
|
1115
1246
|
className: "size-4",
|
|
1116
1247
|
"aria-hidden": "true"
|
|
1117
1248
|
}), "Dismiss"]
|
|
@@ -1121,6 +1252,6 @@ function st({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPe
|
|
|
1121
1252
|
});
|
|
1122
1253
|
}
|
|
1123
1254
|
//#endregion
|
|
1124
|
-
export {
|
|
1255
|
+
export { W as RiskPage };
|
|
1125
1256
|
|
|
1126
1257
|
//# sourceMappingURL=RiskPage.js.map
|