@mx-cartographer/experiences 9.4.1-alpha.al0 → 9.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -2
- package/dist/budgets/BubbleBudgetsWidget.es.js +29 -29
- package/dist/budgets/BubbleBudgetsWidget.es.js.map +1 -1
- package/dist/budgets/components/AddBudgets.es.js +16 -13
- package/dist/budgets/components/AddBudgets.es.js.map +1 -1
- package/dist/budgets/components/BudgetDetailsDrawer.es.js +95 -95
- package/dist/budgets/components/BudgetDetailsDrawer.es.js.map +1 -1
- package/dist/budgets/components/BudgetDetailsDrawerV2.es.js +16 -13
- package/dist/budgets/components/BudgetDetailsDrawerV2.es.js.map +1 -1
- package/dist/budgets/components/addbudget/RecalculateBudgets.es.js +14 -11
- package/dist/budgets/components/addbudget/RecalculateBudgets.es.js.map +1 -1
- package/dist/budgets/components/budgetdetails/AddSubBudget.es.js +63 -61
- package/dist/budgets/components/budgetdetails/AddSubBudget.es.js.map +1 -1
- package/dist/budgets/components/budgetdetails/BudgetDetails.es.js +8 -5
- package/dist/budgets/components/budgetdetails/BudgetDetails.es.js.map +1 -1
- package/dist/budgets/components/budgetdetails/SubBudgetAmounts.d.ts +3 -4
- package/dist/budgets/components/budgetdetails/SubBudgetAmounts.es.js +42 -31
- package/dist/budgets/components/budgetdetails/SubBudgetAmounts.es.js.map +1 -1
- package/dist/budgets/components/budgetdetails/SubBudgetList.es.js +71 -59
- package/dist/budgets/components/budgetdetails/SubBudgetList.es.js.map +1 -1
- package/dist/budgets/components/shared/SubBudgetCategory.d.ts +2 -2
- package/dist/budgets/components/shared/SubBudgetCategory.es.js.map +1 -1
- package/dist/core/stores/BudgetsStore.d.ts +13 -6
- package/dist/core/stores/BudgetsStore.es.js +36 -42
- package/dist/core/stores/BudgetsStore.es.js.map +1 -1
- package/dist/core/types/RepeatingTransaction.d.ts +2 -2
- package/dist/core/types/RepeatingTransaction.es.js.map +1 -1
- package/dist/core/utils/BudgetUtil.d.ts +1 -0
- package/dist/core/utils/BudgetUtil.es.js +55 -57
- package/dist/core/utils/BudgetUtil.es.js.map +1 -1
- package/dist/recurringtransactions/components/RecurrenceRow.es.js +1 -1
- package/dist/recurringtransactions/components/RecurrenceRow.es.js.map +1 -1
- package/dist/recurringtransactions/components/RecurringTransactionDetails.es.js +1 -1
- package/dist/recurringtransactions/components/RecurringTransactionDetails.es.js.map +1 -1
- package/dist/recurringtransactions/components/RecurringTransactionList.es.js +1 -1
- package/dist/recurringtransactions/components/RecurringTransactionList.es.js.map +1 -1
- package/dist/recurringtransactions/components/shared/recurringsettings/RecurringRow.es.js +1 -1
- package/dist/recurringtransactions/components/shared/recurringsettings/RecurringRow.es.js.map +1 -1
- package/dist/recurringtransactions/components/shared/recurringsettings/SelectTransaction.es.js +14 -15
- package/dist/recurringtransactions/components/shared/recurringsettings/SelectTransaction.es.js.map +1 -1
- package/dist/transactions/components/shared/transactiondetails/actions/AddMerchantBudgetAction.es.js +85 -82
- package/dist/transactions/components/shared/transactiondetails/actions/AddMerchantBudgetAction.es.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubBudgetAmounts.es.js","names":[],"sources":["../../../../src/budgets/components/budgetdetails/SubBudgetAmounts.tsx"],"sourcesContent":["import React from 'react'\n\nimport List from '@mui/material/List'\nimport ListItem from '@mui/material/ListItem'\nimport Stack from '@mui/material/Stack'\nimport { Text } from '@mxenabled/mxui'\nimport { CurrencyInput, formatCurrency, useGlobalCopyStore } from '../../../common'\nimport { buildDynamicCopy } from '../../../core/utils/Localization'\nimport { DetailedBudget } from '../../../core'\n\nimport { SubBudgetCategory } from '../shared/SubBudgetCategory'\nimport { Divider } from '@mui/material'\n\nexport interface SubBudgetAmountsProps {\n
|
|
1
|
+
{"version":3,"file":"SubBudgetAmounts.es.js","names":[],"sources":["../../../../src/budgets/components/budgetdetails/SubBudgetAmounts.tsx"],"sourcesContent":["import React from 'react'\n\nimport List from '@mui/material/List'\nimport ListItem from '@mui/material/ListItem'\nimport Stack from '@mui/material/Stack'\nimport { Text } from '@mxenabled/mxui'\nimport { CurrencyInput, formatCurrency, useGlobalCopyStore } from '../../../common'\nimport { buildDynamicCopy } from '../../../core/utils/Localization'\nimport { DetailedBudget } from '../../../core'\nimport { isInvalidAmount } from '../../../core/utils/BudgetUtil'\n\nimport { SubBudgetCategory } from '../shared/SubBudgetCategory'\nimport { Divider } from '@mui/material'\n\nexport interface SubBudgetAmountsProps {\n categoryName: string\n subBudgets: DetailedBudget[]\n subBudgetAmounts: Record<string, string>\n onSubBudgetAmountChanged: (guid: string, amount: string) => void\n}\n\nexport const SubBudgetAmounts: React.FC<SubBudgetAmountsProps> = ({\n categoryName,\n subBudgets,\n subBudgetAmounts,\n onSubBudgetAmountChanged,\n}) => {\n const { budgets: copy } = useGlobalCopyStore()\n\n const total = subBudgets.reduce((s, sb) => s + (Number(subBudgetAmounts[sb.guid]) || 0), 0)\n\n return (\n <React.Fragment>\n <Stack>\n <Text aria-live=\"polite\" sx={{ pb: 12 }}>\n {\n buildDynamicCopy(\n copy.your_budget_summary,\n categoryName,\n <Text bold={true} component=\"span\">\n {formatCurrency(total, '0,0')}\n </Text>,\n ) as React.ReactNode\n }\n </Text>\n <Stack sx={{ flexDirection: 'row', mt: 12 }}>\n <Text bold={true} id=\"sub-budget-col-name\" sx={{ width: '50%' }} variant=\"caption\">\n {copy.details_subbudgets_tab}\n </Text>\n <Text\n bold={true}\n id=\"sub-budget-col-total\"\n sx={{ textAlign: 'right', width: '50%' }}\n variant=\"caption\"\n >\n {copy.monthly_total}\n </Text>\n </Stack>\n </Stack>\n <List aria-label={copy.details_subbudgets_tab}>\n {subBudgets.map((subBudget, index) => {\n const val = subBudgetAmounts[subBudget.guid] ?? `${subBudget.amount}`\n return (\n <React.Fragment key={subBudget.guid}>\n <ListItem>\n <SubBudgetCategory budget={subBudget} />\n <CurrencyInput\n amount={val}\n aria-describedby=\"sub-budget-col-total\"\n aria-invalid={isInvalidAmount(val)}\n label={subBudget.category.name}\n minAmount={0}\n setAmount={(newVal) => onSubBudgetAmountChanged(subBudget.guid, newVal)}\n sx={{ '.MuiTypography-body1': { p: 0 }, width: '25%', flexShrink: 0 }}\n />\n </ListItem>\n <Divider sx={{ ml: index === subBudgets.length - 1 ? 0 : 48 }} />\n </React.Fragment>\n )\n })}\n </List>\n </React.Fragment>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAqBA,IAAa,IAAA,CAAqD,EAChE,cAAA,GACA,YAAA,GACA,kBAAA,GACA,0BAAA,EAAA,MACI;AACJ,QAAM,EAAE,SAAS,EAAA,IAAS,EAAmB,GAEvC,IAAQ,EAAW,OAAA,CAAQ,GAAG,MAAO,KAAK,OAAO,EAAiB,EAAG,IAAA,CAAK,KAAK,IAAI,CAAC;AAE1F,SACE,gBAAA,EAAC,EAAM,UAAP,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,IAAM,aAAU;AAAA,IAAS,IAAI,EAAE,IAAI,GAAG;AAAA,IAElC,UAAA,EACE,EAAK,qBACL,GACA,gBAAA,EAAC,GAAD;AAAA,MAAM,MAAM;AAAA,MAAM,WAAU;AAAA,MACzB,UAAA,EAAe,GAAO,KAAK;AAAA,IACxB,CAAA,CACR;AAAA,EAEE,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,eAAe;AAAA,MAAO,IAAI;AAAA,IAAG;AAAA,IAA1C,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MAAM,MAAM;AAAA,MAAM,IAAG;AAAA,MAAsB,IAAI,EAAE,OAAO,MAAM;AAAA,MAAG,SAAQ;AAAA,MACtE,UAAA,EAAK;AAAA,IACF,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM;AAAA,MACN,IAAG;AAAA,MACH,IAAI;AAAA,QAAE,WAAW;AAAA,QAAS,OAAO;AAAA,MAAM;AAAA,MACvC,SAAQ;AAAA,MAEP,UAAA,EAAK;AAAA,IACF,CAAA,CACD;AAAA,EACF,CAAA,CAAA,EAAA,CAAA,GACP,gBAAA,EAAC,GAAD;AAAA,IAAM,cAAY,EAAK;AAAA,IACpB,UAAA,EAAW,IAAA,CAAK,GAAW,MAAU;AACpC,YAAM,IAAM,EAAiB,EAAU,IAAA,KAAS,GAAG,EAAU,MAAA;AAC7D,aACE,gBAAA,EAAC,EAAM,UAAP,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,EAAmB,QAAQ,EAAY,CAAA,GACvC,gBAAA,EAAC,GAAD;AAAA,QACE,QAAQ;AAAA,QACR,oBAAiB;AAAA,QACjB,gBAAc,EAAgB,CAAG;AAAA,QACjC,OAAO,EAAU,SAAS;AAAA,QAC1B,WAAW;AAAA,QACX,WAAA,CAAY,MAAW,EAAyB,EAAU,MAAM,CAAM;AAAA,QACtE,IAAI;AAAA,UAAE,wBAAwB,EAAE,GAAG,EAAE;AAAA,UAAG,OAAO;AAAA,UAAO,YAAY;AAAA,QAAE;AAAA,MACrE,CAAA,CACO,EAAA,CAAA,GACV,gBAAA,EAAC,GAAD,EAAS,IAAI,EAAE,IAAI,MAAU,EAAW,SAAS,IAAI,IAAI,GAAG,EAAI,CAAA,CAClD,EAAA,GAdK,EAAU,IAcf;AAAA,IAEpB,CAAC;AAAA,EACG,CAAA,CACQ,EAAA,CAAA;AAEpB"}
|
|
@@ -1,99 +1,111 @@
|
|
|
1
|
-
import { buildDynamicCopy as
|
|
2
|
-
import { useBudgetsStore as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { BudgetAmount as
|
|
7
|
-
import { Header as
|
|
8
|
-
import { SubBudgetZeroState as
|
|
9
|
-
import { SubBudgetRow as
|
|
10
|
-
import { AddSubBudget as
|
|
1
|
+
import { buildDynamicCopy as c } from "../../../core/utils/Localization.es.js";
|
|
2
|
+
import { useBudgetsStore as O, useGlobalCopyStore as T, useTransactionStore as N } from "../../../common/context/hooks.es.js";
|
|
3
|
+
import b from "../../../common/components/dialog/Dialog.es.js";
|
|
4
|
+
import w from "../../../common/components/drawer/Drawer.es.js";
|
|
5
|
+
import F from "../../../transactions/components/shared/TransactionList.es.js";
|
|
6
|
+
import { BudgetAmount as L } from "../shared/BudgetAmount.es.js";
|
|
7
|
+
import { Header as P } from "./Header.es.js";
|
|
8
|
+
import { SubBudgetZeroState as k } from "../budgetlist/SubBudgetZeroState.es.js";
|
|
9
|
+
import { SubBudgetRow as E } from "../budgetlist/SubBudgetRow.es.js";
|
|
10
|
+
import { AddSubBudget as j } from "./AddSubBudget.es.js";
|
|
11
11
|
import i from "react";
|
|
12
|
-
import { observer as
|
|
13
|
-
import
|
|
14
|
-
import { Text as
|
|
15
|
-
import { jsx as
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
var
|
|
19
|
-
const { category:
|
|
12
|
+
import { observer as I } from "mobx-react-lite";
|
|
13
|
+
import R from "@mui/material/Stack";
|
|
14
|
+
import { Text as $ } from "@mxenabled/mxui";
|
|
15
|
+
import { jsx as r, jsxs as s } from "react/jsx-runtime";
|
|
16
|
+
import G from "@mui/material/Divider";
|
|
17
|
+
import H from "@mui/material/List";
|
|
18
|
+
var ae = I(({ budget: n }) => {
|
|
19
|
+
const { category: h, subBudgets: u } = n, { budgets: o, common: l } = T(), { deleteBudget: S, selectedSubBudget: e, setAlert: g, setSelectedSubBudget: B, updateBudget: C } = O(), { filter: p, setFilter: y } = N(), [x, m] = i.useState(!1), [v, d] = i.useState(!1), [a, f] = i.useState("");
|
|
20
20
|
i.useEffect(() => {
|
|
21
|
-
e && (
|
|
22
|
-
...
|
|
23
|
-
custom: (
|
|
21
|
+
e && (f(`${e.amount}`), y({
|
|
22
|
+
...p,
|
|
23
|
+
custom: (t) => t.category_guid === e.category_guid
|
|
24
24
|
}));
|
|
25
25
|
}, [e]);
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
const A = async () => {
|
|
27
|
+
if (e) {
|
|
28
|
+
const t = await C({
|
|
29
|
+
...e,
|
|
30
|
+
amount: Number(a)
|
|
31
|
+
});
|
|
32
|
+
m(!1), t || g({
|
|
33
|
+
msg: c(o.error_alert_edit_merchant_budget, e.category.name),
|
|
34
|
+
severity: "error"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, D = async () => {
|
|
38
|
+
if (e) {
|
|
39
|
+
const t = await S(e.guid);
|
|
40
|
+
d(!1), t ? _() : g({
|
|
41
|
+
msg: c(o.error_alert_delete_merchant_budget, e.category.name),
|
|
42
|
+
severity: "error"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}, _ = () => {
|
|
46
|
+
y({
|
|
47
|
+
...p,
|
|
48
|
+
custom: (t) => t.category_guid === n.category_guid || t.top_level_category_guid === n.category_guid
|
|
49
|
+
}), B(void 0);
|
|
38
50
|
};
|
|
39
51
|
return /* @__PURE__ */ s(i.Fragment, { children: [
|
|
40
|
-
/* @__PURE__ */ s(
|
|
52
|
+
/* @__PURE__ */ s(H, {
|
|
41
53
|
sx: { bgcolor: "background.paper" },
|
|
42
|
-
children: [
|
|
43
|
-
category:
|
|
54
|
+
children: [u.length === 0 ? /* @__PURE__ */ r(k, {}) : u.map((t) => /* @__PURE__ */ s(i.Fragment, { children: [/* @__PURE__ */ r(E, { budget: t }), /* @__PURE__ */ r(G, {})] }, t.guid)), /* @__PURE__ */ r(j, {
|
|
55
|
+
category: h,
|
|
44
56
|
parentBudget: n
|
|
45
57
|
})]
|
|
46
58
|
}),
|
|
47
|
-
/* @__PURE__ */
|
|
48
|
-
ariaLabelClose:
|
|
59
|
+
/* @__PURE__ */ r(w, {
|
|
60
|
+
ariaLabelClose: l.close_aria,
|
|
49
61
|
isOpen: !!e,
|
|
50
|
-
onClose:
|
|
51
|
-
onPrimaryAction: () =>
|
|
52
|
-
onSecondaryAction: () =>
|
|
62
|
+
onClose: _,
|
|
63
|
+
onPrimaryAction: () => m(!0),
|
|
64
|
+
onSecondaryAction: () => d(!0),
|
|
53
65
|
primaryText: o.details_edit_button,
|
|
54
66
|
secondaryText: o.details_delete_button,
|
|
55
67
|
title: o.details_title,
|
|
56
|
-
children: e && /* @__PURE__ */ s(
|
|
68
|
+
children: e && /* @__PURE__ */ s(R, {
|
|
57
69
|
gap: 24,
|
|
58
|
-
children: [/* @__PURE__ */
|
|
70
|
+
children: [/* @__PURE__ */ r(P, { budget: e }), /* @__PURE__ */ r(F, { height: "100%" })]
|
|
59
71
|
})
|
|
60
72
|
}),
|
|
61
|
-
e && /* @__PURE__ */ s(i.Fragment, { children: [/* @__PURE__ */
|
|
73
|
+
e && /* @__PURE__ */ s(i.Fragment, { children: [/* @__PURE__ */ r(b, {
|
|
62
74
|
copy: {
|
|
63
|
-
close_aria:
|
|
75
|
+
close_aria: l.close_aria,
|
|
64
76
|
title: o.details_edit_title_subbudget
|
|
65
77
|
},
|
|
66
78
|
disablePrimaryButton: a === "" || Number(a) < 0 || isNaN(Number(a)),
|
|
67
|
-
isOpen:
|
|
68
|
-
onClose: () =>
|
|
69
|
-
onPrimaryAction:
|
|
79
|
+
isOpen: x,
|
|
80
|
+
onClose: () => m(!1),
|
|
81
|
+
onPrimaryAction: A,
|
|
70
82
|
primaryText: o.edit_save_button,
|
|
71
|
-
sx: { "& .MuiStack-root:first-
|
|
72
|
-
children: /* @__PURE__ */
|
|
83
|
+
sx: { "& .MuiStack-root:first-of-type": { pb: 8 } },
|
|
84
|
+
children: /* @__PURE__ */ r(L, {
|
|
73
85
|
amount: a,
|
|
74
86
|
categoryName: e.category.name,
|
|
75
|
-
onAmountChanged:
|
|
87
|
+
onAmountChanged: f
|
|
76
88
|
})
|
|
77
|
-
}), /* @__PURE__ */
|
|
89
|
+
}), /* @__PURE__ */ r(b, {
|
|
78
90
|
copy: {
|
|
79
|
-
close_aria:
|
|
91
|
+
close_aria: l.close_aria,
|
|
80
92
|
title: o.delete_title
|
|
81
93
|
},
|
|
82
|
-
isOpen:
|
|
83
|
-
onClose: () =>
|
|
84
|
-
onPrimaryAction:
|
|
94
|
+
isOpen: v,
|
|
95
|
+
onClose: () => d(!1),
|
|
96
|
+
onPrimaryAction: D,
|
|
85
97
|
primaryColor: "error",
|
|
86
98
|
primaryText: "Delete",
|
|
87
99
|
secondaryColor: "secondary",
|
|
88
|
-
children: /* @__PURE__ */
|
|
100
|
+
children: /* @__PURE__ */ r($, {
|
|
89
101
|
variant: "subtitle1",
|
|
90
|
-
children:
|
|
102
|
+
children: c(o.delete_description, e.category.name)
|
|
91
103
|
})
|
|
92
104
|
})] })
|
|
93
105
|
] });
|
|
94
106
|
});
|
|
95
107
|
export {
|
|
96
|
-
|
|
108
|
+
ae as SubBudgetList
|
|
97
109
|
};
|
|
98
110
|
|
|
99
111
|
//# sourceMappingURL=SubBudgetList.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubBudgetList.es.js","names":[],"sources":["../../../../src/budgets/components/budgetdetails/SubBudgetList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Divider from '@mui/material/Divider'\nimport List from '@mui/material/List'\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport {\n Dialog,\n Drawer,\n useBudgetsStore,\n useGlobalCopyStore,\n useTransactionStore,\n} from '../../../common'\nimport { type Budget, type DetailedBudget, type Transaction } from '../../../core'\n\nimport { TransactionList } from '../../../transactions'\n\nimport { SubBudgetZeroState } from '../budgetlist/SubBudgetZeroState'\nimport { SubBudgetRow } from '../budgetlist/SubBudgetRow'\nimport { BudgetAmount } from '../shared/BudgetAmount'\nimport { AddSubBudget } from './AddSubBudget'\nimport { Header } from './Header'\nimport { buildDynamicCopy } from '../../../core/utils/Localization'\n\ninterface SubBudgetListProps {\n budget: DetailedBudget\n}\n\nexport const SubBudgetList: React.FC<SubBudgetListProps> = observer(({ budget }) => {\n const { category, subBudgets } = budget\n const { budgets: copy, common: commonCopy } = useGlobalCopyStore()\n const { deleteBudget, selectedSubBudget, setSelectedSubBudget, updateBudget }
|
|
1
|
+
{"version":3,"file":"SubBudgetList.es.js","names":[],"sources":["../../../../src/budgets/components/budgetdetails/SubBudgetList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Divider from '@mui/material/Divider'\nimport List from '@mui/material/List'\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport {\n Dialog,\n Drawer,\n useBudgetsStore,\n useGlobalCopyStore,\n useTransactionStore,\n} from '../../../common'\nimport { type Budget, type DetailedBudget, type Transaction } from '../../../core'\n\nimport { TransactionList } from '../../../transactions'\n\nimport { SubBudgetZeroState } from '../budgetlist/SubBudgetZeroState'\nimport { SubBudgetRow } from '../budgetlist/SubBudgetRow'\nimport { BudgetAmount } from '../shared/BudgetAmount'\nimport { AddSubBudget } from './AddSubBudget'\nimport { Header } from './Header'\nimport { buildDynamicCopy } from '../../../core/utils/Localization'\n\ninterface SubBudgetListProps {\n budget: DetailedBudget\n}\n\nexport const SubBudgetList: React.FC<SubBudgetListProps> = observer(({ budget }) => {\n const { category, subBudgets } = budget\n const { budgets: copy, common: commonCopy } = useGlobalCopyStore()\n const { deleteBudget, selectedSubBudget, setAlert, setSelectedSubBudget, updateBudget } =\n useBudgetsStore()\n const { filter, setFilter } = useTransactionStore()\n\n const [isEditOpen, setIsEditOpen] = React.useState(false)\n const [isDeleteOpen, setIsDeleteOpen] = React.useState(false)\n const [amount, setAmount] = React.useState(``)\n\n React.useEffect(() => {\n if (selectedSubBudget) {\n setAmount(`${selectedSubBudget.amount}`)\n setFilter({\n ...filter,\n custom: (t: Transaction) => t.category_guid === selectedSubBudget.category_guid,\n })\n }\n }, [selectedSubBudget])\n\n const handleUpdateBudget = async () => {\n if (selectedSubBudget) {\n const result = await updateBudget({\n ...selectedSubBudget,\n amount: Number(amount),\n } as Budget)\n setIsEditOpen(false)\n if (!result) {\n setAlert({\n msg: buildDynamicCopy(\n copy.error_alert_edit_merchant_budget,\n selectedSubBudget.category.name,\n ) as string,\n severity: 'error',\n })\n }\n }\n }\n\n const handleDeleteBudget = async () => {\n if (selectedSubBudget) {\n const result = await deleteBudget(selectedSubBudget.guid)\n setIsDeleteOpen(false)\n if (result) {\n handleClose()\n } else {\n setAlert({\n msg: buildDynamicCopy(\n copy.error_alert_delete_merchant_budget,\n selectedSubBudget.category.name,\n ) as string,\n severity: 'error',\n })\n }\n }\n }\n\n const handleClose = () => {\n setFilter({\n ...filter,\n custom: (t: Transaction) =>\n t.category_guid === budget.category_guid ||\n t.top_level_category_guid === budget.category_guid,\n })\n setSelectedSubBudget(undefined)\n }\n\n return (\n <React.Fragment>\n <List sx={{ bgcolor: 'background.paper' }}>\n {subBudgets.length === 0 ? (\n <SubBudgetZeroState />\n ) : (\n subBudgets.map((subBudget) => (\n <React.Fragment key={subBudget.guid}>\n <SubBudgetRow budget={subBudget} />\n <Divider />\n </React.Fragment>\n ))\n )}\n <AddSubBudget category={category} parentBudget={budget} />\n </List>\n <Drawer\n ariaLabelClose={commonCopy.close_aria}\n isOpen={Boolean(selectedSubBudget)}\n onClose={handleClose}\n onPrimaryAction={() => setIsEditOpen(true)}\n onSecondaryAction={() => setIsDeleteOpen(true)}\n primaryText={copy.details_edit_button}\n secondaryText={copy.details_delete_button}\n title={copy.details_title}\n >\n {selectedSubBudget && (\n <Stack gap={24}>\n <Header budget={selectedSubBudget} />\n <TransactionList height=\"100%\" />\n </Stack>\n )}\n </Drawer>\n\n {selectedSubBudget && (\n <React.Fragment>\n <Dialog\n copy={{ close_aria: commonCopy.close_aria, title: copy.details_edit_title_subbudget }}\n disablePrimaryButton={amount === '' || Number(amount) < 0 || isNaN(Number(amount))}\n isOpen={isEditOpen}\n onClose={() => setIsEditOpen(false)}\n onPrimaryAction={handleUpdateBudget}\n primaryText={copy.edit_save_button}\n sx={{\n '& .MuiStack-root:first-of-type': {\n pb: 8,\n },\n }}\n >\n <BudgetAmount\n amount={amount}\n categoryName={selectedSubBudget.category.name}\n onAmountChanged={setAmount}\n />\n </Dialog>\n\n <Dialog\n copy={{ close_aria: commonCopy.close_aria, title: copy.delete_title }}\n isOpen={isDeleteOpen}\n onClose={() => setIsDeleteOpen(false)}\n onPrimaryAction={handleDeleteBudget}\n primaryColor=\"error\"\n primaryText=\"Delete\"\n secondaryColor=\"secondary\"\n >\n <Text variant=\"subtitle1\">\n {buildDynamicCopy(copy.delete_description, selectedSubBudget.category.name) as string}\n </Text>\n </Dialog>\n </React.Fragment>\n )}\n </React.Fragment>\n )\n})\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { DetailedBudget } from '../../../core';
|
|
3
|
-
interface
|
|
3
|
+
interface SubBudgetCategoryProps {
|
|
4
4
|
budget: DetailedBudget;
|
|
5
5
|
}
|
|
6
|
-
export declare const SubBudgetCategory: React.FC<
|
|
6
|
+
export declare const SubBudgetCategory: React.FC<SubBudgetCategoryProps>;
|
|
7
7
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubBudgetCategory.es.js","names":[],"sources":["../../../../src/budgets/components/shared/SubBudgetCategory.tsx"],"sourcesContent":["import React from 'react'\n\nimport ListItemText from '@mui/material/ListItemText'\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { BudgetDonut } from './BudgetDonut'\nimport { type DetailedBudget } from '../../../core'\nimport { formatCurrency } from '../../../core/utils/NumberFormatting'\n\ninterface
|
|
1
|
+
{"version":3,"file":"SubBudgetCategory.es.js","names":[],"sources":["../../../../src/budgets/components/shared/SubBudgetCategory.tsx"],"sourcesContent":["import React from 'react'\n\nimport ListItemText from '@mui/material/ListItemText'\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { BudgetDonut } from './BudgetDonut'\nimport { type DetailedBudget } from '../../../core'\nimport { formatCurrency } from '../../../core/utils/NumberFormatting'\n\ninterface SubBudgetCategoryProps {\n budget: DetailedBudget\n}\n\nexport const SubBudgetCategory: React.FC<SubBudgetCategoryProps> = ({ budget }) => {\n const {\n amount,\n budgetColors: { background },\n category,\n percentage,\n transaction_total,\n } = budget\n\n return (\n <>\n <BudgetDonut\n background={background}\n categoryGuid={category.parent_guid}\n percentage={percentage}\n />\n <ListItemText\n primary={\n <Stack component=\"span\" direction=\"row\" justifyContent=\"space-between\">\n <Text bold={true} truncate={true} variant=\"body1\">\n {budget.category.name}\n </Text>\n </Stack>\n }\n secondary={\n <Stack component=\"span\" direction=\"row\" justifyContent=\"space-between\">\n <Text fontWeight={400} variant=\"body1\">\n {`\n ${formatCurrency(transaction_total, '0,0')} / \n ${formatCurrency(amount, '0,0')}\n `}\n </Text>\n </Stack>\n }\n />\n </>\n )\n}\n"],"mappings":";;;;;;;AAeA,IAAa,IAAA,CAAuD,EAAE,QAAA,EAAA,MAAa;AACjF,QAAM,EACJ,QAAA,GACA,cAAc,EAAE,YAAA,EAAA,GAChB,UAAA,GACA,YAAA,GACA,mBAAA,EAAA,IACE;AAEJ,SACE,gBAAA,EAAA,GAAA,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,IACc,YAAA;AAAA,IACZ,cAAc,EAAS;AAAA,IACX,YAAA;AAAA,EACb,CAAA,GACD,gBAAA,EAAC,GAAD;AAAA,IACE,SACE,gBAAA,EAAC,GAAD;AAAA,MAAO,WAAU;AAAA,MAAO,WAAU;AAAA,MAAM,gBAAe;AAAA,MACrD,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,UAAU;AAAA,QAAM,SAAQ;AAAA,QACvC,UAAA,EAAO,SAAS;AAAA,MACb,CAAA;AAAA,IACD,CAAA;AAAA,IAET,WACE,gBAAA,EAAC,GAAD;AAAA,MAAO,WAAU;AAAA,MAAO,WAAU;AAAA,MAAM,gBAAe;AAAA,MACrD,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAM,YAAY;AAAA,QAAK,SAAQ;AAAA,QAC5B,UAAA;AAAA,kBACG,EAAe,GAAmB,KAAK,CAAA;AAAA,kBACvC,EAAe,GAAQ,KAAK,CAAA;AAAA;AAAA,MAE5B,CAAA;AAAA,IACD,CAAA;AAAA,EAEV,CAAA,CACD,EAAA,CAAA;AAEN"}
|
|
@@ -5,7 +5,10 @@ import { Budget, Category, DateRange, DetailedBudget, DetailedCategory, Merchant
|
|
|
5
5
|
export declare class BudgetsStore {
|
|
6
6
|
api: BudgetsApi;
|
|
7
7
|
globalStore: GlobalStore;
|
|
8
|
-
alert:
|
|
8
|
+
alert: {
|
|
9
|
+
msg: string;
|
|
10
|
+
severity: 'success' | 'error';
|
|
11
|
+
} | null;
|
|
9
12
|
dateRange: DateRange;
|
|
10
13
|
budgets: Budget[];
|
|
11
14
|
selectedBudget: DetailedBudget | undefined;
|
|
@@ -20,9 +23,15 @@ export declare class BudgetsStore {
|
|
|
20
23
|
get unbudgetedCategories(): DetailedCategory[];
|
|
21
24
|
get totalBudgeted(): number;
|
|
22
25
|
addBudget: (category: Category, amount: number, parentGuid?: string | null) => Promise<void>;
|
|
23
|
-
deleteBudget: (guid: string) => Promise<
|
|
26
|
+
deleteBudget: (guid: string) => Promise<boolean>;
|
|
24
27
|
loadBudgets: () => Promise<void>;
|
|
25
|
-
setAlert: (alert:
|
|
28
|
+
setAlert: (alert: {
|
|
29
|
+
msg: string;
|
|
30
|
+
severity: "success" | "error";
|
|
31
|
+
} | null) => {
|
|
32
|
+
msg: string;
|
|
33
|
+
severity: "success" | "error";
|
|
34
|
+
} | null;
|
|
26
35
|
setBudgets: (budgets: Budget[]) => void;
|
|
27
36
|
setDateRange: (dateRange: DateRange) => DateRange;
|
|
28
37
|
setSelectedBudget: (budget: DetailedBudget | undefined) => DetailedBudget | undefined;
|
|
@@ -36,9 +45,7 @@ export declare class BudgetsStore {
|
|
|
36
45
|
data: Budget[];
|
|
37
46
|
isSuccess: boolean;
|
|
38
47
|
}>;
|
|
39
|
-
updateBudget: (budget: Budget) => Promise<
|
|
40
|
-
isSuccess: boolean;
|
|
41
|
-
}>;
|
|
48
|
+
updateBudget: (budget: Budget) => Promise<boolean>;
|
|
42
49
|
getMerchantBudgetByMerchantGuid: (merchantGuid: string) => MerchantBudget | undefined;
|
|
43
50
|
setMerchantBudgets: (merchantBudgets: MerchantBudget[]) => void;
|
|
44
51
|
addMerchantBudget: (merchantGuid: string, amount: number) => Promise<{
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { CategoryGuids as
|
|
2
|
-
import { BudgetsApi as
|
|
3
|
-
import { upsertByGuid as
|
|
4
|
-
import { augmentBudgets as
|
|
5
|
-
import { endOfMonth as
|
|
6
|
-
import { startOfMonth as
|
|
1
|
+
import { CategoryGuids as o } from "../constants/Category.es.js";
|
|
2
|
+
import { BudgetsApi as g } from "../api/BudgetsApi.es.js";
|
|
3
|
+
import { upsertByGuid as n } from "../utils/upsertByGuid.es.js";
|
|
4
|
+
import { augmentBudgets as c, findBudget as h, findSubBudget as p } from "../utils/BudgetUtil.es.js";
|
|
5
|
+
import { endOfMonth as B } from "date-fns/endOfMonth";
|
|
6
|
+
import { startOfMonth as f } from "date-fns/startOfMonth";
|
|
7
7
|
import { startOfToday as l } from "date-fns/startOfToday";
|
|
8
|
-
import { makeAutoObservable as
|
|
9
|
-
var
|
|
10
|
-
api = new
|
|
8
|
+
import { makeAutoObservable as S, reaction as b, runInAction as i } from "mobx";
|
|
9
|
+
var A = class {
|
|
10
|
+
api = new g("/", "");
|
|
11
11
|
globalStore;
|
|
12
|
-
alert =
|
|
12
|
+
alert = null;
|
|
13
13
|
dateRange = {
|
|
14
|
-
start:
|
|
15
|
-
end:
|
|
14
|
+
start: f(l()),
|
|
15
|
+
end: B(l())
|
|
16
16
|
};
|
|
17
17
|
budgets = [];
|
|
18
18
|
selectedBudget;
|
|
@@ -21,23 +21,23 @@ var C = class {
|
|
|
21
21
|
theme = {};
|
|
22
22
|
merchantBudgets = [];
|
|
23
23
|
constructor(t) {
|
|
24
|
-
this.globalStore = t, this.api = new
|
|
24
|
+
this.globalStore = t, this.api = new g(t.endpoint, t.sessionToken, t.onError), S(this);
|
|
25
25
|
}
|
|
26
26
|
loadBudgetData = async () => {
|
|
27
|
-
this.globalStore.recurringTransactionsStore.isDataLoaded || await this.globalStore.recurringTransactionsStore.loadRepeatingTransactionData(), await this.loadBudgets(),
|
|
27
|
+
this.globalStore.recurringTransactionsStore.isDataLoaded || await this.globalStore.recurringTransactionsStore.loadRepeatingTransactionData(), await this.loadBudgets(), b(() => this.detailedBudgets, (t) => {
|
|
28
28
|
if (t) {
|
|
29
29
|
const e = this.selectedBudget;
|
|
30
|
-
e && (this.selectedBudget =
|
|
30
|
+
e && (this.selectedBudget = h(t, e.guid));
|
|
31
31
|
const r = this.selectedSubBudget;
|
|
32
|
-
r && r.parent_guid && (this.selectedSubBudget =
|
|
32
|
+
r && r.parent_guid && (this.selectedSubBudget = p(t, r.guid, r.parent_guid));
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
36
|
get detailedBudgets() {
|
|
37
|
-
return
|
|
37
|
+
return c(this.budgets.filter((t) => t.category_guid !== o.INCOME && t.category_guid !== o.TRANSFER && t.category_guid !== o.INVESTMENTS), this.globalStore.categoryStore.detailedCategories, this.globalStore.copyStore.copy.budgets, this.theme).sort((t, e) => t.percentage > e.percentage ? -1 : t.percentage < e.percentage ? 1 : 0);
|
|
38
38
|
}
|
|
39
39
|
get incomeBudget() {
|
|
40
|
-
return
|
|
40
|
+
return c(this.budgets.filter((t) => !t.parent_guid), this.globalStore.categoryStore.detailedCategories, this.globalStore.copyStore.copy.budgets, this.theme).reduce((t, e) => e.category_guid !== o.INCOME ? t : !t || e.percentage > t.percentage ? e : t, void 0)?.amount;
|
|
41
41
|
}
|
|
42
42
|
get unbudgetedCategories() {
|
|
43
43
|
return this.globalStore.categoryStore.spendCategories.filter((t) => !this.detailedBudgets.find((e) => e.category_guid === t.guid));
|
|
@@ -49,29 +49,23 @@ var C = class {
|
|
|
49
49
|
try {
|
|
50
50
|
const s = await this.api.addBudget(t, e, r);
|
|
51
51
|
i(() => {
|
|
52
|
-
this.budgets =
|
|
52
|
+
this.budgets = n(this.budgets, s);
|
|
53
53
|
});
|
|
54
54
|
} catch (s) {
|
|
55
55
|
console.error("Error adding budget:", s), this.globalStore.captureException(s, { store: "BudgetsStore" });
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
deleteBudget = async (t) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.budgets.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
70
|
-
const g = a.find((d) => d.status === "rejected");
|
|
71
|
-
if (g) throw g.reason;
|
|
72
|
-
} catch (e) {
|
|
73
|
-
console.error("Error deleting budget:", e), this.globalStore.captureException(e, { store: "BudgetsStore" });
|
|
74
|
-
}
|
|
59
|
+
const e = [t, ...this.budgets.filter((a) => a.parent_guid === t).map((a) => a.guid)], r = await Promise.allSettled(e.map((a) => this.api.deleteBudget(a))), s = new Set(e.filter((a, u) => r[u].status === "fulfilled"));
|
|
60
|
+
i(() => {
|
|
61
|
+
this.budgets = this.budgets.filter((a) => !s.has(a.guid));
|
|
62
|
+
});
|
|
63
|
+
let d = !1;
|
|
64
|
+
for (const [a, u] of r.entries()) u.status === "rejected" && (d = !0, console.error("Error deleting budget:", u.reason), this.globalStore.captureException(u.reason, {
|
|
65
|
+
store: "BudgetsStore",
|
|
66
|
+
guid: e[a]
|
|
67
|
+
}));
|
|
68
|
+
return !d;
|
|
75
69
|
};
|
|
76
70
|
loadBudgets = async () => {
|
|
77
71
|
try {
|
|
@@ -92,7 +86,7 @@ var C = class {
|
|
|
92
86
|
recalculateBudgets = async (t) => {
|
|
93
87
|
try {
|
|
94
88
|
for (const r of t) {
|
|
95
|
-
const s = this.budgets.find((
|
|
89
|
+
const s = this.budgets.find((d) => d.category_guid === r.guid);
|
|
96
90
|
s ? await this.api.updateBudget({
|
|
97
91
|
...s,
|
|
98
92
|
amount: r.totalAverageAmount
|
|
@@ -117,9 +111,9 @@ var C = class {
|
|
|
117
111
|
return i(() => {
|
|
118
112
|
const r = this.budgets.findIndex((s) => s.guid === t.guid);
|
|
119
113
|
r >= 0 && (this.budgets[r] = e);
|
|
120
|
-
}),
|
|
114
|
+
}), !0;
|
|
121
115
|
} catch (e) {
|
|
122
|
-
return console.error("Error updating budget:", e), this.globalStore.captureException(e, { store: "BudgetsStore" }),
|
|
116
|
+
return console.error("Error updating budget:", e), this.globalStore.captureException(e, { store: "BudgetsStore" }), !1;
|
|
123
117
|
}
|
|
124
118
|
};
|
|
125
119
|
getMerchantBudgetByMerchantGuid = (t) => this.merchantBudgets.find((e) => e?.merchant_guid === t);
|
|
@@ -130,7 +124,7 @@ var C = class {
|
|
|
130
124
|
try {
|
|
131
125
|
const r = await this.api.addMerchantBudget(t, e);
|
|
132
126
|
return i(() => {
|
|
133
|
-
this.merchantBudgets =
|
|
127
|
+
this.merchantBudgets = n(this.merchantBudgets, r);
|
|
134
128
|
}), { isSuccess: !0 };
|
|
135
129
|
} catch (r) {
|
|
136
130
|
return console.error("Error adding merchant budget:", r), this.globalStore.captureException(r, { store: "BudgetsStore" }), { isSuccess: !1 };
|
|
@@ -140,8 +134,8 @@ var C = class {
|
|
|
140
134
|
try {
|
|
141
135
|
const { guid: e, amount: r } = t, s = await this.api.updateMerchantBudget(e, r);
|
|
142
136
|
return i(() => {
|
|
143
|
-
const
|
|
144
|
-
|
|
137
|
+
const d = this.merchantBudgets.findIndex((a) => a.guid === t.guid);
|
|
138
|
+
d >= 0 && (this.merchantBudgets[d] = s);
|
|
145
139
|
}), { isSuccess: !0 };
|
|
146
140
|
} catch (e) {
|
|
147
141
|
return console.error("Error updating merchant budget:", e), this.globalStore.captureException(e, { store: "BudgetsStore" }), { isSuccess: !1 };
|
|
@@ -158,7 +152,7 @@ var C = class {
|
|
|
158
152
|
};
|
|
159
153
|
};
|
|
160
154
|
export {
|
|
161
|
-
|
|
155
|
+
A as BudgetsStore
|
|
162
156
|
};
|
|
163
157
|
|
|
164
158
|
//# sourceMappingURL=BudgetsStore.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BudgetsStore.es.js","names":[],"sources":["../../../src/core/stores/BudgetsStore.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction } from 'mobx'\n\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\n\nimport { Theme } from '@mui/system'\n\nimport { BudgetsApi } from '../api'\nimport { upsertByGuid } from '../utils/upsertByGuid'\nimport { CategoryGuids } from '../constants'\nimport { augmentBudgets, findBudget, findSubBudget } from '../utils/BudgetUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nimport type {\n Budget,\n Category,\n DateRange,\n DetailedBudget,\n DetailedCategory,\n MerchantBudget,\n} from '../types'\n\nexport class BudgetsStore {\n api: BudgetsApi = new BudgetsApi('/', '')\n\n globalStore: GlobalStore\n\n alert: string = ''\n dateRange: DateRange = { start: startOfMonth(startOfToday()), end: endOfMonth(startOfToday()) }\n budgets: Budget[] = []\n selectedBudget: DetailedBudget | undefined\n selectedSubBudget: DetailedBudget | undefined\n isDataLoaded = false\n theme = {} as Theme\n merchantBudgets: MerchantBudget[] = []\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new BudgetsApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n loadBudgetData = async () => {\n if (!this.globalStore.recurringTransactionsStore.isDataLoaded) {\n await this.globalStore.recurringTransactionsStore.loadRepeatingTransactionData()\n }\n await this.loadBudgets()\n\n /** Reaction to update the selected budget/sub-budget if detailedBudgets is updated **/\n reaction(\n () => this.detailedBudgets,\n (detailedBudgets) => {\n if (detailedBudgets) {\n const budget = this.selectedBudget\n if (budget) {\n this.selectedBudget = findBudget(detailedBudgets, budget.guid)\n }\n\n const subBudget = this.selectedSubBudget\n if (subBudget && subBudget.parent_guid) {\n this.selectedSubBudget = findSubBudget(\n detailedBudgets,\n subBudget.guid,\n subBudget.parent_guid,\n )\n }\n }\n },\n )\n }\n\n get detailedBudgets(): DetailedBudget[] {\n return augmentBudgets(\n this.budgets.filter(\n (budget: Budget) =>\n budget.category_guid !== CategoryGuids.INCOME &&\n budget.category_guid !== CategoryGuids.TRANSFER &&\n budget.category_guid !== CategoryGuids.INVESTMENTS,\n ),\n this.globalStore.categoryStore.detailedCategories,\n this.globalStore.copyStore.copy.budgets,\n this.theme,\n ).sort((a, b) => {\n if (a.percentage > b.percentage) return -1\n if (a.percentage < b.percentage) return 1\n return 0\n })\n }\n\n // TODO: Replace this with income from recurring transactions. Income budgets are deprecated.\n get incomeBudget(): number | undefined {\n const filteredBudgets = augmentBudgets(\n this.budgets.filter((budget: Budget) => !budget.parent_guid),\n this.globalStore.categoryStore.detailedCategories,\n this.globalStore.copyStore.copy.budgets,\n this.theme,\n )\n\n const incomeBudget = filteredBudgets.reduce(\n (acc, curr) => {\n if (curr.category_guid !== CategoryGuids.INCOME) return acc\n if (!acc || curr.percentage > acc.percentage) return curr\n return acc\n },\n undefined as DetailedBudget | undefined,\n )\n\n return incomeBudget?.amount\n }\n\n get unbudgetedCategories(): DetailedCategory[] {\n return this.globalStore.categoryStore.spendCategories.filter(\n (category) => !this.detailedBudgets.find((budget) => budget.category_guid === category.guid),\n )\n }\n\n get totalBudgeted(): number {\n return this.detailedBudgets.reduce((total, budget) => total + budget.amount, 0)\n }\n\n addBudget = async (category: Category, amount: number, parentGuid: string | null = null) => {\n try {\n const budget = await this.api.addBudget(category, amount, parentGuid)\n runInAction(() => {\n this.budgets = upsertByGuid(this.budgets, budget)\n })\n } catch (error) {\n console.error('Error adding budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n }\n }\n\n deleteBudget = async (guid: string) => {\n try {\n const detailedParent = this.detailedBudgets.find((b) => b.guid === guid)\n const subBudgetGuids = new Set<string>()\n\n this.budgets.forEach((b) => {\n if (b.parent_guid === guid) {\n subBudgetGuids.add(b.guid)\n }\n })\n\n if (detailedParent?.subBudgets) {\n detailedParent.subBudgets.forEach((sb) => {\n subBudgetGuids.add(sb.guid)\n })\n }\n\n const allGuidsToDelete = [guid, ...Array.from(subBudgetGuids)]\n\n const results = await Promise.allSettled(\n allGuidsToDelete.map((id) => this.api.deleteBudget(id)),\n )\n const deleted = new Set(allGuidsToDelete.filter((_, i) => results[i].status === 'fulfilled'))\n\n runInAction(() => {\n this.budgets = this.budgets.filter((budget) => !deleted.has(budget.guid))\n })\n\n const firstRejection = results.find(\n (r): r is PromiseRejectedResult => r.status === 'rejected',\n )\n if (firstRejection) {\n throw firstRejection.reason\n }\n } catch (error) {\n console.error('Error deleting budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n }\n }\n\n loadBudgets = async () => {\n try {\n const budgets = await this.api.getBudgets()\n this.setBudgets(budgets)\n } catch (error) {\n console.error('Error occurred while loading budgets:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n throw error\n }\n }\n\n setAlert = (alert: string) => (this.alert = alert)\n\n setBudgets = (budgets: Budget[]) => {\n this.budgets = budgets\n this.isDataLoaded = true\n }\n\n setDateRange = (dateRange: DateRange) => (this.dateRange = dateRange)\n\n setSelectedBudget = (budget: DetailedBudget | undefined) => (this.selectedBudget = budget)\n\n setSelectedSubBudget = (budget: DetailedBudget | undefined) => (this.selectedSubBudget = budget)\n\n setTheme = (theme: Theme) => (this.theme = theme)\n\n /**\n * Recalculate budget by using the average amount from top-level categories\n * @param categories Detailed categories\n */\n recalculateBudgets = async (categories: DetailedCategory[]) => {\n try {\n for (const category of categories) {\n const budget = this.budgets.find((budget) => budget.category_guid === category.guid)\n if (budget) {\n await this.api.updateBudget({\n ...budget,\n amount: category.totalAverageAmount,\n })\n } else {\n await this.api.addBudget(category, category.totalAverageAmount)\n }\n }\n const budgetsToDelete = this.budgets.filter(\n (budget) => !categories.find((c) => c.guid === budget.category_guid),\n )\n\n for (const budgetToDelete of budgetsToDelete) {\n await this.api.deleteBudget(budgetToDelete.guid)\n }\n\n await this.loadBudgets()\n\n return { data: this.budgets, isSuccess: true }\n } catch (error) {\n console.error('Error recalculating budgets:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { data: [], isSuccess: false }\n }\n }\n\n updateBudget = async (budget: Budget): Promise<{ isSuccess: boolean }> => {\n try {\n const updatedBudget = await this.api.updateBudget(budget)\n\n runInAction(() => {\n const index = this.budgets.findIndex((b) => b.guid === budget.guid)\n if (index >= 0) {\n this.budgets[index] = updatedBudget\n }\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error updating budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n\n getMerchantBudgetByMerchantGuid = (merchantGuid: string): MerchantBudget | undefined => {\n return this.merchantBudgets.find(\n (eachMerchantBudget) => eachMerchantBudget?.merchant_guid === merchantGuid,\n )\n }\n\n setMerchantBudgets = (merchantBudgets: MerchantBudget[]) => {\n this.merchantBudgets = merchantBudgets\n }\n\n addMerchantBudget = async (merchantGuid: string, amount: number) => {\n try {\n const newMerchantBudget = await this.api.addMerchantBudget(merchantGuid, amount)\n\n runInAction(() => {\n this.merchantBudgets = upsertByGuid(this.merchantBudgets, newMerchantBudget)\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error adding merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n\n updateMerchantBudget = async (merchantBudget: MerchantBudget) => {\n try {\n const { guid: merchantBudgetGuid, amount } = merchantBudget\n const updatedMerchantBudget = await this.api.updateMerchantBudget(merchantBudgetGuid, amount)\n\n runInAction(() => {\n const index = this.merchantBudgets.findIndex((b) => b.guid === merchantBudget.guid)\n if (index >= 0) {\n this.merchantBudgets[index] = updatedMerchantBudget\n }\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error updating merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n\n deleteMerchantBudget = async (merchantBudgetGuid: string) => {\n try {\n await this.api.deleteMerchantBudget(merchantBudgetGuid)\n\n runInAction(() => {\n this.merchantBudgets = this.merchantBudgets.filter((b) => b.guid !== merchantBudgetGuid)\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error deleting merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BudgetsStore.es.js","names":[],"sources":["../../../src/core/stores/BudgetsStore.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction } from 'mobx'\n\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\n\nimport { Theme } from '@mui/system'\n\nimport { BudgetsApi } from '../api'\nimport { upsertByGuid } from '../utils/upsertByGuid'\nimport { CategoryGuids } from '../constants'\nimport { augmentBudgets, findBudget, findSubBudget } from '../utils/BudgetUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nimport type {\n Budget,\n Category,\n DateRange,\n DetailedBudget,\n DetailedCategory,\n MerchantBudget,\n} from '../types'\n\nexport class BudgetsStore {\n api: BudgetsApi = new BudgetsApi('/', '')\n\n globalStore: GlobalStore\n\n alert: { msg: string; severity: 'success' | 'error' } | null = null\n dateRange: DateRange = { start: startOfMonth(startOfToday()), end: endOfMonth(startOfToday()) }\n budgets: Budget[] = []\n selectedBudget: DetailedBudget | undefined\n selectedSubBudget: DetailedBudget | undefined\n isDataLoaded = false\n theme = {} as Theme\n merchantBudgets: MerchantBudget[] = []\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new BudgetsApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n loadBudgetData = async () => {\n if (!this.globalStore.recurringTransactionsStore.isDataLoaded) {\n await this.globalStore.recurringTransactionsStore.loadRepeatingTransactionData()\n }\n await this.loadBudgets()\n\n /** Reaction to update the selected budget/sub-budget if detailedBudgets is updated **/\n reaction(\n () => this.detailedBudgets,\n (detailedBudgets) => {\n if (detailedBudgets) {\n const budget = this.selectedBudget\n if (budget) {\n this.selectedBudget = findBudget(detailedBudgets, budget.guid)\n }\n\n const subBudget = this.selectedSubBudget\n if (subBudget && subBudget.parent_guid) {\n this.selectedSubBudget = findSubBudget(\n detailedBudgets,\n subBudget.guid,\n subBudget.parent_guid,\n )\n }\n }\n },\n )\n }\n\n get detailedBudgets(): DetailedBudget[] {\n return augmentBudgets(\n this.budgets.filter(\n (budget: Budget) =>\n budget.category_guid !== CategoryGuids.INCOME &&\n budget.category_guid !== CategoryGuids.TRANSFER &&\n budget.category_guid !== CategoryGuids.INVESTMENTS,\n ),\n this.globalStore.categoryStore.detailedCategories,\n this.globalStore.copyStore.copy.budgets,\n this.theme,\n ).sort((a, b) => {\n if (a.percentage > b.percentage) return -1\n if (a.percentage < b.percentage) return 1\n return 0\n })\n }\n\n // TODO: Replace this with income from recurring transactions. Income budgets are deprecated.\n get incomeBudget(): number | undefined {\n const filteredBudgets = augmentBudgets(\n this.budgets.filter((budget: Budget) => !budget.parent_guid),\n this.globalStore.categoryStore.detailedCategories,\n this.globalStore.copyStore.copy.budgets,\n this.theme,\n )\n\n const incomeBudget = filteredBudgets.reduce(\n (acc, curr) => {\n if (curr.category_guid !== CategoryGuids.INCOME) return acc\n if (!acc || curr.percentage > acc.percentage) return curr\n return acc\n },\n undefined as DetailedBudget | undefined,\n )\n\n return incomeBudget?.amount\n }\n\n get unbudgetedCategories(): DetailedCategory[] {\n return this.globalStore.categoryStore.spendCategories.filter(\n (category) => !this.detailedBudgets.find((budget) => budget.category_guid === category.guid),\n )\n }\n\n get totalBudgeted(): number {\n return this.detailedBudgets.reduce((total, budget) => total + budget.amount, 0)\n }\n\n addBudget = async (category: Category, amount: number, parentGuid: string | null = null) => {\n try {\n const budget = await this.api.addBudget(category, amount, parentGuid)\n runInAction(() => {\n this.budgets = upsertByGuid(this.budgets, budget)\n })\n } catch (error) {\n console.error('Error adding budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n }\n }\n\n deleteBudget = async (guid: string): Promise<boolean> => {\n const guids = [guid, ...this.budgets.filter((b) => b.parent_guid === guid).map((b) => b.guid)]\n const results = await Promise.allSettled(guids.map((g) => this.api.deleteBudget(g)))\n const deleted = new Set(guids.filter((_, i) => results[i].status === 'fulfilled'))\n runInAction(() => {\n this.budgets = this.budgets.filter((b) => !deleted.has(b.guid))\n })\n let failed = false\n for (const [i, r] of results.entries()) {\n if (r.status === 'rejected') {\n failed = true\n console.error('Error deleting budget:', r.reason)\n this.globalStore.captureException(r.reason, { store: 'BudgetsStore', guid: guids[i] })\n }\n }\n return !failed\n }\n\n loadBudgets = async () => {\n try {\n const budgets = await this.api.getBudgets()\n this.setBudgets(budgets)\n } catch (error) {\n console.error('Error occurred while loading budgets:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n throw error\n }\n }\n\n setAlert = (alert: { msg: string; severity: 'success' | 'error' } | null) => (this.alert = alert)\n\n setBudgets = (budgets: Budget[]) => {\n this.budgets = budgets\n this.isDataLoaded = true\n }\n\n setDateRange = (dateRange: DateRange) => (this.dateRange = dateRange)\n\n setSelectedBudget = (budget: DetailedBudget | undefined) => (this.selectedBudget = budget)\n\n setSelectedSubBudget = (budget: DetailedBudget | undefined) => (this.selectedSubBudget = budget)\n\n setTheme = (theme: Theme) => (this.theme = theme)\n\n /**\n * Recalculate budget by using the average amount from top-level categories\n * @param categories Detailed categories\n */\n recalculateBudgets = async (categories: DetailedCategory[]) => {\n try {\n for (const category of categories) {\n const budget = this.budgets.find((budget) => budget.category_guid === category.guid)\n if (budget) {\n await this.api.updateBudget({\n ...budget,\n amount: category.totalAverageAmount,\n })\n } else {\n await this.api.addBudget(category, category.totalAverageAmount)\n }\n }\n const budgetsToDelete = this.budgets.filter(\n (budget) => !categories.find((c) => c.guid === budget.category_guid),\n )\n\n for (const budgetToDelete of budgetsToDelete) {\n await this.api.deleteBudget(budgetToDelete.guid)\n }\n\n await this.loadBudgets()\n\n return { data: this.budgets, isSuccess: true }\n } catch (error) {\n console.error('Error recalculating budgets:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { data: [], isSuccess: false }\n }\n }\n\n updateBudget = async (budget: Budget): Promise<boolean> => {\n try {\n const updatedBudget = await this.api.updateBudget(budget)\n\n runInAction(() => {\n const index = this.budgets.findIndex((b) => b.guid === budget.guid)\n if (index >= 0) {\n this.budgets[index] = updatedBudget\n }\n })\n return true\n } catch (error) {\n console.error('Error updating budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return false\n }\n }\n\n getMerchantBudgetByMerchantGuid = (merchantGuid: string): MerchantBudget | undefined => {\n return this.merchantBudgets.find(\n (eachMerchantBudget) => eachMerchantBudget?.merchant_guid === merchantGuid,\n )\n }\n\n setMerchantBudgets = (merchantBudgets: MerchantBudget[]) => {\n this.merchantBudgets = merchantBudgets\n }\n\n addMerchantBudget = async (merchantGuid: string, amount: number) => {\n try {\n const newMerchantBudget = await this.api.addMerchantBudget(merchantGuid, amount)\n\n runInAction(() => {\n this.merchantBudgets = upsertByGuid(this.merchantBudgets, newMerchantBudget)\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error adding merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n\n updateMerchantBudget = async (merchantBudget: MerchantBudget) => {\n try {\n const { guid: merchantBudgetGuid, amount } = merchantBudget\n const updatedMerchantBudget = await this.api.updateMerchantBudget(merchantBudgetGuid, amount)\n\n runInAction(() => {\n const index = this.merchantBudgets.findIndex((b) => b.guid === merchantBudget.guid)\n if (index >= 0) {\n this.merchantBudgets[index] = updatedMerchantBudget\n }\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error updating merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n\n deleteMerchantBudget = async (merchantBudgetGuid: string) => {\n try {\n await this.api.deleteMerchantBudget(merchantBudgetGuid)\n\n runInAction(() => {\n this.merchantBudgets = this.merchantBudgets.filter((b) => b.guid !== merchantBudgetGuid)\n })\n return { isSuccess: true }\n } catch (error) {\n console.error('Error deleting merchant budget:', error)\n this.globalStore.captureException(error, { store: 'BudgetsStore' })\n return { isSuccess: false }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -32,7 +32,7 @@ export interface RepeatingTransaction {
|
|
|
32
32
|
account_guid: string;
|
|
33
33
|
created_by: number;
|
|
34
34
|
member_guid: string;
|
|
35
|
-
merchant_guid
|
|
35
|
+
merchant_guid?: string | null;
|
|
36
36
|
user_guid: string;
|
|
37
37
|
description: string;
|
|
38
38
|
amount: number;
|
|
@@ -53,7 +53,7 @@ export interface Recurrence {
|
|
|
53
53
|
frequency: Frequency;
|
|
54
54
|
institutionGuid: string;
|
|
55
55
|
institutionName: string;
|
|
56
|
-
merchantGuid
|
|
56
|
+
merchantGuid?: string | null;
|
|
57
57
|
name: string;
|
|
58
58
|
occurredOnDate?: Date;
|
|
59
59
|
recurrenceDay: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RepeatingTransaction.es.js","names":[],"sources":["../../../src/core/types/RepeatingTransaction.ts"],"sourcesContent":["import { Account } from './Account'\nimport { Transaction, TransactionType } from './Transaction'\n\nexport enum Frequency {\n Unknown = 0,\n EveryWeek = 1,\n EveryOtherWeek = 2,\n EveryMonth = 3,\n EveryOtherMonth = 4,\n EveryQuarter = 5,\n EveryOtherQuarter = 6,\n EveryYear = 7,\n TwiceAMonth = 8,\n}\n\nexport enum RecurrenceStatus {\n Paid = 0,\n Missed = 1,\n Upcoming = 2,\n}\n\nexport enum RecurrenceType {\n Expense = 0,\n Income = 1,\n}\n\nexport enum RepeatingType {\n Unknown = 0,\n Subscription = 1,\n Bill = 2,\n Income = 3,\n Transfer = 4,\n}\n\nexport interface RepeatingTransaction {\n // API fields\n guid: string\n account_guid: string\n created_by: number\n member_guid: string\n merchant_guid
|
|
1
|
+
{"version":3,"file":"RepeatingTransaction.es.js","names":[],"sources":["../../../src/core/types/RepeatingTransaction.ts"],"sourcesContent":["import { Account } from './Account'\nimport { Transaction, TransactionType } from './Transaction'\n\nexport enum Frequency {\n Unknown = 0,\n EveryWeek = 1,\n EveryOtherWeek = 2,\n EveryMonth = 3,\n EveryOtherMonth = 4,\n EveryQuarter = 5,\n EveryOtherQuarter = 6,\n EveryYear = 7,\n TwiceAMonth = 8,\n}\n\nexport enum RecurrenceStatus {\n Paid = 0,\n Missed = 1,\n Upcoming = 2,\n}\n\nexport enum RecurrenceType {\n Expense = 0,\n Income = 1,\n}\n\nexport enum RepeatingType {\n Unknown = 0,\n Subscription = 1,\n Bill = 2,\n Income = 3,\n Transfer = 4,\n}\n\nexport interface RepeatingTransaction {\n // API fields\n guid: string\n account_guid: string\n created_by: number\n member_guid: string\n merchant_guid?: string | null\n user_guid: string\n description: string\n amount: number\n predicted_occurs_on: string\n transaction_type: TransactionType\n recurrence_type: Frequency\n recurrence_day: number\n repeating_transaction_type: RepeatingType\n second_recurrence_day?: number\n\n // UI fields\n account?: Account\n transactions: Transaction[]\n}\n\nexport interface Recurrence {\n accountGuid: string\n amount: number\n categoryGuid: string\n expectedDate: Date\n frequency: Frequency\n institutionGuid: string\n institutionName: string\n merchantGuid?: string | null\n name: string\n occurredOnDate?: Date\n recurrenceDay: number\n repeatingTransactionGuid: string\n secondRecurrenceDay?: number\n status: RecurrenceStatus\n type: RecurrenceType\n transaction?: Transaction\n}\n"],"mappings":"AAGA,IAAY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,YAAA,CAAA,IAAA,aACA,EAAA,EAAA,iBAAA,CAAA,IAAA,kBACA,EAAA,EAAA,aAAA,CAAA,IAAA,cACA,EAAA,EAAA,kBAAA,CAAA,IAAA,mBACA,EAAA,EAAA,eAAA,CAAA,IAAA,gBACA,EAAA,EAAA,oBAAA,CAAA,IAAA,qBACA,EAAA,EAAA,YAAA,CAAA,IAAA,aACA,EAAA,EAAA,cAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA,GAEY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,OAAA,CAAA,IAAA,QACA,EAAA,EAAA,SAAA,CAAA,IAAA,UACA,EAAA,EAAA,WAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA,GAEY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,SAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA,GAEY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,eAAA,CAAA,IAAA,gBACA,EAAA,EAAA,OAAA,CAAA,IAAA,QACA,EAAA,EAAA,SAAA,CAAA,IAAA,UACA,EAAA,EAAA,WAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Theme } from '@mui/system';
|
|
2
2
|
import { Budget, BudgetColors, BudgetsCopy, DetailedCategory, DetailedBudget } from '../types';
|
|
3
|
+
export declare const isInvalidAmount: (val: string | undefined) => boolean;
|
|
3
4
|
export declare const getBudgetPercentage: (budgetAmount: number, totalAmount: number) => number;
|
|
4
5
|
export declare const getBudgetColors: (percentage: number, theme: Theme) => BudgetColors;
|
|
5
6
|
export declare const getBudgetDifference: (budgets: DetailedBudget[]) => number;
|