@burdenoff/microfe-brainyrich 2026.525.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.
Files changed (66) hide show
  1. package/dist/brainyrich/BrainyRichRoot.js +55 -90
  2. package/dist/brainyrich/BrainyRichRoot.js.map +1 -1
  3. package/dist/brainyrich/BrainyRichRoutes.js +15 -35
  4. package/dist/brainyrich/BrainyRichRoutes.js.map +1 -1
  5. package/dist/brainyrich/components/ActorName.js +38 -0
  6. package/dist/brainyrich/components/ActorName.js.map +1 -0
  7. package/dist/brainyrich/components/ConfirmDialog.js +25 -0
  8. package/dist/brainyrich/components/ConfirmDialog.js.map +1 -0
  9. package/dist/brainyrich/components/LoadMore.js +24 -0
  10. package/dist/brainyrich/components/LoadMore.js.map +1 -0
  11. package/dist/brainyrich/components/index.js +5 -0
  12. package/dist/brainyrich/components/notify.js +38 -0
  13. package/dist/brainyrich/components/notify.js.map +1 -0
  14. package/dist/brainyrich/components/pickers.js +232 -0
  15. package/dist/brainyrich/components/pickers.js.map +1 -0
  16. package/dist/brainyrich/components/reuse/CommentThread.js +208 -0
  17. package/dist/brainyrich/components/reuse/CommentThread.js.map +1 -0
  18. package/dist/brainyrich/components/reuse/DocumentsPanel.js +237 -0
  19. package/dist/brainyrich/components/reuse/DocumentsPanel.js.map +1 -0
  20. package/dist/brainyrich/components/reuse/TagField.js +206 -0
  21. package/dist/brainyrich/components/reuse/TagField.js.map +1 -0
  22. package/dist/brainyrich/components/reuse/transport.js +24 -0
  23. package/dist/brainyrich/components/reuse/transport.js.map +1 -0
  24. package/dist/brainyrich/hooks/useBrainyRichApi.js +815 -0
  25. package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -0
  26. package/dist/brainyrich/index.js +0 -1
  27. package/dist/brainyrich/pages/AccountsPage.js +743 -160
  28. package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
  29. package/dist/brainyrich/pages/AiAssistantPage.js +556 -363
  30. package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
  31. package/dist/brainyrich/pages/AnalyticsPage.js +601 -268
  32. package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
  33. package/dist/brainyrich/pages/DashboardPage.js +375 -231
  34. package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
  35. package/dist/brainyrich/pages/FamilyPage.js +599 -337
  36. package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
  37. package/dist/brainyrich/pages/GoalsPage.js +810 -141
  38. package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
  39. package/dist/brainyrich/pages/InvestmentsPage.js +410 -311
  40. package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
  41. package/dist/brainyrich/pages/PortfoliosPage.js +867 -156
  42. package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
  43. package/dist/brainyrich/pages/ReportsPage.js +421 -251
  44. package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
  45. package/dist/brainyrich/pages/RiskPage.js +557 -194
  46. package/dist/brainyrich/pages/RiskPage.js.map +1 -1
  47. package/dist/brainyrich/pages/TaxPage.js +655 -221
  48. package/dist/brainyrich/pages/TaxPage.js.map +1 -1
  49. package/dist/brainyrich/pages/_shared.js +222 -41
  50. package/dist/brainyrich/pages/_shared.js.map +1 -1
  51. package/dist/index.js +2 -3
  52. package/dist/node_modules/sonner/dist/index.js +163 -0
  53. package/dist/node_modules/sonner/dist/index.js.map +1 -0
  54. package/package.json +3 -2
  55. package/dist/brainyrich/pages/AdvisorsPage.js +0 -375
  56. package/dist/brainyrich/pages/AdvisorsPage.js.map +0 -1
  57. package/dist/brainyrich/pages/AssistantPage.js +0 -332
  58. package/dist/brainyrich/pages/AssistantPage.js.map +0 -1
  59. package/dist/brainyrich/pages/EstatePage.js +0 -269
  60. package/dist/brainyrich/pages/EstatePage.js.map +0 -1
  61. package/dist/brainyrich/pages/InsurancePage.js +0 -181
  62. package/dist/brainyrich/pages/InsurancePage.js.map +0 -1
  63. package/dist/brainyrich/pages/MarketplacePage.js +0 -450
  64. package/dist/brainyrich/pages/MarketplacePage.js.map +0 -1
  65. package/dist/brainyrich/store/brainyrichStore.js +0 -272
  66. package/dist/brainyrich/store/brainyrichStore.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PortfoliosPage.js","names":[],"sources":["../../../src/brainyrich/pages/PortfoliosPage.tsx"],"sourcesContent":["import {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Badge,\n Button,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\nimport { Briefcase, TrendingUp, PieChart, Plus, RefreshCw } from 'lucide-react';\nimport { useBrainyRichStore } from '../store/brainyrichStore';\nimport { SectionShell, KpiGrid, formatMoney } from './_shared';\n\nexport function PortfoliosPage() {\n const { portfolios, holdings } = useBrainyRichStore();\n const totalValue = portfolios.reduce((s, p) => s + p.value, 0);\n const weightedReturn = portfolios.reduce((s, p) => s + p.ytdReturnPct * p.value, 0) / totalValue;\n\n return (\n <SectionShell\n title=\"Portfolio Management\"\n description=\"Monitor, analyze, and rebalance your investment portfolios\"\n actionLabel=\"Create Portfolio\"\n badges={['3 Active Portfolios']}\n >\n <KpiGrid\n items={[\n {\n label: 'Total Portfolio Value',\n value: formatMoney(totalValue),\n trend: '+9.8% overall',\n },\n { label: 'Active Portfolios', value: String(portfolios.length) },\n {\n label: 'Weighted YTD Return',\n value: `${weightedReturn.toFixed(1)}%`,\n trend: 'Above benchmark',\n },\n { label: 'Asset Count', value: String(holdings.length), trend: 'Across all strategies' },\n ]}\n />\n\n {/* Portfolio cards */}\n <div className=\"grid gap-4 lg:grid-cols-3\">\n {portfolios.map((p) => {\n const allocPct = Math.round((p.value / totalValue) * 100);\n return (\n <Card key={p.id}>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Briefcase className=\"h-4 w-4\" />\n {p.name}\n </CardTitle>\n <Badge\n variant={\n p.risk === 'High'\n ? 'destructive'\n : p.risk === 'Moderate'\n ? 'secondary'\n : 'outline'\n }\n >\n {p.risk} Risk\n </Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div>\n <span className=\"text-2xl font-bold\">{formatMoney(p.value)}</span>\n <span className=\"ml-2 text-sm text-emerald-600\">+{p.ytdReturnPct}% YTD</span>\n </div>\n <div className=\"space-y-1\">\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>Portfolio allocation</span>\n <span>{allocPct}%</span>\n </div>\n <div className=\"h-2 rounded bg-muted overflow-hidden\">\n <div className=\"h-2 rounded bg-primary\" style={{ width: `${allocPct}%` }} />\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" className=\"flex-1\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Analyze\n </Button>\n <Button variant=\"outline\" size=\"sm\" className=\"flex-1\">\n <RefreshCw className=\"mr-1 h-3 w-3\" />\n Rebalance\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n {/* Allocation breakdown bar */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <PieChart className=\"h-5 w-5\" />\n Allocation Breakdown\n </CardTitle>\n <CardDescription>Visual distribution of capital across strategies</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex h-8 rounded overflow-hidden\">\n {portfolios.map((p, i) => {\n const colors = ['bg-blue-500', 'bg-purple-500', 'bg-emerald-500'];\n const pct = (p.value / totalValue) * 100;\n return (\n <div\n key={p.id}\n className={`${colors[i % colors.length]} flex items-center justify-center text-[10px] font-medium text-white`}\n style={{ width: `${pct}%` }}\n >\n {pct.toFixed(0)}%\n </div>\n );\n })}\n </div>\n <div className=\"mt-3 flex flex-wrap gap-4\">\n {portfolios.map((p, i) => {\n const dotColors = ['bg-blue-500', 'bg-purple-500', 'bg-emerald-500'];\n return (\n <div key={p.id} className=\"flex items-center gap-2 text-sm\">\n <div className={`h-3 w-3 rounded-full ${dotColors[i % dotColors.length]}`} />\n {p.name}\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Holdings table */}\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <div>\n <CardTitle>Holdings</CardTitle>\n <CardDescription>All securities across every portfolio</CardDescription>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Position\n </Button>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Symbol</TableHead>\n <TableHead>Name</TableHead>\n <TableHead>Sector</TableHead>\n <TableHead className=\"text-right\">Market Value</TableHead>\n <TableHead className=\"text-right\">Change %</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {holdings.map((h) => (\n <TableRow key={h.symbol}>\n <TableCell className=\"font-semibold\">{h.symbol}</TableCell>\n <TableCell>{h.name}</TableCell>\n <TableCell>\n <Badge variant=\"outline\">{h.sector}</Badge>\n </TableCell>\n <TableCell className=\"text-right\">{formatMoney(h.marketValue)}</TableCell>\n <TableCell\n className={`text-right ${h.changePct >= 0 ? 'text-emerald-600' : 'text-red-600'}`}\n >\n {h.changePct >= 0 ? '+' : ''}\n {h.changePct}%\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </SectionShell>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"PortfoliosPage.js","names":[],"sources":["../../../src/brainyrich/pages/PortfoliosPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowDownRight,\n ArrowUpRight,\n Briefcase,\n MoreHorizontal,\n Pencil,\n Plus,\n Trash2,\n} from 'lucide-react';\n\nimport {\n useArchivePortfolio,\n useCreateHolding,\n useCreatePortfolio,\n useDeleteHolding,\n useHouseholds,\n useModelPortfolios,\n usePagedPortfolios,\n usePortfolio,\n useUpdateHolding,\n useUpdatePortfolio,\n} from '../hooks/useBrainyRichApi';\nimport { AccountPicker, ConfirmDialog, LoadMore } from '../components';\nimport { CommentThread } from '../components/reuse/CommentThread';\nimport { TagField } from '../components/reuse/TagField';\nimport type { BraAssetClass, BraHolding, BraPortfolio, BraPortfolioStatus } from '../types/bra';\nimport {\n AllocationBars,\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatMoney,\n formatPct,\n statusBadgeVariant,\n type AllocationDatum,\n} from './_shared';\n\nconst ASSET_CLASSES: BraAssetClass[] = [\n 'EQUITY',\n 'FIXED_INCOME',\n 'CASH',\n 'REAL_ESTATE',\n 'COMMODITY',\n 'CRYPTO',\n 'ALTERNATIVE',\n];\n\nconst PORTFOLIO_STATUSES: BraPortfolioStatus[] = ['DRAFT', 'ACTIVE', 'ARCHIVED'];\n\nconst NONE = '__none__';\n\nconst prettyEnum = (value: string): string =>\n value\n .toLowerCase()\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n\nconst toNumber = (value: string): number | undefined => {\n if (value.trim() === '') return undefined;\n const n = Number(value);\n return Number.isFinite(n) ? n : undefined;\n};\n\n/** Read a `targetAllocation` JSON blob as an assetClass → percentage map. */\nfunction parseTargetAllocation(raw: unknown): AllocationDatum[] {\n if (!raw || typeof raw !== 'object') return [];\n return Object.entries(raw as Record<string, unknown>)\n .map(([label, value]) => ({ label, value: Number(value) }))\n .filter((d) => Number.isFinite(d.value))\n .map((d) => ({ label: prettyEnum(d.label), value: d.value, tone: 'accent' as const }));\n}\n\n// ============================================================================\n// Gain cell — signed money with icon + semantic color (color never sole signal)\n// ============================================================================\n\nfunction GainValue({ value, currency }: { value: number; currency: string }) {\n const positive = value > 0;\n const negative = value < 0;\n const tone = positive\n ? 'text-status-success-text'\n : negative\n ? 'text-status-error-text'\n : 'text-text-secondary';\n const Icon = positive ? ArrowUpRight : negative ? ArrowDownRight : null;\n return (\n <span className={`inline-flex items-center justify-end gap-1 font-medium ${tone}`}>\n {Icon ? <Icon className=\"size-3.5\" aria-hidden=\"true\" /> : null}\n {positive ? '+' : ''}\n {formatMoney(value, currency)}\n </span>\n );\n}\n\n// ============================================================================\n// Portfolio create / edit dialog\n// ============================================================================\n\ninterface PortfolioFormState {\n name: string;\n baseCurrency: string;\n description: string;\n driftThresholdPct: string;\n status: BraPortfolioStatus;\n modelPortfolioId: string;\n householdId: string;\n}\n\nfunction emptyForm(): PortfolioFormState {\n return {\n name: '',\n baseCurrency: 'USD',\n description: '',\n driftThresholdPct: '5',\n status: 'DRAFT',\n modelPortfolioId: NONE,\n householdId: NONE,\n };\n}\n\nfunction PortfolioFormDialog({\n open,\n onOpenChange,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n editing: BraPortfolio | null;\n}) {\n const { data: models } = useModelPortfolios();\n const { data: households } = useHouseholds();\n const createPortfolio = useCreatePortfolio();\n const updatePortfolio = useUpdatePortfolio();\n\n const [form, setForm] = useState<PortfolioFormState>(emptyForm);\n // Re-seed the form whenever the dialog target changes.\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const targetKey = editing?.id ?? 'new';\n if (open && seededFor !== targetKey) {\n setSeededFor(targetKey);\n setForm(\n editing\n ? {\n name: editing.name,\n baseCurrency: editing.baseCurrency,\n description: editing.description ?? '',\n driftThresholdPct: String(editing.driftThresholdPct),\n status: editing.status,\n modelPortfolioId: editing.modelPortfolioId ?? NONE,\n householdId: editing.householdId ?? NONE,\n }\n : emptyForm()\n );\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const pending = createPortfolio.isPending || updatePortfolio.isPending;\n const nameValid = form.name.trim().length > 0;\n\n const handleSubmit = () => {\n if (!nameValid) return;\n const drift = toNumber(form.driftThresholdPct);\n const modelPortfolioId = form.modelPortfolioId === NONE ? null : form.modelPortfolioId;\n const householdId = form.householdId === NONE ? null : form.householdId;\n\n if (editing) {\n updatePortfolio.mutate(\n {\n id: editing.id,\n input: {\n name: form.name.trim(),\n baseCurrency: form.baseCurrency.trim() || 'USD',\n description: form.description.trim() || null,\n driftThresholdPct: drift,\n status: form.status,\n modelPortfolioId,\n },\n },\n { onSuccess: () => onOpenChange(false) }\n );\n } else {\n createPortfolio.mutate(\n {\n name: form.name.trim(),\n baseCurrency: form.baseCurrency.trim() || 'USD',\n description: form.description.trim() || null,\n driftThresholdPct: drift,\n modelPortfolioId,\n householdId,\n },\n { onSuccess: () => onOpenChange(false) }\n );\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>{editing ? 'Edit portfolio' : 'New portfolio'}</DialogTitle>\n <DialogDescription>\n {editing\n ? 'Update this portfolio’s strategy settings.'\n : 'Create an investment portfolio to organize and rebalance holdings.'}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-name\">Name</Label>\n <Input\n id=\"pf-name\"\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n placeholder=\"Growth Portfolio\"\n aria-invalid={!nameValid}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-currency\">Base currency</Label>\n <Input\n id=\"pf-currency\"\n value={form.baseCurrency}\n onChange={(e) =>\n setForm((f) => ({ ...f, baseCurrency: e.target.value.toUpperCase() }))\n }\n placeholder=\"USD\"\n maxLength={3}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-drift\">Drift threshold %</Label>\n <Input\n id=\"pf-drift\"\n type=\"number\"\n min={0}\n step=\"0.5\"\n value={form.driftThresholdPct}\n onChange={(e) => setForm((f) => ({ ...f, driftThresholdPct: e.target.value }))}\n />\n </div>\n </div>\n\n {editing ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-status\">Status</Label>\n <Select\n value={form.status}\n onValueChange={(v) => setForm((f) => ({ ...f, status: v as BraPortfolioStatus }))}\n >\n <SelectTrigger id=\"pf-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {PORTFOLIO_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {prettyEnum(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-model\">Model portfolio</Label>\n <Select\n value={form.modelPortfolioId}\n onValueChange={(v) => setForm((f) => ({ ...f, modelPortfolioId: v }))}\n >\n <SelectTrigger id=\"pf-model\">\n <SelectValue placeholder=\"None\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>None</SelectItem>\n {models.map((m) => (\n <SelectItem key={m.id} value={m.id}>\n {m.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {!editing ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-household\">Household</Label>\n <Select\n value={form.householdId}\n onValueChange={(v) => setForm((f) => ({ ...f, householdId: v }))}\n >\n <SelectTrigger id=\"pf-household\">\n <SelectValue placeholder=\"None\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>None</SelectItem>\n {households.map((h) => (\n <SelectItem key={h.id} value={h.id}>\n {h.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"pf-desc\">Description</Label>\n <Textarea\n id=\"pf-desc\"\n value={form.description}\n onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))}\n placeholder=\"Optional notes about this strategy\"\n rows={3}\n />\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={pending}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={!nameValid || pending}>\n {pending ? 'Saving…' : editing ? 'Save changes' : 'Create portfolio'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Holding create / edit dialog (scoped to a portfolio)\n// ============================================================================\n\ninterface HoldingFormState {\n accountId: string;\n symbol: string;\n name: string;\n assetClass: BraAssetClass;\n quantity: string;\n lastPrice: string;\n costBasis: string;\n}\n\nfunction emptyHoldingForm(): HoldingFormState {\n return {\n accountId: '',\n symbol: '',\n name: '',\n assetClass: 'EQUITY',\n quantity: '0',\n lastPrice: '0',\n costBasis: '0',\n };\n}\n\nfunction HoldingFormDialog({\n open,\n onOpenChange,\n portfolioId,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n portfolioId: string;\n editing: BraHolding | null;\n}) {\n const createHolding = useCreateHolding();\n const updateHolding = useUpdateHolding();\n\n const [form, setForm] = useState<HoldingFormState>(emptyHoldingForm);\n const [seededFor, setSeededFor] = useState<string | null>(null);\n const targetKey = editing?.id ?? 'new';\n if (open && seededFor !== targetKey) {\n setSeededFor(targetKey);\n setForm(\n editing\n ? {\n accountId: editing.accountId,\n symbol: editing.symbol,\n name: editing.name ?? '',\n assetClass: editing.assetClass,\n quantity: String(editing.quantity),\n lastPrice: String(editing.lastPrice),\n costBasis: String(editing.costBasis),\n }\n : emptyHoldingForm()\n );\n }\n if (!open && seededFor !== null) {\n setSeededFor(null);\n }\n\n const pending = createHolding.isPending || updateHolding.isPending;\n const symbolValid = form.symbol.trim().length > 0;\n const accountValid = editing ? true : form.accountId.trim().length > 0;\n const canSubmit = symbolValid && accountValid && !pending;\n\n const handleSubmit = () => {\n if (!symbolValid || !accountValid) return;\n if (editing) {\n updateHolding.mutate(\n {\n id: editing.id,\n input: {\n name: form.name.trim() || null,\n assetClass: form.assetClass,\n quantity: toNumber(form.quantity),\n lastPrice: toNumber(form.lastPrice),\n costBasis: toNumber(form.costBasis),\n },\n },\n { onSuccess: () => onOpenChange(false) }\n );\n } else {\n createHolding.mutate(\n {\n accountId: form.accountId,\n portfolioId,\n symbol: form.symbol.trim().toUpperCase(),\n name: form.name.trim() || null,\n assetClass: form.assetClass,\n quantity: toNumber(form.quantity),\n lastPrice: toNumber(form.lastPrice),\n costBasis: toNumber(form.costBasis),\n },\n { onSuccess: () => onOpenChange(false) }\n );\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>{editing ? 'Edit holding' : 'Add holding'}</DialogTitle>\n <DialogDescription>\n {editing\n ? 'Update the position details for this holding.'\n : 'Add a position to this portfolio from one of your accounts.'}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n {!editing ? (\n <AccountPicker\n id=\"h-account\"\n value={form.accountId}\n onChange={(v) => setForm((f) => ({ ...f, accountId: v }))}\n placeholder=\"Select account\"\n />\n ) : null}\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-symbol\">Symbol</Label>\n <Input\n id=\"h-symbol\"\n value={form.symbol}\n onChange={(e) => setForm((f) => ({ ...f, symbol: e.target.value }))}\n placeholder=\"AAPL\"\n disabled={Boolean(editing)}\n aria-invalid={!symbolValid}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-class\">Asset class</Label>\n <Select\n value={form.assetClass}\n onValueChange={(v) => setForm((f) => ({ ...f, assetClass: v as BraAssetClass }))}\n >\n <SelectTrigger id=\"h-class\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ASSET_CLASSES.map((c) => (\n <SelectItem key={c} value={c}>\n {prettyEnum(c)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-name\">Name</Label>\n <Input\n id=\"h-name\"\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n placeholder=\"Apple Inc.\"\n />\n </div>\n\n <div className=\"grid grid-cols-3 gap-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-qty\">Quantity</Label>\n <Input\n id=\"h-qty\"\n type=\"number\"\n step=\"any\"\n value={form.quantity}\n onChange={(e) => setForm((f) => ({ ...f, quantity: e.target.value }))}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-price\">Last price</Label>\n <Input\n id=\"h-price\"\n type=\"number\"\n step=\"any\"\n value={form.lastPrice}\n onChange={(e) => setForm((f) => ({ ...f, lastPrice: e.target.value }))}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"h-cost\">Cost basis</Label>\n <Input\n id=\"h-cost\"\n type=\"number\"\n step=\"any\"\n value={form.costBasis}\n onChange={(e) => setForm((f) => ({ ...f, costBasis: e.target.value }))}\n />\n </div>\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={pending}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={!canSubmit}>\n {pending ? 'Saving…' : editing ? 'Save changes' : 'Add holding'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Portfolio detail sheet — holdings table + target vs actual allocation\n// ============================================================================\n\nfunction PortfolioDetailSheet({\n portfolioId,\n onOpenChange,\n}: {\n portfolioId: string | null;\n onOpenChange: (open: boolean) => void;\n}) {\n const { data: portfolio, isLoading, isError, refetch } = usePortfolio(portfolioId ?? undefined);\n const deleteHolding = useDeleteHolding();\n\n const [holdingDialogOpen, setHoldingDialogOpen] = useState(false);\n const [editingHolding, setEditingHolding] = useState<BraHolding | null>(null);\n const [holdingToDelete, setHoldingToDelete] = useState<BraHolding | null>(null);\n\n const holdings = portfolio?.holdings ?? [];\n const currency = portfolio?.baseCurrency ?? 'USD';\n const totalMarketValue = holdings.reduce((s, h) => s + h.marketValue, 0);\n\n const actualAllocation: AllocationDatum[] = useMemo(() => {\n if (holdings.length === 0 || totalMarketValue <= 0) return [];\n const byClass = new Map<string, number>();\n holdings.forEach((h) =>\n byClass.set(h.assetClass, (byClass.get(h.assetClass) ?? 0) + h.marketValue)\n );\n return Array.from(byClass.entries())\n .map(([label, mv]) => ({\n label: prettyEnum(label),\n value: (mv / totalMarketValue) * 100,\n caption: formatMoney(mv, currency),\n tone: 'default' as const,\n }))\n .sort((a, b) => b.value - a.value);\n }, [holdings, totalMarketValue, currency]);\n\n const targetAllocation = useMemo(\n () => parseTargetAllocation(portfolio?.targetAllocation),\n [portfolio?.targetAllocation]\n );\n\n const openAddHolding = () => {\n setEditingHolding(null);\n setHoldingDialogOpen(true);\n };\n const openEditHolding = (h: BraHolding) => {\n setEditingHolding(h);\n setHoldingDialogOpen(true);\n };\n\n return (\n <Sheet open={portfolioId !== null} onOpenChange={onOpenChange}>\n <SheetContent className=\"flex w-full flex-col gap-0 overflow-y-auto p-0 sm:max-w-2xl\">\n {isLoading ? (\n <div className=\"p-6\">\n <LoadingState rows={5} />\n </div>\n ) : isError ? (\n <div className=\"p-6\">\n <ErrorState onRetry={() => refetch()} />\n </div>\n ) : !portfolio ? (\n <div className=\"p-6\">\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title=\"Portfolio not found\"\n description=\"This portfolio may have been archived or removed.\"\n />\n </div>\n ) : (\n <>\n <SheetHeader className=\"border-b border-border-subtle p-6\">\n <div className=\"flex items-center gap-2\">\n <SheetTitle className=\"text-xl\">{portfolio.name}</SheetTitle>\n <Badge variant={statusBadgeVariant(portfolio.status)}>\n {prettyEnum(portfolio.status)}\n </Badge>\n </div>\n <SheetDescription>\n {portfolio.description?.trim()\n ? portfolio.description\n : `${portfolio.baseCurrency} · Drift threshold ${formatPct(portfolio.driftThresholdPct)}`}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"space-y-6 p-6\">\n {/* Summary numbers */}\n <div className=\"grid grid-cols-2 gap-4\">\n <Card>\n <CardContent className=\"space-y-1 p-4\">\n <p className=\"text-xs text-text-secondary\">Market value</p>\n <p className=\"text-2xl font-semibold text-text-primary\">\n {formatMoney(totalMarketValue, currency)}\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"space-y-1 p-4\">\n <p className=\"text-xs text-text-secondary\">Holdings</p>\n <p className=\"text-2xl font-semibold text-text-primary\">{holdings.length}</p>\n </CardContent>\n </Card>\n </div>\n\n {/* Allocation */}\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-sm\">Target allocation</CardTitle>\n </CardHeader>\n <CardContent>\n {targetAllocation.length > 0 ? (\n <AllocationBars data={targetAllocation} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No target allocation set for this portfolio.\n </p>\n )}\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-sm\">Actual allocation</CardTitle>\n </CardHeader>\n <CardContent>\n {actualAllocation.length > 0 ? (\n <AllocationBars data={actualAllocation} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Add holdings to see the live allocation.\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n\n {/* Holdings table */}\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <div>\n <CardTitle className=\"text-base\">Holdings</CardTitle>\n <CardDescription>Positions held in this portfolio</CardDescription>\n </div>\n <Button size=\"sm\" onClick={openAddHolding}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n Add holding\n </Button>\n </CardHeader>\n <CardContent>\n {holdings.length === 0 ? (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No holdings yet\"\n description=\"Add positions to start tracking this portfolio.\"\n action={\n <Button size=\"sm\" onClick={openAddHolding}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n Add holding\n </Button>\n }\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Symbol</TableHead>\n <TableHead>Class</TableHead>\n <TableHead className=\"text-right\">Qty</TableHead>\n <TableHead className=\"text-right\">Price</TableHead>\n <TableHead className=\"text-right\">Market value</TableHead>\n <TableHead className=\"text-right\">Gain</TableHead>\n <TableHead className=\"w-10\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {holdings.map((h) => {\n const gain = h.marketValue - h.costBasis;\n return (\n <TableRow key={h.id}>\n <TableCell>\n <div className=\"font-semibold text-text-primary\">{h.symbol}</div>\n {h.name ? (\n <div className=\"text-xs text-text-secondary\">{h.name}</div>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant=\"outline\">{prettyEnum(h.assetClass)}</Badge>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {h.quantity}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {formatMoney(h.lastPrice, h.currency)}\n </TableCell>\n <TableCell className=\"text-right font-medium tabular-nums\">\n {formatMoney(h.marketValue, h.currency)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <GainValue value={gain} currency={h.currency} />\n </TableCell>\n <TableCell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-10\"\n aria-label={`Actions for ${h.symbol}`}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>{h.symbol}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"gap-2\"\n onClick={() => openEditHolding(h)}\n >\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem\n className=\"gap-2 text-status-error-text focus:text-status-error-text\"\n onClick={() => setHoldingToDelete(h)}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Tags — real UniversalTag assignments keyed by entity */}\n <Card>\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-sm\">Tags</CardTitle>\n <CardDescription>Organize and filter this portfolio.</CardDescription>\n </CardHeader>\n <CardContent>\n <TagField\n entityType=\"brainyrich-portfolio\"\n entityId={portfolio.id}\n hideLabel\n />\n </CardContent>\n </Card>\n\n {/* Discussion — threaded comments keyed by entity */}\n <Card>\n <CardContent className=\"pt-6\">\n <CommentThread entityType=\"brainyrich-portfolio\" entityId={portfolio.id} />\n </CardContent>\n </Card>\n </div>\n\n <HoldingFormDialog\n open={holdingDialogOpen}\n onOpenChange={setHoldingDialogOpen}\n portfolioId={portfolio.id}\n editing={editingHolding}\n />\n\n <ConfirmDialog\n open={holdingToDelete !== null}\n onOpenChange={(open) => {\n if (!open) setHoldingToDelete(null);\n }}\n title=\"Delete holding?\"\n description={\n holdingToDelete\n ? `Remove ${holdingToDelete.symbol} from this portfolio. This cannot be undone.`\n : undefined\n }\n confirmLabel=\"Delete\"\n pendingLabel=\"Deleting…\"\n destructive\n pending={deleteHolding.isPending}\n onConfirm={() => {\n if (!holdingToDelete) return;\n deleteHolding.mutate(holdingToDelete.id, {\n onSuccess: () => setHoldingToDelete(null),\n });\n }}\n />\n </>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n\n// ============================================================================\n// Page\n// ============================================================================\n\nexport function PortfoliosPage() {\n const {\n items: portfolios,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedPortfolios();\n const archivePortfolio = useArchivePortfolio();\n\n const [formOpen, setFormOpen] = useState(false);\n const [editingPortfolio, setEditingPortfolio] = useState<BraPortfolio | null>(null);\n const [detailId, setDetailId] = useState<string | null>(null);\n const [portfolioToArchive, setPortfolioToArchive] = useState<BraPortfolio | null>(null);\n\n const activeCount = portfolios.filter((p) => p.status === 'ACTIVE').length;\n const draftCount = portfolios.filter((p) => p.status === 'DRAFT').length;\n const avgDrift =\n portfolios.length > 0\n ? portfolios.reduce((s, p) => s + p.driftThresholdPct, 0) / portfolios.length\n : 0;\n\n const openCreate = () => {\n setEditingPortfolio(null);\n setFormOpen(true);\n };\n const openEdit = (p: BraPortfolio) => {\n setEditingPortfolio(p);\n setFormOpen(true);\n };\n\n return (\n <SectionShell\n title=\"Portfolios\"\n description=\"Organize holdings into strategies and keep allocations on target.\"\n badges={portfolios.length > 0 ? [`${portfolios.length} total`] : []}\n actions={\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n New portfolio\n </Button>\n }\n >\n {isLoading ? (\n <LoadingState rows={4} />\n ) : isError ? (\n <ErrorState onRetry={() => refetch()} />\n ) : portfolios.length === 0 ? (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title=\"No portfolios yet\"\n description=\"Create your first portfolio to start organizing holdings and tracking drift.\"\n action={\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n New portfolio\n </Button>\n }\n />\n ) : (\n <>\n <KpiGrid\n items={[\n { label: 'Portfolios', value: String(portfolios.length) },\n { label: 'Active', value: String(activeCount) },\n { label: 'Drafts', value: String(draftCount) },\n { label: 'Avg drift threshold', value: formatPct(avgDrift) },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {portfolios.map((p) => (\n <Card key={p.id} className=\"flex flex-col\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Briefcase className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {p.name}\n </CardTitle>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-10\"\n aria-label={`Actions for ${p.name}`}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>{p.name}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem className=\"gap-2\" onClick={() => openEdit(p)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem\n className=\"gap-2 text-status-error-text focus:text-status-error-text\"\n disabled={p.status === 'ARCHIVED'}\n onClick={() => setPortfolioToArchive(p)}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n Archive\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n {p.description?.trim() ? (\n <CardDescription className=\"line-clamp-2\">{p.description}</CardDescription>\n ) : null}\n </CardHeader>\n <CardContent className=\"flex flex-1 flex-col justify-between gap-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={statusBadgeVariant(p.status)}>{prettyEnum(p.status)}</Badge>\n <Badge variant=\"outline\">{p.baseCurrency}</Badge>\n <Badge variant=\"secondary\">Drift {formatPct(p.driftThresholdPct)}</Badge>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(p.id)}\n >\n View holdings\n </Button>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <LoadMore hasMore={hasMore} onClick={loadMore} loading={isFetchingNextPage} />\n </>\n )}\n\n <PortfolioFormDialog open={formOpen} onOpenChange={setFormOpen} editing={editingPortfolio} />\n\n <PortfolioDetailSheet\n portfolioId={detailId}\n onOpenChange={(open) => {\n if (!open) setDetailId(null);\n }}\n />\n\n <ConfirmDialog\n open={portfolioToArchive !== null}\n onOpenChange={(open) => {\n if (!open) setPortfolioToArchive(null);\n }}\n title=\"Archive portfolio?\"\n description={\n portfolioToArchive\n ? `Archive “${portfolioToArchive.name}”. It will move to archived status and stop appearing in active views.`\n : undefined\n }\n confirmLabel=\"Archive\"\n pendingLabel=\"Archiving…\"\n destructive\n pending={archivePortfolio.isPending}\n onConfirm={() => {\n if (!portfolioToArchive) return;\n archivePortfolio.mutate(portfolioToArchive.id, {\n onSuccess: () => setPortfolioToArchive(null),\n });\n }}\n />\n </SectionShell>\n );\n}\n"],"mappings":"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"}