@mx-cartographer/experiences 9.4.42 → 9.4.43
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/CHANGELOG.md +8 -0
- package/dist/categories/components/CategoryList.es.js +34 -27
- package/dist/categories/components/CategoryList.es.js.map +1 -1
- package/dist/common/components/listitems/CollapseExpandListItem.es.js +26 -25
- package/dist/common/components/listitems/CollapseExpandListItem.es.js.map +1 -1
- package/dist/core/stores/TransactionStore.es.js +1 -1
- package/dist/core/stores/TransactionStore.es.js.map +1 -1
- package/dist/core/types/localization/CommonCopy.d.ts +2 -0
- package/dist/core/types/localization/TrendsCopy.d.ts +0 -1
- package/dist/core/utils/CategoryUtil.d.ts +11 -0
- package/dist/core/utils/CategoryUtil.es.js +36 -32
- package/dist/core/utils/CategoryUtil.es.js.map +1 -1
- package/dist/core/utils/NetWorthUtils.d.ts +2 -2
- package/dist/core/utils/NetWorthUtils.es.js +64 -64
- package/dist/core/utils/NetWorthUtils.es.js.map +1 -1
- package/dist/core/utils/TransactionUtils.d.ts +2 -2
- package/dist/core/utils/TransactionUtils.es.js +93 -92
- package/dist/core/utils/TransactionUtils.es.js.map +1 -1
- package/dist/debts/components/debtstable/AccountCell.es.js +13 -13
- package/dist/debts/components/debtstable/AccountCell.es.js.map +1 -1
- package/dist/finstrong/components/SpendLessThanYouMake/SpendLessThanYouMakeComponent.es.js +40 -36
- package/dist/finstrong/components/SpendLessThanYouMake/SpendLessThanYouMakeComponent.es.js.map +1 -1
- package/dist/networth/components/AssetsLiabilitiesDetail.es.js +47 -47
- package/dist/networth/components/AssetsLiabilitiesDetail.es.js.map +1 -1
- package/dist/spending/components/MiniSpendingChart.es.js +52 -47
- package/dist/spending/components/MiniSpendingChart.es.js.map +1 -1
- package/dist/spending/components/Spending.es.js +82 -74
- package/dist/spending/components/Spending.es.js.map +1 -1
- package/dist/spending/utils/SpendingData.d.ts +7 -5
- package/dist/spending/utils/SpendingData.es.js +34 -31
- package/dist/spending/utils/SpendingData.es.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,123 +1,131 @@
|
|
|
1
1
|
import { CategoryGuids as i } from "../../core/constants/Category.es.js";
|
|
2
|
-
import { useAppConfig as
|
|
3
|
-
import
|
|
4
|
-
import { exportTransactionsToCSV as
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { getIncomeData as
|
|
8
|
-
import
|
|
9
|
-
import
|
|
2
|
+
import { useAppConfig as O, useCategoryStore as K, useGlobalCopyStore as P, useGlobalUiStore as Q, useTransactionStore as X } from "../../common/context/hooks.es.js";
|
|
3
|
+
import G from "../../common/components/drawer/Drawer.es.js";
|
|
4
|
+
import { exportTransactionsToCSV as Y } from "../../core/utils/TransactionUtils.es.js";
|
|
5
|
+
import Z from "../../transactions/components/shared/TransactionList.es.js";
|
|
6
|
+
import tt from "../../transactions/components/shared/TransactionDetails.es.js";
|
|
7
|
+
import { getIncomeData as et, getSpendingData as ot } from "../utils/SpendingData.es.js";
|
|
8
|
+
import N from "./SpendingTabLabel.es.js";
|
|
9
|
+
import R from "./SpendingChart.es.js";
|
|
10
10
|
import s from "react";
|
|
11
|
-
import { observer as
|
|
12
|
-
import
|
|
13
|
-
import { Icon as
|
|
14
|
-
import
|
|
15
|
-
import { jsx as e, jsxs as
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import { useTheme as
|
|
20
|
-
var
|
|
11
|
+
import { observer as at } from "mobx-react-lite";
|
|
12
|
+
import k from "@mui/material/Stack";
|
|
13
|
+
import { Icon as nt } from "@mxenabled/mxui";
|
|
14
|
+
import rt from "@mui/material/Button";
|
|
15
|
+
import { jsx as e, jsxs as b } from "react/jsx-runtime";
|
|
16
|
+
import st from "@mui/material/Box";
|
|
17
|
+
import A from "@mui/material/Tab";
|
|
18
|
+
import it from "@mui/material/Tabs";
|
|
19
|
+
import { useTheme as ct } from "@mui/material";
|
|
20
|
+
var lt = (n) => [
|
|
21
21
|
n.palette.chartMono.chartMono5,
|
|
22
22
|
n.palette.chartMono.chartMono4,
|
|
23
23
|
n.palette.chartMono.chartMono3,
|
|
24
24
|
n.palette.chartMono.chartMono2,
|
|
25
25
|
n.palette.chartMono.chartMono1,
|
|
26
26
|
n.palette.chartMono.chartMono6
|
|
27
|
-
],
|
|
28
|
-
const n =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
], dt = () => {
|
|
28
|
+
const n = ct(), { is_mobile_webview: B } = O(), { clientConfig: T } = O(), { categories: c, dateRangeCategoryTotals: l } = K(), { categories: d, goals: V, spending: r, transactions: L } = P(), { displayedDateRange: y, selectedAccountGuids: v } = Q(), { setFilter: p, sortedTransactions: _, sortedTransactionsWithSplits: j, tags: F } = X(), m = T?.master?.deep_link_params?.account_guids, W = T?.master?.deep_link_params?.view, [u, M] = s.useState(""), [g, z] = s.useState(W === "income" ? 1 : 0), [w, I] = s.useState(""), [U, f] = s.useState(!1), h = s.useMemo(() => ot(c, V, d, n, l), [
|
|
29
|
+
c,
|
|
30
|
+
d,
|
|
31
|
+
l
|
|
32
|
+
]), x = s.useMemo(() => et(c, d, l, lt(n)), [
|
|
33
|
+
c,
|
|
34
|
+
d,
|
|
35
|
+
l
|
|
36
|
+
]), S = s.useMemo(() => _.find((t) => t.guid === w), [w, _]), $ = (t, a) => {
|
|
37
|
+
z(a), M("");
|
|
38
|
+
}, D = (t, a = !1) => {
|
|
39
|
+
a ? q(t) : M(u === t || t === "0" ? "" : t);
|
|
40
|
+
}, q = (t) => {
|
|
41
|
+
p({
|
|
42
|
+
accounts: m || v,
|
|
43
|
+
dateRange: y,
|
|
44
|
+
custom: (a) => u === "other" ? a.top_level_category_guid === t : a.category_guid === t,
|
|
37
45
|
showSplits: !0
|
|
38
|
-
}),
|
|
39
|
-
},
|
|
46
|
+
}), f(!0);
|
|
47
|
+
}, E = (t) => {
|
|
40
48
|
const a = {
|
|
41
|
-
accounts:
|
|
42
|
-
dateRange:
|
|
49
|
+
accounts: m || v,
|
|
50
|
+
dateRange: y
|
|
43
51
|
};
|
|
44
|
-
if (
|
|
45
|
-
const o =
|
|
46
|
-
|
|
52
|
+
if (g === 0) if (t === "other") {
|
|
53
|
+
const o = h.categoryData.find((C) => C.guid === "other");
|
|
54
|
+
p({
|
|
47
55
|
...a,
|
|
48
|
-
custom: (
|
|
56
|
+
custom: (C) => !!o?.categoryTotals?.find((J) => J.guid === C.top_level_category_guid)
|
|
49
57
|
});
|
|
50
|
-
} else
|
|
58
|
+
} else p({
|
|
51
59
|
...a,
|
|
52
60
|
custom: (o) => t ? o.top_level_category_guid === t : o.top_level_category_guid !== i.INCOME && o.category_guid !== i.INCOME && o.top_level_category_guid !== i.INVESTMENTS && o.top_level_category_guid !== i.TRANSFER,
|
|
53
61
|
showSplits: !!t
|
|
54
62
|
});
|
|
55
|
-
else
|
|
63
|
+
else p({
|
|
56
64
|
...a,
|
|
57
65
|
custom: (o) => t ? o.category_guid === t : o.category_guid === i.INCOME || o.top_level_category_guid === i.INCOME
|
|
58
66
|
});
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
|
|
67
|
+
f(!0);
|
|
68
|
+
}, H = () => {
|
|
69
|
+
Y(j, F);
|
|
62
70
|
};
|
|
63
|
-
return /* @__PURE__ */
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
-
onChange:
|
|
66
|
-
value:
|
|
71
|
+
return /* @__PURE__ */ b(st, { children: [
|
|
72
|
+
/* @__PURE__ */ b(it, {
|
|
73
|
+
onChange: $,
|
|
74
|
+
value: g,
|
|
67
75
|
variant: "fullWidth",
|
|
68
|
-
children: [/* @__PURE__ */ e(
|
|
69
|
-
amount:
|
|
76
|
+
children: [/* @__PURE__ */ e(A, { label: /* @__PURE__ */ e(N, {
|
|
77
|
+
amount: h.totalAmount,
|
|
70
78
|
label: r.spend_tab_title
|
|
71
|
-
}) }), /* @__PURE__ */ e(
|
|
72
|
-
amount:
|
|
79
|
+
}) }), /* @__PURE__ */ e(A, { label: /* @__PURE__ */ e(N, {
|
|
80
|
+
amount: x.totalAmount,
|
|
73
81
|
label: r.income_tab_title
|
|
74
82
|
}) })]
|
|
75
83
|
}),
|
|
76
|
-
|
|
77
|
-
data:
|
|
78
|
-
onSelected:
|
|
79
|
-
onViewTransactions:
|
|
80
|
-
selectedId:
|
|
84
|
+
g === 0 && /* @__PURE__ */ e(R, {
|
|
85
|
+
data: h,
|
|
86
|
+
onSelected: D,
|
|
87
|
+
onViewTransactions: E,
|
|
88
|
+
selectedId: u,
|
|
81
89
|
title: r.spend_tab_title
|
|
82
90
|
}),
|
|
83
|
-
|
|
84
|
-
data:
|
|
85
|
-
onSelected:
|
|
86
|
-
onViewTransactions:
|
|
87
|
-
selectedId:
|
|
91
|
+
g === 1 && /* @__PURE__ */ e(R, {
|
|
92
|
+
data: x,
|
|
93
|
+
onSelected: D,
|
|
94
|
+
onViewTransactions: E,
|
|
95
|
+
selectedId: u,
|
|
88
96
|
title: r.income_tab_title
|
|
89
97
|
}),
|
|
90
|
-
/* @__PURE__ */ e(
|
|
98
|
+
/* @__PURE__ */ e(G, {
|
|
91
99
|
ariaLabelClose: r.close_drawer_aria,
|
|
92
|
-
isOpen:
|
|
93
|
-
onClose: () =>
|
|
100
|
+
isOpen: U,
|
|
101
|
+
onClose: () => f(!1),
|
|
94
102
|
title: r.transactions_drawer_title,
|
|
95
|
-
children: /* @__PURE__ */
|
|
103
|
+
children: /* @__PURE__ */ b(k, { children: [!B && _.length > 0 && /* @__PURE__ */ e(k, {
|
|
96
104
|
direction: "row",
|
|
97
105
|
justifyContent: "right",
|
|
98
106
|
mb: -24,
|
|
99
107
|
mr: 8,
|
|
100
108
|
mt: 8,
|
|
101
109
|
zIndex: 1,
|
|
102
|
-
children: /* @__PURE__ */ e(
|
|
103
|
-
onClick:
|
|
104
|
-
startIcon: /* @__PURE__ */ e(
|
|
110
|
+
children: /* @__PURE__ */ e(rt, {
|
|
111
|
+
onClick: H,
|
|
112
|
+
startIcon: /* @__PURE__ */ e(nt, { name: "ios_share" }),
|
|
105
113
|
variant: "text",
|
|
106
|
-
children:
|
|
114
|
+
children: L.export_csv_btn
|
|
107
115
|
})
|
|
108
|
-
}), /* @__PURE__ */ e(
|
|
116
|
+
}), /* @__PURE__ */ e(Z, { onClick: I })] })
|
|
109
117
|
}),
|
|
110
|
-
/* @__PURE__ */ e(
|
|
118
|
+
/* @__PURE__ */ e(G, {
|
|
111
119
|
ariaLabelClose: r.close_drawer_aria,
|
|
112
|
-
isOpen: !!
|
|
113
|
-
onClose: () =>
|
|
120
|
+
isOpen: !!S,
|
|
121
|
+
onClose: () => I(""),
|
|
114
122
|
title: r.transaction_details_drawer_title,
|
|
115
|
-
children:
|
|
123
|
+
children: S && /* @__PURE__ */ e(tt, { transaction: S })
|
|
116
124
|
})
|
|
117
125
|
] });
|
|
118
|
-
},
|
|
126
|
+
}, Ot = at(dt);
|
|
119
127
|
export {
|
|
120
|
-
|
|
128
|
+
Ot as default
|
|
121
129
|
};
|
|
122
130
|
|
|
123
131
|
//# sourceMappingURL=Spending.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spending.es.js","names":[],"sources":["../../../src/spending/components/Spending.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\nimport { useTheme } from '@mui/material'\nimport type { Theme } from '@mui/system'\n\nimport { Icon } from '@mxenabled/mxui'\n\nimport {\n Drawer,\n useAppConfig,\n useCategoryStore,\n useGlobalCopyStore,\n useGlobalUiStore,\n useTransactionStore,\n} from '../../common'\nimport { CategoryGuids } from '../../core/constants'\nimport { Transaction } from '../../core'\nimport { exportTransactionsToCSV } from '../../core/utils/TransactionUtils'\n\nimport { TransactionDetails, TransactionList } from '../../transactions'\nimport { getIncomeData, getSpendingData } from '../utils/SpendingData'\nimport SpendingChart from './SpendingChart'\nimport SpendingTabLabel from './SpendingTabLabel'\n\nconst getIncomeColors = (theme: Theme) => {\n return [\n theme.palette.chartMono.chartMono5,\n theme.palette.chartMono.chartMono4,\n theme.palette.chartMono.chartMono3,\n theme.palette.chartMono.chartMono2,\n theme.palette.chartMono.chartMono1,\n theme.palette.chartMono.chartMono6,\n ]\n}\n\nconst Spending = () => {\n const theme = useTheme()\n const { is_mobile_webview } = useAppConfig()\n\n const { clientConfig } = useAppConfig()\n const { categories, dateRangeCategoryTotals } = useCategoryStore()\n\n const {\n goals: goalsCopy,\n spending: spendingCopy,\n transactions: transactionCopy,\n } = useGlobalCopyStore()\n const { displayedDateRange, selectedAccountGuids } = useGlobalUiStore()\n const {\n setFilter,\n sortedTransactions: transactions,\n sortedTransactionsWithSplits,\n tags,\n } = useTransactionStore()\n\n const accountGuids = clientConfig?.master?.deep_link_params?.account_guids\n const view = clientConfig?.master?.deep_link_params?.view\n\n const [selectedId, setSelectedId] = React.useState('')\n const [selectedTab, setSelectedTab] = React.useState(view === 'income' ? 1 : 0)\n const [transactionGuid, setTransactionGuid] = React.useState('')\n const [transactionsOpen, setTransactionsOpen] = React.useState(false)\n\n const spendingData = React.useMemo(\n () => getSpendingData(categories, goalsCopy, theme, dateRangeCategoryTotals),\n [categories, dateRangeCategoryTotals],\n )\n\n const incomeData = React.useMemo(\n () => getIncomeData(categories, dateRangeCategoryTotals, getIncomeColors(theme)),\n [categories, dateRangeCategoryTotals],\n )\n\n const transaction = React.useMemo(\n () => transactions.find((t) => t.guid === transactionGuid),\n [transactionGuid, transactions],\n )\n\n const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {\n setSelectedTab(newValue)\n setSelectedId('')\n }\n\n const handleSelected = (id: string, isSubcategory: boolean = false) => {\n if (isSubcategory) {\n handleSelectedSubcategory(id)\n } else {\n setSelectedId(selectedId === id || id === '0' ? '' : id)\n }\n }\n\n const handleSelectedSubcategory = (id: string) => {\n const transactionFilter = {\n accounts: accountGuids ? accountGuids : selectedAccountGuids,\n dateRange: displayedDateRange,\n }\n\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n selectedId === 'other' ? t.top_level_category_guid === id : t.category_guid === id,\n showSplits: true,\n })\n\n setTransactionsOpen(true)\n }\n\n const handleViewTransactions = (id: string) => {\n const transactionFilter = {\n accounts: accountGuids ? accountGuids : selectedAccountGuids,\n dateRange: displayedDateRange,\n }\n\n if (selectedTab === 0) {\n // Spending\n if (id === 'other') {\n const other = spendingData.categoryData.find((c) => c.guid === 'other')\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n Boolean(other?.categoryTotals?.find((ct) => ct.guid === t.top_level_category_guid)),\n })\n } else {\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n id\n ? t.top_level_category_guid === id\n : t.top_level_category_guid !== CategoryGuids.INCOME &&\n t.category_guid !== CategoryGuids.INCOME &&\n t.top_level_category_guid !== CategoryGuids.INVESTMENTS &&\n t.top_level_category_guid !== CategoryGuids.TRANSFER,\n showSplits: Boolean(id),\n })\n }\n } else {\n // Income\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n id\n ? t.category_guid === id\n : t.category_guid === CategoryGuids.INCOME ||\n t.top_level_category_guid === CategoryGuids.INCOME,\n })\n }\n\n setTransactionsOpen(true)\n }\n\n const handleExportToCsv = () => {\n exportTransactionsToCSV(sortedTransactionsWithSplits, tags)\n }\n\n return (\n <Box>\n <Tabs onChange={handleTabChange} value={selectedTab} variant=\"fullWidth\">\n <Tab\n label={\n <SpendingTabLabel\n amount={spendingData.totalAmount}\n label={spendingCopy.spend_tab_title}\n />\n }\n />\n <Tab\n label={\n <SpendingTabLabel\n amount={incomeData.totalAmount}\n label={spendingCopy.income_tab_title}\n />\n }\n />\n </Tabs>\n {selectedTab === 0 && (\n <SpendingChart\n data={spendingData}\n onSelected={handleSelected}\n onViewTransactions={handleViewTransactions}\n selectedId={selectedId}\n title={spendingCopy.spend_tab_title}\n />\n )}\n {selectedTab === 1 && (\n <SpendingChart\n data={incomeData}\n onSelected={handleSelected}\n onViewTransactions={handleViewTransactions}\n selectedId={selectedId}\n title={spendingCopy.income_tab_title}\n />\n )}\n <Drawer\n ariaLabelClose={spendingCopy.close_drawer_aria}\n isOpen={transactionsOpen}\n onClose={() => setTransactionsOpen(false)}\n title={spendingCopy.transactions_drawer_title}\n >\n <Stack>\n {!is_mobile_webview && transactions.length > 0 && (\n <Stack direction=\"row\" justifyContent=\"right\" mb={-24} mr={8} mt={8} zIndex={1}>\n <Button\n onClick={handleExportToCsv}\n startIcon={<Icon name=\"ios_share\" />}\n variant=\"text\"\n >\n {transactionCopy.export_csv_btn}\n </Button>\n </Stack>\n )}\n <TransactionList onClick={setTransactionGuid} />\n </Stack>\n </Drawer>\n <Drawer\n ariaLabelClose={spendingCopy.close_drawer_aria}\n isOpen={Boolean(transaction)}\n onClose={() => setTransactionGuid('')}\n title={spendingCopy.transaction_details_drawer_title}\n >\n {transaction && <TransactionDetails transaction={transaction} />}\n </Drawer>\n </Box>\n )\n}\n\nexport default observer(Spending)\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8BA,IAAM,KAAA,CAAmB,MAChB;AAAA,EACL,EAAM,QAAQ,UAAU;AAAA,EACxB,EAAM,QAAQ,UAAU;AAAA,EACxB,EAAM,QAAQ,UAAU;AAAA,EACxB,EAAM,QAAQ,UAAU;AAAA,EACxB,EAAM,QAAQ,UAAU;AAAA,EACxB,EAAM,QAAQ,UAAU;AAC1B,GAGI,KAAA,MAAiB;AACrB,QAAM,IAAQ,GAAS,GACjB,EAAE,mBAAA,EAAA,IAAsB,EAAa,GAErC,EAAE,cAAA,EAAA,IAAiB,EAAa,GAChC,EAAE,YAAA,GAAY,yBAAA,EAAA,IAA4B,EAAiB,GAE3D,EACJ,OAAO,GACP,UAAU,GACV,cAAc,EAAA,IACZ,EAAmB,GACjB,EAAE,oBAAA,GAAoB,sBAAA,EAAA,IAAyB,EAAiB,GAChE,EACJ,WAAA,GACA,oBAAoB,GACpB,8BAAA,GACA,MAAA,EAAA,IACE,EAAoB,GAElB,IAAe,GAAc,QAAQ,kBAAkB,eACvD,IAAO,GAAc,QAAQ,kBAAkB,MAE/C,CAAC,GAAY,CAAA,IAAiB,EAAM,SAAS,EAAE,GAC/C,CAAC,GAAa,CAAA,IAAkB,EAAM,SAAS,MAAS,WAAW,IAAI,CAAC,GACxE,CAAC,GAAiB,CAAA,IAAsB,EAAM,SAAS,EAAE,GACzD,CAAC,GAAkB,CAAA,IAAuB,EAAM,SAAS,EAAK,GAE9D,IAAe,EAAM,QAAA,MACnB,GAAgB,GAAY,GAAW,GAAO,CAAuB,GAC3E,CAAC,GAAY,CAAuB,CACtC,GAEM,IAAa,EAAM,QAAA,MACjB,GAAc,GAAY,GAAyB,GAAgB,CAAK,CAAC,GAC/E,CAAC,GAAY,CAAuB,CACtC,GAEM,IAAc,EAAM,QAAA,MAClB,EAAa,KAAA,CAAM,MAAM,EAAE,SAAS,CAAe,GACzD,CAAC,GAAiB,CAAY,CAChC,GAEM,IAAA,CAAmB,GAA8B,MAAqB;AAC1E,IAAA,EAAe,CAAQ,GACvB,EAAc,EAAE;AAAA,EAClB,GAEM,IAAA,CAAkB,GAAY,IAAyB,OAAU;AACrE,IAAI,IACF,EAA0B,CAAE,IAE5B,EAAc,MAAe,KAAM,MAAO,MAAM,KAAK,CAAE;AAAA,EAE3D,GAEM,IAAA,CAA6B,MAAe;AAMhD,IAAA,EAAU;AAAA,MAJR,UAAU,KAA8B;AAAA,MACxC,WAAW;AAAA,MAKX,QAAA,CAAS,MACP,MAAe,UAAU,EAAE,4BAA4B,IAAK,EAAE,kBAAkB;AAAA,MAClF,YAAY;AAAA,IACd,CAAC,GAED,EAAoB,EAAI;AAAA,EAC1B,GAEM,IAAA,CAA0B,MAAe;AAC7C,UAAM,IAAoB;AAAA,MACxB,UAAU,KAA8B;AAAA,MACxC,WAAW;AAAA,IACb;AAEA,QAAI,MAAgB,EAElB,KAAI,MAAO,SAAS;AAClB,YAAM,IAAQ,EAAa,aAAa,KAAA,CAAM,MAAM,EAAE,SAAS,OAAO;AACtE,MAAA,EAAU;AAAA,QACR,GAAG;AAAA,QACH,QAAA,CAAS,MACP,EAAQ,GAAO,gBAAgB,KAAA,CAAM,MAAO,EAAG,SAAS,EAAE,uBAAuB;AAAA,MACrF,CAAC;AAAA,IACH,MACE,CAAA,EAAU;AAAA,MACR,GAAG;AAAA,MACH,QAAA,CAAS,MACP,IACI,EAAE,4BAA4B,IAC9B,EAAE,4BAA4B,EAAc,UAC5C,EAAE,kBAAkB,EAAc,UAClC,EAAE,4BAA4B,EAAc,eAC5C,EAAE,4BAA4B,EAAc;AAAA,MAClD,YAAY,EAAQ;AAAA,IACtB,CAAC;AAAA,QAIH,CAAA,EAAU;AAAA,MACR,GAAG;AAAA,MACH,QAAA,CAAS,MACP,IACI,EAAE,kBAAkB,IACpB,EAAE,kBAAkB,EAAc,UAClC,EAAE,4BAA4B,EAAc;AAAA,IACpD,CAAC;AAGH,IAAA,EAAoB,EAAI;AAAA,EAC1B,GAEM,IAAA,MAA0B;AAC9B,IAAA,EAAwB,GAA8B,CAAI;AAAA,EAC5D;AAEA,SACE,gBAAA,EAAC,IAAD,EAAA,UAAA;AAAA,IACE,gBAAA,EAAC,IAAD;AAAA,MAAM,UAAU;AAAA,MAAiB,OAAO;AAAA,MAAa,SAAQ;AAAA,MAA7D,UAAA,CACE,gBAAA,EAAC,GAAD,EACE,OACE,gBAAA,EAAC,GAAD;AAAA,QACE,QAAQ,EAAa;AAAA,QACrB,OAAO,EAAa;AAAA,MACrB,CAAA,EAEJ,CAAA,GACD,gBAAA,EAAC,GAAD,EACE,OACE,gBAAA,EAAC,GAAD;AAAA,QACE,QAAQ,EAAW;AAAA,QACnB,OAAO,EAAa;AAAA,MACrB,CAAA,EAEJ,CAAA,CACG;AAAA;IACL,MAAgB,KACf,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACR,YAAA;AAAA,MACZ,OAAO,EAAa;AAAA,IACrB,CAAA;AAAA,IAEF,MAAgB,KACf,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACR,YAAA;AAAA,MACZ,OAAO,EAAa;AAAA,IACrB,CAAA;AAAA,IAEH,gBAAA,EAAC,GAAD;AAAA,MACE,gBAAgB,EAAa;AAAA,MAC7B,QAAQ;AAAA,MACR,SAAA,MAAe,EAAoB,EAAK;AAAA,MACxC,OAAO,EAAa;AAAA,MAEpB,UAAA,gBAAA,EAAC,GAAD,EAAA,UAAA,CACG,CAAC,KAAqB,EAAa,SAAS,KAC3C,gBAAA,EAAC,GAAD;AAAA,QAAO,WAAU;AAAA,QAAM,gBAAe;AAAA,QAAQ,IAAI;AAAA,QAAK,IAAI;AAAA,QAAG,IAAI;AAAA,QAAG,QAAQ;AAAA,QAC3E,UAAA,gBAAA,EAAC,IAAD;AAAA,UACE,SAAS;AAAA,UACT,WAAW,gBAAA,EAAC,IAAD,EAAM,MAAK,YAAa,CAAA;AAAA,UACnC,SAAQ;AAAA,UAEP,UAAA,EAAgB;AAAA,QACX,CAAA;AAAA,MACH,CAAA,GAET,gBAAA,EAAC,GAAD,EAAiB,SAAS,EAAqB,CAAA,CAC1C,EAAA,CAAA;AAAA,IACD,CAAA;AAAA,IACR,gBAAA,EAAC,GAAD;AAAA,MACE,gBAAgB,EAAa;AAAA,MAC7B,QAAQ,EAAQ;AAAA,MAChB,SAAA,MAAe,EAAmB,EAAE;AAAA,MACpC,OAAO,EAAa;AAAA,MAEnB,UAAA,KAAe,gBAAA,EAAC,GAAD,EAAiC,aAAA,EAAc,CAAA;AAAA,IACzD,CAAA;AAAA,EACL,EAAA,CAAA;AAET,GAEA,KAAe,GAAS,EAAQ"}
|
|
1
|
+
{"version":3,"file":"Spending.es.js","names":[],"sources":["../../../src/spending/components/Spending.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\nimport { useTheme } from '@mui/material'\nimport type { Theme } from '@mui/system'\n\nimport { Icon } from '@mxenabled/mxui'\n\nimport {\n Drawer,\n useAppConfig,\n useCategoryStore,\n useGlobalCopyStore,\n useGlobalUiStore,\n useTransactionStore,\n} from '../../common'\nimport { CategoryGuids } from '../../core/constants'\nimport { Transaction } from '../../core'\nimport { exportTransactionsToCSV } from '../../core/utils/TransactionUtils'\n\nimport { TransactionDetails, TransactionList } from '../../transactions'\nimport { getIncomeData, getSpendingData } from '../utils/SpendingData'\nimport SpendingChart from './SpendingChart'\nimport SpendingTabLabel from './SpendingTabLabel'\n\nconst getIncomeColors = (theme: Theme) => {\n return [\n theme.palette.chartMono.chartMono5,\n theme.palette.chartMono.chartMono4,\n theme.palette.chartMono.chartMono3,\n theme.palette.chartMono.chartMono2,\n theme.palette.chartMono.chartMono1,\n theme.palette.chartMono.chartMono6,\n ]\n}\n\nconst Spending = () => {\n const theme = useTheme()\n const { is_mobile_webview } = useAppConfig()\n\n const { clientConfig } = useAppConfig()\n const { categories, dateRangeCategoryTotals } = useCategoryStore()\n\n const {\n categories: categoriesCopy,\n goals: goalsCopy,\n spending: spendingCopy,\n transactions: transactionCopy,\n } = useGlobalCopyStore()\n const { displayedDateRange, selectedAccountGuids } = useGlobalUiStore()\n const {\n setFilter,\n sortedTransactions: transactions,\n sortedTransactionsWithSplits,\n tags,\n } = useTransactionStore()\n\n const accountGuids = clientConfig?.master?.deep_link_params?.account_guids\n const view = clientConfig?.master?.deep_link_params?.view\n\n const [selectedId, setSelectedId] = React.useState('')\n const [selectedTab, setSelectedTab] = React.useState(view === 'income' ? 1 : 0)\n const [transactionGuid, setTransactionGuid] = React.useState('')\n const [transactionsOpen, setTransactionsOpen] = React.useState(false)\n\n const spendingData = React.useMemo(\n () => getSpendingData(categories, goalsCopy, categoriesCopy, theme, dateRangeCategoryTotals),\n [categories, categoriesCopy, dateRangeCategoryTotals],\n )\n\n const incomeData = React.useMemo(\n () =>\n getIncomeData(categories, categoriesCopy, dateRangeCategoryTotals, getIncomeColors(theme)),\n [categories, categoriesCopy, dateRangeCategoryTotals],\n )\n\n const transaction = React.useMemo(\n () => transactions.find((t) => t.guid === transactionGuid),\n [transactionGuid, transactions],\n )\n\n const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {\n setSelectedTab(newValue)\n setSelectedId('')\n }\n\n const handleSelected = (id: string, isSubcategory: boolean = false) => {\n if (isSubcategory) {\n handleSelectedSubcategory(id)\n } else {\n setSelectedId(selectedId === id || id === '0' ? '' : id)\n }\n }\n\n const handleSelectedSubcategory = (id: string) => {\n const transactionFilter = {\n accounts: accountGuids ? accountGuids : selectedAccountGuids,\n dateRange: displayedDateRange,\n }\n\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n selectedId === 'other' ? t.top_level_category_guid === id : t.category_guid === id,\n showSplits: true,\n })\n\n setTransactionsOpen(true)\n }\n\n const handleViewTransactions = (id: string) => {\n const transactionFilter = {\n accounts: accountGuids ? accountGuids : selectedAccountGuids,\n dateRange: displayedDateRange,\n }\n\n if (selectedTab === 0) {\n // Spending\n if (id === 'other') {\n const other = spendingData.categoryData.find((c) => c.guid === 'other')\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n Boolean(other?.categoryTotals?.find((ct) => ct.guid === t.top_level_category_guid)),\n })\n } else {\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n id\n ? t.top_level_category_guid === id\n : t.top_level_category_guid !== CategoryGuids.INCOME &&\n t.category_guid !== CategoryGuids.INCOME &&\n t.top_level_category_guid !== CategoryGuids.INVESTMENTS &&\n t.top_level_category_guid !== CategoryGuids.TRANSFER,\n showSplits: Boolean(id),\n })\n }\n } else {\n // Income\n setFilter({\n ...transactionFilter,\n custom: (t: Transaction) =>\n id\n ? t.category_guid === id\n : t.category_guid === CategoryGuids.INCOME ||\n t.top_level_category_guid === CategoryGuids.INCOME,\n })\n }\n\n setTransactionsOpen(true)\n }\n\n const handleExportToCsv = () => {\n exportTransactionsToCSV(sortedTransactionsWithSplits, tags)\n }\n\n return (\n <Box>\n <Tabs onChange={handleTabChange} value={selectedTab} variant=\"fullWidth\">\n <Tab\n label={\n <SpendingTabLabel\n amount={spendingData.totalAmount}\n label={spendingCopy.spend_tab_title}\n />\n }\n />\n <Tab\n label={\n <SpendingTabLabel\n amount={incomeData.totalAmount}\n label={spendingCopy.income_tab_title}\n />\n }\n />\n </Tabs>\n {selectedTab === 0 && (\n <SpendingChart\n data={spendingData}\n onSelected={handleSelected}\n onViewTransactions={handleViewTransactions}\n selectedId={selectedId}\n title={spendingCopy.spend_tab_title}\n />\n )}\n {selectedTab === 1 && (\n <SpendingChart\n data={incomeData}\n onSelected={handleSelected}\n onViewTransactions={handleViewTransactions}\n selectedId={selectedId}\n title={spendingCopy.income_tab_title}\n />\n )}\n <Drawer\n ariaLabelClose={spendingCopy.close_drawer_aria}\n isOpen={transactionsOpen}\n onClose={() => setTransactionsOpen(false)}\n title={spendingCopy.transactions_drawer_title}\n >\n <Stack>\n {!is_mobile_webview && transactions.length > 0 && (\n <Stack direction=\"row\" justifyContent=\"right\" mb={-24} mr={8} mt={8} zIndex={1}>\n <Button\n onClick={handleExportToCsv}\n startIcon={<Icon name=\"ios_share\" />}\n variant=\"text\"\n >\n {transactionCopy.export_csv_btn}\n </Button>\n </Stack>\n )}\n <TransactionList onClick={setTransactionGuid} />\n </Stack>\n </Drawer>\n <Drawer\n ariaLabelClose={spendingCopy.close_drawer_aria}\n isOpen={Boolean(transaction)}\n onClose={() => setTransactionGuid('')}\n title={spendingCopy.transaction_details_drawer_title}\n >\n {transaction && <TransactionDetails transaction={transaction} />}\n </Drawer>\n </Box>\n )\n}\n\nexport default observer(Spending)\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Theme } from '@mui/material';
|
|
2
|
-
import { Category, DateRangeCategoryTotals, GoalsCopy } from '../../core';
|
|
2
|
+
import { Category, CategoryCopy, DateRangeCategoryTotals, GoalsCopy } from '../../core';
|
|
3
3
|
import { DonutData } from '../../common/components/charts/Donut';
|
|
4
4
|
export interface CategoryTotal {
|
|
5
5
|
guid: string;
|
|
@@ -18,18 +18,20 @@ export interface SpendingData {
|
|
|
18
18
|
* Excludes Income and Transfers
|
|
19
19
|
*
|
|
20
20
|
* @param categories - Array of all categories
|
|
21
|
-
* @param
|
|
21
|
+
* @param goalsCopy - Goals copy (supplies the "Other" bucket + parent rollup labels)
|
|
22
|
+
* @param categoryCopy - Category copy (default category names)
|
|
22
23
|
* @param theme - The current theme to use for colors
|
|
23
24
|
* @param totals - And array of type DateRangeCategoryTotals
|
|
24
25
|
*/
|
|
25
|
-
export declare const getSpendingData: (categories: Category[],
|
|
26
|
-
theme: Theme, totals: DateRangeCategoryTotals[]) => SpendingData;
|
|
26
|
+
export declare const getSpendingData: (categories: Category[], goalsCopy: GoalsCopy, // TODO: Replace after `Other` is added to SpendingCopy
|
|
27
|
+
categoryCopy: CategoryCopy, theme: Theme, totals: DateRangeCategoryTotals[]) => SpendingData;
|
|
27
28
|
/**
|
|
28
29
|
* Returns an object of type SpendingData containing a subset of category totals related to income
|
|
29
30
|
* Only includes Income subcategories
|
|
30
31
|
*
|
|
31
32
|
* @param categories - Array of all categories
|
|
33
|
+
* @param categoryCopy - Localized category copy (default category names)
|
|
32
34
|
* @param monthlyTotals - And array of type DateRangeCategoryTotals
|
|
33
35
|
* @param colors - An array of color strings to use for income colors
|
|
34
36
|
*/
|
|
35
|
-
export declare const getIncomeData: (categories: Category[], monthlyTotals: DateRangeCategoryTotals[], colors: string[]) => SpendingData;
|
|
37
|
+
export declare const getIncomeData: (categories: Category[], categoryCopy: CategoryCopy, monthlyTotals: DateRangeCategoryTotals[], colors: string[]) => SpendingData;
|
|
@@ -1,58 +1,61 @@
|
|
|
1
|
-
import { CategoryGuids as
|
|
2
|
-
import { getCategoryColor as
|
|
3
|
-
var
|
|
1
|
+
import { CategoryGuids as p } from "../../core/constants/Category.es.js";
|
|
2
|
+
import { getCategoryColor as f, getLocalizedCategoryName as h } from "../../core/utils/CategoryUtil.es.js";
|
|
3
|
+
var _ = 5, y = (i, l, s, r, m) => m.reduce((a, n) => {
|
|
4
4
|
const t = i.find((d) => d.guid === n.category_guid);
|
|
5
5
|
if (!t) return a;
|
|
6
|
-
const e = t.parent_guid ?? t.guid,
|
|
7
|
-
if (!
|
|
8
|
-
const o = {
|
|
6
|
+
const e = t.parent_guid ?? t.guid, u = i.find((d) => d.guid === e);
|
|
7
|
+
if (!u || n.total <= 0) return a;
|
|
8
|
+
const o = h(t, s), g = {
|
|
9
9
|
guid: t.guid,
|
|
10
|
-
name: t.guid === e ? `${l.parent_category_totals_label_general} ${
|
|
11
|
-
color:
|
|
10
|
+
name: t.guid === e ? `${l.parent_category_totals_label_general} ${o}` : o,
|
|
11
|
+
color: f(u.guid, r),
|
|
12
12
|
amount: n.total
|
|
13
|
-
},
|
|
14
|
-
return
|
|
13
|
+
}, c = a.find((d) => d.guid === e);
|
|
14
|
+
return c ? (c.amount += n.total, c.categoryTotals?.push(g)) : a.push({
|
|
15
15
|
guid: e,
|
|
16
|
-
name:
|
|
17
|
-
color:
|
|
18
|
-
categoryTotals: [
|
|
16
|
+
name: h(u, s),
|
|
17
|
+
color: f(u.guid, r),
|
|
18
|
+
categoryTotals: [g],
|
|
19
19
|
amount: n.total
|
|
20
20
|
}), a;
|
|
21
|
-
}, []),
|
|
22
|
-
const a =
|
|
21
|
+
}, []), T = (i, l, s, r, m) => {
|
|
22
|
+
const a = y(i, l, s, r, m).filter((o) => o.guid !== p.INCOME && o.guid !== p.INVESTMENTS && o.guid !== p.TRANSFER && o.amount > 0).sort((o, g) => g.amount - o.amount), n = a.reduce((o, g) => o + g.amount, 0), t = a.length > _ ? _ : a.length, e = a.slice(0, t), u = e.map((o) => ({
|
|
23
23
|
id: o.guid,
|
|
24
|
-
color:
|
|
24
|
+
color: f(o.guid, r),
|
|
25
25
|
label: o.name,
|
|
26
26
|
value: o.amount / n * 100
|
|
27
27
|
}));
|
|
28
28
|
if (a.length > 5) {
|
|
29
|
-
const o = a.slice(
|
|
29
|
+
const o = a.slice(_), g = o.reduce((c, d) => c + d.amount, 0);
|
|
30
30
|
e.push({
|
|
31
31
|
guid: "other",
|
|
32
32
|
color: r.palette.categories.others || "",
|
|
33
33
|
name: l.saving_goal_other,
|
|
34
34
|
categoryTotals: o,
|
|
35
|
-
amount:
|
|
36
|
-
}),
|
|
35
|
+
amount: g
|
|
36
|
+
}), u.push({
|
|
37
37
|
id: "other",
|
|
38
38
|
color: r.palette.categories.others || "",
|
|
39
39
|
label: l.saving_goal_other,
|
|
40
|
-
value:
|
|
40
|
+
value: g / n * 100
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
return {
|
|
44
44
|
categoryData: e,
|
|
45
|
-
donutData:
|
|
45
|
+
donutData: u,
|
|
46
46
|
totalAmount: n
|
|
47
47
|
};
|
|
48
|
-
},
|
|
49
|
-
const
|
|
50
|
-
guid
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
}, N = (i, l, s, r) => {
|
|
49
|
+
const m = i.filter((t) => t.guid === p.INCOME || t.parent_guid === p.INCOME), a = s.filter((t) => m.some((e) => e.guid === t.category_guid)).sort((t, e) => t.total - e.total).map((t, e) => {
|
|
50
|
+
const u = i.find((o) => o.guid === t.category_guid);
|
|
51
|
+
return {
|
|
52
|
+
guid: t.category_guid,
|
|
53
|
+
name: u ? h(u, l) : void 0,
|
|
54
|
+
color: r[e % r.length],
|
|
55
|
+
categoryTotals: [],
|
|
56
|
+
amount: Math.abs(t.total)
|
|
57
|
+
};
|
|
58
|
+
}), n = a.reduce((t, e) => t + e.amount, 0);
|
|
56
59
|
return {
|
|
57
60
|
categoryData: a,
|
|
58
61
|
donutData: a.map((t) => ({
|
|
@@ -65,8 +68,8 @@ var c = 5, f = (i, l, r, s) => s.reduce((a, n) => {
|
|
|
65
68
|
};
|
|
66
69
|
};
|
|
67
70
|
export {
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
N as getIncomeData,
|
|
72
|
+
T as getSpendingData
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
//# sourceMappingURL=SpendingData.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpendingData.es.js","names":[],"sources":["../../../src/spending/utils/SpendingData.ts"],"sourcesContent":["import { Theme } from '@mui/material'\n\nimport { getCategoryColor } from '../../core/utils/CategoryUtil'\nimport { CategoryGuids } from '../../core/constants'\nimport { Category, DateRangeCategoryTotals, GoalsCopy } from '../../core'\nimport type { DonutData } from '../../common/components/charts/Donut'\n\nconst TOP_CATEGORY_LENGTH = 5\n\nexport interface CategoryTotal {\n guid: string\n name: string\n color: string\n categoryTotals?: CategoryTotal[]\n amount: number\n}\n\nexport interface SpendingData {\n categoryData: CategoryTotal[]\n donutData: DonutData[]\n totalAmount: number\n}\n\n/**\n * Rolls all categories up into parent categories and return an array of CategoryTotal items.\n * @param categories - Array of all categories\n * @param theme - The current theme to use for colors\n * @param totals - And array of type DateRangeCategoryTotals\n */\nconst getTotalsByParentCategory = (\n categories: Category[],\n copy: GoalsCopy,\n theme: Theme,\n totals: DateRangeCategoryTotals[],\n): CategoryTotal[] => {\n // Iterate over the category data from BE and roll up all categories into parent categories\n // acc is the accumulated category totals of type CategoryTotal that is initialized as an empty []\n // curr is the current DateRangeCategoryTotal\n return totals.reduce((acc, curr) => {\n // Find category and if it doesn't exist, return acc\n const category = categories.find((c) => c.guid === curr.category_guid)\n if (!category) return acc\n\n // Find parent category and if it doesn't exist, return acc\n const parentGuid = category.parent_guid ?? category.guid\n const parentCategory = categories.find((c) => c.guid === parentGuid)\n if (!parentCategory) return acc\n\n // Skip negative totals — they represent credits/income/transfers, not spending\n if (curr.total <= 0) return acc\n\n const categoryTotal = {\n guid: category.guid,\n name:\n category.guid === parentGuid\n ? `${copy.parent_category_totals_label_general} ${category.name}`\n : category.name,\n color: getCategoryColor(parentCategory.guid, theme),\n amount: curr.total,\n }\n\n // If parent category has already been added to acc then find it and add the current total,\n // otherwise add the parent category to acc.\n const parentCategoryTotal = acc.find((ct) => ct.guid === parentGuid)\n if (parentCategoryTotal) {\n parentCategoryTotal.amount += curr.total\n parentCategoryTotal.categoryTotals?.push(categoryTotal)\n } else {\n acc.push({\n guid: parentGuid,\n name: parentCategory.name,\n color: getCategoryColor(parentCategory.guid, theme),\n categoryTotals: [categoryTotal],\n amount: curr.total,\n })\n }\n\n return acc\n }, [] as CategoryTotal[])\n}\n\n/**\n * Returns an object of type SpendingData containing a subset of category totals related to spending\n * Excludes Income and Transfers\n *\n * @param categories - Array of all categories\n * @param copy - Localized copy\n * @param theme - The current theme to use for colors\n * @param totals - And array of type DateRangeCategoryTotals\n */\nexport const getSpendingData = (\n categories: Category[],\n copy: GoalsCopy, // TODO: Replace after `Other` is added to SpendingCopy\n theme: Theme,\n totals: DateRangeCategoryTotals[],\n): SpendingData => {\n const parentCategoryTotals = getTotalsByParentCategory(categories, copy, theme, totals)\n\n // Filter out Income and Transfers from spending totals\n // Sort in decending order by amount\n const spendingTotals = parentCategoryTotals\n .filter(\n (ct) =>\n ct.guid !== CategoryGuids.INCOME &&\n ct.guid !== CategoryGuids.INVESTMENTS &&\n ct.guid !== CategoryGuids.TRANSFER &&\n ct.amount > 0,\n )\n .sort((cat1, cat2) => cat2.amount - cat1.amount)\n\n // Calculate the total spend\n const totalAmount = spendingTotals.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n\n // Find the number of top categories to include\n const length =\n spendingTotals.length > TOP_CATEGORY_LENGTH ? TOP_CATEGORY_LENGTH : spendingTotals.length\n\n // Only include the top categories\n const categoryData = spendingTotals.slice(0, length)\n\n // Map the category data to donut data\n const donutData = categoryData.map((categoryTotal) => ({\n id: categoryTotal.guid,\n color: getCategoryColor(categoryTotal.guid, theme),\n label: categoryTotal.name,\n value: (categoryTotal.amount / totalAmount) * 100,\n }))\n\n // If there additional categories outside of the top categories, combine them into an Other category\n if (spendingTotals.length > 5) {\n const otherCategories = spendingTotals.slice(TOP_CATEGORY_LENGTH)\n const otherTotal = otherCategories.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n categoryData.push({\n guid: 'other',\n color: theme.palette.categories.others || '',\n name: copy.saving_goal_other,\n categoryTotals: otherCategories,\n amount: otherTotal,\n })\n\n donutData.push({\n id: 'other',\n color: theme.palette.categories.others || '',\n label: copy.saving_goal_other,\n value: (otherTotal / totalAmount) * 100,\n })\n }\n\n // Return an object of type SpendingData\n return {\n categoryData,\n donutData,\n totalAmount,\n }\n}\n\n/**\n * Returns an object of type SpendingData containing a subset of category totals related to income\n * Only includes Income subcategories\n *\n * @param categories - Array of all categories\n * @param monthlyTotals - And array of type DateRangeCategoryTotals\n * @param colors - An array of color strings to use for income colors\n */\nexport const getIncomeData = (\n categories: Category[],\n monthlyTotals: DateRangeCategoryTotals[],\n colors: string[],\n): SpendingData => {\n // Get all income subcategories\n const incomeCategories = categories.filter(\n (category) =>\n category.guid === CategoryGuids.INCOME || category.parent_guid === CategoryGuids.INCOME,\n )\n\n // Filter, sort & map DateRangeCategoryTotals to CategoryTotal objects\n // The filter return only subcategories with a parent category of Income\n // The sort is in acending order due to amounts being negative\n const incomeTotals: CategoryTotal[] = monthlyTotals\n .filter((total) => incomeCategories.some((category) => category.guid === total.category_guid))\n .sort((total1, total2) => total1.total - total2.total)\n .map((total, index) => {\n return {\n guid: total.category_guid,\n name: categories.find((cat) => cat.guid === total.category_guid)?.name,\n color: colors[index % colors.length],\n categoryTotals: [],\n amount: Math.abs(total.total),\n }\n }) as CategoryTotal[]\n\n // Calculates the total income amount\n const totalAmount = incomeTotals.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n\n // Maps the income totals to donut data\n const donutData = incomeTotals.map((incomeTotal) => ({\n id: incomeTotal.guid,\n color: incomeTotal.color,\n label: incomeTotal.name,\n value: (incomeTotal.amount / totalAmount) * 100,\n }))\n\n // Return an object of type SpendingData\n return {\n categoryData: incomeTotals,\n donutData,\n totalAmount,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SpendingData.es.js","names":[],"sources":["../../../src/spending/utils/SpendingData.ts"],"sourcesContent":["import { Theme } from '@mui/material'\n\nimport { getCategoryColor, getLocalizedCategoryName } from '../../core/utils/CategoryUtil'\nimport { CategoryGuids } from '../../core/constants'\nimport { Category, CategoryCopy, DateRangeCategoryTotals, GoalsCopy } from '../../core'\nimport type { DonutData } from '../../common/components/charts/Donut'\n\nconst TOP_CATEGORY_LENGTH = 5\n\nexport interface CategoryTotal {\n guid: string\n name: string\n color: string\n categoryTotals?: CategoryTotal[]\n amount: number\n}\n\nexport interface SpendingData {\n categoryData: CategoryTotal[]\n donutData: DonutData[]\n totalAmount: number\n}\n\n/**\n * Rolls all categories up into parent categories and return an array of CategoryTotal items.\n * @param categories - Array of all categories\n * @param goalsCopy - Goals copy (supplies the parent-category rollup label)\n * @param categoryCopy - Localized category copy (default category names)\n * @param theme - The current theme to use for colors\n * @param totals - And array of type DateRangeCategoryTotals\n */\nconst getTotalsByParentCategory = (\n categories: Category[],\n goalsCopy: GoalsCopy,\n categoryCopy: CategoryCopy,\n theme: Theme,\n totals: DateRangeCategoryTotals[],\n): CategoryTotal[] => {\n // Iterate over the category data from BE and roll up all categories into parent categories\n // acc is the accumulated category totals of type CategoryTotal that is initialized as an empty []\n // curr is the current DateRangeCategoryTotal\n return totals.reduce((acc, curr) => {\n // Find category and if it doesn't exist, return acc\n const category = categories.find((c) => c.guid === curr.category_guid)\n if (!category) return acc\n\n // Find parent category and if it doesn't exist, return acc\n const parentGuid = category.parent_guid ?? category.guid\n const parentCategory = categories.find((c) => c.guid === parentGuid)\n if (!parentCategory) return acc\n\n // Skip negative totals — they represent credits/income/transfers, not spending\n if (curr.total <= 0) return acc\n\n const localizedCategoryName = getLocalizedCategoryName(category, categoryCopy)\n\n const categoryTotal = {\n guid: category.guid,\n name:\n category.guid === parentGuid\n ? `${goalsCopy.parent_category_totals_label_general} ${localizedCategoryName}`\n : localizedCategoryName,\n color: getCategoryColor(parentCategory.guid, theme),\n amount: curr.total,\n }\n\n // If parent category has already been added to acc then find it and add the current total,\n // otherwise add the parent category to acc.\n const parentCategoryTotal = acc.find((ct) => ct.guid === parentGuid)\n if (parentCategoryTotal) {\n parentCategoryTotal.amount += curr.total\n parentCategoryTotal.categoryTotals?.push(categoryTotal)\n } else {\n acc.push({\n guid: parentGuid,\n name: getLocalizedCategoryName(parentCategory, categoryCopy),\n color: getCategoryColor(parentCategory.guid, theme),\n categoryTotals: [categoryTotal],\n amount: curr.total,\n })\n }\n\n return acc\n }, [] as CategoryTotal[])\n}\n\n/**\n * Returns an object of type SpendingData containing a subset of category totals related to spending\n * Excludes Income and Transfers\n *\n * @param categories - Array of all categories\n * @param goalsCopy - Goals copy (supplies the \"Other\" bucket + parent rollup labels)\n * @param categoryCopy - Category copy (default category names)\n * @param theme - The current theme to use for colors\n * @param totals - And array of type DateRangeCategoryTotals\n */\nexport const getSpendingData = (\n categories: Category[],\n goalsCopy: GoalsCopy, // TODO: Replace after `Other` is added to SpendingCopy\n categoryCopy: CategoryCopy,\n theme: Theme,\n totals: DateRangeCategoryTotals[],\n): SpendingData => {\n const parentCategoryTotals = getTotalsByParentCategory(\n categories,\n goalsCopy,\n categoryCopy,\n theme,\n totals,\n )\n\n // Filter out Income and Transfers from spending totals\n // Sort in decending order by amount\n const spendingTotals = parentCategoryTotals\n .filter(\n (ct) =>\n ct.guid !== CategoryGuids.INCOME &&\n ct.guid !== CategoryGuids.INVESTMENTS &&\n ct.guid !== CategoryGuids.TRANSFER &&\n ct.amount > 0,\n )\n .sort((cat1, cat2) => cat2.amount - cat1.amount)\n\n // Calculate the total spend\n const totalAmount = spendingTotals.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n\n // Find the number of top categories to include\n const length =\n spendingTotals.length > TOP_CATEGORY_LENGTH ? TOP_CATEGORY_LENGTH : spendingTotals.length\n\n // Only include the top categories\n const categoryData = spendingTotals.slice(0, length)\n\n // Map the category data to donut data\n const donutData = categoryData.map((categoryTotal) => ({\n id: categoryTotal.guid,\n color: getCategoryColor(categoryTotal.guid, theme),\n label: categoryTotal.name,\n value: (categoryTotal.amount / totalAmount) * 100,\n }))\n\n // If there additional categories outside of the top categories, combine them into an Other category\n if (spendingTotals.length > 5) {\n const otherCategories = spendingTotals.slice(TOP_CATEGORY_LENGTH)\n const otherTotal = otherCategories.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n categoryData.push({\n guid: 'other',\n color: theme.palette.categories.others || '',\n name: goalsCopy.saving_goal_other,\n categoryTotals: otherCategories,\n amount: otherTotal,\n })\n\n donutData.push({\n id: 'other',\n color: theme.palette.categories.others || '',\n label: goalsCopy.saving_goal_other,\n value: (otherTotal / totalAmount) * 100,\n })\n }\n\n // Return an object of type SpendingData\n return {\n categoryData,\n donutData,\n totalAmount,\n }\n}\n\n/**\n * Returns an object of type SpendingData containing a subset of category totals related to income\n * Only includes Income subcategories\n *\n * @param categories - Array of all categories\n * @param categoryCopy - Localized category copy (default category names)\n * @param monthlyTotals - And array of type DateRangeCategoryTotals\n * @param colors - An array of color strings to use for income colors\n */\nexport const getIncomeData = (\n categories: Category[],\n categoryCopy: CategoryCopy,\n monthlyTotals: DateRangeCategoryTotals[],\n colors: string[],\n): SpendingData => {\n // Get all income subcategories\n const incomeCategories = categories.filter(\n (category) =>\n category.guid === CategoryGuids.INCOME || category.parent_guid === CategoryGuids.INCOME,\n )\n\n // Filter, sort & map DateRangeCategoryTotals to CategoryTotal objects\n // The filter return only subcategories with a parent category of Income\n // The sort is in acending order due to amounts being negative\n const incomeTotals: CategoryTotal[] = monthlyTotals\n .filter((total) => incomeCategories.some((category) => category.guid === total.category_guid))\n .sort((total1, total2) => total1.total - total2.total)\n .map((total, index) => {\n const category = categories.find((cat) => cat.guid === total.category_guid)\n return {\n guid: total.category_guid,\n name: category ? getLocalizedCategoryName(category, categoryCopy) : undefined,\n color: colors[index % colors.length],\n categoryTotals: [],\n amount: Math.abs(total.total),\n }\n }) as CategoryTotal[]\n\n // Calculates the total income amount\n const totalAmount = incomeTotals.reduce(\n (acc: number, total: CategoryTotal) => acc + total.amount,\n 0,\n )\n\n // Maps the income totals to donut data\n const donutData = incomeTotals.map((incomeTotal) => ({\n id: incomeTotal.guid,\n color: incomeTotal.color,\n label: incomeTotal.name,\n value: (incomeTotal.amount / totalAmount) * 100,\n }))\n\n // Return an object of type SpendingData\n return {\n categoryData: incomeTotals,\n donutData,\n totalAmount,\n }\n}\n"],"mappings":"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"}
|