@mx-cartographer/experiences 9.4.19 → 9.4.21

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 (25) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/dist/core/types/AppData.d.ts +2 -0
  3. package/dist/core/utils/InvestmentUtil.d.ts +9 -0
  4. package/dist/core/utils/InvestmentUtil.es.js +68 -50
  5. package/dist/core/utils/InvestmentUtil.es.js.map +1 -1
  6. package/dist/investments/components/HoldingDrawer.d.ts +3 -0
  7. package/dist/investments/components/HoldingDrawer.es.js +33 -29
  8. package/dist/investments/components/HoldingDrawer.es.js.map +1 -1
  9. package/dist/investments/components/HoldingTable.d.ts +3 -0
  10. package/dist/investments/components/HoldingTable.es.js +37 -33
  11. package/dist/investments/components/HoldingTable.es.js.map +1 -1
  12. package/dist/investments/components/Overview.es.js +163 -134
  13. package/dist/investments/components/Overview.es.js.map +1 -1
  14. package/dist/investments/components/allocation/InvestmentsAllocationChart.d.ts +1 -0
  15. package/dist/investments/components/allocation/InvestmentsAllocationChart.es.js +16 -16
  16. package/dist/investments/components/allocation/InvestmentsAllocationChart.es.js.map +1 -1
  17. package/dist/investments/components/allocation/util/createInvestementsAllocationData.d.ts +1 -0
  18. package/dist/investments/components/allocation/util/createInvestementsAllocationData.es.js +58 -54
  19. package/dist/investments/components/allocation/util/createInvestementsAllocationData.es.js.map +1 -1
  20. package/dist/rum/index.d.ts +1 -0
  21. package/dist/rum/index.es.js +7 -0
  22. package/dist/rum/rum.d.ts +13 -0
  23. package/dist/rum/rum.es.js +37 -0
  24. package/dist/rum/rum.es.js.map +1 -0
  25. package/package.json +15 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Overview.es.js","names":[],"sources":["../../../src/investments/components/Overview.tsx"],"sourcesContent":["import React, { useState } from 'react'\n\nimport { observer } from 'mobx-react-lite'\nimport Accordion from '@mui/material/Accordion'\nimport AccordionDetails from '@mui/material/AccordionDetails'\nimport AccordionSummary from '@mui/material/AccordionSummary'\nimport Paper from '@mui/material/Paper'\nimport Stack from '@mui/system/Stack'\nimport { useTheme } from '@mui/material/styles'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { InstitutionLogo, P, Text } from '@mxenabled/mxui'\n\nimport ConnectionsDrawer from '../../accounts/components/ConnectionsDrawer'\nimport {\n Loader,\n useAccountStore,\n useGlobalCopyStore,\n useGlobalUiStore,\n useHoldingStore,\n useScreenSize,\n} from '../../common'\nimport { EmptyStateFooterComponent } from './EmptyStateFooterComponent'\nimport InvestmentDetailsDrawer from './HoldingDrawer'\nimport HoldingsTable from './HoldingTable'\n\ninterface HoldingDetail {\n id: string\n description: string\n qty: number\n holding: string\n costBasis: number\n totalGainLoss: number\n marketValue: number\n}\n\nconst Overview = () => {\n const { isMobile } = useScreenSize()\n const [expandedStates, setExpandedStates] = useState<Record<string, boolean>>({})\n const [openDrawer, setOpenDrawer] = useState(false)\n const { selectedAccountGuids } = useGlobalUiStore()\n const { visibleHoldings: holdings, updateHoldings } = useHoldingStore()\n const [showConnectionsWidget, setShowConnectionsWidget] = React.useState(false)\n\n const [accountHoldingsData, setAccountHoldingsData] = useState<{\n accounts: any\n holdings: HoldingDetail[]\n }>({\n accounts: [],\n holdings: [],\n })\n const { accounts: accountsCopy, investments: copy } = useGlobalCopyStore()\n const { isCopyLoaded } = useGlobalUiStore()\n const [editingHoldingId, setEditingHoldingId] = useState<string | null>(null)\n const [currentEditedCostBasis, setCurrentEditedCostBasis] = useState<string>('')\n\n const theme = useTheme()\n\n const isDarkMode = theme.palette.mode === 'dark'\n\n const gainDisplayColor = isDarkMode ? '#0AC295' : '#09A57F'\n\n const lossDisplayColor = isDarkMode ? 'grey.300' : 'grey.700'\n\n const gainLossDisplayColor = (value: number, type: string = 'lesserThan') => {\n if (type === 'greaterThan') {\n return value >= 0 ? gainDisplayColor : lossDisplayColor\n }\n return value <= 0 ? lossDisplayColor : gainDisplayColor\n }\n\n const handleCostBasisClick = (holdingId: string, currentCostBasis: number) => {\n setEditingHoldingId(holdingId)\n setCurrentEditedCostBasis(currentCostBasis.toFixed(2))\n }\n\n const handleCostBasisChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Allow only numbers and a single decimal point\n const value = event.target.value\n if (/^\\d*\\.?\\d*$/.test(value)) {\n setCurrentEditedCostBasis(value)\n }\n }\n\n const handleCostBasisKeyDown = (event: React.KeyboardEvent<HTMLInputElement>, id: string) => {\n if (event.key === 'Enter') {\n handleCostBasisBlur(id)\n } else if (event.key === 'Escape') {\n setEditingHoldingId(null)\n }\n }\n\n const handleCostBasisBlur = (id: string) => {\n const holding = holdings.find(({ guid }) => guid === id)\n if (!holding) return\n\n const updatedCostBasis = Number(currentEditedCostBasis)\n updateHoldings({ ...holding, cost_basis: updatedCostBasis })\n\n if (isMobile) {\n const updatedHoldings = accountHoldingsData.holdings.map((h) =>\n h.id === id ? { ...h, costBasis: updatedCostBasis } : h,\n )\n\n setAccountHoldingsData((prev) => ({\n ...prev,\n holdings: updatedHoldings,\n }))\n }\n\n setEditingHoldingId(null)\n }\n\n const handleAccordionChange =\n (accountId: string) => (_event: React.SyntheticEvent, isExpanded: boolean) => {\n setExpandedStates((prevStates) => ({\n ...prevStates,\n [accountId]: isExpanded,\n }))\n }\n\n const { visibleHoldings: allHoldings } = useHoldingStore()\n const { visibleInvestmentAccounts } = useAccountStore()\n\n const accounts = visibleInvestmentAccounts.filter(({ guid }) =>\n selectedAccountGuids.includes(guid),\n )\n\n const totalPortfolioValue = accounts.reduce((sum, account) => sum + (account.balance || 0), 0)\n\n const accountGuids = accounts.map(({ guid }) => guid)\n\n const updatedHoldings = allHoldings.filter(({ account_guid }) =>\n accountGuids.includes(account_guid),\n )\n\n const gainLoss = updatedHoldings.reduce((sum, holding) => {\n const hl = holding.market_value ? holding.market_value - (holding.cost_basis || 0) : 0\n return sum + hl\n }, 0)\n\n const closeDrawer = () => {\n setOpenDrawer(false)\n }\n\n if (!isCopyLoaded) {\n return <Loader />\n }\n\n return (\n <Stack sx={{ alignItems: 'center', gap: 48, pt: 48, width: '100%' }}>\n {/* header content */}\n {!!accounts.length && (\n <Stack sx={{ alignItems: 'center' }}>\n <Text sx={{ color: 'text.secondary' }}>{copy.overview.total_portfolio}</Text>\n <P variant=\"h1\">\n {totalPortfolioValue.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </P>\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n <Icon\n name={gainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(gainLoss, 'greaterThan') }}\n />\n <Text\n sx={{ color: gainLossDisplayColor(gainLoss, 'greaterThan'), fontWeight: 700 }}\n variant=\"body2\"\n >\n {gainLoss.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n )}\n\n {accounts.map((account) => {\n const accountHoldings: HoldingDetail[] = allHoldings\n .filter((holding) => holding.account_guid === account.guid)\n .map((holding) => ({\n id: holding.guid,\n qty: holding.shares || 0,\n holding: holding.symbol || holding.description || 'Unknown',\n costBasis: holding.cost_basis || 0,\n totalGainLoss: holding.market_value\n ? holding.market_value - (holding.cost_basis || 0)\n : 0,\n marketValue: holding.market_value || 0,\n description: holding.description || '',\n }))\n\n const hasHoldingsData = accountHoldings.length > 0\n\n const accountTotalValue = account.balance\n const accountGainLoss = accountHoldings.reduce(\n (sum, holding) => holding.totalGainLoss + sum,\n 0,\n )\n\n const accountGainLossPercentage = accountTotalValue\n ? (accountGainLoss / accountTotalValue) * 100\n : 0\n\n // Mobile View: Use a simplified presentation\n if (isMobile) {\n return (\n <Paper\n key={account.guid}\n onClick={\n accountHoldings.length\n ? () => {\n setOpenDrawer(true)\n setAccountHoldingsData({\n holdings: accountHoldings,\n accounts: account,\n })\n }\n : undefined\n }\n sx={{\n width: '100%',\n overflow: 'hidden',\n }}\n >\n <Stack\n sx={{\n border: 1,\n borderColor: 'divider',\n borderRadius: '8px',\n ml: 16,\n mr: 16,\n overflow: 'hidden',\n pt: 14,\n }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n borderBottom: 1,\n borderColor: 'divider',\n flexDirection: 'row',\n pb: 14,\n pl: 14,\n pr: 14,\n }}\n >\n <InstitutionLogo\n alt={account.institutionName || ''}\n institutionGuid={account.institution_guid || ''}\n size={32}\n />\n <Stack sx={{ overflow: 'hidden', pl: 13, pr: 13 }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {account.memberName}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {account.user_name || account.name}\n </Text>\n </Stack>\n </Stack>\n\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n justifyContent: 'space-between',\n pb: 8,\n pt: 8,\n }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n borderRight: 1,\n borderColor: 'divider',\n flex: 1,\n justifyContent: 'center',\n pb: 14,\n pl: 7,\n pr: 7,\n pt: 14,\n }}\n >\n <Text sx={{ color: 'text.secondary', fontSize: 11 }} variant=\"body2\">\n {copy.overview.total_gain_Loss}\n </Text>\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 2,\n justifyContent: 'flex-end',\n }}\n >\n {accountGainLoss !== 0 && (\n <Icon\n name={accountGainLoss > 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(accountGainLoss) }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {accountGainLossPercentage.toFixed(2)}%\n </Text>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n |\n </Text>\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {Math.abs(accountGainLoss).toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n\n <Stack\n sx={{\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n pb: 14,\n pl: 7,\n pr: 7,\n pt: 14,\n }}\n >\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_value}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {accountTotalValue?.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </Paper>\n )\n }\n\n const disabledColor = isDarkMode ? 'grey.700' : 'grey.400'\n const logoColor = accountHoldings.length ? 'text.primary' : disabledColor\n\n return (\n <Accordion\n expanded={expandedStates[account.guid] === true}\n key={account.guid}\n onChange={hasHoldingsData ? handleAccordionChange(account.guid) : () => {}}\n sx={{\n border: 1,\n borderColor: 'divider',\n borderRadius: '4px',\n width: '100%',\n }}\n >\n <AccordionSummary\n aria-controls=\"panel1a-content\"\n id=\"panel1a-header\"\n sx={[\n expandedStates[account.guid] && {\n borderBottom: 1,\n borderColor: 'divider',\n maxHeight: 88,\n },\n ]}\n >\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 13,\n p: 14,\n width: '100%',\n }}\n >\n <Icon name={'expand_more'} size={20} sx={{ color: logoColor }} />\n <InstitutionLogo\n alt={account.institutionName || ''}\n institutionGuid={account.institution_guid || ''}\n size={32}\n />\n\n <Stack sx={{ alignItems: 'flex-start' }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {account.memberName}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {account.user_name || account.name}\n </Text>\n </Stack>\n </Stack>\n\n <Stack sx={{ flexDirection: 'row' }}>\n <Stack sx={{ alignItems: 'flex-end', pb: 14, pl: 24, pr: 24, pt: 14 }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_gain_Loss}\n </Text>\n\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 2,\n justifyContent: 'flex-end',\n }}\n >\n {accountGainLoss !== 0 && (\n <Icon\n name={accountGainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(accountGainLoss) }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {accountGainLossPercentage.toFixed(2)}%\n </Text>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n |\n </Text>\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {Math.abs(accountGainLoss).toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n\n <Stack sx={{ alignItems: 'flex-end', gap: 12, pb: 14, pl: 16, pr: 16, pt: 14 }}>\n <Stack sx={{ alignItems: 'flex-end' }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_value}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {accountTotalValue?.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </AccordionSummary>\n <AccordionDetails sx={{ bgcolor: 'background.default', p: 12 }}>\n <Paper sx={{ border: 1, borderColor: 'neutral.light' }}>\n <HoldingsTable\n currentEditedCostBasis={currentEditedCostBasis}\n data={accountHoldings}\n editingHoldingId={editingHoldingId}\n handleCostBasisBlur={handleCostBasisBlur}\n handleCostBasisChange={handleCostBasisChange}\n handleCostBasisClick={handleCostBasisClick}\n handleCostBasisKeyDown={handleCostBasisKeyDown}\n />\n </Paper>\n </AccordionDetails>\n </Accordion>\n )\n })}\n\n {/* footer content */}\n <EmptyStateFooterComponent />\n\n {/* Drawer Component */}\n <InvestmentDetailsDrawer\n accountHoldingsData={accountHoldingsData}\n currentEditedCostBasis={currentEditedCostBasis}\n editingHoldingId={editingHoldingId}\n handleCostBasisBlur={handleCostBasisBlur}\n handleCostBasisChange={handleCostBasisChange}\n handleCostBasisClick={handleCostBasisClick}\n handleCostBasisKeyDown={handleCostBasisKeyDown}\n isOpen={openDrawer}\n onClose={closeDrawer}\n />\n\n <ConnectionsDrawer\n onClose={() => setShowConnectionsWidget(false)}\n showConnectionsWidget={showConnectionsWidget}\n title={accountsCopy.manage_connections}\n />\n </Stack>\n )\n}\n\nexport default observer(Overview)\n"],"mappings":"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"}
1
+ {"version":3,"file":"Overview.es.js","names":[],"sources":["../../../src/investments/components/Overview.tsx"],"sourcesContent":["import React, { useState } from 'react'\n\nimport { observer } from 'mobx-react-lite'\nimport Accordion from '@mui/material/Accordion'\nimport AccordionDetails from '@mui/material/AccordionDetails'\nimport AccordionSummary from '@mui/material/AccordionSummary'\nimport Paper from '@mui/material/Paper'\nimport Stack from '@mui/system/Stack'\nimport { useTheme } from '@mui/material/styles'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { InstitutionLogo, P, Text } from '@mxenabled/mxui'\n\nimport { getHoldingGainLoss, getHoldingMarketValue } from '../../core/utils/InvestmentUtil'\nimport ConnectionsDrawer from '../../accounts/components/ConnectionsDrawer'\nimport {\n Loader,\n useAccountStore,\n useGlobalCopyStore,\n useGlobalUiStore,\n useHoldingStore,\n useScreenSize,\n} from '../../common'\nimport { EmptyStateFooterComponent } from './EmptyStateFooterComponent'\nimport InvestmentDetailsDrawer from './HoldingDrawer'\nimport HoldingsTable from './HoldingTable'\n\ninterface HoldingDetail {\n id: string\n description: string\n qty: number\n holding: string\n costBasis: number\n rawCostBasis: number\n totalGainLoss: number\n gainLossAvailable: boolean\n gainLossBasis: number\n marketValue: number\n}\n\nconst Overview = () => {\n const { isMobile } = useScreenSize()\n const [expandedStates, setExpandedStates] = useState<Record<string, boolean>>({})\n const [openDrawer, setOpenDrawer] = useState(false)\n const { selectedAccountGuids } = useGlobalUiStore()\n const { visibleHoldings: holdings, updateHoldings } = useHoldingStore()\n const [showConnectionsWidget, setShowConnectionsWidget] = React.useState(false)\n\n const [accountHoldingsData, setAccountHoldingsData] = useState<{\n accounts: any\n holdings: HoldingDetail[]\n }>({\n accounts: [],\n holdings: [],\n })\n const { accounts: accountsCopy, investments: copy } = useGlobalCopyStore()\n const { isCopyLoaded } = useGlobalUiStore()\n const [editingHoldingId, setEditingHoldingId] = useState<string | null>(null)\n const [currentEditedCostBasis, setCurrentEditedCostBasis] = useState<string>('')\n\n const theme = useTheme()\n\n const isDarkMode = theme.palette.mode === 'dark'\n\n const gainDisplayColor = isDarkMode ? '#0AC295' : '#09A57F'\n\n const lossDisplayColor = isDarkMode ? 'grey.300' : 'grey.700'\n\n const gainLossDisplayColor = (value: number, type: string = 'lesserThan') => {\n if (type === 'greaterThan') {\n return value >= 0 ? gainDisplayColor : lossDisplayColor\n }\n return value <= 0 ? lossDisplayColor : gainDisplayColor\n }\n\n const handleCostBasisClick = (holdingId: string, currentCostBasis: number) => {\n setEditingHoldingId(holdingId)\n setCurrentEditedCostBasis(currentCostBasis.toFixed(2))\n }\n\n const handleCostBasisChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Allow only numbers and a single decimal point\n const value = event.target.value\n if (/^\\d*\\.?\\d*$/.test(value)) {\n setCurrentEditedCostBasis(value)\n }\n }\n\n const handleCostBasisKeyDown = (event: React.KeyboardEvent<HTMLInputElement>, id: string) => {\n if (event.key === 'Enter') {\n handleCostBasisBlur(id)\n } else if (event.key === 'Escape') {\n setEditingHoldingId(null)\n }\n }\n\n const handleCostBasisBlur = (id: string) => {\n const holding = holdings.find(({ guid }) => guid === id)\n if (!holding) return\n\n const updatedCostBasis = Number(currentEditedCostBasis)\n updateHoldings({ ...holding, cost_basis: updatedCostBasis })\n\n if (isMobile) {\n const updatedHoldings = accountHoldingsData.holdings.map((h) =>\n h.id === id\n ? {\n ...h,\n costBasis: updatedCostBasis,\n rawCostBasis: updatedCostBasis,\n // Recompute gain/loss against the new basis so the drawer's %/$\n // stay consistent with the edited Cost Basis instead of going stale.\n gainLossBasis: updatedCostBasis,\n totalGainLoss: h.marketValue - updatedCostBasis,\n gainLossAvailable: true,\n }\n : h,\n )\n\n setAccountHoldingsData((prev) => ({\n ...prev,\n holdings: updatedHoldings,\n }))\n }\n\n setEditingHoldingId(null)\n }\n\n const handleAccordionChange =\n (accountId: string) => (_event: React.SyntheticEvent, isExpanded: boolean) => {\n setExpandedStates((prevStates) => ({\n ...prevStates,\n [accountId]: isExpanded,\n }))\n }\n\n const { visibleHoldings: allHoldings } = useHoldingStore()\n const { visibleInvestmentAccounts } = useAccountStore()\n\n const accounts = visibleInvestmentAccounts.filter(({ guid }) =>\n selectedAccountGuids.includes(guid),\n )\n\n const totalPortfolioValue = accounts.reduce((sum, account) => sum + (account.balance || 0), 0)\n\n const accountGuids = new Set(accounts.map(({ guid }) => guid))\n\n const updatedHoldings = allHoldings.filter(({ account_guid }) => accountGuids.has(account_guid))\n\n // Only holdings with a known cost basis contribute to the aggregate; holdings\n // whose basis is unknown are excluded rather than counted as 100% gain.\n const gainLoss = updatedHoldings.reduce((sum, holding) => {\n const { available, gainLoss: hl } = getHoldingGainLoss(holding)\n return available ? sum + hl : sum\n }, 0)\n\n // When no holding in the portfolio has a known basis, render \"—\" instead of a\n // fabricated $0.00 gain.\n const gainLossAvailable = updatedHoldings.some((holding) => getHoldingGainLoss(holding).available)\n\n const closeDrawer = () => {\n setOpenDrawer(false)\n }\n\n if (!isCopyLoaded) {\n return <Loader />\n }\n\n return (\n <Stack sx={{ alignItems: 'center', gap: 48, pt: 48, width: '100%' }}>\n {/* header content */}\n {!!accounts.length && (\n <Stack sx={{ alignItems: 'center' }}>\n <Text sx={{ color: 'text.secondary' }}>{copy.overview.total_portfolio}</Text>\n <P variant=\"h1\">\n {totalPortfolioValue.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </P>\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {!gainLossAvailable ? (\n <Text sx={{ color: 'text.secondary', fontWeight: 700 }} variant=\"body2\">\n —\n </Text>\n ) : (\n <>\n <Icon\n name={gainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(gainLoss, 'greaterThan') }}\n />\n <Text\n sx={{ color: gainLossDisplayColor(gainLoss, 'greaterThan'), fontWeight: 700 }}\n variant=\"body2\"\n >\n {gainLoss.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </>\n )}\n </Stack>\n </Stack>\n )}\n\n {accounts.map((account) => {\n const accountHoldings: HoldingDetail[] = allHoldings\n .filter((holding) => holding.account_guid === account.guid)\n .map((holding) => {\n // Option A: the effective basis (cost_basis, else purchase_price)\n // drives both the Cost Basis column and gain/loss, so the row\n // reconciles. `available` is false only when neither is known.\n const { available, basis, gainLoss } = getHoldingGainLoss(holding)\n return {\n id: holding.guid,\n qty: holding.shares || 0,\n holding: holding.symbol || holding.description || 'Unknown',\n costBasis: basis,\n // The true persisted cost_basis (0 when unset) seeds the editor, so\n // an unmodified edit never writes the purchase_price fallback back\n // to Abacus as a user-set cost_basis.\n rawCostBasis: holding.cost_basis || 0,\n totalGainLoss: gainLoss,\n gainLossAvailable: available,\n gainLossBasis: basis,\n marketValue: getHoldingMarketValue(holding),\n description: holding.description || '',\n }\n })\n\n const hasHoldingsData = accountHoldings.length > 0\n\n const accountTotalValue = account.balance\n const accountGainLoss = accountHoldings.reduce(\n (sum, holding) => holding.totalGainLoss + sum,\n 0,\n )\n\n // Mirror the per-holding rule at the account level: if no holding in the\n // account has a known cost basis, show \"—\" rather than a fabricated\n // $0.00 / 0.00% rollup.\n const accountGainLossAvailable = accountHoldings.some((h) => h.gainLossAvailable)\n\n const accountGainLossPercentage = accountTotalValue\n ? (accountGainLoss / accountTotalValue) * 100\n : 0\n\n // Mobile View: Use a simplified presentation\n if (isMobile) {\n return (\n <Paper\n key={account.guid}\n onClick={\n accountHoldings.length\n ? () => {\n setOpenDrawer(true)\n setAccountHoldingsData({\n holdings: accountHoldings,\n accounts: account,\n })\n }\n : undefined\n }\n sx={{\n width: '100%',\n overflow: 'hidden',\n }}\n >\n <Stack\n sx={{\n border: 1,\n borderColor: 'divider',\n borderRadius: '8px',\n ml: 16,\n mr: 16,\n overflow: 'hidden',\n pt: 14,\n }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n borderBottom: 1,\n borderColor: 'divider',\n flexDirection: 'row',\n pb: 14,\n pl: 14,\n pr: 14,\n }}\n >\n <InstitutionLogo\n alt={account.institutionName || ''}\n institutionGuid={account.institution_guid || ''}\n size={32}\n />\n <Stack sx={{ overflow: 'hidden', pl: 13, pr: 13 }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {account.memberName}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {account.user_name || account.name}\n </Text>\n </Stack>\n </Stack>\n\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n justifyContent: 'space-between',\n pb: 8,\n pt: 8,\n }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n borderRight: 1,\n borderColor: 'divider',\n flex: 1,\n justifyContent: 'center',\n pb: 14,\n pl: 7,\n pr: 7,\n pt: 14,\n }}\n >\n <Text sx={{ color: 'text.secondary', fontSize: 11 }} variant=\"body2\">\n {copy.overview.total_gain_Loss}\n </Text>\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 2,\n justifyContent: 'flex-end',\n }}\n >\n {!accountGainLossAvailable ? (\n <Text sx={{ color: 'text.secondary' }} variant=\"body1\">\n —\n </Text>\n ) : (\n <>\n {accountGainLoss !== 0 && (\n <Icon\n name={accountGainLoss > 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(accountGainLoss) }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {accountGainLossPercentage.toFixed(2)}%\n </Text>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n |\n </Text>\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {Math.abs(accountGainLoss).toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </>\n )}\n </Stack>\n </Stack>\n\n <Stack\n sx={{\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n pb: 14,\n pl: 7,\n pr: 7,\n pt: 14,\n }}\n >\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_value}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {accountTotalValue?.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </Paper>\n )\n }\n\n const disabledColor = isDarkMode ? 'grey.700' : 'grey.400'\n const logoColor = accountHoldings.length ? 'text.primary' : disabledColor\n\n return (\n <Accordion\n expanded={expandedStates[account.guid] === true}\n key={account.guid}\n onChange={hasHoldingsData ? handleAccordionChange(account.guid) : () => {}}\n sx={{\n border: 1,\n borderColor: 'divider',\n borderRadius: '4px',\n width: '100%',\n }}\n >\n <AccordionSummary\n aria-controls=\"panel1a-content\"\n id=\"panel1a-header\"\n sx={[\n expandedStates[account.guid] && {\n borderBottom: 1,\n borderColor: 'divider',\n maxHeight: 88,\n },\n ]}\n >\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 13,\n p: 14,\n width: '100%',\n }}\n >\n <Icon name={'expand_more'} size={20} sx={{ color: logoColor }} />\n <InstitutionLogo\n alt={account.institutionName || ''}\n institutionGuid={account.institution_guid || ''}\n size={32}\n />\n\n <Stack sx={{ alignItems: 'flex-start' }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {account.memberName}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {account.user_name || account.name}\n </Text>\n </Stack>\n </Stack>\n\n <Stack sx={{ flexDirection: 'row' }}>\n <Stack sx={{ alignItems: 'flex-end', pb: 14, pl: 24, pr: 24, pt: 14 }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_gain_Loss}\n </Text>\n\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 2,\n justifyContent: 'flex-end',\n }}\n >\n {!accountGainLossAvailable ? (\n <Text sx={{ color: 'text.secondary' }} variant=\"body1\">\n —\n </Text>\n ) : (\n <>\n {accountGainLoss !== 0 && (\n <Icon\n name={accountGainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor(accountGainLoss) }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {accountGainLossPercentage.toFixed(2)}%\n </Text>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n |\n </Text>\n <Text\n sx={{\n color: gainLossDisplayColor(accountGainLoss),\n fontWeight: 600,\n }}\n variant=\"body1\"\n >\n {Math.abs(accountGainLoss).toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </>\n )}\n </Stack>\n </Stack>\n\n <Stack sx={{ alignItems: 'flex-end', gap: 12, pb: 14, pl: 16, pr: 16, pt: 14 }}>\n <Stack sx={{ alignItems: 'flex-end' }}>\n <Text sx={{ color: 'text.secondary' }} variant=\"caption\">\n {copy.overview.total_value}\n </Text>\n <Text sx={{ color: 'text.primary', fontWeight: 600 }} variant=\"body1\">\n {accountTotalValue?.toLocaleString('en-US', {\n currency: 'USD',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n style: 'currency',\n })}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </AccordionSummary>\n <AccordionDetails sx={{ bgcolor: 'background.default', p: 12 }}>\n <Paper sx={{ border: 1, borderColor: 'neutral.light' }}>\n <HoldingsTable\n currentEditedCostBasis={currentEditedCostBasis}\n data={accountHoldings}\n editingHoldingId={editingHoldingId}\n handleCostBasisBlur={handleCostBasisBlur}\n handleCostBasisChange={handleCostBasisChange}\n handleCostBasisClick={handleCostBasisClick}\n handleCostBasisKeyDown={handleCostBasisKeyDown}\n />\n </Paper>\n </AccordionDetails>\n </Accordion>\n )\n })}\n\n {/* footer content */}\n <EmptyStateFooterComponent />\n\n {/* Drawer Component */}\n <InvestmentDetailsDrawer\n accountHoldingsData={accountHoldingsData}\n currentEditedCostBasis={currentEditedCostBasis}\n editingHoldingId={editingHoldingId}\n handleCostBasisBlur={handleCostBasisBlur}\n handleCostBasisChange={handleCostBasisChange}\n handleCostBasisClick={handleCostBasisClick}\n handleCostBasisKeyDown={handleCostBasisKeyDown}\n isOpen={openDrawer}\n onClose={closeDrawer}\n />\n\n <ConnectionsDrawer\n onClose={() => setShowConnectionsWidget(false)}\n showConnectionsWidget={showConnectionsWidget}\n title={accountsCopy.manage_connections}\n />\n </Stack>\n )\n}\n\nexport default observer(Overview)\n"],"mappings":"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"}
@@ -11,6 +11,7 @@ export interface InvestmentsData {
11
11
  donutData: DonutData[];
12
12
  totalAmount: number;
13
13
  totalGainLoss: number;
14
+ totalGainLossAvailable: boolean;
14
15
  totalMarketValue: number;
15
16
  totalGainLossPercentage: number;
16
17
  }
@@ -1,22 +1,22 @@
1
- import L from "../../../common/components/charts/Donut.es.js";
2
- import { useGlobalCopyStore as I } from "../../../common/context/hooks.es.js";
3
- import { currencyDisplay as c, percentageDisplay as j } from "./util/createInvestementsAllocationData.es.js";
1
+ import b from "../../../common/components/charts/Donut.es.js";
2
+ import { useGlobalCopyStore as k } from "../../../common/context/hooks.es.js";
3
+ import { currencyDisplay as c, percentageDisplay as A } from "./util/createInvestementsAllocationData.es.js";
4
4
  import m from "react";
5
5
  import r from "@mui/material/Stack";
6
- import { P as M, Text as p } from "@mxenabled/mxui";
7
- import { Icon as b } from "@mxenabled/mx-icons";
6
+ import { P as I, Text as p } from "@mxenabled/mxui";
7
+ import { Icon as j } from "@mxenabled/mx-icons";
8
8
  import { jsx as e, jsxs as u } from "react/jsx-runtime";
9
- import { useTheme as w } from "@mui/material/styles";
10
- var V = ({ data: t, hoveredId: h, isPercentage: g, onMouseEnter: f, onMouseLeave: y, onSelected: d, selectedId: o, size: i = 150, totalLabel: x }) => {
11
- const s = w(), l = s.palette.mode === "dark", n = m.useMemo(() => o ? t.investmentsData.find(({ guid: G }) => G === o) : void 0, [o]), { investments: { allocation: D } } = I(), v = m.useMemo(() => t.donutData.length > 0 ? t.donutData : [{
9
+ import { useTheme as M } from "@mui/material/styles";
10
+ var V = ({ data: t, hoveredId: h, isPercentage: g, onMouseEnter: f, onMouseLeave: y, onSelected: x, selectedId: o, size: i = 150, totalLabel: d }) => {
11
+ const s = M(), l = s.palette.mode === "dark", n = m.useMemo(() => o ? t.investmentsData.find(({ guid: _ }) => _ === o) : void 0, [o]), { investments: { allocation: v } } = k(), D = m.useMemo(() => t.donutData.length > 0 ? t.donutData : [{
12
12
  id: "0",
13
13
  color: s.palette.neutral.light,
14
14
  value: 100
15
- }], [t, s]), C = l ? "#0AC295" : "#09A57F", _ = l ? "grey.300" : "grey.700", k = () => n ? D.pie_chart_centered_click_for_details : g ? j(t.totalGainLossPercentage) : c(t.totalGainLoss), a = t.totalGainLoss >= 0 ? C : _;
16
- return /* @__PURE__ */ e(L, {
17
- data: v,
15
+ }], [t, s]), C = l ? "#0AC295" : "#09A57F", G = l ? "grey.300" : "grey.700", L = () => n ? v.pie_chart_centered_click_for_details : t.totalGainLossAvailable ? g ? A(t.totalGainLossPercentage) : c(t.totalGainLoss) : "—", a = t.totalGainLossAvailable ? t.totalGainLoss >= 0 ? C : G : "text.secondary";
16
+ return /* @__PURE__ */ e(b, {
17
+ data: D,
18
18
  hoveredId: h,
19
- onClick: d,
19
+ onClick: x,
20
20
  onMouseEnter: f,
21
21
  onMouseLeave: y,
22
22
  selectedId: o,
@@ -47,9 +47,9 @@ var V = ({ data: t, hoveredId: h, isPercentage: g, onMouseEnter: f, onMouseLeave
47
47
  /* @__PURE__ */ e(p, {
48
48
  color: "text.secondary",
49
49
  noWrap: !0,
50
- children: n?.displayName ?? x
50
+ children: n?.displayName ?? d
51
51
  }),
52
- /* @__PURE__ */ e(M, {
52
+ /* @__PURE__ */ e(I, {
53
53
  color: "text.primary",
54
54
  variant: "h1",
55
55
  children: c(n?.value ?? t.totalMarketValue)
@@ -60,7 +60,7 @@ var V = ({ data: t, hoveredId: h, isPercentage: g, onMouseEnter: f, onMouseLeave
60
60
  flexDirection: "row",
61
61
  gap: 4
62
62
  },
63
- children: [!n && /* @__PURE__ */ e(b, {
63
+ children: [!n && t.totalGainLossAvailable && /* @__PURE__ */ e(j, {
64
64
  name: t.totalGainLoss >= 0 ? "trending_up" : "trending_down",
65
65
  size: 20,
66
66
  sx: { color: a }
@@ -70,7 +70,7 @@ var V = ({ data: t, hoveredId: h, isPercentage: g, onMouseEnter: f, onMouseLeave
70
70
  fontWeight: 700
71
71
  },
72
72
  variant: "body2",
73
- children: k()
73
+ children: L()
74
74
  })]
75
75
  })
76
76
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"InvestmentsAllocationChart.es.js","names":[],"sources":["../../../../src/investments/components/allocation/InvestmentsAllocationChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Stack from '@mui/material/Stack'\nimport { useTheme } from '@mui/material/styles'\n\nimport { P, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useGlobalCopyStore } from '../../../common'\nimport Donut from '../../../common/components/charts/Donut'\n\nimport {\n currencyDisplay,\n InvestmentsAllocationData,\n percentageDisplay,\n} from './util/createInvestementsAllocationData'\n\nexport interface DonutData {\n id: string\n label?: string\n color: string\n value: number\n}\nexport interface InvestmentsData {\n investmentsData: InvestmentsAllocationData[]\n donutData: DonutData[]\n totalAmount: number\n totalGainLoss: number\n totalMarketValue: number\n totalGainLossPercentage: number\n}\ninterface InvestementAllocationProps {\n data: InvestmentsData\n hoveredId?: string\n isPercentage?: boolean\n onSelected: (id: string) => void\n onMouseEnter: (id: string) => void\n onMouseLeave: (id: string) => void\n selectedId?: string\n size?: number\n totalLabel: string\n}\n\nexport const InvestementsAllocationChart: React.FC<InvestementAllocationProps> = ({\n data,\n hoveredId,\n isPercentage,\n onMouseEnter,\n onMouseLeave,\n onSelected,\n selectedId,\n size = 150,\n totalLabel,\n}) => {\n const theme = useTheme()\n const isDarkMode = theme.palette.mode === 'dark'\n\n const selectedInvestments = React.useMemo(\n () =>\n selectedId\n ? data.investmentsData.find(({ guid }: InvestmentsAllocationData) => guid === selectedId)\n : undefined,\n [selectedId],\n )\n const {\n investments: { allocation: copy },\n } = useGlobalCopyStore()\n const donutData = React.useMemo(() => {\n if (data.donutData.length > 0) return data.donutData\n\n // Empty Donut zero state\n return [{ id: '0', color: theme.palette.neutral.light, value: 100 }]\n }, [data, theme])\n\n const gainDisplayColor = isDarkMode ? '#0AC295' : '#09A57F'\n const lossDisplayColor = isDarkMode ? 'grey.300' : 'grey.700'\n\n const getGainLossDisplay = () => {\n if (selectedInvestments) return copy.pie_chart_centered_click_for_details\n if (isPercentage) return percentageDisplay(data.totalGainLossPercentage)\n return currencyDisplay(data.totalGainLoss)\n }\n\n const gainLossDisplayColor = data.totalGainLoss >= 0 ? gainDisplayColor : lossDisplayColor\n\n return (\n <Donut\n data={donutData}\n hoveredId={hoveredId}\n onClick={onSelected}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n selectedId={selectedId}\n size={size}\n >\n <Stack alignItems=\"center\" height=\"100%\" justifyContent=\"center\" width=\"100%\">\n <Stack alignItems=\"center\" justifyContent=\"center\" minHeight={size} minWidth={size}>\n <Stack alignItems=\"center\" sx={{ gap: { xs: 4, xl: 8 }, mb: { xs: 4, xl: 8 } }}>\n <Text color=\"text.secondary\" noWrap={true}>\n {selectedInvestments?.displayName ?? totalLabel}\n </Text>\n <P color=\"text.primary\" variant=\"h1\">\n {currencyDisplay(selectedInvestments?.value ?? data.totalMarketValue)}\n </P>\n\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 4 }}>\n {!selectedInvestments && (\n <Icon\n name={data.totalGainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor,\n fontWeight: 700,\n }}\n variant=\"body2\"\n >\n {getGainLossDisplay()}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Donut>\n )\n}\n"],"mappings":";;;;;;;;;AA2CA,IAAa,IAAA,CAAqE,EAChF,MAAA,GACA,WAAA,GACA,cAAA,GACA,cAAA,GACA,cAAA,GACA,YAAA,GACA,YAAA,GACA,MAAA,IAAO,KACP,YAAA,EAAA,MACI;AACJ,QAAM,IAAQ,EAAS,GACjB,IAAa,EAAM,QAAQ,SAAS,QAEpC,IAAsB,EAAM,QAAA,MAE9B,IACI,EAAK,gBAAgB,KAAA,CAAM,EAAE,MAAA,EAAA,MAAsC,MAAS,CAAU,IACtF,QACN,CAAC,CAAU,CACb,GACM,EACJ,aAAa,EAAE,YAAY,EAAA,EAAA,IACzB,EAAmB,GACjB,IAAY,EAAM,QAAA,MAClB,EAAK,UAAU,SAAS,IAAU,EAAK,YAGpC,CAAC;AAAA,IAAE,IAAI;AAAA,IAAK,OAAO,EAAM,QAAQ,QAAQ;AAAA,IAAO,OAAO;AAAA,EAAI,CAAC,GAClE,CAAC,GAAM,CAAK,CAAC,GAEV,IAAmB,IAAa,YAAY,WAC5C,IAAmB,IAAa,aAAa,YAE7C,IAAA,MACA,IAA4B,EAAK,uCACjC,IAAqB,EAAkB,EAAK,uBAAuB,IAChE,EAAgB,EAAK,aAAa,GAGrC,IAAuB,EAAK,iBAAiB,IAAI,IAAmB;AAE1E,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,MAAM;AAAA,IACK,WAAA;AAAA,IACX,SAAS;AAAA,IACK,cAAA;AAAA,IACA,cAAA;AAAA,IACF,YAAA;AAAA,IACN,MAAA;AAAA,IAEN,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,YAAW;AAAA,MAAS,QAAO;AAAA,MAAO,gBAAe;AAAA,MAAS,OAAM;AAAA,MACrE,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAO,YAAW;AAAA,QAAS,gBAAe;AAAA,QAAS,WAAW;AAAA,QAAM,UAAU;AAAA,QAC5E,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAO,YAAW;AAAA,UAAS,IAAI;AAAA,YAAE,KAAK;AAAA,cAAE,IAAI;AAAA,cAAG,IAAI;AAAA,YAAE;AAAA,YAAG,IAAI;AAAA,cAAE,IAAI;AAAA,cAAG,IAAI;AAAA,YAAE;AAAA,UAAE;AAAA,UAA7E,UAAA;AAAA,YACE,gBAAA,EAAC,GAAD;AAAA,cAAM,OAAM;AAAA,cAAiB,QAAQ;AAAA,cAClC,UAAA,GAAqB,eAAe;AAAA,YACjC,CAAA;AAAA,YACN,gBAAA,EAAC,GAAD;AAAA,cAAG,OAAM;AAAA,cAAe,SAAQ;AAAA,cAC7B,UAAA,EAAgB,GAAqB,SAAS,EAAK,gBAAgB;AAAA,YACnE,CAAA;AAAA,YAEH,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,YAAY;AAAA,gBAAU,eAAe;AAAA,gBAAO,KAAK;AAAA,cAAE;AAAA,cAAhE,UAAA,CACG,CAAC,KACA,gBAAA,EAAC,GAAD;AAAA,gBACE,MAAM,EAAK,iBAAiB,IAAI,gBAAgB;AAAA,gBAChD,MAAM;AAAA,gBACN,IAAI,EAAE,OAAO,EAAqB;AAAA,cACnC,CAAA,GAEH,gBAAA,EAAC,GAAD;AAAA,gBACE,IAAI;AAAA,kBACF,OAAO;AAAA,kBACP,YAAY;AAAA,gBACd;AAAA,gBACA,SAAQ;AAAA,gBAEP,UAAA,EAAmB;AAAA,cAChB,CAAA,CACD;AAAA;UACF;AAAA;MACF,CAAA;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AAEX"}
1
+ {"version":3,"file":"InvestmentsAllocationChart.es.js","names":[],"sources":["../../../../src/investments/components/allocation/InvestmentsAllocationChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Stack from '@mui/material/Stack'\nimport { useTheme } from '@mui/material/styles'\n\nimport { P, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useGlobalCopyStore } from '../../../common'\nimport Donut from '../../../common/components/charts/Donut'\n\nimport {\n currencyDisplay,\n InvestmentsAllocationData,\n percentageDisplay,\n} from './util/createInvestementsAllocationData'\n\nexport interface DonutData {\n id: string\n label?: string\n color: string\n value: number\n}\nexport interface InvestmentsData {\n investmentsData: InvestmentsAllocationData[]\n donutData: DonutData[]\n totalAmount: number\n totalGainLoss: number\n totalGainLossAvailable: boolean\n totalMarketValue: number\n totalGainLossPercentage: number\n}\ninterface InvestementAllocationProps {\n data: InvestmentsData\n hoveredId?: string\n isPercentage?: boolean\n onSelected: (id: string) => void\n onMouseEnter: (id: string) => void\n onMouseLeave: (id: string) => void\n selectedId?: string\n size?: number\n totalLabel: string\n}\n\nexport const InvestementsAllocationChart: React.FC<InvestementAllocationProps> = ({\n data,\n hoveredId,\n isPercentage,\n onMouseEnter,\n onMouseLeave,\n onSelected,\n selectedId,\n size = 150,\n totalLabel,\n}) => {\n const theme = useTheme()\n const isDarkMode = theme.palette.mode === 'dark'\n\n const selectedInvestments = React.useMemo(\n () =>\n selectedId\n ? data.investmentsData.find(({ guid }: InvestmentsAllocationData) => guid === selectedId)\n : undefined,\n [selectedId],\n )\n const {\n investments: { allocation: copy },\n } = useGlobalCopyStore()\n const donutData = React.useMemo(() => {\n if (data.donutData.length > 0) return data.donutData\n\n // Empty Donut zero state\n return [{ id: '0', color: theme.palette.neutral.light, value: 100 }]\n }, [data, theme])\n\n const gainDisplayColor = isDarkMode ? '#0AC295' : '#09A57F'\n const lossDisplayColor = isDarkMode ? 'grey.300' : 'grey.700'\n\n const getGainLossDisplay = () => {\n if (selectedInvestments) return copy.pie_chart_centered_click_for_details\n if (!data.totalGainLossAvailable) return '—'\n if (isPercentage) return percentageDisplay(data.totalGainLossPercentage)\n return currencyDisplay(data.totalGainLoss)\n }\n\n const gainLossDisplayColor = !data.totalGainLossAvailable\n ? 'text.secondary'\n : data.totalGainLoss >= 0\n ? gainDisplayColor\n : lossDisplayColor\n\n return (\n <Donut\n data={donutData}\n hoveredId={hoveredId}\n onClick={onSelected}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n selectedId={selectedId}\n size={size}\n >\n <Stack alignItems=\"center\" height=\"100%\" justifyContent=\"center\" width=\"100%\">\n <Stack alignItems=\"center\" justifyContent=\"center\" minHeight={size} minWidth={size}>\n <Stack alignItems=\"center\" sx={{ gap: { xs: 4, xl: 8 }, mb: { xs: 4, xl: 8 } }}>\n <Text color=\"text.secondary\" noWrap={true}>\n {selectedInvestments?.displayName ?? totalLabel}\n </Text>\n <P color=\"text.primary\" variant=\"h1\">\n {currencyDisplay(selectedInvestments?.value ?? data.totalMarketValue)}\n </P>\n\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 4 }}>\n {!selectedInvestments && data.totalGainLossAvailable && (\n <Icon\n name={data.totalGainLoss >= 0 ? 'trending_up' : 'trending_down'}\n size={20}\n sx={{ color: gainLossDisplayColor }}\n />\n )}\n <Text\n sx={{\n color: gainLossDisplayColor,\n fontWeight: 700,\n }}\n variant=\"body2\"\n >\n {getGainLossDisplay()}\n </Text>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Donut>\n )\n}\n"],"mappings":";;;;;;;;;AA4CA,IAAa,IAAA,CAAqE,EAChF,MAAA,GACA,WAAA,GACA,cAAA,GACA,cAAA,GACA,cAAA,GACA,YAAA,GACA,YAAA,GACA,MAAA,IAAO,KACP,YAAA,EAAA,MACI;AACJ,QAAM,IAAQ,EAAS,GACjB,IAAa,EAAM,QAAQ,SAAS,QAEpC,IAAsB,EAAM,QAAA,MAE9B,IACI,EAAK,gBAAgB,KAAA,CAAM,EAAE,MAAA,EAAA,MAAsC,MAAS,CAAU,IACtF,QACN,CAAC,CAAU,CACb,GACM,EACJ,aAAa,EAAE,YAAY,EAAA,EAAA,IACzB,EAAmB,GACjB,IAAY,EAAM,QAAA,MAClB,EAAK,UAAU,SAAS,IAAU,EAAK,YAGpC,CAAC;AAAA,IAAE,IAAI;AAAA,IAAK,OAAO,EAAM,QAAQ,QAAQ;AAAA,IAAO,OAAO;AAAA,EAAI,CAAC,GAClE,CAAC,GAAM,CAAK,CAAC,GAEV,IAAmB,IAAa,YAAY,WAC5C,IAAmB,IAAa,aAAa,YAE7C,IAAA,MACA,IAA4B,EAAK,uCAChC,EAAK,yBACN,IAAqB,EAAkB,EAAK,uBAAuB,IAChE,EAAgB,EAAK,aAAa,IAFA,KAKrC,IAAwB,EAAK,yBAE/B,EAAK,iBAAiB,IACpB,IACA,IAHF;AAKJ,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,MAAM;AAAA,IACK,WAAA;AAAA,IACX,SAAS;AAAA,IACK,cAAA;AAAA,IACA,cAAA;AAAA,IACF,YAAA;AAAA,IACN,MAAA;AAAA,IAEN,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,YAAW;AAAA,MAAS,QAAO;AAAA,MAAO,gBAAe;AAAA,MAAS,OAAM;AAAA,MACrE,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAO,YAAW;AAAA,QAAS,gBAAe;AAAA,QAAS,WAAW;AAAA,QAAM,UAAU;AAAA,QAC5E,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAO,YAAW;AAAA,UAAS,IAAI;AAAA,YAAE,KAAK;AAAA,cAAE,IAAI;AAAA,cAAG,IAAI;AAAA,YAAE;AAAA,YAAG,IAAI;AAAA,cAAE,IAAI;AAAA,cAAG,IAAI;AAAA,YAAE;AAAA,UAAE;AAAA,UAA7E,UAAA;AAAA,YACE,gBAAA,EAAC,GAAD;AAAA,cAAM,OAAM;AAAA,cAAiB,QAAQ;AAAA,cAClC,UAAA,GAAqB,eAAe;AAAA,YACjC,CAAA;AAAA,YACN,gBAAA,EAAC,GAAD;AAAA,cAAG,OAAM;AAAA,cAAe,SAAQ;AAAA,cAC7B,UAAA,EAAgB,GAAqB,SAAS,EAAK,gBAAgB;AAAA,YACnE,CAAA;AAAA,YAEH,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,YAAY;AAAA,gBAAU,eAAe;AAAA,gBAAO,KAAK;AAAA,cAAE;AAAA,cAAhE,UAAA,CACG,CAAC,KAAuB,EAAK,0BAC5B,gBAAA,EAAC,GAAD;AAAA,gBACE,MAAM,EAAK,iBAAiB,IAAI,gBAAgB;AAAA,gBAChD,MAAM;AAAA,gBACN,IAAI,EAAE,OAAO,EAAqB;AAAA,cACnC,CAAA,GAEH,gBAAA,EAAC,GAAD;AAAA,gBACE,IAAI;AAAA,kBACF,OAAO;AAAA,kBACP,YAAY;AAAA,gBACd;AAAA,gBACA,SAAQ;AAAA,gBAEP,UAAA,EAAmB;AAAA,cAChB,CAAA,CACD;AAAA;UACF;AAAA;MACF,CAAA;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AAEX"}
@@ -21,6 +21,7 @@ export declare const createInvestmentsAllocationData: (accounts: Account[], copy
21
21
  donutData: DonutData[];
22
22
  totalAmount: number;
23
23
  totalGainLoss: number;
24
+ totalGainLossAvailable: boolean;
24
25
  totalMarketValue: number;
25
26
  totalGainLossPercentage: number;
26
27
  };
@@ -1,6 +1,7 @@
1
- import { formatCurrency as L, formatPercentage as k } from "../../../../core/utils/NumberFormatting.es.js";
2
- import { ALLOCATION_KEYS as B } from "../../../../core/constants/Investments.es.js";
3
- var C = {
1
+ import { formatCurrency as D, formatPercentage as k } from "../../../../core/utils/NumberFormatting.es.js";
2
+ import { ALLOCATION_KEYS as y } from "../../../../core/constants/Investments.es.js";
3
+ import { getHoldingGainLoss as b, getHoldingMarketValue as v } from "../../../../core/utils/InvestmentUtil.es.js";
4
+ var G = {
4
5
  allocations_cash: "#AEDCCC",
5
6
  allocations_convertible: "#80CAD0",
6
7
  allocations_foreign_bond: "#51B9D4",
@@ -10,85 +11,88 @@ var C = {
10
11
  allocations_unknown: "#161D6A",
11
12
  allocations_us_bond: "#254995",
12
13
  allocations_us_stock: "#1E2D84"
13
- }, y = B.map((t) => ({ name: t })), V = (t, l, r) => {
14
- const i = r === void 0 ? 0 : l, e = r === void 0 ? l : r;
15
- return t >= Math.min(i, e) && t < Math.max(i, e);
16
- }, h = (t, l, r) => {
17
- const i = [...new Set(t.map((c) => c.name.toLowerCase()))];
18
- let e;
14
+ }, V = y.map((e) => ({ name: e })), w = (e, l, r) => {
15
+ const i = r === void 0 ? 0 : l, t = r === void 0 ? l : r;
16
+ return e >= Math.min(i, t) && e < Math.max(i, t);
17
+ }, E = (e, l, r) => {
18
+ const i = [...new Set(e.map((c) => c.name.toLowerCase()))];
19
+ let t;
19
20
  return i.map((c) => {
20
- const _ = t.reduce((m, s) => {
21
- const p = s.name;
22
- return p.toLowerCase() === c ? (e = p, d(s) * s[l] / 100 + m) : m;
21
+ const p = e.reduce((m, o) => {
22
+ const d = o.name;
23
+ return d.toLowerCase() === c ? (t = d, v(o) * o[l] / 100 + m) : m;
23
24
  }, 0);
24
25
  return {
25
- displayName: e,
26
- name: e,
27
- value: _,
28
- percentage: _ / r
26
+ displayName: t,
27
+ name: t,
28
+ value: p,
29
+ percentage: p / r
29
30
  };
30
31
  });
31
- }, d = (t) => t.calculated_market_value ? t.calculated_market_value : t.market_value, E = (t, l, r) => {
32
- const i = Object.values(l.allocations_list), e = [];
32
+ }, S = (e, l, r) => {
33
+ const i = Object.values(l.allocations_list), t = [];
33
34
  let c = 0;
34
- const _ = new Set(t.map(({ guid: a }) => a)), m = r.filter(({ account_guid: a }) => _.has(a)).map((a) => ({
35
+ const p = new Set(e.map(({ guid: a }) => a)), m = r.filter(({ account_guid: a }) => p.has(a)).map((a) => ({
35
36
  ...a,
36
37
  name: a.symbol || a.description,
37
- gainLoss: a.cost_basis || a.cost_basis === 0 ? d(a) - a.cost_basis : 0
38
- })), { cashBalance: s, totalAccountBalance: p } = t.reduce((a, n) => ({
38
+ gainLoss: b(a).gainLoss
39
+ })), { cashBalance: o, totalAccountBalance: d } = e.reduce((a, n) => ({
39
40
  cashBalance: a.cashBalance + (n.cash_balance || 0),
40
41
  totalAccountBalance: a.totalAccountBalance + (n.balance || 0)
41
42
  }), {
42
43
  cashBalance: 0,
43
44
  totalAccountBalance: 0
44
- }), { marketValue: b, totalGainLoss: A } = m.reduce((a, n) => ({
45
- marketValue: a.marketValue + d(n),
45
+ }), { marketValue: h, totalGainLoss: f } = m.reduce((a, n) => ({
46
+ marketValue: a.marketValue + v(n),
46
47
  totalGainLoss: a.totalGainLoss + n.gainLoss
47
48
  }), {
48
49
  marketValue: 0,
49
50
  totalGainLoss: 0
50
- }), f = b + s;
51
- return y.forEach((a, n) => {
52
- const v = m.filter((u) => !!u[a.name]);
53
- let o = v.reduce((u, g) => u + d(g) * g[a.name] / 100, 0);
54
- const D = h(v, a.name, o);
55
- if (a.name === "allocations_cash" && s > 0) {
56
- o += s;
51
+ }), _ = h + o;
52
+ V.forEach((a, n) => {
53
+ const g = m.filter((u) => !!u[a.name]);
54
+ let s = g.reduce((u, L) => u + v(L) * L[a.name] / 100, 0);
55
+ const A = E(g, a.name, s);
56
+ if (a.name === "allocations_cash" && o > 0) {
57
+ s += o;
57
58
  const u = {
58
59
  displayName: l.cash_balance_display_name,
59
60
  name: "allocations_name",
60
- value: s,
61
- percentage: s / f
61
+ value: o,
62
+ percentage: o / _
62
63
  };
63
- D.push(u);
64
+ A.push(u);
64
65
  }
65
- o > 0 && (e.push({
66
+ s > 0 && (t.push({
66
67
  name: a.name,
67
68
  displayName: i[n],
68
69
  guid: `${a.name}-${n}`,
69
- holdings: D,
70
- percentage: o / f,
71
- value: o,
72
- color: C[a.name]
73
- }), c += o);
74
- }), {
75
- investmentsData: e,
76
- donutData: e.map(({ displayName: a, guid: n, color: v, value: o }) => ({
77
- id: n,
78
- color: v,
79
- label: a,
80
- value: o / c * 100
81
- })),
70
+ holdings: A,
71
+ percentage: s / _,
72
+ value: s,
73
+ color: G[a.name]
74
+ }), c += s);
75
+ });
76
+ const B = t.map(({ displayName: a, guid: n, color: g, value: s }) => ({
77
+ id: n,
78
+ color: g,
79
+ label: a,
80
+ value: s / c * 100
81
+ })), C = m.some((a) => b(a).available);
82
+ return {
83
+ investmentsData: t,
84
+ donutData: B,
82
85
  totalAmount: c,
83
- totalGainLoss: A,
84
- totalMarketValue: f,
85
- totalGainLossPercentage: A / p
86
+ totalGainLoss: f,
87
+ totalGainLossAvailable: C,
88
+ totalMarketValue: _,
89
+ totalGainLossPercentage: f / d
86
90
  };
87
- }, N = (t) => t < 1e-3 ? "< 0.1%" : k(t), S = (t) => t === 0 ? L(t, "0,0.00") : V(t, -0.01, 0.01) ? "< $0.01" : L(t, "0,0.00");
91
+ }, T = (e) => e < 1e-3 ? "< 0.1%" : k(e), O = (e) => e === 0 ? D(e, "0,0.00") : w(e, -0.01, 0.01) ? "< $0.01" : D(e, "0,0.00");
88
92
  export {
89
- E as createInvestmentsAllocationData,
90
- S as currencyDisplay,
91
- N as percentageDisplay
93
+ S as createInvestmentsAllocationData,
94
+ O as currencyDisplay,
95
+ T as percentageDisplay
92
96
  };
93
97
 
94
98
  //# sourceMappingURL=createInvestementsAllocationData.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createInvestementsAllocationData.es.js","names":[],"sources":["../../../../../src/investments/components/allocation/util/createInvestementsAllocationData.tsx"],"sourcesContent":["import { Account, Holding } from '../../../../core'\nimport { ALLOCATION_KEYS, type AllocationKey } from '../../../../core/constants/Investments'\nimport { InvestmentAllocationCopy } from '../../../../core/types/localization/InvestmentsCopy'\nimport type { DonutData } from '../InvestmentsAllocationChart'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\n\nexport interface InvestmentsAllocationData {\n name: string\n displayName: string\n guid: string\n holdings: InvestmentAllocationTotals[]\n percentage: number\n value: number\n color: string\n}\nexport interface InvestmentAllocationTotals {\n displayName: string\n name: string\n value: number\n percentage: number\n}\n\nconst allocationColors: Record<AllocationKey, string> = {\n allocations_cash: '#AEDCCC',\n allocations_convertible: '#80CAD0',\n allocations_foreign_bond: '#51B9D4',\n allocations_foreign_stock: '#3DA0C9',\n allocations_other: '#3583B8',\n allocations_preferred: '#2D66A7',\n allocations_unknown: '#161D6A',\n allocations_us_bond: '#254995',\n allocations_us_stock: '#1E2D84',\n}\nconst allocationsList = ALLOCATION_KEYS.map((name) => ({ name }))\n\nconst inRange = (n: number, start: number, end?: number) => {\n const rangeStart = end === undefined ? 0 : start\n const rangeEnd = end === undefined ? start : end\n return n >= Math.min(rangeStart, rangeEnd) && n < Math.max(rangeStart, rangeEnd)\n}\n\nconst createHoldingsData = (\n holdings: Holding[],\n allocationName: string,\n allocationValue: number,\n) => {\n const uniqueHoldings = [\n ...new Set(holdings.map((holding: Holding) => holding.name.toLowerCase())),\n ]\n let displayName: string\n const investmentAllocationTotals = uniqueHoldings.map((holdingName) => {\n // sum all the holdings with the same \"name\"\n const holdingsTotalValue = holdings.reduce((acc, hold: Holding) => {\n const name = hold.name\n\n if (name.toLowerCase() === holdingName) {\n // Since we lose the capitalization with the unique names, we take it from the last match.\n displayName = name\n return (\n (getHoldingValue(hold) * hold[allocationName as keyof typeof allocationColors]) / 100 +\n acc\n )\n }\n\n return acc\n }, 0)\n\n return {\n displayName,\n name: displayName,\n value: holdingsTotalValue,\n percentage: holdingsTotalValue / allocationValue,\n }\n })\n return investmentAllocationTotals\n}\n\nconst getHoldingValue = (holding: Holding) =>\n holding.calculated_market_value ? holding.calculated_market_value : holding.market_value\n\nexport const createInvestmentsAllocationData = (\n accounts: Account[],\n copy: InvestmentAllocationCopy,\n holdings: Holding[],\n) => {\n const allocationListDisplayNames = Object.values(copy.allocations_list)\n const investementAllocationData: InvestmentsAllocationData[] = []\n\n let totalAmount = 0\n\n const accountGuids = new Set(accounts.map(({ guid }) => guid))\n const updatedHoldings: Holding[] = holdings\n .filter(({ account_guid }) => accountGuids.has(account_guid))\n .map((eachHolding) => {\n return {\n ...eachHolding,\n name: eachHolding.symbol || eachHolding.description,\n gainLoss:\n eachHolding.cost_basis || eachHolding.cost_basis === 0\n ? getHoldingValue(eachHolding) - eachHolding.cost_basis\n : 0,\n }\n })\n\n const { cashBalance, totalAccountBalance } = accounts.reduce(\n (sum, account) => {\n return {\n cashBalance: sum.cashBalance + (account.cash_balance || 0),\n totalAccountBalance: sum.totalAccountBalance + (account.balance || 0),\n }\n },\n { cashBalance: 0, totalAccountBalance: 0 },\n )\n const { marketValue, totalGainLoss } = updatedHoldings.reduce(\n (acc, holding) => {\n return {\n marketValue: acc.marketValue + getHoldingValue(holding),\n totalGainLoss: acc.totalGainLoss + holding.gainLoss,\n }\n },\n { marketValue: 0, totalGainLoss: 0 },\n )\n const totalMarketValue = marketValue + cashBalance\n\n allocationsList.forEach((allocation, index) => {\n const filteredHoldings = updatedHoldings.filter(\n (eachHolding) => !!eachHolding[allocation.name as keyof typeof allocationColors],\n )\n let holdingsTotal = filteredHoldings.reduce(\n (sum, holding) =>\n sum +\n (getHoldingValue(holding) * holding[allocation.name as keyof typeof allocationColors]) /\n 100,\n 0,\n )\n const investmentAllocationTotals = createHoldingsData(\n filteredHoldings,\n allocation.name,\n holdingsTotal,\n )\n if (allocation.name === 'allocations_cash' && cashBalance > 0) {\n // Updating holdingsTotal to include cash balance\n // This affects the holdingsTotal and percentage for this allocation\n holdingsTotal += cashBalance\n\n // Creating a holding item for cash balance\n const cashBalanceHolding = {\n displayName: copy.cash_balance_display_name,\n name: 'allocations_name',\n value: cashBalance,\n percentage: cashBalance / totalMarketValue,\n }\n\n investmentAllocationTotals.push(cashBalanceHolding)\n }\n\n // Shows allocation if holdingsTotal is greater than zero\n if (holdingsTotal > 0) {\n investementAllocationData.push({\n name: allocation.name,\n displayName: allocationListDisplayNames[index],\n guid: `${allocation.name}-${index}`,\n holdings: investmentAllocationTotals,\n percentage: holdingsTotal / totalMarketValue,\n value: holdingsTotal,\n color: allocationColors[allocation.name as keyof typeof allocationColors],\n })\n totalAmount += holdingsTotal\n }\n })\n const donutData: DonutData[] = investementAllocationData.map(\n ({ displayName, guid, color, value }) => ({\n id: guid,\n color: color,\n label: displayName,\n value: (value / totalAmount) * 100,\n }),\n )\n\n return {\n investmentsData: investementAllocationData,\n donutData,\n totalAmount,\n totalGainLoss,\n totalMarketValue,\n totalGainLossPercentage: totalGainLoss / totalAccountBalance,\n }\n}\n\nexport const percentageDisplay = (value: number) =>\n value < 0.001 ? '< 0.1%' : formatPercentage(value)\n\nexport const currencyDisplay = (value: number) => {\n if (value === 0) return formatCurrency(value, '0,0.00')\n return inRange(value, -0.01, 0.01) ? '< $0.01' : formatCurrency(value, '0,0.00')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createInvestementsAllocationData.es.js","names":[],"sources":["../../../../../src/investments/components/allocation/util/createInvestementsAllocationData.tsx"],"sourcesContent":["import { Account, Holding } from '../../../../core'\nimport { ALLOCATION_KEYS, type AllocationKey } from '../../../../core/constants/Investments'\nimport { InvestmentAllocationCopy } from '../../../../core/types/localization/InvestmentsCopy'\nimport type { DonutData } from '../InvestmentsAllocationChart'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\nimport { getHoldingGainLoss, getHoldingMarketValue } from '../../../../core/utils/InvestmentUtil'\n\nexport interface InvestmentsAllocationData {\n name: string\n displayName: string\n guid: string\n holdings: InvestmentAllocationTotals[]\n percentage: number\n value: number\n color: string\n}\nexport interface InvestmentAllocationTotals {\n displayName: string\n name: string\n value: number\n percentage: number\n}\n\nconst allocationColors: Record<AllocationKey, string> = {\n allocations_cash: '#AEDCCC',\n allocations_convertible: '#80CAD0',\n allocations_foreign_bond: '#51B9D4',\n allocations_foreign_stock: '#3DA0C9',\n allocations_other: '#3583B8',\n allocations_preferred: '#2D66A7',\n allocations_unknown: '#161D6A',\n allocations_us_bond: '#254995',\n allocations_us_stock: '#1E2D84',\n}\nconst allocationsList = ALLOCATION_KEYS.map((name) => ({ name }))\n\nconst inRange = (n: number, start: number, end?: number) => {\n const rangeStart = end === undefined ? 0 : start\n const rangeEnd = end === undefined ? start : end\n return n >= Math.min(rangeStart, rangeEnd) && n < Math.max(rangeStart, rangeEnd)\n}\n\nconst createHoldingsData = (\n holdings: Holding[],\n allocationName: string,\n allocationValue: number,\n) => {\n const uniqueHoldings = [\n ...new Set(holdings.map((holding: Holding) => holding.name.toLowerCase())),\n ]\n let displayName: string\n const investmentAllocationTotals = uniqueHoldings.map((holdingName) => {\n // sum all the holdings with the same \"name\"\n const holdingsTotalValue = holdings.reduce((acc, hold: Holding) => {\n const name = hold.name\n\n if (name.toLowerCase() === holdingName) {\n // Since we lose the capitalization with the unique names, we take it from the last match.\n displayName = name\n return (\n (getHoldingMarketValue(hold) * hold[allocationName as keyof typeof allocationColors]) /\n 100 +\n acc\n )\n }\n\n return acc\n }, 0)\n\n return {\n displayName,\n name: displayName,\n value: holdingsTotalValue,\n percentage: holdingsTotalValue / allocationValue,\n }\n })\n return investmentAllocationTotals\n}\n\nexport const createInvestmentsAllocationData = (\n accounts: Account[],\n copy: InvestmentAllocationCopy,\n holdings: Holding[],\n) => {\n const allocationListDisplayNames = Object.values(copy.allocations_list)\n const investementAllocationData: InvestmentsAllocationData[] = []\n\n let totalAmount = 0\n\n const accountGuids = new Set(accounts.map(({ guid }) => guid))\n const updatedHoldings: Holding[] = holdings\n .filter(({ account_guid }) => accountGuids.has(account_guid))\n .map((eachHolding) => {\n return {\n ...eachHolding,\n name: eachHolding.symbol || eachHolding.description,\n // Falls back to purchase_price when cost_basis is unset, and contributes\n // 0 (not a fabricated gain) only when no basis is known at all.\n gainLoss: getHoldingGainLoss(eachHolding).gainLoss,\n }\n })\n\n const { cashBalance, totalAccountBalance } = accounts.reduce(\n (sum, account) => {\n return {\n cashBalance: sum.cashBalance + (account.cash_balance || 0),\n totalAccountBalance: sum.totalAccountBalance + (account.balance || 0),\n }\n },\n { cashBalance: 0, totalAccountBalance: 0 },\n )\n const { marketValue, totalGainLoss } = updatedHoldings.reduce(\n (acc, holding) => {\n return {\n marketValue: acc.marketValue + getHoldingMarketValue(holding),\n totalGainLoss: acc.totalGainLoss + holding.gainLoss,\n }\n },\n { marketValue: 0, totalGainLoss: 0 },\n )\n const totalMarketValue = marketValue + cashBalance\n\n allocationsList.forEach((allocation, index) => {\n const filteredHoldings = updatedHoldings.filter(\n (eachHolding) => !!eachHolding[allocation.name as keyof typeof allocationColors],\n )\n let holdingsTotal = filteredHoldings.reduce(\n (sum, holding) =>\n sum +\n (getHoldingMarketValue(holding) *\n holding[allocation.name as keyof typeof allocationColors]) /\n 100,\n 0,\n )\n const investmentAllocationTotals = createHoldingsData(\n filteredHoldings,\n allocation.name,\n holdingsTotal,\n )\n if (allocation.name === 'allocations_cash' && cashBalance > 0) {\n // Updating holdingsTotal to include cash balance\n // This affects the holdingsTotal and percentage for this allocation\n holdingsTotal += cashBalance\n\n // Creating a holding item for cash balance\n const cashBalanceHolding = {\n displayName: copy.cash_balance_display_name,\n name: 'allocations_name',\n value: cashBalance,\n percentage: cashBalance / totalMarketValue,\n }\n\n investmentAllocationTotals.push(cashBalanceHolding)\n }\n\n // Shows allocation if holdingsTotal is greater than zero\n if (holdingsTotal > 0) {\n investementAllocationData.push({\n name: allocation.name,\n displayName: allocationListDisplayNames[index],\n guid: `${allocation.name}-${index}`,\n holdings: investmentAllocationTotals,\n percentage: holdingsTotal / totalMarketValue,\n value: holdingsTotal,\n color: allocationColors[allocation.name as keyof typeof allocationColors],\n })\n totalAmount += holdingsTotal\n }\n })\n const donutData: DonutData[] = investementAllocationData.map(\n ({ displayName, guid, color, value }) => ({\n id: guid,\n color: color,\n label: displayName,\n value: (value / totalAmount) * 100,\n }),\n )\n\n // When no holding in the filtered set has a known basis, the donut center\n // renders \"—\" rather than a fabricated $0.00 / 0% gain.\n const totalGainLossAvailable = updatedHoldings.some(\n (holding) => getHoldingGainLoss(holding).available,\n )\n\n return {\n investmentsData: investementAllocationData,\n donutData,\n totalAmount,\n totalGainLoss,\n totalGainLossAvailable,\n totalMarketValue,\n totalGainLossPercentage: totalGainLoss / totalAccountBalance,\n }\n}\n\nexport const percentageDisplay = (value: number) =>\n value < 0.001 ? '< 0.1%' : formatPercentage(value)\n\nexport const currencyDisplay = (value: number) => {\n if (value === 0) return formatCurrency(value, '0,0.00')\n return inRange(value, -0.01, 0.01) ? '< $0.01' : formatCurrency(value, '0,0.00')\n}\n"],"mappings":";;;AAuBA,IAAM,IAAkD;AAAA,EACtD,kBAAkB;AAAA,EAClB,yBAAyB;AAAA,EACzB,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,sBAAsB;AACxB,GACM,IAAkB,EAAgB,IAAA,CAAK,OAAU,EAAE,MAAA,EAAK,EAAE,GAE1D,IAAA,CAAW,GAAW,GAAe,MAAiB;AAC1D,QAAM,IAAa,MAAQ,SAAY,IAAI,GACrC,IAAW,MAAQ,SAAY,IAAQ;AAC7C,SAAO,KAAK,KAAK,IAAI,GAAY,CAAQ,KAAK,IAAI,KAAK,IAAI,GAAY,CAAQ;AACjF,GAEM,IAAA,CACJ,GACA,GACA,MACG;AACH,QAAM,IAAiB,CACrB,GAAG,IAAI,IAAI,EAAS,IAAA,CAAK,MAAqB,EAAQ,KAAK,YAAY,CAAC,CAAC,CAC3E;AACA,MAAI;AA0BJ,SAzBmC,EAAe,IAAA,CAAK,MAAgB;AAErE,UAAM,IAAqB,EAAS,OAAA,CAAQ,GAAK,MAAkB;AACjE,YAAM,IAAO,EAAK;AAElB,aAAI,EAAK,YAAY,MAAM,KAEzB,IAAc,GAEX,EAAsB,CAAI,IAAI,EAAK,CAAA,IAClC,MACF,KAIG;AAAA,IACT,GAAG,CAAC;AAEJ,WAAO;AAAA,MACL,aAAA;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY,IAAqB;AAAA,IACnC;AAAA,EACF,CACO;AACT,GAEa,IAAA,CACX,GACA,GACA,MACG;AACH,QAAM,IAA6B,OAAO,OAAO,EAAK,gBAAgB,GAChE,IAAyD,CAAC;AAEhE,MAAI,IAAc;AAElB,QAAM,IAAe,IAAI,IAAI,EAAS,IAAA,CAAK,EAAE,MAAA,EAAA,MAAW,CAAI,CAAC,GACvD,IAA6B,EAChC,OAAA,CAAQ,EAAE,cAAA,EAAA,MAAmB,EAAa,IAAI,CAAY,CAAC,EAC3D,IAAA,CAAK,OACG;AAAA,IACL,GAAG;AAAA,IACH,MAAM,EAAY,UAAU,EAAY;AAAA,IAGxC,UAAU,EAAmB,CAAW,EAAE;AAAA,EAC5C,EACD,GAEG,EAAE,aAAA,GAAa,qBAAA,EAAA,IAAwB,EAAS,OAAA,CACnD,GAAK,OACG;AAAA,IACL,aAAa,EAAI,eAAe,EAAQ,gBAAgB;AAAA,IACxD,qBAAqB,EAAI,uBAAuB,EAAQ,WAAW;AAAA,EACrE,IAEF;AAAA,IAAE,aAAa;AAAA,IAAG,qBAAqB;AAAA,EAAE,CAC3C,GACM,EAAE,aAAA,GAAa,eAAA,EAAA,IAAkB,EAAgB,OAAA,CACpD,GAAK,OACG;AAAA,IACL,aAAa,EAAI,cAAc,EAAsB,CAAO;AAAA,IAC5D,eAAe,EAAI,gBAAgB,EAAQ;AAAA,EAC7C,IAEF;AAAA,IAAE,aAAa;AAAA,IAAG,eAAe;AAAA,EAAE,CACrC,GACM,IAAmB,IAAc;AAEvC,EAAA,EAAgB,QAAA,CAAS,GAAY,MAAU;AAC7C,UAAM,IAAmB,EAAgB,OAAA,CACtC,MAAgB,CAAC,CAAC,EAAY,EAAW,IAAA,CAC5C;AACA,QAAI,IAAgB,EAAiB,OAAA,CAClC,GAAK,MACJ,IACC,EAAsB,CAAO,IAC5B,EAAQ,EAAW,IAAA,IACnB,KACJ,CACF;AACA,UAAM,IAA6B,EACjC,GACA,EAAW,MACX,CACF;AACA,QAAI,EAAW,SAAS,sBAAsB,IAAc,GAAG;AAG7D,MAAA,KAAiB;AAGjB,YAAM,IAAqB;AAAA,QACzB,aAAa,EAAK;AAAA,QAClB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,YAAY,IAAc;AAAA,MAC5B;AAEA,MAAA,EAA2B,KAAK,CAAkB;AAAA,IACpD;AAGA,IAAI,IAAgB,MAClB,EAA0B,KAAK;AAAA,MAC7B,MAAM,EAAW;AAAA,MACjB,aAAa,EAA2B,CAAA;AAAA,MACxC,MAAM,GAAG,EAAW,IAAA,IAAQ,CAAA;AAAA,MAC5B,UAAU;AAAA,MACV,YAAY,IAAgB;AAAA,MAC5B,OAAO;AAAA,MACP,OAAO,EAAiB,EAAW,IAAA;AAAA,IACrC,CAAC,GACD,KAAe;AAAA,EAEnB,CAAC;AACD,QAAM,IAAyB,EAA0B,IAAA,CACtD,EAAE,aAAA,GAAa,MAAA,GAAM,OAAA,GAAO,OAAA,EAAA,OAAa;AAAA,IACxC,IAAI;AAAA,IACG,OAAA;AAAA,IACP,OAAO;AAAA,IACP,OAAQ,IAAQ,IAAe;AAAA,EACjC,EACF,GAIM,IAAyB,EAAgB,KAAA,CAC5C,MAAY,EAAmB,CAAO,EAAE,SAC3C;AAEA,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,WAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA;AAAA,IACA,wBAAA;AAAA,IACA,kBAAA;AAAA,IACA,yBAAyB,IAAgB;AAAA,EAC3C;AACF,GAEa,IAAA,CAAqB,MAChC,IAAQ,OAAQ,WAAW,EAAiB,CAAK,GAEtC,IAAA,CAAmB,MAC1B,MAAU,IAAU,EAAe,GAAO,QAAQ,IAC/C,EAAQ,GAAO,OAAO,IAAI,IAAI,YAAY,EAAe,GAAO,QAAQ"}
@@ -0,0 +1 @@
1
+ export { buildRumBeforeSend, createRumErrorBuffer, DEFAULT_RUM_ERROR_BUFFER_SIZE, redactSsoPath, type RumBeforeSendOptions, type RumErrorBuffer, } from './rum';
@@ -0,0 +1,7 @@
1
+ import { DEFAULT_RUM_ERROR_BUFFER_SIZE as e, buildRumBeforeSend as R, createRumErrorBuffer as o, redactSsoPath as t } from "./rum.es.js";
2
+ export {
3
+ e as DEFAULT_RUM_ERROR_BUFFER_SIZE,
4
+ R as buildRumBeforeSend,
5
+ o as createRumErrorBuffer,
6
+ t as redactSsoPath
7
+ };
@@ -0,0 +1,13 @@
1
+ import { RumInitConfiguration } from '@datadog/browser-rum';
2
+ export declare const redactSsoPath: <T extends string | undefined>(value: T) => T;
3
+ export interface RumBeforeSendOptions {
4
+ scrubSsoPaths?: boolean;
5
+ }
6
+ export declare function buildRumBeforeSend({ scrubSsoPaths, }?: RumBeforeSendOptions): NonNullable<RumInitConfiguration['beforeSend']>;
7
+ export interface RumErrorBuffer<Context = Record<string, unknown>> {
8
+ push(error: unknown, context?: Context): boolean;
9
+ flush(send: (error: unknown, context?: Context) => void): void;
10
+ readonly size: number;
11
+ }
12
+ export declare const DEFAULT_RUM_ERROR_BUFFER_SIZE = 50;
13
+ export declare function createRumErrorBuffer<Context = Record<string, unknown>>(maxSize?: number): RumErrorBuffer<Context>;
@@ -0,0 +1,37 @@
1
+ var t = /(\/(?:md\/[^/?#]+|login)\/)[^?#]+/g, s = (e) => typeof e == "string" ? e.replace(t, "$1REDACTED") : e;
2
+ function i({ scrubSsoPaths: e = !1 } = {}) {
3
+ return (r) => {
4
+ if (e && (r.view.url = s(r.view.url), r.view.referrer = s(r.view.referrer), r.type === "resource" && (r.resource.url = s(r.resource.url)), r.type === "error" && r.error.resource && (r.error.resource.url = s(r.error.resource.url))), r.type !== "resource" || r.resource.type === "xhr" || r.resource.type === "fetch") return !0;
5
+ const u = r.resource.status_code;
6
+ return !(u !== void 0 && u > 0 && u < 400);
7
+ };
8
+ }
9
+ var c = 50;
10
+ function f(e = 50) {
11
+ const r = [];
12
+ return {
13
+ push(u, o) {
14
+ return r.length >= e ? !1 : (r.push({
15
+ error: u,
16
+ context: o
17
+ }), !0);
18
+ },
19
+ flush(u) {
20
+ for (; r.length > 0; ) {
21
+ const o = r.shift();
22
+ o && u(o.error, o.context);
23
+ }
24
+ },
25
+ get size() {
26
+ return r.length;
27
+ }
28
+ };
29
+ }
30
+ export {
31
+ c as DEFAULT_RUM_ERROR_BUFFER_SIZE,
32
+ i as buildRumBeforeSend,
33
+ f as createRumErrorBuffer,
34
+ s as redactSsoPath
35
+ };
36
+
37
+ //# sourceMappingURL=rum.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rum.es.js","names":[],"sources":["../../src/rum/rum.ts"],"sourcesContent":["import type { RumEvent, RumInitConfiguration } from '@datadog/browser-rum'\n\n// scrub the really long sso token because it's unhelpful and noisy in events\nconst SSO_PATH_PATTERN = /(\\/(?:md\\/[^/?#]+|login)\\/)[^?#]+/g\n\nexport const redactSsoPath = <T extends string | undefined>(value: T): T =>\n typeof value === 'string' ? (value.replace(SSO_PATH_PATTERN, '$1REDACTED') as T) : value\n\nexport interface RumBeforeSendOptions {\n scrubSsoPaths?: boolean\n}\n\n// runs on every RUM event before it is sent to Datadog\nexport function buildRumBeforeSend({\n scrubSsoPaths = false,\n}: RumBeforeSendOptions = {}): NonNullable<RumInitConfiguration['beforeSend']> {\n return (event: RumEvent) => {\n if (scrubSsoPaths) {\n event.view.url = redactSsoPath(event.view.url)\n event.view.referrer = redactSsoPath(event.view.referrer)\n if (event.type === 'resource') event.resource.url = redactSsoPath(event.resource.url)\n if (event.type === 'error' && event.error.resource) {\n event.error.resource.url = redactSsoPath(event.error.resource.url)\n }\n }\n\n if (event.type !== 'resource') return true\n if (event.resource.type === 'xhr' || event.resource.type === 'fetch') return true\n const status = event.resource.status_code\n return !(status !== undefined && status > 0 && status < 400)\n }\n}\n\n// Holds errors that happen before Datadog RUM has started up, so they aren't lost\nexport interface RumErrorBuffer<Context = Record<string, unknown>> {\n push(error: unknown, context?: Context): boolean\n flush(send: (error: unknown, context?: Context) => void): void\n readonly size: number\n}\n\nexport const DEFAULT_RUM_ERROR_BUFFER_SIZE = 50\n\nexport function createRumErrorBuffer<Context = Record<string, unknown>>(\n maxSize: number = DEFAULT_RUM_ERROR_BUFFER_SIZE,\n): RumErrorBuffer<Context> {\n const items: Array<{ error: unknown; context?: Context }> = []\n return {\n push(error, context) {\n if (items.length >= maxSize) return false\n items.push({ error, context })\n return true\n },\n flush(send) {\n while (items.length > 0) {\n const item = items.shift()\n if (item) send(item.error, item.context)\n }\n },\n get size() {\n return items.length\n },\n }\n}\n"],"mappings":"AAGA,IAAM,IAAmB,sCAEZ,IAAA,CAA+C,MAC1D,OAAO,KAAU,WAAY,EAAM,QAAQ,GAAkB,YAAY,IAAU;AAOrF,SAAgB,EAAmB,EACjC,eAAA,IAAgB,GAAA,IACQ,CAAC,GAAoD;AAC7E,SAAA,CAAQ,MAAoB;AAW1B,QAVI,MACF,EAAM,KAAK,MAAM,EAAc,EAAM,KAAK,GAAG,GAC7C,EAAM,KAAK,WAAW,EAAc,EAAM,KAAK,QAAQ,GACnD,EAAM,SAAS,eAAY,EAAM,SAAS,MAAM,EAAc,EAAM,SAAS,GAAG,IAChF,EAAM,SAAS,WAAW,EAAM,MAAM,aACxC,EAAM,MAAM,SAAS,MAAM,EAAc,EAAM,MAAM,SAAS,GAAG,KAIjE,EAAM,SAAS,cACf,EAAM,SAAS,SAAS,SAAS,EAAM,SAAS,SAAS,QAAS,QAAO;AAC7E,UAAM,IAAS,EAAM,SAAS;AAC9B,WAAO,EAAE,MAAW,UAAa,IAAS,KAAK,IAAS;AAAA,EAC1D;AACF;AASA,IAAa,IAAgC;AAE7C,SAAgB,EACd,IAAA,IACyB;AACzB,QAAM,IAAsD,CAAC;AAC7D,SAAO;AAAA,IACL,KAAK,GAAO,GAAS;AACnB,aAAI,EAAM,UAAU,IAAgB,MACpC,EAAM,KAAK;AAAA,QAAE,OAAA;AAAA,QAAO,SAAA;AAAA,MAAQ,CAAC,GACtB;AAAA,IACT;AAAA,IACA,MAAM,GAAM;AACV,aAAO,EAAM,SAAS,KAAG;AACvB,cAAM,IAAO,EAAM,MAAM;AACzB,QAAI,KAAM,EAAK,EAAK,OAAO,EAAK,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,IACA,IAAI,OAAO;AACT,aAAO,EAAM;AAAA,IACf;AAAA,EACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.4.19",
3
+ "version": "9.4.21",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",
@@ -104,6 +104,10 @@
104
104
  "./trends": {
105
105
  "import": "./dist/trends/index.es.js",
106
106
  "types": "./dist/trends/index.d.ts"
107
+ },
108
+ "./rum": {
109
+ "import": "./dist/rum/index.es.js",
110
+ "types": "./dist/rum/index.d.ts"
107
111
  }
108
112
  },
109
113
  "typesVersions": {
@@ -179,6 +183,9 @@
179
183
  ],
180
184
  "trends": [
181
185
  "./dist/trends/index.d.ts"
186
+ ],
187
+ "rum": [
188
+ "./dist/rum/index.d.ts"
182
189
  ]
183
190
  }
184
191
  },
@@ -232,6 +239,7 @@
232
239
  },
233
240
  "devDependencies": {
234
241
  "@babel/core": "^7.29.7",
242
+ "@datadog/browser-rum": "7.12.0",
235
243
  "@storybook/addon-a11y": "^10.5.5",
236
244
  "@storybook/addon-docs": "^10.5.5",
237
245
  "@storybook/addon-links": "^10.5.5",
@@ -275,6 +283,7 @@
275
283
  "vitest": "^4.1.10"
276
284
  },
277
285
  "peerDependencies": {
286
+ "@datadog/browser-rum": "^7",
278
287
  "@mui/material": "^7",
279
288
  "@mxenabled/mxui": "^2",
280
289
  "d3": "^7",
@@ -300,5 +309,10 @@
300
309
  "workerDirectory": [
301
310
  ".storybook/static"
302
311
  ]
312
+ },
313
+ "peerDependenciesMeta": {
314
+ "@datadog/browser-rum": {
315
+ "optional": true
316
+ }
303
317
  }
304
318
  }