@burdenoff/microfe-brainyrich 2026.525.1 → 2026.705.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brainyrich/BrainyRichRoot.js +53 -88
- package/dist/brainyrich/BrainyRichRoot.js.map +1 -1
- package/dist/brainyrich/BrainyRichRoutes.js +15 -35
- package/dist/brainyrich/BrainyRichRoutes.js.map +1 -1
- package/dist/brainyrich/hooks/useBrainyRichApi.js +543 -0
- package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -0
- package/dist/brainyrich/index.js +0 -1
- package/dist/brainyrich/pages/AccountsPage.js +690 -160
- package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js +537 -363
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js +587 -268
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js +350 -232
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js +550 -337
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js +775 -142
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js +410 -311
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js +823 -154
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +388 -251
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +411 -196
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/TaxPage.js +622 -221
- package/dist/brainyrich/pages/TaxPage.js.map +1 -1
- package/dist/brainyrich/pages/_shared.js +222 -41
- package/dist/brainyrich/pages/_shared.js.map +1 -1
- package/dist/index.js +2 -3
- package/package.json +1 -1
- package/dist/brainyrich/pages/AdvisorsPage.js +0 -375
- package/dist/brainyrich/pages/AdvisorsPage.js.map +0 -1
- package/dist/brainyrich/pages/AssistantPage.js +0 -332
- package/dist/brainyrich/pages/AssistantPage.js.map +0 -1
- package/dist/brainyrich/pages/EstatePage.js +0 -269
- package/dist/brainyrich/pages/EstatePage.js.map +0 -1
- package/dist/brainyrich/pages/InsurancePage.js +0 -181
- package/dist/brainyrich/pages/InsurancePage.js.map +0 -1
- package/dist/brainyrich/pages/MarketplacePage.js +0 -450
- package/dist/brainyrich/pages/MarketplacePage.js.map +0 -1
- package/dist/brainyrich/store/brainyrichStore.js +0 -272
- package/dist/brainyrich/store/brainyrichStore.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvestmentsPage.js","names":[],"sources":["../../../src/brainyrich/pages/InvestmentsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\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 Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n DollarSign,\n TrendingUp,\n PieChart,\n Target,\n Plus,\n ArrowUpRight,\n ArrowDownRight,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useBrainyRichStore } from '../store/brainyrichStore';\nimport { tWithFallback } from '../utils/i18n';\nimport { SectionShell, KpiGrid, formatMoney } from './_shared';\n\nconst tradeHistory = [\n {\n id: 't1',\n date: '2026-05-28',\n symbol: 'AAPL',\n type: 'BUY' as const,\n qty: 25,\n price: 189.4,\n status: 'Executed',\n },\n {\n id: 't2',\n date: '2026-05-22',\n symbol: 'VTI',\n type: 'BUY' as const,\n qty: 50,\n price: 228.1,\n status: 'Executed',\n },\n {\n id: 't3',\n date: '2026-05-15',\n symbol: 'HDFC',\n type: 'SELL' as const,\n qty: 30,\n price: 1620.5,\n status: 'Executed',\n },\n];\n\nconst sectorBreakdown = [\n { sector: 'Technology', value: 142760, pct: 47.8 },\n { sector: 'Index / ETF', value: 113400, pct: 38.0 },\n { sector: 'Financial', value: 42900, pct: 14.2 },\n];\n\nexport function InvestmentsPage() {\n const { t } = useI18n();\n const [tab, setTab] = useState('overview');\n const { holdings, portfolios } = useBrainyRichStore();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n const totalInvested = holdings.reduce((s, h) => s + h.marketValue, 0);\n const totalPortfolioValue = portfolios.reduce((s, p) => s + p.value, 0);\n\n return (\n <SectionShell\n title={translate('brainyrich.investments.title', 'Investment Portfolio')}\n description={translate(\n 'brainyrich.investments.description',\n 'Track, trade, and optimize your investment positions'\n )}\n actionLabel={translate('brainyrich.investments.actions.newTrade', 'New Trade')}\n badges={[\n translate('brainyrich.investments.badges.holdingsCount', '{count} Holdings', {\n count: holdings.length,\n }),\n ]}\n >\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.investments.metrics.totalInvested', 'Total Invested'),\n value: formatMoney(totalInvested),\n trend: translate(\n 'brainyrich.investments.metrics.totalInvestedTrend',\n 'Across all accounts'\n ),\n },\n {\n label: translate('brainyrich.investments.metrics.dayChange', 'Day Change'),\n value: '+$2,410',\n trend: '+0.81%',\n },\n {\n label: translate('brainyrich.investments.metrics.holdingsCount', 'Holdings Count'),\n value: String(holdings.length),\n },\n {\n label: translate('brainyrich.investments.metrics.totalGainLoss', 'Total Gain/Loss'),\n value: '+$45,230',\n trend: translate(\n 'brainyrich.investments.metrics.totalGainLossTrend',\n '+10.2% all-time'\n ),\n },\n ]}\n />\n\n <Tabs value={tab} onValueChange={setTab} className=\"space-y-4\">\n <TabsList className=\"grid w-full grid-cols-4\">\n <TabsTrigger value=\"overview\">\n {translate('brainyrich.investments.tabs.overview', 'Overview')}\n </TabsTrigger>\n <TabsTrigger value=\"holdings\">\n {translate('brainyrich.investments.tabs.holdings', 'Holdings')}\n </TabsTrigger>\n <TabsTrigger value=\"sectors\">\n {translate('brainyrich.investments.tabs.sectors', 'Sector Analysis')}\n </TabsTrigger>\n <TabsTrigger value=\"history\">\n {translate('brainyrich.investments.tabs.history', 'Trade History')}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n {[\n {\n icon: DollarSign,\n label: translate('brainyrich.investments.overview.totalValue', 'Total Value'),\n val: formatMoney(totalPortfolioValue),\n color: 'bg-blue-100 text-blue-600',\n },\n {\n icon: TrendingUp,\n label: translate('brainyrich.investments.overview.todaysChange', \"Today's Change\"),\n val: '+$2,410',\n color: 'bg-emerald-100 text-emerald-600',\n },\n {\n icon: PieChart,\n label: translate('brainyrich.investments.overview.holdings', 'Holdings'),\n val: String(holdings.length),\n color: 'bg-purple-100 text-purple-600',\n },\n {\n icon: Target,\n label: translate('brainyrich.investments.overview.performance', 'Performance'),\n val: '+10.2%',\n color: 'bg-orange-100 text-orange-600',\n },\n ].map((kpi) => (\n <Card key={kpi.label}>\n <CardContent className=\"flex items-center gap-4 p-4\">\n <div className={`rounded-lg p-2 ${kpi.color}`}>\n <kpi.icon className=\"h-5 w-5\" />\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">{kpi.label}</p>\n <p className=\"text-xl font-bold\">{kpi.val}</p>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <div>\n <CardTitle>\n {translate('brainyrich.investments.sections.topHoldings', 'Top Holdings')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.investments.sections.topHoldingsDescription',\n 'Largest positions by market value'\n )}\n </CardDescription>\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setTab('holdings')}>\n {translate('brainyrich.investments.actions.viewAll', 'View All')}\n </Button>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {holdings.map((h) => (\n <div\n key={h.symbol}\n className=\"flex items-center justify-between rounded-lg border p-3\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-xs font-bold text-blue-600\">\n {h.symbol.slice(0, 2)}\n </div>\n <div>\n <p className=\"font-medium text-sm\">{h.symbol}</p>\n <p className=\"text-xs text-muted-foreground\">{h.name}</p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">{formatMoney(h.marketValue)}</p>\n <p\n className={`text-xs flex items-center justify-end gap-0.5 ${h.changePct >= 0 ? 'text-emerald-600' : 'text-red-600'}`}\n >\n {h.changePct >= 0 ? (\n <ArrowUpRight className=\"h-3 w-3\" />\n ) : (\n <ArrowDownRight className=\"h-3 w-3\" />\n )}\n {h.changePct >= 0 ? '+' : ''}\n {h.changePct}%\n </p>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"holdings\">\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle>\n {translate('brainyrich.investments.sections.allHoldings', 'All Holdings')}\n </CardTitle>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n {translate('brainyrich.investments.actions.addPosition', 'Add Position')}\n </Button>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>\n {translate('brainyrich.investments.table.symbol', 'Symbol')}\n </TableHead>\n <TableHead>{translate('brainyrich.investments.table.name', 'Name')}</TableHead>\n <TableHead>\n {translate('brainyrich.investments.table.sector', 'Sector')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.table.marketValue', 'Market Value')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.table.changePct', 'Change %')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.table.allocation', 'Allocation')}\n </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 <TableCell className=\"text-right\">\n {((h.marketValue / totalInvested) * 100).toFixed(1)}%\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"sectors\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>\n {translate('brainyrich.investments.sections.sectorAllocation', 'Sector Allocation')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.investments.sections.sectorAllocationDescription',\n 'How your investments are distributed across sectors'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {sectorBreakdown.map((s) => (\n <div key={s.sector} className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium\">{s.sector}</span>\n <span>\n {formatMoney(s.value)} ({s.pct}%)\n </span>\n </div>\n <div className=\"h-3 rounded bg-muted overflow-hidden\">\n <div className=\"h-3 rounded bg-primary\" style={{ width: `${s.pct}%` }} />\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"history\">\n <Card>\n <CardHeader>\n <CardTitle>\n {translate('brainyrich.investments.sections.tradeHistory', 'Trade History')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.investments.sections.tradeHistoryDescription',\n 'Your recent trading activity'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>\n {translate('brainyrich.investments.history.date', 'Date')}\n </TableHead>\n <TableHead>\n {translate('brainyrich.investments.history.symbol', 'Symbol')}\n </TableHead>\n <TableHead>\n {translate('brainyrich.investments.history.type', 'Type')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.history.qty', 'Qty')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.history.price', 'Price')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.investments.history.total', 'Total')}\n </TableHead>\n <TableHead>\n {translate('brainyrich.investments.history.status', 'Status')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {tradeHistory.map((t) => (\n <TableRow key={t.id}>\n <TableCell className=\"text-sm\">{t.date}</TableCell>\n <TableCell className=\"font-semibold\">{t.symbol}</TableCell>\n <TableCell>\n <Badge variant={t.type === 'BUY' ? 'default' : 'destructive'}>\n {t.type}\n </Badge>\n </TableCell>\n <TableCell className=\"text-right\">{t.qty}</TableCell>\n <TableCell className=\"text-right\">${t.price.toLocaleString()}</TableCell>\n <TableCell className=\"text-right\">{formatMoney(t.qty * t.price)}</TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{t.status}</Badge>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </SectionShell>\n );\n}\n"],"mappings":";;;;;;;;;AAkCA,IAAM,IAAe;CACnB;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,MAAM;EACN,KAAK;EACL,OAAO;EACP,QAAQ;EACT;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,MAAM;EACN,KAAK;EACL,OAAO;EACP,QAAQ;EACT;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,MAAM;EACN,KAAK;EACL,OAAO;EACP,QAAQ;EACT;CACF,EAEK,IAAkB;CACtB;EAAE,QAAQ;EAAc,OAAO;EAAQ,KAAK;EAAM;CAClD;EAAE,QAAQ;EAAe,OAAO;EAAQ,KAAK;EAAM;CACnD;EAAE,QAAQ;EAAa,OAAO;EAAO,KAAK;EAAM;CACjD;AAED,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,GAAS,EACjB,CAAC,GAAK,KAAU,EAAS,WAAW,EACpC,EAAE,aAAU,kBAAe,GAAoB,EAC/C,KAAa,GAAa,GAAkB,MAChD,EAAc,GAAG,GAAK,GAAU,EAAO,EACnC,IAAgB,EAAS,QAAQ,GAAG,MAAM,IAAI,EAAE,aAAa,EAAE,EAC/D,IAAsB,EAAW,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE;AAEvE,QACE,kBAAC,GAAD;EACE,OAAO,EAAU,gCAAgC,uBAAuB;EACxE,aAAa,EACX,sCACA,uDACD;EACD,aAAa,EAAU,2CAA2C,YAAY;EAC9E,QAAQ,CACN,EAAU,+CAA+C,oBAAoB,EAC3E,OAAO,EAAS,QACjB,CAAC,CACH;YAXH,CAaE,kBAAC,GAAD,EACE,OAAO;GACL;IACE,OAAO,EAAU,gDAAgD,iBAAiB;IAClF,OAAO,EAAY,EAAc;IACjC,OAAO,EACL,qDACA,sBACD;IACF;GACD;IACE,OAAO,EAAU,4CAA4C,aAAa;IAC1E,OAAO;IACP,OAAO;IACR;GACD;IACE,OAAO,EAAU,gDAAgD,iBAAiB;IAClF,OAAO,OAAO,EAAS,OAAO;IAC/B;GACD;IACE,OAAO,EAAU,gDAAgD,kBAAkB;IACnF,OAAO;IACP,OAAO,EACL,qDACA,kBACD;IACF;GACF,EACD,CAAA,EAEF,kBAAC,GAAD;GAAM,OAAO;GAAK,eAAe;GAAQ,WAAU;aAAnD;IACE,kBAAC,GAAD;KAAU,WAAU;eAApB;MACE,kBAAC,GAAD;OAAa,OAAM;iBAChB,EAAU,wCAAwC,WAAW;OAClD,CAAA;MACd,kBAAC,GAAD;OAAa,OAAM;iBAChB,EAAU,wCAAwC,WAAW;OAClD,CAAA;MACd,kBAAC,GAAD;OAAa,OAAM;iBAChB,EAAU,uCAAuC,kBAAkB;OACxD,CAAA;MACd,kBAAC,GAAD;OAAa,OAAM;iBAChB,EAAU,uCAAuC,gBAAgB;OACtD,CAAA;MACL;;IAEX,kBAAC,GAAD;KAAa,OAAM;KAAW,WAAU;eAAxC,CACE,kBAAC,OAAD;MAAK,WAAU;gBACZ;OACC;QACE,MAAM;QACN,OAAO,EAAU,8CAA8C,cAAc;QAC7E,KAAK,EAAY,EAAoB;QACrC,OAAO;QACR;OACD;QACE,MAAM;QACN,OAAO,EAAU,gDAAgD,iBAAiB;QAClF,KAAK;QACL,OAAO;QACR;OACD;QACE,MAAM;QACN,OAAO,EAAU,4CAA4C,WAAW;QACxE,KAAK,OAAO,EAAS,OAAO;QAC5B,OAAO;QACR;OACD;QACE,MAAM;QACN,OAAO,EAAU,+CAA+C,cAAc;QAC9E,KAAK;QACL,OAAO;QACR;OACF,CAAC,KAAK,MACL,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAa,WAAU;iBAAvB,CACE,kBAAC,OAAD;QAAK,WAAW,kBAAkB,EAAI;kBACpC,kBAAC,EAAI,MAAL,EAAU,WAAU,WAAY,CAAA;QAC5B,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAiC,EAAI;QAAU,CAAA,EAC5D,kBAAC,KAAD;QAAG,WAAU;kBAAqB,EAAI;QAAQ,CAAA,CAC1C,EAAA,CAAA,CACM;UACT,EAVI,EAAI,MAUR,CACP;MACE,CAAA,EAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,EAAU,+CAA+C,eAAe,EAC/D,CAAA,EACZ,kBAAC,GAAD,EAAA,UACG,EACC,0DACA,oCACD,EACe,CAAA,CACd,EAAA,CAAA,EACN,kBAAC,GAAD;OAAQ,SAAQ;OAAU,MAAK;OAAK,eAAe,EAAO,WAAW;iBAClE,EAAU,0CAA0C,WAAW;OACzD,CAAA,CACE;SACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAS,KAAK,MACb,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAE,OAAO,MAAM,GAAG,EAAE;SACjB,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBAAuB,EAAE;SAAW,CAAA,EACjD,kBAAC,KAAD;SAAG,WAAU;mBAAiC,EAAE;SAAS,CAAA,CACrD,EAAA,CAAA,CACF;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAU;mBAAuB,EAAY,EAAE,YAAY;SAAK,CAAA,EACnE,kBAAC,KAAD;SACE,WAAW,iDAAiD,EAAE,aAAa,IAAI,qBAAqB;mBADtG;UAGG,EAAE,aAAa,IACd,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA,GAEpC,kBAAC,GAAD,EAAgB,WAAU,WAAY,CAAA;UAEvC,EAAE,aAAa,IAAI,MAAM;UACzB,EAAE;UAAU;UACX;WACA;UACF;SA1BC,EAAE,OA0BH,CACN;MACU,CAAA,CACT,EAAA,CAAA,CACK;;IAEd,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD,EAAA,UACG,EAAU,+CAA+C,eAAe,EAC/D,CAAA,EACZ,kBAAC,GAAD;OAAQ,MAAK;iBAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAChC,EAAU,8CAA8C,eAAe,CACjE;SACE;SACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,GAAD,EAAA,UACG,EAAU,uCAAuC,SAAS,EACjD,CAAA;MACZ,kBAAC,GAAD,EAAA,UAAY,EAAU,qCAAqC,OAAO,EAAa,CAAA;MAC/E,kBAAC,GAAD,EAAA,UACG,EAAU,uCAAuC,SAAS,EACjD,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,4CAA4C,eAAe;OAC5D,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,0CAA0C,WAAW;OACtD,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,2CAA2C,aAAa;OACzD,CAAA;MACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAS,KAAK,MACb,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,GAAD;OAAW,WAAU;iBAAiB,EAAE;OAAmB,CAAA;MAC3D,kBAAC,GAAD,EAAA,UAAY,EAAE,MAAiB,CAAA;MAC/B,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAO,SAAQ;iBAAW,EAAE;OAAe,CAAA,EACjC,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAAc,EAAY,EAAE,YAAY;OAAa,CAAA;MAC1E,kBAAC,GAAD;OACE,WAAW,cAAc,EAAE,aAAa,IAAI,qBAAqB;iBADnE;QAGG,EAAE,aAAa,IAAI,MAAM;QACzB,EAAE;QAAU;QACH;;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAArB,EACK,EAAE,cAAc,IAAiB,KAAK,QAAQ,EAAE,EAAC,IAC1C;;MACH,EAAA,EAhBI,EAAE,OAgBN,CACX,EACQ,CAAA,CACN,EAAA,CAAA,EACI,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IAEd,kBAAC,GAAD;KAAa,OAAM;KAAU,WAAU;eACrC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,EAAU,oDAAoD,oBAAoB,EACzE,CAAA,EACZ,kBAAC,GAAD,EAAA,UACG,EACC,+DACA,sDACD,EACe,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAgB,KAAK,MACpB,kBAAC,OAAD;OAAoB,WAAU;iBAA9B,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAE;SAAc,CAAA,EAC/C,kBAAC,QAAD,EAAA,UAAA;SACG,EAAY,EAAE,MAAM;SAAC;SAAG,EAAE;SAAI;SAC1B,EAAA,CAAA,CACH;WACN,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,OAAD;SAAK,WAAU;SAAyB,OAAO,EAAE,OAAO,GAAG,EAAE,IAAI,IAAI;SAAI,CAAA;QACrE,CAAA,CACF;SAVI,EAAE,OAUN,CACN;MACU,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IAEd,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,EAAU,gDAAgD,gBAAgB,EACjE,CAAA,EACZ,kBAAC,GAAD,EAAA,UACG,EACC,2DACA,+BACD,EACe,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,GAAD,EAAA,UACG,EAAU,uCAAuC,OAAO,EAC/C,CAAA;MACZ,kBAAC,GAAD,EAAA,UACG,EAAU,yCAAyC,SAAS,EACnD,CAAA;MACZ,kBAAC,GAAD,EAAA,UACG,EAAU,uCAAuC,OAAO,EAC/C,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,sCAAsC,MAAM;OAC7C,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,wCAAwC,QAAQ;OACjD,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,wCAAwC,QAAQ;OACjD,CAAA;MACZ,kBAAC,GAAD,EAAA,UACG,EAAU,yCAAyC,SAAS,EACnD,CAAA;MACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAa,KAAK,MACjB,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,GAAD;OAAW,WAAU;iBAAW,EAAE;OAAiB,CAAA;MACnD,kBAAC,GAAD;OAAW,WAAU;iBAAiB,EAAE;OAAmB,CAAA;MAC3D,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAO,SAAS,EAAE,SAAS,QAAQ,YAAY;iBAC5C,EAAE;OACG,CAAA,EACE,CAAA;MACZ,kBAAC,GAAD;OAAW,WAAU;iBAAc,EAAE;OAAgB,CAAA;MACrD,kBAAC,GAAD;OAAW,WAAU;iBAArB,CAAkC,KAAE,EAAE,MAAM,gBAAgB,CAAa;;MACzE,kBAAC,GAAD;OAAW,WAAU;iBAAc,EAAY,EAAE,MAAM,EAAE,MAAM;OAAa,CAAA;MAC5E,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAO,SAAQ;iBAAa,EAAE;OAAe,CAAA,EACnC,CAAA;MACH,EAAA,EAdI,EAAE,GAcN,CACX,EACQ,CAAA,CACN,EAAA,CAAA,EACI,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IACT;KACM"}
|
|
1
|
+
{"version":3,"file":"InvestmentsPage.js","names":[],"sources":["../../../src/brainyrich/pages/InvestmentsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Badge,\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PieChart, Plus, Trash2, X } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useModelPortfolios,\n useModelPortfolio,\n useCreateModelPortfolio,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAssetClass,\n BraRiskProfile,\n BraModelAllocationInput,\n} from '../types/bra';\nimport {\n SectionShell,\n KpiGrid,\n AllocationBars,\n EmptyState,\n LoadingState,\n ErrorState,\n formatDate,\n statusBadgeVariant,\n type AllocationDatum,\n} from './_shared';\n\n// ----------------------------------------------------------------------------\n// Enum option sets (mirror the SDL enums in ../types/bra) + humanizers.\n// No fabricated data: these are the exact allowed input values.\n// ----------------------------------------------------------------------------\n\nconst RISK_PROFILES: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\n\nconst ASSET_CLASSES: BraAssetClass[] = [\n 'EQUITY',\n 'FIXED_INCOME',\n 'CASH',\n 'REAL_ESTATE',\n 'COMMODITY',\n 'CRYPTO',\n 'ALTERNATIVE',\n];\n\n/** Turn an UPPER_SNAKE enum member into a readable label (derived, not invented). */\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nconst ALLOCATION_TONES: AllocationDatum['tone'][] = [\n 'accent',\n 'default',\n 'positive',\n 'warning',\n 'negative',\n];\n\ninterface AllocationRow {\n assetClass: BraAssetClass;\n targetPct: string;\n}\n\nconst emptyRow = (): AllocationRow => ({ assetClass: 'EQUITY', targetPct: '' });\n\nexport function InvestmentsPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const { data: models, isLoading, isError, refetch } = useModelPortfolios();\n const createModel = useCreateModelPortfolio();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n // -------- Create form state --------\n const [name, setName] = useState('');\n const [riskProfile, setRiskProfile] = useState<BraRiskProfile>('BALANCED');\n const [baseCurrency, setBaseCurrency] = useState('USD');\n const [description, setDescription] = useState('');\n const [rows, setRows] = useState<AllocationRow[]>([emptyRow()]);\n const [formError, setFormError] = useState<string | null>(null);\n\n const resetForm = () => {\n setName('');\n setRiskProfile('BALANCED');\n setBaseCurrency('USD');\n setDescription('');\n setRows([emptyRow()]);\n setFormError(null);\n };\n\n const allocationSum = useMemo(\n () => rows.reduce((s, r) => s + (Number.isFinite(parseFloat(r.targetPct)) ? parseFloat(r.targetPct) : 0), 0),\n [rows]\n );\n\n const updateRow = (index: number, patch: Partial<AllocationRow>) => {\n setRows((prev) => prev.map((r, i) => (i === index ? { ...r, ...patch } : r)));\n };\n const addRow = () => setRows((prev) => [...prev, emptyRow()]);\n const removeRow = (index: number) =>\n setRows((prev) => (prev.length > 1 ? prev.filter((_, i) => i !== index) : prev));\n\n const handleSubmit = () => {\n setFormError(null);\n const trimmedName = name.trim();\n if (!trimmedName) {\n setFormError(translate('brainyrich.investments.form.errorName', 'A model name is required.'));\n return;\n }\n const allocations: BraModelAllocationInput[] = [];\n for (const r of rows) {\n const pct = parseFloat(r.targetPct);\n if (!r.targetPct.trim() || !Number.isFinite(pct)) {\n setFormError(\n translate(\n 'brainyrich.investments.form.errorPct',\n 'Every allocation row needs a numeric target %.'\n )\n );\n return;\n }\n if (pct < 0) {\n setFormError(\n translate('brainyrich.investments.form.errorNegative', 'Target % cannot be negative.')\n );\n return;\n }\n allocations.push({ assetClass: r.assetClass, targetPct: pct });\n }\n if (Math.abs(allocationSum - 100) > 0.5) {\n setFormError(\n translate('brainyrich.investments.form.errorSum', 'Allocation targets must sum to ~100% (currently {sum}%).', {\n sum: allocationSum.toFixed(1),\n })\n );\n return;\n }\n\n createModel.mutate(\n {\n name: trimmedName,\n riskProfile,\n baseCurrency: baseCurrency.trim() || 'USD',\n description: description.trim() ? description.trim() : null,\n allocations,\n },\n {\n onSuccess: () => {\n setCreateOpen(false);\n resetForm();\n },\n onError: (err: unknown) => {\n setFormError(\n err instanceof Error\n ? err.message\n : translate('brainyrich.investments.form.errorGeneric', 'Could not create the model.')\n );\n },\n }\n );\n };\n\n const title = translate('brainyrich.investments.title', 'Model Portfolios');\n const description2 = translate(\n 'brainyrich.investments.description',\n 'Reusable target allocations you can benchmark and drive rebalancing against'\n );\n\n const activeCount = models.filter((m) => m.isActive).length;\n const riskCount = new Set(models.map((m) => m.riskProfile)).size;\n const classCount = new Set(models.flatMap((m) => m.allocations.map((a) => a.assetClass))).size;\n const kpis = [\n {\n label: translate('brainyrich.investments.kpi.total', 'Model portfolios'),\n value: String(models.length),\n },\n {\n label: translate('brainyrich.investments.kpi.active', 'Active'),\n value: String(activeCount),\n },\n {\n label: translate('brainyrich.investments.kpi.risk', 'Risk profiles'),\n value: String(riskCount),\n },\n {\n label: translate('brainyrich.investments.kpi.classes', 'Asset classes'),\n value: String(classCount),\n },\n ];\n\n const newModelLabel = translate('brainyrich.investments.actions.newModel', 'New model');\n\n const renderBody = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.investments.error.title', 'Could not load model portfolios')}\n onRetry={() => refetch()}\n />\n );\n if (models.length === 0)\n return (\n <EmptyState\n icon={<PieChart className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.empty.title', 'No model portfolios yet')}\n description={translate(\n 'brainyrich.investments.empty.description',\n 'Create a target allocation model to benchmark portfolios and drive rebalancing.'\n )}\n action={\n <Button size=\"sm\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {newModelLabel}\n </Button>\n }\n />\n );\n\n return (\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {models.map((m) => {\n const bars: AllocationDatum[] = m.allocations.map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n return (\n <Card key={m.id} className=\"flex flex-col\">\n <CardHeader className=\"space-y-2\">\n <div className=\"flex items-start justify-between gap-2\">\n <CardTitle className=\"text-base text-text-primary\">{m.name}</CardTitle>\n <Badge variant={m.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {m.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(m.riskProfile)}</Badge>\n <Badge variant=\"outline\">{m.baseCurrency}</Badge>\n </div>\n {m.description ? (\n <CardDescription className=\"text-text-secondary\">{m.description}</CardDescription>\n ) : null}\n </CardHeader>\n <CardContent className=\"mt-auto space-y-4\">\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate('brainyrich.investments.card.noAllocations', 'No target allocations set.')}\n </p>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(m.id)}\n >\n {translate('brainyrich.investments.actions.viewDetails', 'View details')}\n </Button>\n </CardContent>\n </Card>\n );\n })}\n </div>\n );\n };\n\n return (\n <>\n <SectionShell\n title={title}\n description={description2}\n actionLabel={newModelLabel}\n onAction={() => setCreateOpen(true)}\n badges={\n !isLoading && !isError\n ? [\n translate('brainyrich.investments.badges.count', '{count} models', {\n count: models.length,\n }),\n ]\n : []\n }\n >\n {!isLoading && !isError && models.length > 0 ? <KpiGrid items={kpis} /> : null}\n {renderBody()}\n </SectionShell>\n\n {/* ---------------- Create model dialog ---------------- */}\n <Dialog\n open={createOpen}\n onOpenChange={(open) => {\n setCreateOpen(open);\n if (!open) resetForm();\n }}\n >\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>{newModelLabel}</DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.investments.form.subtitle',\n 'Define a target allocation. Targets should sum to about 100%.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-name\">\n {translate('brainyrich.investments.form.name', 'Name')}\n </Label>\n <Input\n id=\"bra-model-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate('brainyrich.investments.form.namePlaceholder', 'Balanced Growth 60/40')}\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-risk\">\n {translate('brainyrich.investments.form.risk', 'Risk profile')}\n </Label>\n <Select\n value={riskProfile}\n onValueChange={(v) => setRiskProfile(v as BraRiskProfile)}\n >\n <SelectTrigger id=\"bra-model-risk\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_PROFILES.map((r) => (\n <SelectItem key={r} value={r}>\n {humanize(r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-currency\">\n {translate('brainyrich.investments.form.currency', 'Base currency')}\n </Label>\n <Input\n id=\"bra-model-currency\"\n value={baseCurrency}\n onChange={(e) => setBaseCurrency(e.target.value.toUpperCase().slice(0, 3))}\n placeholder=\"USD\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-desc\">\n {translate('brainyrich.investments.form.description', 'Description')}\n </Label>\n <Textarea\n id=\"bra-model-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n placeholder={translate(\n 'brainyrich.investments.form.descriptionPlaceholder',\n 'Who this model is for and how it is used'\n )}\n />\n </div>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <Label>{translate('brainyrich.investments.form.allocations', 'Target allocations')}</Label>\n <span\n className={\n Math.abs(allocationSum - 100) <= 0.5\n ? 'text-xs font-medium text-status-success-text'\n : 'text-xs font-medium text-status-warning-text'\n }\n >\n {translate('brainyrich.investments.form.sum', 'Sum: {sum}%', {\n sum: allocationSum.toFixed(1),\n })}\n </span>\n </div>\n <div className=\"space-y-2\">\n {rows.map((r, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <Select\n value={r.assetClass}\n onValueChange={(v) => updateRow(i, { assetClass: v as BraAssetClass })}\n >\n <SelectTrigger className=\"flex-1\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ASSET_CLASSES.map((c) => (\n <SelectItem key={c} value={c}>\n {humanize(c)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Input\n type=\"number\"\n inputMode=\"decimal\"\n min={0}\n max={100}\n step=\"0.1\"\n className=\"w-24\"\n value={r.targetPct}\n onChange={(e) => updateRow(i, { targetPct: e.target.value })}\n placeholder=\"%\"\n aria-label={translate('brainyrich.investments.form.targetPct', 'Target percent')}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= 1}\n aria-label={translate('brainyrich.investments.form.removeRow', 'Remove allocation row')}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n ))}\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addRow}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.investments.form.addRow', 'Add asset class')}\n </Button>\n </div>\n\n {formError ? (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {formError}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setCreateOpen(false);\n resetForm();\n }}\n disabled={createModel.isPending}\n >\n {translate('brainyrich.investments.form.cancel', 'Cancel')}\n </Button>\n <Button onClick={handleSubmit} disabled={createModel.isPending}>\n {createModel.isPending\n ? translate('brainyrich.investments.form.saving', 'Creating…')\n : translate('brainyrich.investments.form.create', 'Create model')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* ---------------- Detail dialog ---------------- */}\n <ModelDetailDialog\n id={detailId}\n onClose={() => setDetailId(null)}\n translate={translate}\n />\n </>\n );\n}\n\n// ----------------------------------------------------------------------------\n// Detail dialog — reads the single model via useModelPortfolio(id).\n// ----------------------------------------------------------------------------\n\nfunction ModelDetailDialog({\n id,\n onClose,\n translate,\n}: {\n id: string | null;\n onClose: () => void;\n translate: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}) {\n const { data: model, isLoading, isError, refetch } = useModelPortfolio(id ?? undefined);\n\n const bars: AllocationDatum[] = (model?.allocations ?? []).map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n\n return (\n <Dialog open={Boolean(id)} onOpenChange={(open) => (!open ? onClose() : undefined)}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center justify-between gap-2 pr-6\">\n {model?.name ??\n translate('brainyrich.investments.detail.title', 'Model portfolio')}\n </DialogTitle>\n {model?.description ? (\n <DialogDescription>{model.description}</DialogDescription>\n ) : null}\n </DialogHeader>\n\n {isLoading ? (\n <LoadingState rows={3} />\n ) : isError ? (\n <ErrorState\n title={translate('brainyrich.investments.detail.error', 'Could not load this model')}\n onRetry={() => refetch()}\n />\n ) : !model ? (\n <EmptyState\n icon={<X className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.detail.notFound', 'Model not found')}\n />\n ) : (\n <div className=\"space-y-5 py-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={model.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {model.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n <Badge variant=\"outline\">{humanize(model.riskProfile)}</Badge>\n <Badge variant=\"outline\">{model.baseCurrency}</Badge>\n </div>\n\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">\n {translate('brainyrich.investments.detail.allocations', 'Target allocations')}\n </p>\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate('brainyrich.investments.card.noAllocations', 'No target allocations set.')}\n </p>\n )}\n </div>\n\n <dl className=\"grid grid-cols-2 gap-4 border-t border-border-subtle pt-4 text-sm\">\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.created', 'Created')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.createdAt)}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.updated', 'Updated')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.updatedAt)}</dd>\n </div>\n </dl>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>\n {translate('brainyrich.investments.detail.close', 'Close')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|