@mx-cartographer/experiences 9.4.41 → 9.4.42-alph.mm1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/categories/components/CategoryList.es.js +34 -27
  3. package/dist/categories/components/CategoryList.es.js.map +1 -1
  4. package/dist/common/components/listitems/CollapseExpandListItem.es.js +26 -25
  5. package/dist/common/components/listitems/CollapseExpandListItem.es.js.map +1 -1
  6. package/dist/core/stores/TransactionStore.es.js +1 -1
  7. package/dist/core/stores/TransactionStore.es.js.map +1 -1
  8. package/dist/core/types/localization/CommonCopy.d.ts +2 -0
  9. package/dist/core/types/localization/TrendsCopy.d.ts +0 -1
  10. package/dist/core/utils/CategoryUtil.d.ts +11 -0
  11. package/dist/core/utils/CategoryUtil.es.js +36 -32
  12. package/dist/core/utils/CategoryUtil.es.js.map +1 -1
  13. package/dist/core/utils/NetWorthUtils.d.ts +2 -2
  14. package/dist/core/utils/NetWorthUtils.es.js +64 -64
  15. package/dist/core/utils/NetWorthUtils.es.js.map +1 -1
  16. package/dist/core/utils/TransactionUtils.d.ts +2 -2
  17. package/dist/core/utils/TransactionUtils.es.js +93 -92
  18. package/dist/core/utils/TransactionUtils.es.js.map +1 -1
  19. package/dist/debts/components/debtstable/AccountCell.es.js +13 -13
  20. package/dist/debts/components/debtstable/AccountCell.es.js.map +1 -1
  21. package/dist/finstrong/components/SpendLessThanYouMake/SpendLessThanYouMakeComponent.es.js +40 -36
  22. package/dist/finstrong/components/SpendLessThanYouMake/SpendLessThanYouMakeComponent.es.js.map +1 -1
  23. package/dist/networth/components/AssetsLiabilitiesDetail.es.js +47 -47
  24. package/dist/networth/components/AssetsLiabilitiesDetail.es.js.map +1 -1
  25. package/dist/spending/components/MiniSpendingChart.es.js +52 -47
  26. package/dist/spending/components/MiniSpendingChart.es.js.map +1 -1
  27. package/dist/spending/components/Spending.es.js +82 -74
  28. package/dist/spending/components/Spending.es.js.map +1 -1
  29. package/dist/spending/utils/SpendingData.d.ts +7 -5
  30. package/dist/spending/utils/SpendingData.es.js +34 -31
  31. package/dist/spending/utils/SpendingData.es.js.map +1 -1
  32. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [9.4.42] - 09-25-2026
2
+
3
+ - **FIXED** - Category names now render localized copy instead of the raw API value in the Spending widget (main view list, drawer, donut legend), the Spending mini widget, the Finstrong spend-less-than-you-make chart, and the Transactions table Category column. (MEW-4166)
4
+ - **FIXED** - Trends category list "View more"/"View less" toggle is now localized and moved to common copy (MEW-4166)
5
+ - **FIXED** - Account type labels (e.g. Checking, Savings, Investment) in the Net Worth "Assets & Liabilities" drawer accordion and the Debts table account cell now use localized copy instead of hardcoded English (MEW-4166)
6
+ - **FIXED** - Category names in the shared category selection drawer (used by the transaction category-edit and split actions, and transaction-rule category edit) now render localized copy instead of the raw API value, and the search filter matches on the localized name (MEW-4166)
7
+ - **CHANGED** - Copy contract: added required `common.view_more` and `common.view_less` keys and removed the unused `trends.view_more` key. Consumers must supply the new `common` keys (delivered via mrs_content); the component falls back to English if they are absent (MEW-4166)
8
+
1
9
  ## [9.4.41] - 09-24-2026
2
10
 
3
11
  - **FIXED** - Account-to-account transfers now show the institution name instead of the raw feed description in the transaction detail header title and the transactions table/list Payee column (MEW-3972)
@@ -1,38 +1,45 @@
1
- import { buildDynamicCopy as p } from "../../core/utils/Localization.es.js";
2
- import { useCategoryStore as u, useGlobalCopyStore as c } from "../../common/context/hooks.es.js";
3
- import { useCategoryUiStore as g } from "../context/hooks.es.js";
4
- import f from "./CategoryRow.es.js";
1
+ import { buildDynamicCopy as c } from "../../core/utils/Localization.es.js";
2
+ import { useCategoryStore as g, useGlobalCopyStore as u } from "../../common/context/hooks.es.js";
3
+ import { getLocalizedCategoryName as f } from "../../core/utils/CategoryUtil.es.js";
4
+ import { useCategoryUiStore as C } from "../context/hooks.es.js";
5
+ import y from "./CategoryRow.es.js";
5
6
  import "react";
6
- import { observer as C } from "mobx-react-lite";
7
- import y from "@mui/material/Paper";
8
- import { jsx as t } from "react/jsx-runtime";
9
- import b from "@mui/material/List";
10
- var h = () => {
11
- const { categories: n } = u(), { searchValue: m } = g(), { categories: l } = c(), d = ((o, r = "") => o.reduce((a, e) => {
12
- if (e.parent_guid === null) {
13
- const i = [{
14
- ...e,
15
- name: p(l.all_parent_category, e.name),
16
- parent_guid: e.guid
17
- }, ...o].filter((s) => s.parent_guid === e.guid && s.name.toLowerCase().includes(r.toLowerCase()));
18
- if (e.name.toLowerCase().includes(r.toLowerCase()) || i.length > 0) return [...a, {
19
- category: { ...e },
20
- children: i
21
- }];
22
- }
23
- return a;
24
- }, []))(n, m);
25
- return /* @__PURE__ */ t(y, {
7
+ import { observer as L } from "mobx-react-lite";
8
+ import b from "@mui/material/Paper";
9
+ import { jsx as r } from "react/jsx-runtime";
10
+ import h from "@mui/material/List";
11
+ var _ = () => {
12
+ const { categories: l } = g(), { searchValue: d } = C(), { categories: a } = u(), p = ((o, i = "") => {
13
+ const s = o.map((t) => ({
14
+ ...t,
15
+ name: f(t, a)
16
+ }));
17
+ return s.reduce((t, e) => {
18
+ if (e.parent_guid === null) {
19
+ const m = [{
20
+ ...e,
21
+ name: c(a.all_parent_category, e.name),
22
+ parent_guid: e.guid
23
+ }, ...s].filter((n) => n.parent_guid === e.guid && n.name.toLowerCase().includes(i.toLowerCase()));
24
+ if (e.name.toLowerCase().includes(i.toLowerCase()) || m.length > 0) return [...t, {
25
+ category: { ...e },
26
+ children: m
27
+ }];
28
+ }
29
+ return t;
30
+ }, []);
31
+ })(l, d);
32
+ return /* @__PURE__ */ r(b, {
26
33
  className: "mx-cat-category-list",
27
34
  sx: { boxShadow: "none" },
28
- children: /* @__PURE__ */ t(b, { children: d.map((o) => /* @__PURE__ */ t(f, {
35
+ children: /* @__PURE__ */ r(h, { children: p.map((o) => /* @__PURE__ */ r(y, {
29
36
  category: o.category,
30
37
  subCategories: o.children
31
38
  }, o.category.guid)) })
32
39
  });
33
- }, P = C(h);
40
+ }, V = L(_);
34
41
  export {
35
- P as default
42
+ V as default
36
43
  };
37
44
 
38
45
  //# sourceMappingURL=CategoryList.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CategoryList.es.js","names":[],"sources":["../../../src/categories/components/CategoryList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\nimport List from '@mui/material/List'\nimport Paper from '@mui/material/Paper'\n\nimport { useCategoryStore, useGlobalCopyStore } from '../../common'\nimport type { Category } from '../../core'\n\nimport { useCategoryUiStore } from '../context/hooks'\nimport CategoryRow from './CategoryRow'\nimport { buildDynamicCopy } from '../../core/utils/Localization'\n\ninterface NestedCategory {\n category: Category\n children: Category[]\n}\n\nconst CategoryList: React.FC = () => {\n const { categories } = useCategoryStore()\n const { searchValue } = useCategoryUiStore()\n const { categories: copy } = useGlobalCopyStore()\n\n const buildNestedCategories = (categories: Category[], filter = ''): NestedCategory[] => {\n return categories.reduce((acc, currCategory) => {\n if (currCategory.parent_guid === null) {\n const categoriesWithParent = [\n {\n ...currCategory,\n name: buildDynamicCopy(copy.all_parent_category, currCategory.name) as string,\n parent_guid: currCategory.guid,\n },\n ...categories,\n ]\n const children = categoriesWithParent.filter(\n (category) =>\n category.parent_guid === currCategory.guid &&\n category.name.toLowerCase().includes(filter.toLowerCase()),\n )\n\n if (currCategory.name.toLowerCase().includes(filter.toLowerCase()) || children.length > 0) {\n return [...acc, { category: { ...currCategory }, children }]\n }\n }\n return acc\n }, [] as NestedCategory[])\n }\n\n const nestedCategories = buildNestedCategories(categories, searchValue)\n\n return (\n <Paper className=\"mx-cat-category-list\" sx={{ boxShadow: 'none' }}>\n <List>\n {nestedCategories.map((nested: NestedCategory) => (\n <CategoryRow\n category={nested.category}\n key={nested.category.guid}\n subCategories={nested.children}\n />\n ))}\n </List>\n </Paper>\n )\n}\n\nexport default observer(CategoryList)\n"],"mappings":";;;;;;;;;AAiBA,IAAM,IAAA,MAA+B;AACnC,QAAM,EAAE,YAAA,EAAA,IAAe,EAAiB,GAClC,EAAE,aAAA,EAAA,IAAgB,EAAmB,GACrC,EAAE,YAAY,EAAA,IAAS,EAAmB,GA2B1C,KAzBA,CAAyB,GAAwB,IAAS,OACvD,EAAW,OAAA,CAAQ,GAAK,MAAiB;AAC9C,QAAI,EAAa,gBAAgB,MAAM;AASrC,YAAM,IAAW,CAPf;AAAA,QACE,GAAG;AAAA,QACH,MAAM,EAAiB,EAAK,qBAAqB,EAAa,IAAI;AAAA,QAClE,aAAa,EAAa;AAAA,MAC5B,GACA,GAAG,CAEY,EAAqB,OAAA,CACnC,MACC,EAAS,gBAAgB,EAAa,QACtC,EAAS,KAAK,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,CAC7D;AAEA,UAAI,EAAa,KAAK,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,KAAK,EAAS,SAAS,EACtF,QAAO,CAAC,GAAG,GAAK;AAAA,QAAE,UAAU,EAAE,GAAG,EAAa;AAAA,QAAG,UAAA;AAAA,MAAS,CAAC;AAAA,IAE/D;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAqB,GAGoB,GAAY,CAAW;AAEtE,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,WAAU;AAAA,IAAuB,IAAI,EAAE,WAAW,OAAO;AAAA,IAC9D,UAAA,gBAAA,EAAC,GAAD,EAAA,UACG,EAAiB,IAAA,CAAK,MACrB,gBAAA,EAAC,GAAD;AAAA,MACE,UAAU,EAAO;AAAA,MAEjB,eAAe,EAAO;AAAA,IACvB,GAFM,EAAO,SAAS,IAEtB,CACF,EACG,CAAA;AAAA,EACD,CAAA;AAEX,GAEA,IAAe,EAAS,CAAY"}
1
+ {"version":3,"file":"CategoryList.es.js","names":[],"sources":["../../../src/categories/components/CategoryList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\nimport List from '@mui/material/List'\nimport Paper from '@mui/material/Paper'\n\nimport { useCategoryStore, useGlobalCopyStore } from '../../common'\nimport type { Category } from '../../core'\n\nimport { useCategoryUiStore } from '../context/hooks'\nimport CategoryRow from './CategoryRow'\nimport { buildDynamicCopy } from '../../core/utils/Localization'\nimport { getLocalizedCategoryName } from '../../core/utils/CategoryUtil'\n\ninterface NestedCategory {\n category: Category\n children: Category[]\n}\n\nconst CategoryList: React.FC = () => {\n const { categories } = useCategoryStore()\n const { searchValue } = useCategoryUiStore()\n const { categories: copy } = useGlobalCopyStore()\n\n const buildNestedCategories = (categories: Category[], filter = ''): NestedCategory[] => {\n const localizedCategories = categories.map((category) => ({\n ...category,\n name: getLocalizedCategoryName(category, copy),\n }))\n\n return localizedCategories.reduce((acc, currCategory) => {\n if (currCategory.parent_guid === null) {\n const categoriesWithParent = [\n {\n ...currCategory,\n name: buildDynamicCopy(copy.all_parent_category, currCategory.name) as string,\n parent_guid: currCategory.guid,\n },\n ...localizedCategories,\n ]\n const children = categoriesWithParent.filter(\n (category) =>\n category.parent_guid === currCategory.guid &&\n category.name.toLowerCase().includes(filter.toLowerCase()),\n )\n\n if (currCategory.name.toLowerCase().includes(filter.toLowerCase()) || children.length > 0) {\n return [...acc, { category: { ...currCategory }, children }]\n }\n }\n return acc\n }, [] as NestedCategory[])\n }\n\n const nestedCategories = buildNestedCategories(categories, searchValue)\n\n return (\n <Paper className=\"mx-cat-category-list\" sx={{ boxShadow: 'none' }}>\n <List>\n {nestedCategories.map((nested: NestedCategory) => (\n <CategoryRow\n category={nested.category}\n key={nested.category.guid}\n subCategories={nested.children}\n />\n ))}\n </List>\n </Paper>\n )\n}\n\nexport default observer(CategoryList)\n"],"mappings":";;;;;;;;;;AAkBA,IAAM,IAAA,MAA+B;AACnC,QAAM,EAAE,YAAA,EAAA,IAAe,EAAiB,GAClC,EAAE,aAAA,EAAA,IAAgB,EAAmB,GACrC,EAAE,YAAY,EAAA,IAAS,EAAmB,GAgC1C,KA9BA,CAAyB,GAAwB,IAAS,OAAyB;AACvF,UAAM,IAAsB,EAAW,IAAA,CAAK,OAAc;AAAA,MACxD,GAAG;AAAA,MACH,MAAM,EAAyB,GAAU,CAAI;AAAA,IAC/C,EAAE;AAEF,WAAO,EAAoB,OAAA,CAAQ,GAAK,MAAiB;AACvD,UAAI,EAAa,gBAAgB,MAAM;AASrC,cAAM,IAAW,CAPf;AAAA,UACE,GAAG;AAAA,UACH,MAAM,EAAiB,EAAK,qBAAqB,EAAa,IAAI;AAAA,UAClE,aAAa,EAAa;AAAA,QAC5B,GACA,GAAG,CAEY,EAAqB,OAAA,CACnC,MACC,EAAS,gBAAgB,EAAa,QACtC,EAAS,KAAK,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,CAC7D;AAEA,YAAI,EAAa,KAAK,YAAY,EAAE,SAAS,EAAO,YAAY,CAAC,KAAK,EAAS,SAAS,EACtF,QAAO,CAAC,GAAG,GAAK;AAAA,UAAE,UAAU,EAAE,GAAG,EAAa;AAAA,UAAG,UAAA;AAAA,QAAS,CAAC;AAAA,MAE/D;AACA,aAAO;AAAA,IACT,GAAG,CAAC,CAAqB;AAAA,EAC3B,GAE+C,GAAY,CAAW;AAEtE,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,WAAU;AAAA,IAAuB,IAAI,EAAE,WAAW,OAAO;AAAA,IAC9D,UAAA,gBAAA,EAAC,GAAD,EAAA,UACG,EAAiB,IAAA,CAAK,MACrB,gBAAA,EAAC,GAAD;AAAA,MACE,UAAU,EAAO;AAAA,MAEjB,eAAe,EAAO;AAAA,IACvB,GAFM,EAAO,SAAS,IAEtB,CACF,EACG,CAAA;AAAA,EACD,CAAA;AAEX,GAEA,IAAe,EAAS,CAAY"}
@@ -1,42 +1,43 @@
1
- import i from "react";
2
- import { observer as n } from "mobx-react-lite";
3
- import s from "@mui/material/Stack";
4
- import { Text as a } from "@mxenabled/mxui";
5
- import { ExpandLess as p, ExpandMore as f } from "@mxenabled/mx-icons";
6
- import { jsx as r, jsxs as l } from "react/jsx-runtime";
7
- import { useTheme as c } from "@mui/material/styles";
8
- import x from "@mui/material/ListItem";
9
- import d from "@mui/material/ListItemButton";
10
- import h from "@mui/material/ListItemIcon";
11
- import I from "@mui/material/ListItemText";
12
- var V = n(i.forwardRef(({ isExpanded: t, onClick: o }, m) => {
13
- const e = c();
14
- return /* @__PURE__ */ r(x, { children: /* @__PURE__ */ r(d, {
15
- ref: m,
16
- onClick: o,
1
+ import { useGlobalCopyStore as s } from "../../context/hooks.es.js";
2
+ import n from "react";
3
+ import { observer as a } from "mobx-react-lite";
4
+ import p from "@mui/material/Stack";
5
+ import { Text as l } from "@mxenabled/mxui";
6
+ import { ExpandLess as c, ExpandMore as f } from "@mxenabled/mx-icons";
7
+ import { jsx as r, jsxs as x } from "react/jsx-runtime";
8
+ import { useTheme as d } from "@mui/material/styles";
9
+ import h from "@mui/material/ListItem";
10
+ import u from "@mui/material/ListItemButton";
11
+ import I from "@mui/material/ListItemIcon";
12
+ import w from "@mui/material/ListItemText";
13
+ var k = a(n.forwardRef(({ isExpanded: o, onClick: m }, i) => {
14
+ const t = d(), { common: e } = s();
15
+ return /* @__PURE__ */ r(h, { children: /* @__PURE__ */ r(u, {
16
+ ref: i,
17
+ onClick: m,
17
18
  sx: { justifyContent: "center" },
18
- children: /* @__PURE__ */ l(s, {
19
+ children: /* @__PURE__ */ x(p, {
19
20
  sx: {
20
- color: e.palette.primary.main,
21
+ color: t.palette.primary.main,
21
22
  flexDirection: "row",
22
23
  alignItems: "center"
23
24
  },
24
- children: [/* @__PURE__ */ r(I, { children: /* @__PURE__ */ r(a, {
25
+ children: [/* @__PURE__ */ r(w, { children: /* @__PURE__ */ r(l, {
25
26
  bold: !0,
26
27
  variant: "body2",
27
- children: t ? "View less" : "View more"
28
- }) }), /* @__PURE__ */ r(h, {
29
- sx: { color: e.palette.primary.main },
30
- children: t ? /* @__PURE__ */ r(p, {}) : /* @__PURE__ */ r(f, { sx: {
28
+ children: o ? e.view_less ?? "View less" : e.view_more ?? "View more"
29
+ }) }), /* @__PURE__ */ r(I, {
30
+ sx: { color: t.palette.primary.main },
31
+ children: o ? /* @__PURE__ */ r(c, {}) : /* @__PURE__ */ r(f, { sx: {
31
32
  transition: "transform 0.3s ease-in-out",
32
- transform: t ? "rotate(180deg)" : "rotate(0deg)"
33
+ transform: o ? "rotate(180deg)" : "rotate(0deg)"
33
34
  } })
34
35
  })]
35
36
  })
36
37
  }) });
37
38
  }));
38
39
  export {
39
- V as CollapseExpandListItem
40
+ k as CollapseExpandListItem
40
41
  };
41
42
 
42
43
  //# sourceMappingURL=CollapseExpandListItem.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CollapseExpandListItem.es.js","names":[],"sources":["../../../../src/common/components/listitems/CollapseExpandListItem.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\nimport React from 'react'\n\nimport ListItem from '@mui/material/ListItem'\nimport ListItemButton from '@mui/material/ListItemButton'\nimport ListItemIcon from '@mui/material/ListItemIcon'\nimport ListItemText from '@mui/material/ListItemText'\nimport Stack from '@mui/material/Stack'\nimport { useTheme } from '@mui/material/styles'\n\nimport { ExpandLess, ExpandMore } from '@mxenabled/mx-icons'\nimport { Text } from '@mxenabled/mxui'\n\ninterface CollapseExpandListItemProps {\n isExpanded: boolean\n onClick: () => void\n}\n\nexport const CollapseExpandListItem = observer(\n React.forwardRef<HTMLDivElement, CollapseExpandListItemProps>(({ isExpanded, onClick }, ref) => {\n const theme = useTheme()\n return (\n <ListItem>\n <ListItemButton ref={ref} onClick={onClick} sx={{ justifyContent: 'center' }}>\n <Stack\n sx={{ color: theme.palette.primary.main, flexDirection: 'row', alignItems: 'center' }}\n >\n <ListItemText>\n <Text bold={true} variant=\"body2\">\n {isExpanded ? `View less` : `View more`}\n </Text>\n </ListItemText>\n <ListItemIcon sx={{ color: theme.palette.primary.main }}>\n {isExpanded ? (\n <ExpandLess />\n ) : (\n <ExpandMore\n sx={{\n transition: 'transform 0.3s ease-in-out',\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n }}\n />\n )}\n </ListItemIcon>\n </Stack>\n </ListItemButton>\n </ListItem>\n )\n }),\n)\n"],"mappings":";;;;;;;;;;;AAkBA,IAAa,IAAyB,EACpC,EAAM,WAAA,CAAyD,EAAE,YAAA,GAAY,SAAA,EAAA,GAAW,MAAQ;AAC9F,QAAM,IAAQ,EAAS;AACvB,SACE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,IAAqB,KAAA;AAAA,IAAc,SAAA;AAAA,IAAS,IAAI,EAAE,gBAAgB,SAAS;AAAA,IACzE,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QAAE,OAAO,EAAM,QAAQ,QAAQ;AAAA,QAAM,eAAe;AAAA,QAAO,YAAY;AAAA,MAAS;AAAA,MADtF,UAAA,CAGE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,SAAQ;AAAA,QACvB,UAAA,IAAa,cAAc;AAAA,MACxB,CAAA,EACM,CAAA,GACd,gBAAA,EAAC,GAAD;AAAA,QAAc,IAAI,EAAE,OAAO,EAAM,QAAQ,QAAQ,KAAK;AAAA,QACnD,UAAA,IACC,gBAAA,EAAC,GAAD,CAAa,CAAA,IAEb,gBAAA,EAAC,GAAD,EACE,IAAI;AAAA,UACF,YAAY;AAAA,UACZ,WAAW,IAAa,mBAAmB;AAAA,QAC7C,EACD,CAAA;AAAA,MAES,CAAA,CACT;AAAA;EACO,CAAA,EACR,CAAA;AAEd,CAAC,CACH"}
1
+ {"version":3,"file":"CollapseExpandListItem.es.js","names":[],"sources":["../../../../src/common/components/listitems/CollapseExpandListItem.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\nimport React from 'react'\n\nimport ListItem from '@mui/material/ListItem'\nimport ListItemButton from '@mui/material/ListItemButton'\nimport ListItemIcon from '@mui/material/ListItemIcon'\nimport ListItemText from '@mui/material/ListItemText'\nimport Stack from '@mui/material/Stack'\nimport { useTheme } from '@mui/material/styles'\n\nimport { ExpandLess, ExpandMore } from '@mxenabled/mx-icons'\nimport { Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../../context'\n\ninterface CollapseExpandListItemProps {\n isExpanded: boolean\n onClick: () => void\n}\n\nexport const CollapseExpandListItem = observer(\n React.forwardRef<HTMLDivElement, CollapseExpandListItemProps>(({ isExpanded, onClick }, ref) => {\n const theme = useTheme()\n const { common: copy } = useGlobalCopyStore()\n return (\n <ListItem>\n <ListItemButton ref={ref} onClick={onClick} sx={{ justifyContent: 'center' }}>\n <Stack\n sx={{ color: theme.palette.primary.main, flexDirection: 'row', alignItems: 'center' }}\n >\n <ListItemText>\n <Text bold={true} variant=\"body2\">\n {isExpanded ? (copy.view_less ?? 'View less') : (copy.view_more ?? 'View more')}\n </Text>\n </ListItemText>\n <ListItemIcon sx={{ color: theme.palette.primary.main }}>\n {isExpanded ? (\n <ExpandLess />\n ) : (\n <ExpandMore\n sx={{\n transition: 'transform 0.3s ease-in-out',\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n }}\n />\n )}\n </ListItemIcon>\n </Stack>\n </ListItemButton>\n </ListItem>\n )\n }),\n)\n"],"mappings":";;;;;;;;;;;;AAoBA,IAAa,IAAyB,EACpC,EAAM,WAAA,CAAyD,EAAE,YAAA,GAAY,SAAA,EAAA,GAAW,MAAQ;AAC9F,QAAM,IAAQ,EAAS,GACjB,EAAE,QAAQ,EAAA,IAAS,EAAmB;AAC5C,SACE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,IAAqB,KAAA;AAAA,IAAc,SAAA;AAAA,IAAS,IAAI,EAAE,gBAAgB,SAAS;AAAA,IACzE,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QAAE,OAAO,EAAM,QAAQ,QAAQ;AAAA,QAAM,eAAe;AAAA,QAAO,YAAY;AAAA,MAAS;AAAA,MADtF,UAAA,CAGE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,SAAQ;AAAA,QACvB,UAAA,IAAc,EAAK,aAAa,cAAgB,EAAK,aAAa;AAAA,MAC/D,CAAA,EACM,CAAA,GACd,gBAAA,EAAC,GAAD;AAAA,QAAc,IAAI,EAAE,OAAO,EAAM,QAAQ,QAAQ,KAAK;AAAA,QACnD,UAAA,IACC,gBAAA,EAAC,GAAD,CAAa,CAAA,IAEb,gBAAA,EAAC,GAAD,EACE,IAAI;AAAA,UACF,YAAY;AAAA,UACZ,WAAW,IAAa,mBAAmB;AAAA,QAC7C,EACD,CAAA;AAAA,MAES,CAAA,CACT;AAAA;EACO,CAAA,EACR,CAAA;AAEd,CAAC,CACH"}
@@ -57,7 +57,7 @@ var j = class {
57
57
  return this.associatedBeatsLoaded && this.tagsLoaded && this.taggingsLoaded && this.transactionRulesLoaded && this.transactionsLoaded;
58
58
  }
59
59
  get detailedTransactions() {
60
- return this.isTransactionDataLoaded ? m(this.transactions, this.globalStore.accountStore.visibleAccounts, this.globalStore.categoryStore.categories, this.taggings) : [];
60
+ return this.isTransactionDataLoaded ? m(this.transactions, this.globalStore.accountStore.visibleAccounts, this.globalStore.categoryStore.categories, this.taggings, this.globalStore.copyStore.copy.categories) : [];
61
61
  }
62
62
  get sortedTransactions() {
63
63
  return L(this.filter, this.uiStore.expandedSplits, this.sortColumn, this.sortDirection, this.tags, this.detailedTransactions);
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionStore.es.js","names":[],"sources":["../../../src/core/stores/TransactionStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { endOfToday } from 'date-fns/endOfToday'\nimport { formatISO } from 'date-fns/formatISO'\nimport { getUnixTime } from 'date-fns/getUnixTime'\nimport { isBefore } from 'date-fns/isBefore'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subDays } from 'date-fns/subDays'\n\nimport { BeatApi, TransactionApi } from '../api'\nimport { TABLE_CONST } from '../constants/Table'\nimport { COLUMN_NAMES, DEFAULT_TRANSACTION } from '../constants/Transaction'\nimport { TransactionType } from '../types'\nimport type { Beat, Tag, Tagging, Transaction, TransactionRule } from '../types'\nimport {\n buildDetailedTransactions,\n flattenTransactionsWithSplits,\n sortAndFilterTransactions,\n} from '../utils/TransactionUtils'\n\nimport { GlobalStore } from './GlobalStore'\nimport { upsertByGuid } from '../utils/upsertByGuid'\n\nexport type TransactionFilter = {\n accounts?: string[]\n dateRange?: { start: Date; end: Date }\n custom?: (value: Transaction) => boolean\n searchTerm?: string\n showSplits?: boolean\n}\n\nexport class TransactionStore {\n globalStore: GlobalStore\n uiStore: UiStore\n api = new TransactionApi('/', '')\n beatApi = new BeatApi('/', '')\n\n associatedBeats: Beat[] = []\n associatedBeatsLoaded: boolean = false\n associatedBeatsLoading: boolean = false\n transactions: Transaction[] = []\n transactionsLoaded: boolean = false\n transactionsLoading: boolean = false\n taggings: Tagging[] = []\n taggingsLoaded: boolean = false\n taggingsLoading: boolean = false\n tags: Tag[] = []\n tagsLoaded: boolean = false\n tagsLoading: boolean = false\n transactionRules: TransactionRule[] = []\n transactionRulesLoaded: boolean = false\n transactionRulesLoading: boolean = false\n transactionSplitting: boolean = false\n\n cachedStartDate: Date = subDays(startOfToday(), 90)\n filter: TransactionFilter = {}\n isLoading = true\n\n alert = ''\n\n sortColumn = COLUMN_NAMES.DATE\n sortDirection = TABLE_CONST.DESC\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.uiStore = new UiStore()\n this.api = new TransactionApi(\n globalStore.endpoint,\n globalStore.sessionToken,\n globalStore.onError,\n )\n this.beatApi = new BeatApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n loadTransactionData = async () => {\n if (!this.globalStore.accountStore.isAccountDataLoaded) {\n await this.globalStore.accountStore.loadAccountData()\n }\n if (!this.globalStore.categoryStore.categoriesLoaded) {\n await this.globalStore.categoryStore.loadCategories()\n }\n await Promise.all([\n this.loadAssociatedBeats(startOfMonth(new Date())),\n this.loadTags(),\n this.loadTaggings(),\n this.loadTransactionRules(),\n // By default loads 90 days of transactions\n this.loadTransactions(this.cachedStartDate),\n ])\n }\n\n get isTransactionDataLoaded(): boolean {\n return (\n this.associatedBeatsLoaded &&\n this.tagsLoaded &&\n this.taggingsLoaded &&\n this.transactionRulesLoaded &&\n this.transactionsLoaded\n )\n }\n\n get detailedTransactions(): Transaction[] {\n return this.isTransactionDataLoaded\n ? buildDetailedTransactions(\n this.transactions,\n this.globalStore.accountStore.visibleAccounts,\n this.globalStore.categoryStore.categories,\n this.taggings,\n )\n : []\n }\n\n get sortedTransactions(): Transaction[] {\n return sortAndFilterTransactions(\n this.filter,\n this.uiStore.expandedSplits,\n this.sortColumn,\n this.sortDirection,\n this.tags,\n this.detailedTransactions,\n )\n }\n\n get sortedTransactionsWithSplits(): Transaction[] {\n return flattenTransactionsWithSplits(this.sortedTransactions, this.detailedTransactions)\n }\n\n setAssociatedBeats = (beats: Beat[]) => {\n this.associatedBeats = beats\n this.associatedBeatsLoading = false\n this.associatedBeatsLoaded = true\n }\n\n setTaggings = (taggings: Tagging[]) => {\n this.taggings = taggings\n this.taggingsLoading = false\n this.taggingsLoaded = true\n }\n\n setTags = (tags: Tag[]) => {\n this.tags = tags\n this.tagsLoading = false\n this.tagsLoaded = true\n }\n\n setTransactionRules = (transactionRules: TransactionRule[]) => {\n this.transactionRules = transactionRules\n this.transactionRulesLoading = false\n this.transactionRulesLoaded = true\n }\n\n setTransactions = (transactions: Transaction[]) => {\n this.transactions = transactions\n this.transactionsLoading = false\n this.transactionsLoaded = true\n }\n\n setAlert = (alert: string) => {\n this.alert = alert\n }\n\n addTag = async (name: string) => {\n try {\n await this.api.addTag({ name } as Tag)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while adding tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addTagging = async (tagGuid: string, transactionGuid: string) => {\n try {\n await this.api.addTagging({\n tag_guid: tagGuid,\n transaction_guid: transactionGuid,\n } as Tagging)\n } catch (error) {\n console.error('Error occurred while adding tagging:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addOrUpdateTransactionRule = async (categoryGuid: string, transaction: Transaction) => {\n try {\n const existingRule = this.transactionRules.find(\n (rule: TransactionRule) => rule.guid === transaction.user_transaction_rule_guid,\n ) as TransactionRule | undefined\n\n if (existingRule) {\n await this.api.updateTransactionRule({\n ...existingRule,\n category_guid: categoryGuid,\n description: transaction.description,\n } as TransactionRule)\n } else {\n await this.api.addTransactionRule({\n category_guid: categoryGuid,\n description: transaction.description,\n match_description: transaction.description,\n } as TransactionRule)\n }\n await this.loadTransactionRules()\n } catch (error) {\n console.error('Error occurred while adding/updating transaction rule:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addTransaction = async (transaction: Transaction) => {\n try {\n const newTransaction = await this.api.addTransaction(transaction)\n\n if (newTransaction) {\n runInAction(() => {\n this.setTransactions(upsertByGuid(this.transactions, newTransaction, true))\n\n // Brokaw may insert the transaction via WebSocket, but it never\n // updates the account balance — that only happens here.\n // See: money-dashboard/src/util/BrokawClient.ts::handleTransactionEvents (search \"setTransactions\")\n // If that handler ever calls updateAccountBalance, remove this call or guard on !existing.\n const balanceChange =\n newTransaction.transaction_type === TransactionType.CREDIT\n ? newTransaction.amount\n : -newTransaction.amount\n\n this.globalStore.accountStore.updateAccountBalance(\n newTransaction.account_guid,\n balanceChange,\n )\n })\n }\n } catch (error) {\n console.error('Error occurred while adding transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n loadAssociatedBeats = async (fromDate?: Date) => {\n if (this.associatedBeatsLoading) return\n\n this.associatedBeatsLoading = true\n const fromDateISO = fromDate ? formatISO(fromDate, { representation: 'date' }) : undefined\n try {\n const beats = await this.beatApi.getBeatsWithAssociatedTransaction(fromDateISO)\n this.setAssociatedBeats(beats)\n } catch (error) {\n console.error('Error occurred while loading associated beats:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setAssociatedBeats([])\n } finally {\n // Clear the in-flight flag even on failure so a later load (e.g. a widget\n // remount) can retry instead of being no-oped by the guard above, which would\n // leave isTransactionDataLoaded false and the list empty until a hard refresh.\n runInAction(() => {\n this.associatedBeatsLoading = false\n })\n }\n }\n\n loadTags = async () => {\n if (this.tagsLoading) return\n\n this.tagsLoading = true\n try {\n const tags = await this.api.getTags()\n this.setTags(tags)\n } catch (error) {\n console.error('Error occurred while loading tags:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n } finally {\n runInAction(() => {\n this.tagsLoading = false\n })\n }\n }\n\n loadTaggings = async () => {\n if (this.taggingsLoading) return\n\n this.taggingsLoading = true\n try {\n const taggings = await this.api.getTaggings()\n this.setTaggings(taggings)\n } catch (error) {\n console.error('Error occurred while loading taggings:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setTaggings([])\n } finally {\n runInAction(() => {\n this.taggingsLoading = false\n })\n }\n }\n\n loadTransactionRules = async () => {\n if (this.transactionRulesLoading) return\n\n this.transactionRulesLoading = true\n try {\n const transactionRules = await this.api.getTransactionRules()\n this.setTransactionRules(transactionRules)\n } catch (error) {\n // Catch so a rejection can't abort the Promise.all in loadTransactionData.\n console.error('Error occurred while loading transaction rules:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setTransactionRules([])\n } finally {\n runInAction(() => {\n this.transactionRulesLoading = false\n })\n }\n }\n\n loadTransactions = async (startDate: Date = this.cachedStartDate) => {\n if (this.transactionsLoading) return\n\n this.setIsLoading(true)\n this.transactionsLoading = true\n\n try {\n const transactions = await this.api.getTransactionsByDateRange(\n getUnixTime(startDate),\n getUnixTime(endOfToday()),\n )\n this.setTransactions(transactions)\n // Advance the cache only after the range is actually loaded, so the invariant\n // \"we hold transactions back to cachedStartDate\" always holds.\n runInAction(() => {\n this.cachedStartDate = startDate\n })\n } catch (error) {\n console.error('Error occurred while loading transactions:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n } finally {\n // See loadAssociatedBeats: clear the flag on failure so retries aren't no-oped.\n runInAction(() => {\n this.transactionsLoading = false\n })\n this.setIsLoading(false)\n }\n }\n\n modifyTransactionByAccountGuid = (guid: string, updates: Partial<Transaction>) => {\n this.transactions = this.transactions.map((txn) =>\n txn.account_guid === guid ? { ...txn, ...updates } : txn,\n )\n }\n\n removeTag = async (tagGuid: string) => {\n try {\n await this.api.removeTag(tagGuid)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while removing tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n removeTagging = async (taggingGuid: string) => {\n try {\n await this.api.removeTagging(taggingGuid)\n } catch (error) {\n console.error('Error occurred while removing tagging:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n removeTransaction = async (transactionGuid: string) => {\n try {\n await this.api.removeTransaction(transactionGuid)\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transactionGuid)\n\n if (index >= 0) {\n const updatedTransactions = [...this.transactions]\n updatedTransactions.splice(index, 1)\n this.setTransactions(updatedTransactions)\n }\n } catch (error) {\n console.error('Error occurred while removing transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n setFilter = (filter: TransactionFilter) => {\n this.filter = filter\n\n // Only reload if the new start date is prior to the cached start date; end date\n // is always today. loadTransactions advances cachedStartDate on success, so we\n // must not advance it here (a skipped/failed load would leave the list empty).\n if (filter.dateRange && isBefore(filter.dateRange.start, this.cachedStartDate)) {\n this.loadTransactions(filter.dateRange.start)\n }\n }\n\n setIsLoading = (isLoading: boolean) => (this.isLoading = isLoading)\n\n splitTransaction = async (transaction: Transaction, splits: Transaction[]) => {\n if (this.transactionSplitting) return\n this.transactionSplitting = true\n\n try {\n const updatedTransaction = await this.api.updateTransaction(transaction)\n const children = [] as Transaction[]\n\n for (let i = 0; i < splits.length; i++) {\n const child = await this.api.addTransaction(splits[i])\n children.push(child)\n }\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transaction.guid)\n\n if (index >= 0) {\n // Remove old parent and any existing children\n const filtered = this.transactions.filter(\n (t) => t.guid !== transaction.guid && t.parent_guid !== transaction.guid,\n )\n\n // Insert updated parent + new children at original position\n this.setTransactions([\n ...filtered.slice(0, index),\n updatedTransaction,\n ...children,\n ...filtered.slice(index),\n ])\n }\n } catch (error) {\n console.error('Error occurred while splitting transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n throw error\n } finally {\n this.transactionSplitting = false\n }\n }\n\n unSplitTransaction = async (guid: string) => {\n try {\n const children = this.transactions.filter((t) => t.parent_guid === guid)\n\n await this.api.removeTransactionSplit(guid)\n\n // Remove children\n const transactions = [...this.transactions]\n children.forEach((child) => {\n const index = transactions.findIndex((t) => t.guid === child.guid)\n\n if (index >= 0) {\n transactions.splice(index, 1)\n }\n })\n\n // Update parent\n const index = transactions.findIndex((t) => t.guid === guid)\n\n runInAction(() => {\n const transaction = transactions[index]\n if (transaction) {\n transaction.has_been_split = false\n }\n\n if (index >= 0) {\n this.setTransactions([\n ...transactions.slice(0, index),\n transaction,\n ...transactions.slice(index + 1),\n ])\n }\n })\n } catch (error) {\n console.error('Error occurred while unsplitting transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTaggings = async (tagGuids: string[], transactionGuid: string) => {\n try {\n const currentTaggings = this.taggings.filter((t) => t.transaction_guid === transactionGuid)\n\n const currentTagGuids = new Set(currentTaggings.map((t) => t.tag_guid))\n const incomingTagGuids = new Set(tagGuids)\n\n // Add new taggings that don't already exist\n for (const tagGuid of tagGuids) {\n if (!currentTagGuids.has(tagGuid)) {\n await this.addTagging(tagGuid, transactionGuid)\n }\n }\n\n // Remove taggings that are no longer needed\n for (const tagging of currentTaggings) {\n if (!incomingTagGuids.has(tagging.tag_guid)) {\n await this.removeTagging(tagging.guid)\n }\n }\n\n await this.loadTaggings()\n } catch (error) {\n console.error('Error occurred while updating taggings:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTag = async (tag: Tag) => {\n try {\n await this.api.updateTag(tag)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while updating tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTransaction = async (transaction: Transaction) => {\n try {\n const updatedTransaction = await this.api.updateTransaction(transaction)\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transaction.guid)\n\n if (index >= 0) {\n this.setTransactions([\n ...this.transactions.slice(0, index),\n updatedTransaction,\n ...this.transactions.slice(index + 1),\n ])\n }\n } catch (error) {\n console.error('Error occurred while updating transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n // This is used for loading the transactions list on demand, on clicking the different transactions of the insightful beats.\n loadEmbeddedInstanceTransactions = async (fromDate: Date) => {\n try {\n const transactions = await this.api.getTransactionsByDateRange(\n getUnixTime(fromDate),\n getUnixTime(endOfToday()),\n )\n this.cachedStartDate = fromDate\n this.transactions = transactions\n } catch (error) {\n console.error('Error occurred while loading embedded instance transactions:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n}\n\nexport class UiStore {\n beginDate = startOfMonth(new Date())\n endDate = endOfMonth(new Date())\n\n expandedSplits = [] as string[]\n height = 550\n width = 1000\n shouldDisableDrawerScroll = false\n\n searchValue = ''\n selectedAccountGuids = [] as string[]\n\n manualTransaction: Transaction = DEFAULT_TRANSACTION\n isAmountValid = false\n\n showInsights = false\n\n constructor() {\n makeAutoObservable(this)\n }\n\n setDateRange = (beginDate: Date, endDate: Date) => {\n this.beginDate = beginDate\n this.endDate = endDate\n }\n\n setIsAmountValid = (valid: boolean) => (this.isAmountValid = valid)\n\n setSearchValue = (searchValue: string) => (this.searchValue = searchValue)\n\n setSelectedAccountGuids = (accountGuids: string[]) => (this.selectedAccountGuids = accountGuids)\n\n setShouldDisableDrawerScroll = (shouldDisable: boolean) =>\n (this.shouldDisableDrawerScroll = shouldDisable)\n\n setShowInsights = (showInsights: boolean) => {\n this.showInsights = showInsights\n }\n\n setSize = (height: number, width: number) => {\n this.height = height\n this.width = width\n }\n\n toggleSplit = (guid: string) => {\n const expandedSplits = [...this.expandedSplits]\n const index = this.expandedSplits.findIndex((splitGuid) => splitGuid === guid)\n\n if (index >= 0) {\n expandedSplits.splice(index, 1)\n } else {\n expandedSplits.push(guid)\n }\n\n this.expandedSplits = expandedSplits\n }\n\n clearExpandedSplits = () => {\n if (this.expandedSplits.length === 0) return\n this.expandedSplits = []\n }\n\n updateManualTransaction = (manualTransaction: Transaction) => {\n this.manualTransaction = manualTransaction\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,IAAa,IAAb,MAA8B;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,MAAM,IAAI,EAAe,KAAK,EAAE;AAAA,EAChC,UAAU,IAAI,EAAQ,KAAK,EAAE;AAAA,EAE7B,kBAA0B,CAAC;AAAA,EAC3B,wBAAiC;AAAA,EACjC,yBAAkC;AAAA,EAClC,eAA8B,CAAC;AAAA,EAC/B,qBAA8B;AAAA,EAC9B,sBAA+B;AAAA,EAC/B,WAAsB,CAAC;AAAA,EACvB,iBAA0B;AAAA,EAC1B,kBAA2B;AAAA,EAC3B,OAAc,CAAC;AAAA,EACf,aAAsB;AAAA,EACtB,cAAuB;AAAA,EACvB,mBAAsC,CAAC;AAAA,EACvC,yBAAkC;AAAA,EAClC,0BAAmC;AAAA,EACnC,uBAAgC;AAAA,EAEhC,kBAAwB,EAAQ,EAAa,GAAG,EAAE;AAAA,EAClD,SAA4B,CAAC;AAAA,EAC7B,YAAY;AAAA,EAEZ,QAAQ;AAAA,EAER,aAAa,EAAa;AAAA,EAC1B,gBAAgB,EAAY;AAAA,EAE5B,YAAY,GAA0B;AACpC,SAAK,cAAc,GACnB,KAAK,UAAU,IAAI,EAAQ,GAC3B,KAAK,MAAM,IAAI,EACb,EAAY,UACZ,EAAY,cACZ,EAAY,OACd,GACA,KAAK,UAAU,IAAI,EAAQ,EAAY,UAAU,EAAY,cAAc,EAAY,OAAO,GAE9F,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,sBAAsB,YAAY;AAChC,IAAK,KAAK,YAAY,aAAa,uBACjC,MAAM,KAAK,YAAY,aAAa,gBAAgB,GAEjD,KAAK,YAAY,cAAc,oBAClC,MAAM,KAAK,YAAY,cAAc,eAAe,GAEtD,MAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,oBAAoB,EAAa,oBAAI,KAAK,CAAC,CAAC;AAAA,MACjD,KAAK,SAAS;AAAA,MACd,KAAK,aAAa;AAAA,MAClB,KAAK,qBAAqB;AAAA,MAE1B,KAAK,iBAAiB,KAAK,eAAe;AAAA,IAC5C,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,0BAAmC;AACrC,WACE,KAAK,yBACL,KAAK,cACL,KAAK,kBACL,KAAK,0BACL,KAAK;AAAA,EAET;AAAA,EAEA,IAAI,uBAAsC;AACxC,WAAO,KAAK,0BACR,EACE,KAAK,cACL,KAAK,YAAY,aAAa,iBAC9B,KAAK,YAAY,cAAc,YAC/B,KAAK,QACP,IACA,CAAC;AAAA,EACP;AAAA,EAEA,IAAI,qBAAoC;AACtC,WAAO,EACL,KAAK,QACL,KAAK,QAAQ,gBACb,KAAK,YACL,KAAK,eACL,KAAK,MACL,KAAK,oBACP;AAAA,EACF;AAAA,EAEA,IAAI,+BAA8C;AAChD,WAAO,EAA8B,KAAK,oBAAoB,KAAK,oBAAoB;AAAA,EACzF;AAAA,EAEA,qBAAA,CAAsB,MAAkB;AACtC,SAAK,kBAAkB,GACvB,KAAK,yBAAyB,IAC9B,KAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEA,cAAA,CAAe,MAAwB;AACrC,SAAK,WAAW,GAChB,KAAK,kBAAkB,IACvB,KAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,UAAA,CAAW,MAAgB;AACzB,SAAK,OAAO,GACZ,KAAK,cAAc,IACnB,KAAK,aAAa;AAAA,EACpB;AAAA,EAEA,sBAAA,CAAuB,MAAwC;AAC7D,SAAK,mBAAmB,GACxB,KAAK,0BAA0B,IAC/B,KAAK,yBAAyB;AAAA,EAChC;AAAA,EAEA,kBAAA,CAAmB,MAAgC;AACjD,SAAK,eAAe,GACpB,KAAK,sBAAsB,IAC3B,KAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,WAAA,CAAY,MAAkB;AAC5B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,SAAS,OAAO,MAAiB;AAC/B,QAAI;AACF,YAAM,KAAK,IAAI,OAAO,EAAE,MAAA,EAAK,CAAQ,GACrC,MAAM,KAAK,SAAS;AAAA,IACtB,SAAS,GAAO;AACd,cAAQ,MAAM,oCAAoC,CAAK,GACvD,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,aAAa,OAAO,GAAiB,MAA4B;AAC/D,QAAI;AACF,YAAM,KAAK,IAAI,WAAW;AAAA,QACxB,UAAU;AAAA,QACV,kBAAkB;AAAA,MACpB,CAAY;AAAA,IACd,SAAS,GAAO;AACd,cAAQ,MAAM,wCAAwC,CAAK,GAC3D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,6BAA6B,OAAO,GAAsB,MAA6B;AACrF,QAAI;AACF,YAAM,IAAe,KAAK,iBAAiB,KAAA,CACxC,MAA0B,EAAK,SAAS,EAAY,0BACvD;AAEA,MAAI,IACF,MAAM,KAAK,IAAI,sBAAsB;AAAA,QACnC,GAAG;AAAA,QACH,eAAe;AAAA,QACf,aAAa,EAAY;AAAA,MAC3B,CAAoB,IAEpB,MAAM,KAAK,IAAI,mBAAmB;AAAA,QAChC,eAAe;AAAA,QACf,aAAa,EAAY;AAAA,QACzB,mBAAmB,EAAY;AAAA,MACjC,CAAoB,GAEtB,MAAM,KAAK,qBAAqB;AAAA,IAClC,SAAS,GAAO;AACd,cAAQ,MAAM,0DAA0D,CAAK,GAC7E,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,iBAAiB,OAAO,MAA6B;AACnD,QAAI;AACF,YAAM,IAAiB,MAAM,KAAK,IAAI,eAAe,CAAW;AAEhE,MAAI,KACF,EAAA,MAAkB;AAChB,aAAK,gBAAgB,EAAa,KAAK,cAAc,GAAgB,EAAI,CAAC;AAM1E,cAAM,IACJ,EAAe,qBAAqB,EAAgB,SAChD,EAAe,SACf,CAAC,EAAe;AAEtB,aAAK,YAAY,aAAa,qBAC5B,EAAe,cACf,CACF;AAAA,MACF,CAAC;AAAA,IAEL,SAAS,GAAO;AACd,cAAQ,MAAM,4CAA4C,CAAK,GAC/D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,sBAAsB,OAAO,MAAoB;AAC/C,QAAI,KAAK,uBAAwB;AAEjC,SAAK,yBAAyB;AAC9B,UAAM,IAAc,IAAW,EAAU,GAAU,EAAE,gBAAgB,OAAO,CAAC,IAAI;AACjF,QAAI;AACF,YAAM,IAAQ,MAAM,KAAK,QAAQ,kCAAkC,CAAW;AAC9E,WAAK,mBAAmB,CAAK;AAAA,IAC/B,SAAS,GAAO;AACd,cAAQ,MAAM,kDAAkD,CAAK,GACrE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC,GACtE,KAAK,mBAAmB,CAAC,CAAC;AAAA,IAC5B,UAAA;AAIE,MAAA,EAAA,MAAkB;AAChB,aAAK,yBAAyB;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,WAAW,YAAY;AACrB,QAAI,MAAK,aAET;AAAA,WAAK,cAAc;AACnB,UAAI;AACF,cAAM,IAAO,MAAM,KAAK,IAAI,QAAQ;AACpC,aAAK,QAAQ,CAAI;AAAA,MACnB,SAAS,GAAO;AACd,gBAAQ,MAAM,sCAAsC,CAAK,GACzD,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,MACxE,UAAA;AACE,QAAA,EAAA,MAAkB;AAChB,eAAK,cAAc;AAAA,QACrB,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAAA,EAEA,eAAe,YAAY;AACzB,QAAI,MAAK,iBAET;AAAA,WAAK,kBAAkB;AACvB,UAAI;AACF,cAAM,IAAW,MAAM,KAAK,IAAI,YAAY;AAC5C,aAAK,YAAY,CAAQ;AAAA,MAC3B,SAAS,GAAO;AACd,gBAAQ,MAAM,0CAA0C,CAAK,GAC7D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC,GACtE,KAAK,YAAY,CAAC,CAAC;AAAA,MACrB,UAAA;AACE,QAAA,EAAA,MAAkB;AAChB,eAAK,kBAAkB;AAAA,QACzB,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAAA,EAEA,uBAAuB,YAAY;AACjC,QAAI,MAAK,yBAET;AAAA,WAAK,0BAA0B;AAC/B,UAAI;AACF,cAAM,IAAmB,MAAM,KAAK,IAAI,oBAAoB;AAC5D,aAAK,oBAAoB,CAAgB;AAAA,MAC3C,SAAS,GAAO;AAEd,gBAAQ,MAAM,mDAAmD,CAAK,GACtE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC,GACtE,KAAK,oBAAoB,CAAC,CAAC;AAAA,MAC7B,UAAA;AACE,QAAA,EAAA,MAAkB;AAChB,eAAK,0BAA0B;AAAA,QACjC,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAAA,EAEA,mBAAmB,OAAO,IAAkB,KAAK,oBAAoB;AACnE,QAAI,MAAK,qBAET;AAAA,WAAK,aAAa,EAAI,GACtB,KAAK,sBAAsB;AAE3B,UAAI;AACF,cAAM,IAAe,MAAM,KAAK,IAAI,2BAClC,EAAY,CAAS,GACrB,EAAY,EAAW,CAAC,CAC1B;AACA,aAAK,gBAAgB,CAAY,GAGjC,EAAA,MAAkB;AAChB,eAAK,kBAAkB;AAAA,QACzB,CAAC;AAAA,MACH,SAAS,GAAO;AACd,gBAAQ,MAAM,8CAA8C,CAAK,GACjE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,MACxE,UAAA;AAEE,QAAA,EAAA,MAAkB;AAChB,eAAK,sBAAsB;AAAA,QAC7B,CAAC,GACD,KAAK,aAAa,EAAK;AAAA,MACzB;AAAA;AAAA,EACF;AAAA,EAEA,iCAAA,CAAkC,GAAc,MAAkC;AAChF,SAAK,eAAe,KAAK,aAAa,IAAA,CAAK,MACzC,EAAI,iBAAiB,IAAO;AAAA,MAAE,GAAG;AAAA,MAAK,GAAG;AAAA,IAAQ,IAAI,CACvD;AAAA,EACF;AAAA,EAEA,YAAY,OAAO,MAAoB;AACrC,QAAI;AACF,YAAM,KAAK,IAAI,UAAU,CAAO,GAChC,MAAM,KAAK,SAAS;AAAA,IACtB,SAAS,GAAO;AACd,cAAQ,MAAM,sCAAsC,CAAK,GACzD,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,gBAAgB,OAAO,MAAwB;AAC7C,QAAI;AACF,YAAM,KAAK,IAAI,cAAc,CAAW;AAAA,IAC1C,SAAS,GAAO;AACd,cAAQ,MAAM,0CAA0C,CAAK,GAC7D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,oBAAoB,OAAO,MAA4B;AACrD,QAAI;AACF,YAAM,KAAK,IAAI,kBAAkB,CAAe;AAEhD,YAAM,IAAQ,KAAK,aAAa,UAAA,CAAW,MAAmB,EAAE,SAAS,CAAe;AAExF,UAAI,KAAS,GAAG;AACd,cAAM,IAAsB,CAAC,GAAG,KAAK,YAAY;AACjD,QAAA,EAAoB,OAAO,GAAO,CAAC,GACnC,KAAK,gBAAgB,CAAmB;AAAA,MAC1C;AAAA,IACF,SAAS,GAAO;AACd,cAAQ,MAAM,8CAA8C,CAAK,GACjE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,YAAA,CAAa,MAA8B;AACzC,SAAK,SAAS,GAKV,EAAO,aAAa,EAAS,EAAO,UAAU,OAAO,KAAK,eAAe,KAC3E,KAAK,iBAAiB,EAAO,UAAU,KAAK;AAAA,EAEhD;AAAA,EAEA,eAAA,CAAgB,MAAwB,KAAK,YAAY;AAAA,EAEzD,mBAAmB,OAAO,GAA0B,MAA0B;AAC5E,QAAI,MAAK,sBACT;AAAA,WAAK,uBAAuB;AAE5B,UAAI;AACF,cAAM,IAAqB,MAAM,KAAK,IAAI,kBAAkB,CAAW,GACjE,IAAW,CAAC;AAElB,iBAAS,IAAI,GAAG,IAAI,EAAO,QAAQ,KAAK;AACtC,gBAAM,IAAQ,MAAM,KAAK,IAAI,eAAe,EAAO,CAAA,CAAE;AACrD,UAAA,EAAS,KAAK,CAAK;AAAA,QACrB;AAEA,cAAM,IAAQ,KAAK,aAAa,UAAA,CAAW,MAAmB,EAAE,SAAS,EAAY,IAAI;AAEzF,YAAI,KAAS,GAAG;AAEd,gBAAM,IAAW,KAAK,aAAa,OAAA,CAChC,MAAM,EAAE,SAAS,EAAY,QAAQ,EAAE,gBAAgB,EAAY,IACtE;AAGA,eAAK,gBAAgB;AAAA,YACnB,GAAG,EAAS,MAAM,GAAG,CAAK;AAAA,YAC1B;AAAA,YACA,GAAG;AAAA,YACH,GAAG,EAAS,MAAM,CAAK;AAAA,UACzB,CAAC;AAAA,QACH;AAAA,MACF,SAAS,GAAO;AACd,sBAAQ,MAAM,+CAA+C,CAAK,GAClE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC,GAChE;AAAA,MACR,UAAA;AACE,aAAK,uBAAuB;AAAA,MAC9B;AAAA;AAAA,EACF;AAAA,EAEA,qBAAqB,OAAO,MAAiB;AAC3C,QAAI;AACF,YAAM,IAAW,KAAK,aAAa,OAAA,CAAQ,MAAM,EAAE,gBAAgB,CAAI;AAEvE,YAAM,KAAK,IAAI,uBAAuB,CAAI;AAG1C,YAAM,IAAe,CAAC,GAAG,KAAK,YAAY;AAC1C,MAAA,EAAS,QAAA,CAAS,MAAU;AAC1B,cAAM,IAAQ,EAAa,UAAA,CAAW,MAAM,EAAE,SAAS,EAAM,IAAI;AAEjE,QAAI,KAAS,KACX,EAAa,OAAO,GAAO,CAAC;AAAA,MAEhC,CAAC;AAGD,YAAM,IAAQ,EAAa,UAAA,CAAW,MAAM,EAAE,SAAS,CAAI;AAE3D,MAAA,EAAA,MAAkB;AAChB,cAAM,IAAc,EAAa,CAAA;AACjC,QAAI,MACF,EAAY,iBAAiB,KAG3B,KAAS,KACX,KAAK,gBAAgB;AAAA,UACnB,GAAG,EAAa,MAAM,GAAG,CAAK;AAAA,UAC9B;AAAA,UACA,GAAG,EAAa,MAAM,IAAQ,CAAC;AAAA,QACjC,CAAC;AAAA,MAEL,CAAC;AAAA,IACH,SAAS,GAAO;AACd,cAAQ,MAAM,iDAAiD,CAAK,GACpE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,iBAAiB,OAAO,GAAoB,MAA4B;AACtE,QAAI;AACF,YAAM,IAAkB,KAAK,SAAS,OAAA,CAAQ,MAAM,EAAE,qBAAqB,CAAe,GAEpF,IAAkB,IAAI,IAAI,EAAgB,IAAA,CAAK,MAAM,EAAE,QAAQ,CAAC,GAChE,IAAmB,IAAI,IAAI,CAAQ;AAGzC,iBAAW,KAAW,EACpB,CAAK,EAAgB,IAAI,CAAO,KAC9B,MAAM,KAAK,WAAW,GAAS,CAAe;AAKlD,iBAAW,KAAW,EACpB,CAAK,EAAiB,IAAI,EAAQ,QAAQ,KACxC,MAAM,KAAK,cAAc,EAAQ,IAAI;AAIzC,YAAM,KAAK,aAAa;AAAA,IAC1B,SAAS,GAAO;AACd,cAAQ,MAAM,2CAA2C,CAAK,GAC9D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,YAAY,OAAO,MAAa;AAC9B,QAAI;AACF,YAAM,KAAK,IAAI,UAAU,CAAG,GAC5B,MAAM,KAAK,SAAS;AAAA,IACtB,SAAS,GAAO;AACd,cAAQ,MAAM,sCAAsC,CAAK,GACzD,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,oBAAoB,OAAO,MAA6B;AACtD,QAAI;AACF,YAAM,IAAqB,MAAM,KAAK,IAAI,kBAAkB,CAAW,GAEjE,IAAQ,KAAK,aAAa,UAAA,CAAW,MAAmB,EAAE,SAAS,EAAY,IAAI;AAEzF,MAAI,KAAS,KACX,KAAK,gBAAgB;AAAA,QACnB,GAAG,KAAK,aAAa,MAAM,GAAG,CAAK;AAAA,QACnC;AAAA,QACA,GAAG,KAAK,aAAa,MAAM,IAAQ,CAAC;AAAA,MACtC,CAAC;AAAA,IAEL,SAAS,GAAO;AACd,cAAQ,MAAM,8CAA8C,CAAK,GACjE,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAGA,mCAAmC,OAAO,MAAmB;AAC3D,QAAI;AACF,YAAM,IAAe,MAAM,KAAK,IAAI,2BAClC,EAAY,CAAQ,GACpB,EAAY,EAAW,CAAC,CAC1B;AACA,WAAK,kBAAkB,GACvB,KAAK,eAAe;AAAA,IACtB,SAAS,GAAO;AACd,cAAQ,MAAM,gEAAgE,CAAK,GACnF,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,mBAAmB,CAAC;AAAA,IACxE;AAAA,EACF;AACF,GAEa,IAAb,MAAqB;AAAA,EACnB,YAAY,EAAa,oBAAI,KAAK,CAAC;AAAA,EACnC,UAAU,EAAW,oBAAI,KAAK,CAAC;AAAA,EAE/B,iBAAiB,CAAC;AAAA,EAClB,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,4BAA4B;AAAA,EAE5B,cAAc;AAAA,EACd,uBAAuB,CAAC;AAAA,EAExB,oBAAiC;AAAA,EACjC,gBAAgB;AAAA,EAEhB,eAAe;AAAA,EAEf,cAAc;AACZ,IAAA,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,eAAA,CAAgB,GAAiB,MAAkB;AACjD,SAAK,YAAY,GACjB,KAAK,UAAU;AAAA,EACjB;AAAA,EAEA,mBAAA,CAAoB,MAAoB,KAAK,gBAAgB;AAAA,EAE7D,iBAAA,CAAkB,MAAyB,KAAK,cAAc;AAAA,EAE9D,0BAAA,CAA2B,MAA4B,KAAK,uBAAuB;AAAA,EAEnF,+BAAA,CAAgC,MAC7B,KAAK,4BAA4B;AAAA,EAEpC,kBAAA,CAAmB,MAA0B;AAC3C,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,UAAA,CAAW,GAAgB,MAAkB;AAC3C,SAAK,SAAS,GACd,KAAK,QAAQ;AAAA,EACf;AAAA,EAEA,cAAA,CAAe,MAAiB;AAC9B,UAAM,IAAiB,CAAC,GAAG,KAAK,cAAc,GACxC,IAAQ,KAAK,eAAe,UAAA,CAAW,MAAc,MAAc,CAAI;AAE7E,IAAI,KAAS,IACX,EAAe,OAAO,GAAO,CAAC,IAE9B,EAAe,KAAK,CAAI,GAG1B,KAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,sBAAA,MAA4B;AAC1B,IAAI,KAAK,eAAe,WAAW,MACnC,KAAK,iBAAiB,CAAC;AAAA,EACzB;AAAA,EAEA,0BAAA,CAA2B,MAAmC;AAC5D,SAAK,oBAAoB;AAAA,EAC3B;AACF"}
1
+ {"version":3,"file":"TransactionStore.es.js","names":[],"sources":["../../../src/core/stores/TransactionStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { endOfToday } from 'date-fns/endOfToday'\nimport { formatISO } from 'date-fns/formatISO'\nimport { getUnixTime } from 'date-fns/getUnixTime'\nimport { isBefore } from 'date-fns/isBefore'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subDays } from 'date-fns/subDays'\n\nimport { BeatApi, TransactionApi } from '../api'\nimport { TABLE_CONST } from '../constants/Table'\nimport { COLUMN_NAMES, DEFAULT_TRANSACTION } from '../constants/Transaction'\nimport { TransactionType } from '../types'\nimport type { Beat, Tag, Tagging, Transaction, TransactionRule } from '../types'\nimport {\n buildDetailedTransactions,\n flattenTransactionsWithSplits,\n sortAndFilterTransactions,\n} from '../utils/TransactionUtils'\n\nimport { GlobalStore } from './GlobalStore'\nimport { upsertByGuid } from '../utils/upsertByGuid'\n\nexport type TransactionFilter = {\n accounts?: string[]\n dateRange?: { start: Date; end: Date }\n custom?: (value: Transaction) => boolean\n searchTerm?: string\n showSplits?: boolean\n}\n\nexport class TransactionStore {\n globalStore: GlobalStore\n uiStore: UiStore\n api = new TransactionApi('/', '')\n beatApi = new BeatApi('/', '')\n\n associatedBeats: Beat[] = []\n associatedBeatsLoaded: boolean = false\n associatedBeatsLoading: boolean = false\n transactions: Transaction[] = []\n transactionsLoaded: boolean = false\n transactionsLoading: boolean = false\n taggings: Tagging[] = []\n taggingsLoaded: boolean = false\n taggingsLoading: boolean = false\n tags: Tag[] = []\n tagsLoaded: boolean = false\n tagsLoading: boolean = false\n transactionRules: TransactionRule[] = []\n transactionRulesLoaded: boolean = false\n transactionRulesLoading: boolean = false\n transactionSplitting: boolean = false\n\n cachedStartDate: Date = subDays(startOfToday(), 90)\n filter: TransactionFilter = {}\n isLoading = true\n\n alert = ''\n\n sortColumn = COLUMN_NAMES.DATE\n sortDirection = TABLE_CONST.DESC\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.uiStore = new UiStore()\n this.api = new TransactionApi(\n globalStore.endpoint,\n globalStore.sessionToken,\n globalStore.onError,\n )\n this.beatApi = new BeatApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n loadTransactionData = async () => {\n if (!this.globalStore.accountStore.isAccountDataLoaded) {\n await this.globalStore.accountStore.loadAccountData()\n }\n if (!this.globalStore.categoryStore.categoriesLoaded) {\n await this.globalStore.categoryStore.loadCategories()\n }\n await Promise.all([\n this.loadAssociatedBeats(startOfMonth(new Date())),\n this.loadTags(),\n this.loadTaggings(),\n this.loadTransactionRules(),\n // By default loads 90 days of transactions\n this.loadTransactions(this.cachedStartDate),\n ])\n }\n\n get isTransactionDataLoaded(): boolean {\n return (\n this.associatedBeatsLoaded &&\n this.tagsLoaded &&\n this.taggingsLoaded &&\n this.transactionRulesLoaded &&\n this.transactionsLoaded\n )\n }\n\n get detailedTransactions(): Transaction[] {\n return this.isTransactionDataLoaded\n ? buildDetailedTransactions(\n this.transactions,\n this.globalStore.accountStore.visibleAccounts,\n this.globalStore.categoryStore.categories,\n this.taggings,\n this.globalStore.copyStore.copy.categories,\n )\n : []\n }\n\n get sortedTransactions(): Transaction[] {\n return sortAndFilterTransactions(\n this.filter,\n this.uiStore.expandedSplits,\n this.sortColumn,\n this.sortDirection,\n this.tags,\n this.detailedTransactions,\n )\n }\n\n get sortedTransactionsWithSplits(): Transaction[] {\n return flattenTransactionsWithSplits(this.sortedTransactions, this.detailedTransactions)\n }\n\n setAssociatedBeats = (beats: Beat[]) => {\n this.associatedBeats = beats\n this.associatedBeatsLoading = false\n this.associatedBeatsLoaded = true\n }\n\n setTaggings = (taggings: Tagging[]) => {\n this.taggings = taggings\n this.taggingsLoading = false\n this.taggingsLoaded = true\n }\n\n setTags = (tags: Tag[]) => {\n this.tags = tags\n this.tagsLoading = false\n this.tagsLoaded = true\n }\n\n setTransactionRules = (transactionRules: TransactionRule[]) => {\n this.transactionRules = transactionRules\n this.transactionRulesLoading = false\n this.transactionRulesLoaded = true\n }\n\n setTransactions = (transactions: Transaction[]) => {\n this.transactions = transactions\n this.transactionsLoading = false\n this.transactionsLoaded = true\n }\n\n setAlert = (alert: string) => {\n this.alert = alert\n }\n\n addTag = async (name: string) => {\n try {\n await this.api.addTag({ name } as Tag)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while adding tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addTagging = async (tagGuid: string, transactionGuid: string) => {\n try {\n await this.api.addTagging({\n tag_guid: tagGuid,\n transaction_guid: transactionGuid,\n } as Tagging)\n } catch (error) {\n console.error('Error occurred while adding tagging:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addOrUpdateTransactionRule = async (categoryGuid: string, transaction: Transaction) => {\n try {\n const existingRule = this.transactionRules.find(\n (rule: TransactionRule) => rule.guid === transaction.user_transaction_rule_guid,\n ) as TransactionRule | undefined\n\n if (existingRule) {\n await this.api.updateTransactionRule({\n ...existingRule,\n category_guid: categoryGuid,\n description: transaction.description,\n } as TransactionRule)\n } else {\n await this.api.addTransactionRule({\n category_guid: categoryGuid,\n description: transaction.description,\n match_description: transaction.description,\n } as TransactionRule)\n }\n await this.loadTransactionRules()\n } catch (error) {\n console.error('Error occurred while adding/updating transaction rule:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n addTransaction = async (transaction: Transaction) => {\n try {\n const newTransaction = await this.api.addTransaction(transaction)\n\n if (newTransaction) {\n runInAction(() => {\n this.setTransactions(upsertByGuid(this.transactions, newTransaction, true))\n\n // Brokaw may insert the transaction via WebSocket, but it never\n // updates the account balance — that only happens here.\n // See: money-dashboard/src/util/BrokawClient.ts::handleTransactionEvents (search \"setTransactions\")\n // If that handler ever calls updateAccountBalance, remove this call or guard on !existing.\n const balanceChange =\n newTransaction.transaction_type === TransactionType.CREDIT\n ? newTransaction.amount\n : -newTransaction.amount\n\n this.globalStore.accountStore.updateAccountBalance(\n newTransaction.account_guid,\n balanceChange,\n )\n })\n }\n } catch (error) {\n console.error('Error occurred while adding transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n loadAssociatedBeats = async (fromDate?: Date) => {\n if (this.associatedBeatsLoading) return\n\n this.associatedBeatsLoading = true\n const fromDateISO = fromDate ? formatISO(fromDate, { representation: 'date' }) : undefined\n try {\n const beats = await this.beatApi.getBeatsWithAssociatedTransaction(fromDateISO)\n this.setAssociatedBeats(beats)\n } catch (error) {\n console.error('Error occurred while loading associated beats:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setAssociatedBeats([])\n } finally {\n // Clear the in-flight flag even on failure so a later load (e.g. a widget\n // remount) can retry instead of being no-oped by the guard above, which would\n // leave isTransactionDataLoaded false and the list empty until a hard refresh.\n runInAction(() => {\n this.associatedBeatsLoading = false\n })\n }\n }\n\n loadTags = async () => {\n if (this.tagsLoading) return\n\n this.tagsLoading = true\n try {\n const tags = await this.api.getTags()\n this.setTags(tags)\n } catch (error) {\n console.error('Error occurred while loading tags:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n } finally {\n runInAction(() => {\n this.tagsLoading = false\n })\n }\n }\n\n loadTaggings = async () => {\n if (this.taggingsLoading) return\n\n this.taggingsLoading = true\n try {\n const taggings = await this.api.getTaggings()\n this.setTaggings(taggings)\n } catch (error) {\n console.error('Error occurred while loading taggings:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setTaggings([])\n } finally {\n runInAction(() => {\n this.taggingsLoading = false\n })\n }\n }\n\n loadTransactionRules = async () => {\n if (this.transactionRulesLoading) return\n\n this.transactionRulesLoading = true\n try {\n const transactionRules = await this.api.getTransactionRules()\n this.setTransactionRules(transactionRules)\n } catch (error) {\n // Catch so a rejection can't abort the Promise.all in loadTransactionData.\n console.error('Error occurred while loading transaction rules:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n this.setTransactionRules([])\n } finally {\n runInAction(() => {\n this.transactionRulesLoading = false\n })\n }\n }\n\n loadTransactions = async (startDate: Date = this.cachedStartDate) => {\n if (this.transactionsLoading) return\n\n this.setIsLoading(true)\n this.transactionsLoading = true\n\n try {\n const transactions = await this.api.getTransactionsByDateRange(\n getUnixTime(startDate),\n getUnixTime(endOfToday()),\n )\n this.setTransactions(transactions)\n // Advance the cache only after the range is actually loaded, so the invariant\n // \"we hold transactions back to cachedStartDate\" always holds.\n runInAction(() => {\n this.cachedStartDate = startDate\n })\n } catch (error) {\n console.error('Error occurred while loading transactions:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n } finally {\n // See loadAssociatedBeats: clear the flag on failure so retries aren't no-oped.\n runInAction(() => {\n this.transactionsLoading = false\n })\n this.setIsLoading(false)\n }\n }\n\n modifyTransactionByAccountGuid = (guid: string, updates: Partial<Transaction>) => {\n this.transactions = this.transactions.map((txn) =>\n txn.account_guid === guid ? { ...txn, ...updates } : txn,\n )\n }\n\n removeTag = async (tagGuid: string) => {\n try {\n await this.api.removeTag(tagGuid)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while removing tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n removeTagging = async (taggingGuid: string) => {\n try {\n await this.api.removeTagging(taggingGuid)\n } catch (error) {\n console.error('Error occurred while removing tagging:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n removeTransaction = async (transactionGuid: string) => {\n try {\n await this.api.removeTransaction(transactionGuid)\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transactionGuid)\n\n if (index >= 0) {\n const updatedTransactions = [...this.transactions]\n updatedTransactions.splice(index, 1)\n this.setTransactions(updatedTransactions)\n }\n } catch (error) {\n console.error('Error occurred while removing transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n setFilter = (filter: TransactionFilter) => {\n this.filter = filter\n\n // Only reload if the new start date is prior to the cached start date; end date\n // is always today. loadTransactions advances cachedStartDate on success, so we\n // must not advance it here (a skipped/failed load would leave the list empty).\n if (filter.dateRange && isBefore(filter.dateRange.start, this.cachedStartDate)) {\n this.loadTransactions(filter.dateRange.start)\n }\n }\n\n setIsLoading = (isLoading: boolean) => (this.isLoading = isLoading)\n\n splitTransaction = async (transaction: Transaction, splits: Transaction[]) => {\n if (this.transactionSplitting) return\n this.transactionSplitting = true\n\n try {\n const updatedTransaction = await this.api.updateTransaction(transaction)\n const children = [] as Transaction[]\n\n for (let i = 0; i < splits.length; i++) {\n const child = await this.api.addTransaction(splits[i])\n children.push(child)\n }\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transaction.guid)\n\n if (index >= 0) {\n // Remove old parent and any existing children\n const filtered = this.transactions.filter(\n (t) => t.guid !== transaction.guid && t.parent_guid !== transaction.guid,\n )\n\n // Insert updated parent + new children at original position\n this.setTransactions([\n ...filtered.slice(0, index),\n updatedTransaction,\n ...children,\n ...filtered.slice(index),\n ])\n }\n } catch (error) {\n console.error('Error occurred while splitting transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n throw error\n } finally {\n this.transactionSplitting = false\n }\n }\n\n unSplitTransaction = async (guid: string) => {\n try {\n const children = this.transactions.filter((t) => t.parent_guid === guid)\n\n await this.api.removeTransactionSplit(guid)\n\n // Remove children\n const transactions = [...this.transactions]\n children.forEach((child) => {\n const index = transactions.findIndex((t) => t.guid === child.guid)\n\n if (index >= 0) {\n transactions.splice(index, 1)\n }\n })\n\n // Update parent\n const index = transactions.findIndex((t) => t.guid === guid)\n\n runInAction(() => {\n const transaction = transactions[index]\n if (transaction) {\n transaction.has_been_split = false\n }\n\n if (index >= 0) {\n this.setTransactions([\n ...transactions.slice(0, index),\n transaction,\n ...transactions.slice(index + 1),\n ])\n }\n })\n } catch (error) {\n console.error('Error occurred while unsplitting transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTaggings = async (tagGuids: string[], transactionGuid: string) => {\n try {\n const currentTaggings = this.taggings.filter((t) => t.transaction_guid === transactionGuid)\n\n const currentTagGuids = new Set(currentTaggings.map((t) => t.tag_guid))\n const incomingTagGuids = new Set(tagGuids)\n\n // Add new taggings that don't already exist\n for (const tagGuid of tagGuids) {\n if (!currentTagGuids.has(tagGuid)) {\n await this.addTagging(tagGuid, transactionGuid)\n }\n }\n\n // Remove taggings that are no longer needed\n for (const tagging of currentTaggings) {\n if (!incomingTagGuids.has(tagging.tag_guid)) {\n await this.removeTagging(tagging.guid)\n }\n }\n\n await this.loadTaggings()\n } catch (error) {\n console.error('Error occurred while updating taggings:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTag = async (tag: Tag) => {\n try {\n await this.api.updateTag(tag)\n await this.loadTags()\n } catch (error) {\n console.error('Error occurred while updating tag:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n updateTransaction = async (transaction: Transaction) => {\n try {\n const updatedTransaction = await this.api.updateTransaction(transaction)\n\n const index = this.transactions.findIndex((t: Transaction) => t.guid === transaction.guid)\n\n if (index >= 0) {\n this.setTransactions([\n ...this.transactions.slice(0, index),\n updatedTransaction,\n ...this.transactions.slice(index + 1),\n ])\n }\n } catch (error) {\n console.error('Error occurred while updating transaction:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n\n // This is used for loading the transactions list on demand, on clicking the different transactions of the insightful beats.\n loadEmbeddedInstanceTransactions = async (fromDate: Date) => {\n try {\n const transactions = await this.api.getTransactionsByDateRange(\n getUnixTime(fromDate),\n getUnixTime(endOfToday()),\n )\n this.cachedStartDate = fromDate\n this.transactions = transactions\n } catch (error) {\n console.error('Error occurred while loading embedded instance transactions:', error)\n this.globalStore.captureException(error, { store: 'TransactionStore' })\n }\n }\n}\n\nexport class UiStore {\n beginDate = startOfMonth(new Date())\n endDate = endOfMonth(new Date())\n\n expandedSplits = [] as string[]\n height = 550\n width = 1000\n shouldDisableDrawerScroll = false\n\n searchValue = ''\n selectedAccountGuids = [] as string[]\n\n manualTransaction: Transaction = DEFAULT_TRANSACTION\n isAmountValid = false\n\n showInsights = false\n\n constructor() {\n makeAutoObservable(this)\n }\n\n setDateRange = (beginDate: Date, endDate: Date) => {\n this.beginDate = beginDate\n this.endDate = endDate\n }\n\n setIsAmountValid = (valid: boolean) => (this.isAmountValid = valid)\n\n setSearchValue = (searchValue: string) => (this.searchValue = searchValue)\n\n setSelectedAccountGuids = (accountGuids: string[]) => (this.selectedAccountGuids = accountGuids)\n\n setShouldDisableDrawerScroll = (shouldDisable: boolean) =>\n (this.shouldDisableDrawerScroll = shouldDisable)\n\n setShowInsights = (showInsights: boolean) => {\n this.showInsights = showInsights\n }\n\n setSize = (height: number, width: number) => {\n this.height = height\n this.width = width\n }\n\n toggleSplit = (guid: string) => {\n const expandedSplits = [...this.expandedSplits]\n const index = this.expandedSplits.findIndex((splitGuid) => splitGuid === guid)\n\n if (index >= 0) {\n expandedSplits.splice(index, 1)\n } else {\n expandedSplits.push(guid)\n }\n\n this.expandedSplits = expandedSplits\n }\n\n clearExpandedSplits = () => {\n if (this.expandedSplits.length === 0) return\n this.expandedSplits = []\n }\n\n updateManualTransaction = (manualTransaction: Transaction) => {\n this.manualTransaction = manualTransaction\n }\n}\n"],"mappings":"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"}
@@ -61,6 +61,8 @@ export interface CommonCopy {
61
61
  unhide_button: string;
62
62
  view_chart: string;
63
63
  view_history: string;
64
+ view_less: string;
65
+ view_more: string;
64
66
  view_table: string;
65
67
  view_toggle: string;
66
68
  }
@@ -25,7 +25,6 @@ export interface TrendsCopy {
25
25
  title: string;
26
26
  transaction: string;
27
27
  transactions: string;
28
- view_more: string;
29
28
  view_transactions: string;
30
29
  zero_state_content_description: string;
31
30
  zero_state_content_header: string;
@@ -1,5 +1,16 @@
1
1
  import { Theme } from '@mui/material';
2
2
  import { Category, DateRangeCategoryTotals, DetailedCategory, DetailedCategoryWithTransactions, MonthlyCategoryTotals, Transaction, CategoryCopy, CategoryTotal } from '../types';
3
+ /**
4
+ * Resolve the localized display name for a category.
5
+ *
6
+ * Default (MX-supplied) categories arrive from the API with fixed English
7
+ * names, but localized copy for them is delivered via CategoryCopy
8
+ * `default_categories` (keyed by category guid). User-created categories have no
9
+ * localized copy and legitimately fall back to their API name.
10
+ * @param category - The category to resolve a name for
11
+ * @param copy - Category copy containing localized default category names
12
+ */
13
+ export declare const getLocalizedCategoryName: (category: Category, copy?: CategoryCopy) => string;
3
14
  /**
4
15
  * Augment categories
5
16
  * @param categories - Categories to augment
@@ -1,60 +1,64 @@
1
- import { CategoryColors as M, CategoryGuids as h, CategoryIcon as T } from "../constants/Category.es.js";
2
- import { DATE_FORMATS_INTL as b, formatDate as D } from "../constants/DateFormats.es.js";
3
- import { CategoryIconList as N } from "@mxenabled/mxui";
1
+ import { CategoryColors as M, CategoryGuids as h, CategoryIcon as N } from "../constants/Category.es.js";
2
+ import { DATE_FORMATS_INTL as T, formatDate as b } from "../constants/DateFormats.es.js";
3
+ import { CategoryIconList as D } from "@mxenabled/mxui";
4
4
  import { format as c } from "date-fns/format";
5
5
  import { startOfMonth as O } from "date-fns/startOfMonth";
6
6
  import { startOfToday as E } from "date-fns/startOfToday";
7
7
  import { subMonths as I } from "date-fns/subMonths";
8
- var R = 3, f = 12, k = (t, e, r, o) => t.filter((a) => !a.parent_guid).map((a) => p(a, e, r, o, t.filter((n) => n.parent_guid === a.guid))), z = (t, e) => {
9
- const r = N.find((o) => o.guid === t);
10
- return r ? e.palette.categories[r.colorName] || "" : e.palette.categories.uncategorized || "";
11
- }, p = (t, e, r, o, a = []) => {
12
- const n = t.guid, u = t.parent_guid || n, s = n === u, g = r.find((i) => i.category_guid === n)?.total || 0, d = y(o.filter((i) => i.category_guid === n)), m = y(o.filter((i) => i.category_guid === n || i.top_level_category_guid === n)), l = a.map((i) => p(i, e, r, o)), A = l.reduce((i, C) => i + C.currentAmount, g), v = e.default_categories[t.guid] ? e.default_categories[t.guid].replace(/&amp;/g, "&") : t.name;
8
+ var R = 3, f = 12, S = (e, r) => {
9
+ const t = r?.default_categories?.[e.guid];
10
+ return t ? t.replace(/&amp;/g, "&") : e.name;
11
+ }, k = (e, r, t, o) => e.filter((a) => !a.parent_guid).map((a) => _(a, r, t, o, e.filter((n) => n.parent_guid === a.guid))), B = (e, r) => {
12
+ const t = D.find((o) => o.guid === e);
13
+ return t ? r.palette.categories[t.colorName] || "" : r.palette.categories.uncategorized || "";
14
+ }, _ = (e, r, t, o, a = []) => {
15
+ const n = e.guid, u = e.parent_guid || n, s = n === u, g = t.find((i) => i.category_guid === n)?.total || 0, d = p(o.filter((i) => i.category_guid === n)), m = p(o.filter((i) => i.category_guid === n || i.top_level_category_guid === n)), l = a.map((i) => _(i, r, t, o)), A = l.reduce((i, C) => i + C.currentAmount, g), v = S(e, r);
13
16
  return {
14
- ...t,
17
+ ...e,
15
18
  currentAmount: g,
16
- averageAmount: _(d),
19
+ averageAmount: y(d),
17
20
  color: M[u],
18
- icon: T[u],
21
+ icon: N[u],
19
22
  isTransfer: u === h.TRANSFER,
20
23
  monthlyAmounts: d,
21
24
  name: v,
22
25
  subCategories: l,
23
26
  totalAmount: s ? A : 0,
24
- totalAverageAmount: _(m),
27
+ totalAverageAmount: y(m),
25
28
  totalMonthlyAmounts: s ? m : []
26
29
  };
27
- }, B = (t, e) => t.map((r) => {
28
- const o = e.filter((a) => a.category_guid === r.guid || a.top_level_category_guid === r.guid);
30
+ }, P = (e, r) => e.map((t) => {
31
+ const o = r.filter((a) => a.category_guid === t.guid || a.top_level_category_guid === t.guid);
29
32
  return {
30
- ...r,
33
+ ...t,
31
34
  transactions: o
32
35
  };
33
- }), _ = (t, e = R) => {
34
- const r = e > history.length ? history.length : e;
35
- return Math.ceil(Math.max(0, t.slice(-r).reduce((o, a) => o + a.amount, 0) / r));
36
- }, y = (t) => {
37
- const e = [], r = E();
36
+ }), y = (e, r = R) => {
37
+ const t = r > history.length ? history.length : r;
38
+ return Math.ceil(Math.max(0, e.slice(-t).reduce((o, a) => o + a.amount, 0) / t));
39
+ }, p = (e) => {
40
+ const r = [], t = E();
38
41
  for (let o = 0; o <= f; o++) {
39
- const a = O(I(r, f - o)), n = t.filter((u) => u.year_month === Number(c(a, "yyyyMM"))).reduce((u, s) => u + s.total, 0);
40
- e.push({
42
+ const a = O(I(t, f - o)), n = e.filter((u) => u.year_month === Number(c(a, "yyyyMM"))).reduce((u, s) => u + s.total, 0);
43
+ r.push({
41
44
  amount: n,
42
45
  isoDate: c(a, "yyyy-MM-dd"),
43
- label: D(a, b.MONTH_YEAR)
46
+ label: b(a, T.MONTH_YEAR)
44
47
  });
45
48
  }
46
- return e;
47
- }, P = (t, e) => t.find((r) => r.guid === e), V = (t, e) => {
48
- const r = t.find((o) => o.subCategories.find((a) => a.guid === e));
49
- if (r)
50
- return r.subCategories.find((o) => o.guid === e);
49
+ return r;
50
+ }, V = (e, r) => e.find((t) => t.guid === r), $ = (e, r) => {
51
+ const t = e.find((o) => o.subCategories.find((a) => a.guid === r));
52
+ if (t)
53
+ return t.subCategories.find((o) => o.guid === r);
51
54
  };
52
55
  export {
53
56
  k as augmentCategories,
54
- P as findDetailedCategory,
55
- V as findDetailedSubCategory,
56
- z as getCategoryColor,
57
- B as getDetailedCategoryTransactions
57
+ V as findDetailedCategory,
58
+ $ as findDetailedSubCategory,
59
+ B as getCategoryColor,
60
+ P as getDetailedCategoryTransactions,
61
+ S as getLocalizedCategoryName
58
62
  };
59
63
 
60
64
  //# sourceMappingURL=CategoryUtil.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CategoryUtil.es.js","names":[],"sources":["../../../src/core/utils/CategoryUtil.ts"],"sourcesContent":["import { format } from 'date-fns/format'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subMonths } from 'date-fns/subMonths'\n\nimport type { Palette, Theme } from '@mui/material'\n\nimport { CategoryIconList } from '@mxenabled/mxui'\n\nimport {\n CategoryColors,\n CategoryGuids,\n CategoryIcon,\n DATE_FORMATS_INTL,\n formatDate,\n} from '../constants'\n\nimport type {\n Category,\n DateRangeCategoryTotals,\n DetailedCategory,\n DetailedCategoryWithTransactions,\n MonthlyAmount,\n MonthlyCategoryTotals,\n Transaction,\n CategoryCopy,\n CategoryTotal,\n} from '../types'\n\nconst MONTHLY_AVERAGE_LENGTH = 3\nconst MONTHS_OF_HISTORY = 12\n\n/**\n * Augment categories\n * @param categories - Categories to augment\n * @param monthlyCategoryTotals - Monthly category totals\n * @param currentCategoryTotals - Current month category totals\n * @param copy - Category copy\n */\nexport const augmentCategories = (\n categories: Category[],\n copy: CategoryCopy,\n currentCategoryTotals: DateRangeCategoryTotals[],\n monthlyCategoryTotals: MonthlyCategoryTotals[],\n): DetailedCategory[] => {\n return categories\n .filter((category) => !category.parent_guid)\n .map((category) =>\n getDetailedCategory(\n category,\n copy,\n currentCategoryTotals,\n monthlyCategoryTotals,\n categories.filter((c) => c.parent_guid === category.guid),\n ),\n )\n}\n\nexport const getCategoryColor = (guid: string, theme: Theme) => {\n const categoryInfo = CategoryIconList.find((c) => c.guid === guid)\n if (!categoryInfo) return theme.palette.categories.uncategorized || ''\n\n return theme.palette.categories[categoryInfo.colorName as keyof Palette['categories']] || ''\n}\n\nexport const getCategoryIcon = (guid: string) => {\n return CategoryIconList.find((c) => c.guid === guid)?.icon\n}\n\n/**\n * Get an augmented category with additional details\n * @param category - The category to augment\n * @param copy - Category copy\n * @param currentCategoryTotals - Current month category totals\n * @param monthlyCategoryTotals - Past monthly category totals\n * @param subCategories - Subcategories for the specified category (If applicable)\n */\nconst getDetailedCategory = (\n category: Category,\n copy: CategoryCopy,\n currentCategoryTotals: DateRangeCategoryTotals[],\n monthlyCategoryTotals: MonthlyCategoryTotals[],\n subCategories: Category[] = [],\n): DetailedCategory => {\n const guid = category.guid\n const parentGuid = category.parent_guid || guid\n const isParent = guid === parentGuid\n\n const currentAmount = currentCategoryTotals.find((t) => t.category_guid === guid)?.total || 0\n const monthlyAmounts = getMonthlyAmounts(\n monthlyCategoryTotals.filter((total) => total.category_guid === guid),\n )\n const totalMonthlyAmounts = getMonthlyAmounts(\n monthlyCategoryTotals.filter(\n (total) => total.category_guid === guid || total.top_level_category_guid === guid,\n ),\n )\n const detailedSubCategories = subCategories.map((subCategory) =>\n getDetailedCategory(subCategory, copy, currentCategoryTotals, monthlyCategoryTotals),\n )\n const totalAmount = detailedSubCategories.reduce(\n (total, current) => total + current.currentAmount,\n currentAmount,\n )\n\n const name = copy.default_categories[category.guid]\n ? copy.default_categories[category.guid].replace(/&amp;/g, '&')\n : category.name\n\n return {\n ...category,\n currentAmount,\n averageAmount: getAverage(monthlyAmounts),\n color: CategoryColors[parentGuid],\n icon: CategoryIcon[parentGuid],\n isTransfer: parentGuid === CategoryGuids.TRANSFER,\n monthlyAmounts,\n name,\n subCategories: detailedSubCategories,\n totalAmount: isParent ? totalAmount : 0,\n totalAverageAmount: getAverage(totalMonthlyAmounts),\n totalMonthlyAmounts: isParent ? totalMonthlyAmounts : [],\n }\n}\n/**\n * get the transactions belonging to parent categories\n * @param detailedCategories - detailed categories from the category store\n * @param transactions - sortedTransactions from the transaction store\n */\nexport const getDetailedCategoryTransactions = (\n detailedCategories: DetailedCategory[],\n transactions: Transaction[],\n): DetailedCategoryWithTransactions[] => {\n return detailedCategories.map((category) => {\n const categoryTransactions = transactions.filter(\n (transaction) =>\n transaction.category_guid === category.guid ||\n transaction.top_level_category_guid === category.guid,\n )\n\n return {\n ...category,\n transactions: categoryTransactions,\n }\n })\n}\n\n/**\n * Get the average amount based on the number of months (numMonths) requested\n * @param monthlyAmounts - Monthly amounts to calculate and average from\n * @param numMonths - Number of months to base the average on (DEFAULT: 3)\n */\nconst getAverage = (\n monthlyAmounts: MonthlyAmount[],\n numMonths: number = MONTHLY_AVERAGE_LENGTH,\n): number => {\n const monthsBack = numMonths > history.length ? history.length : numMonths\n\n return Math.ceil(\n Math.max(\n 0,\n monthlyAmounts.slice(-monthsBack).reduce((total, current) => total + current.amount, 0) /\n monthsBack,\n ),\n )\n}\n\n/**\n * Get the last 12 months of amounts for a category\n * @param categoryTotals - Monthly category totals\n */\nconst getMonthlyAmounts = (categoryTotals: MonthlyCategoryTotals[]): MonthlyAmount[] => {\n const monthlyAmounts: MonthlyAmount[] = []\n const today = startOfToday()\n for (let i = 0; i <= MONTHS_OF_HISTORY; i++) {\n const historyDate = startOfMonth(subMonths(today, MONTHS_OF_HISTORY - i))\n const monthlyTotals = categoryTotals.filter(\n (total) => total.year_month === Number(format(historyDate, 'yyyyMM')),\n )\n const totalAmount = monthlyTotals.reduce((acc, curr) => acc + curr.total, 0)\n\n monthlyAmounts.push({\n amount: totalAmount,\n isoDate: format(historyDate, 'yyyy-MM-dd'),\n label: formatDate(historyDate, DATE_FORMATS_INTL.MONTH_YEAR),\n })\n }\n\n return monthlyAmounts\n}\n\nexport const findCategory = (\n categories: Category[],\n categoryGuid: string | undefined,\n): Category | undefined => {\n return categories.find((c) => c.guid === categoryGuid)\n}\n\nexport const findDetailedCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n return detailedCategories.find((dc) => dc.guid === guid)\n}\n\nexport const findDetailedSubCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n const parent = detailedCategories.find((dc) => dc.subCategories.find((sc) => sc.guid === guid))\n if (!parent) return undefined\n\n return parent.subCategories.find((sc) => sc.guid === guid)\n}\n\nexport const findCategoryTotalsByParent = (\n categories: Category[],\n dateRangeTotals: DateRangeCategoryTotals[],\n): CategoryTotal[] => {\n const categoryTotals = [] as CategoryTotal[]\n\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\n for (const dateRangeTotal of dateRangeTotals) {\n const category = findCategory(categories, dateRangeTotal.category_guid)\n if (!category) continue\n\n const parentGuid = category.parent_guid ?? category.guid\n const parentCategory = findCategory(categories, parentGuid)\n if (!parentCategory) continue\n\n const categoryTotal = {\n amount: dateRangeTotal.total,\n category,\n guid: category.guid,\n subCategoryTotals: [],\n }\n\n const parentCategoryTotal = categoryTotals.find((ct) => ct.guid === parentGuid)\n if (parentCategoryTotal) {\n parentCategoryTotal.amount += dateRangeTotal.total\n parentCategoryTotal.subCategoryTotals.push(categoryTotal)\n } else {\n categoryTotals.push({\n amount: dateRangeTotal.total,\n category: parentCategory,\n guid: parentGuid,\n subCategoryTotals: [categoryTotal],\n })\n }\n }\n\n return categoryTotals\n}\n\nexport const isIncome = (categories: Category[], guid: string) => {\n const category = categories.find((c) => c.guid === guid)\n if (!category) return false\n\n return category.guid === CategoryGuids.INCOME || category.parent_guid === CategoryGuids.INCOME\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CategoryUtil.es.js","names":[],"sources":["../../../src/core/utils/CategoryUtil.ts"],"sourcesContent":["import { format } from 'date-fns/format'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subMonths } from 'date-fns/subMonths'\n\nimport type { Palette, Theme } from '@mui/material'\n\nimport { CategoryIconList } from '@mxenabled/mxui'\n\nimport {\n CategoryColors,\n CategoryGuids,\n CategoryIcon,\n DATE_FORMATS_INTL,\n formatDate,\n} from '../constants'\n\nimport type {\n Category,\n DateRangeCategoryTotals,\n DetailedCategory,\n DetailedCategoryWithTransactions,\n MonthlyAmount,\n MonthlyCategoryTotals,\n Transaction,\n CategoryCopy,\n CategoryTotal,\n} from '../types'\n\nconst MONTHLY_AVERAGE_LENGTH = 3\nconst MONTHS_OF_HISTORY = 12\n\n/**\n * Resolve the localized display name for a category.\n *\n * Default (MX-supplied) categories arrive from the API with fixed English\n * names, but localized copy for them is delivered via CategoryCopy\n * `default_categories` (keyed by category guid). User-created categories have no\n * localized copy and legitimately fall back to their API name.\n * @param category - The category to resolve a name for\n * @param copy - Category copy containing localized default category names\n */\nexport const getLocalizedCategoryName = (category: Category, copy?: CategoryCopy): string => {\n const localizedName = copy?.default_categories?.[category.guid]\n return localizedName ? localizedName.replace(/&amp;/g, '&') : category.name\n}\n\n/**\n * Augment categories\n * @param categories - Categories to augment\n * @param monthlyCategoryTotals - Monthly category totals\n * @param currentCategoryTotals - Current month category totals\n * @param copy - Category copy\n */\nexport const augmentCategories = (\n categories: Category[],\n copy: CategoryCopy,\n currentCategoryTotals: DateRangeCategoryTotals[],\n monthlyCategoryTotals: MonthlyCategoryTotals[],\n): DetailedCategory[] => {\n return categories\n .filter((category) => !category.parent_guid)\n .map((category) =>\n getDetailedCategory(\n category,\n copy,\n currentCategoryTotals,\n monthlyCategoryTotals,\n categories.filter((c) => c.parent_guid === category.guid),\n ),\n )\n}\n\nexport const getCategoryColor = (guid: string, theme: Theme) => {\n const categoryInfo = CategoryIconList.find((c) => c.guid === guid)\n if (!categoryInfo) return theme.palette.categories.uncategorized || ''\n\n return theme.palette.categories[categoryInfo.colorName as keyof Palette['categories']] || ''\n}\n\nexport const getCategoryIcon = (guid: string) => {\n return CategoryIconList.find((c) => c.guid === guid)?.icon\n}\n\n/**\n * Get an augmented category with additional details\n * @param category - The category to augment\n * @param copy - Category copy\n * @param currentCategoryTotals - Current month category totals\n * @param monthlyCategoryTotals - Past monthly category totals\n * @param subCategories - Subcategories for the specified category (If applicable)\n */\nconst getDetailedCategory = (\n category: Category,\n copy: CategoryCopy,\n currentCategoryTotals: DateRangeCategoryTotals[],\n monthlyCategoryTotals: MonthlyCategoryTotals[],\n subCategories: Category[] = [],\n): DetailedCategory => {\n const guid = category.guid\n const parentGuid = category.parent_guid || guid\n const isParent = guid === parentGuid\n\n const currentAmount = currentCategoryTotals.find((t) => t.category_guid === guid)?.total || 0\n const monthlyAmounts = getMonthlyAmounts(\n monthlyCategoryTotals.filter((total) => total.category_guid === guid),\n )\n const totalMonthlyAmounts = getMonthlyAmounts(\n monthlyCategoryTotals.filter(\n (total) => total.category_guid === guid || total.top_level_category_guid === guid,\n ),\n )\n const detailedSubCategories = subCategories.map((subCategory) =>\n getDetailedCategory(subCategory, copy, currentCategoryTotals, monthlyCategoryTotals),\n )\n const totalAmount = detailedSubCategories.reduce(\n (total, current) => total + current.currentAmount,\n currentAmount,\n )\n\n const name = getLocalizedCategoryName(category, copy)\n\n return {\n ...category,\n currentAmount,\n averageAmount: getAverage(monthlyAmounts),\n color: CategoryColors[parentGuid],\n icon: CategoryIcon[parentGuid],\n isTransfer: parentGuid === CategoryGuids.TRANSFER,\n monthlyAmounts,\n name,\n subCategories: detailedSubCategories,\n totalAmount: isParent ? totalAmount : 0,\n totalAverageAmount: getAverage(totalMonthlyAmounts),\n totalMonthlyAmounts: isParent ? totalMonthlyAmounts : [],\n }\n}\n/**\n * get the transactions belonging to parent categories\n * @param detailedCategories - detailed categories from the category store\n * @param transactions - sortedTransactions from the transaction store\n */\nexport const getDetailedCategoryTransactions = (\n detailedCategories: DetailedCategory[],\n transactions: Transaction[],\n): DetailedCategoryWithTransactions[] => {\n return detailedCategories.map((category) => {\n const categoryTransactions = transactions.filter(\n (transaction) =>\n transaction.category_guid === category.guid ||\n transaction.top_level_category_guid === category.guid,\n )\n\n return {\n ...category,\n transactions: categoryTransactions,\n }\n })\n}\n\n/**\n * Get the average amount based on the number of months (numMonths) requested\n * @param monthlyAmounts - Monthly amounts to calculate and average from\n * @param numMonths - Number of months to base the average on (DEFAULT: 3)\n */\nconst getAverage = (\n monthlyAmounts: MonthlyAmount[],\n numMonths: number = MONTHLY_AVERAGE_LENGTH,\n): number => {\n const monthsBack = numMonths > history.length ? history.length : numMonths\n\n return Math.ceil(\n Math.max(\n 0,\n monthlyAmounts.slice(-monthsBack).reduce((total, current) => total + current.amount, 0) /\n monthsBack,\n ),\n )\n}\n\n/**\n * Get the last 12 months of amounts for a category\n * @param categoryTotals - Monthly category totals\n */\nconst getMonthlyAmounts = (categoryTotals: MonthlyCategoryTotals[]): MonthlyAmount[] => {\n const monthlyAmounts: MonthlyAmount[] = []\n const today = startOfToday()\n for (let i = 0; i <= MONTHS_OF_HISTORY; i++) {\n const historyDate = startOfMonth(subMonths(today, MONTHS_OF_HISTORY - i))\n const monthlyTotals = categoryTotals.filter(\n (total) => total.year_month === Number(format(historyDate, 'yyyyMM')),\n )\n const totalAmount = monthlyTotals.reduce((acc, curr) => acc + curr.total, 0)\n\n monthlyAmounts.push({\n amount: totalAmount,\n isoDate: format(historyDate, 'yyyy-MM-dd'),\n label: formatDate(historyDate, DATE_FORMATS_INTL.MONTH_YEAR),\n })\n }\n\n return monthlyAmounts\n}\n\nexport const findCategory = (\n categories: Category[],\n categoryGuid: string | undefined,\n): Category | undefined => {\n return categories.find((c) => c.guid === categoryGuid)\n}\n\nexport const findDetailedCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n return detailedCategories.find((dc) => dc.guid === guid)\n}\n\nexport const findDetailedSubCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n const parent = detailedCategories.find((dc) => dc.subCategories.find((sc) => sc.guid === guid))\n if (!parent) return undefined\n\n return parent.subCategories.find((sc) => sc.guid === guid)\n}\n\nexport const findCategoryTotalsByParent = (\n categories: Category[],\n dateRangeTotals: DateRangeCategoryTotals[],\n): CategoryTotal[] => {\n const categoryTotals = [] as CategoryTotal[]\n\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\n for (const dateRangeTotal of dateRangeTotals) {\n const category = findCategory(categories, dateRangeTotal.category_guid)\n if (!category) continue\n\n const parentGuid = category.parent_guid ?? category.guid\n const parentCategory = findCategory(categories, parentGuid)\n if (!parentCategory) continue\n\n const categoryTotal = {\n amount: dateRangeTotal.total,\n category,\n guid: category.guid,\n subCategoryTotals: [],\n }\n\n const parentCategoryTotal = categoryTotals.find((ct) => ct.guid === parentGuid)\n if (parentCategoryTotal) {\n parentCategoryTotal.amount += dateRangeTotal.total\n parentCategoryTotal.subCategoryTotals.push(categoryTotal)\n } else {\n categoryTotals.push({\n amount: dateRangeTotal.total,\n category: parentCategory,\n guid: parentGuid,\n subCategoryTotals: [categoryTotal],\n })\n }\n }\n\n return categoryTotals\n}\n\nexport const isIncome = (categories: Category[], guid: string) => {\n const category = categories.find((c) => c.guid === guid)\n if (!category) return false\n\n return category.guid === CategoryGuids.INCOME || category.parent_guid === CategoryGuids.INCOME\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Account, AccountGroup, FinancialAccount, HistoricalAccountBalance, Member, MonthlyAccountBalance, NetWorth } from '../types';
1
+ import { Account, AccountGroup, AccountsCopy, FinancialAccount, HistoricalAccountBalance, Member, MonthlyAccountBalance, NetWorth } from '../types';
2
2
  export declare const filterAccounts: (accounts: Account[], members: Member[]) => Account[];
3
3
  export declare const flattenBalances: (allBalances: MonthlyAccountBalance[], currentBalances: MonthlyAccountBalance[]) => MonthlyAccountBalance[];
4
4
  export declare const getLatestNetWorthData: (chartData: NetWorth[]) => NetWorth | undefined;
@@ -24,4 +24,4 @@ export declare const buildAssetsLiabilities: (accounts: Account[]) => {
24
24
  totalLiabilities: number;
25
25
  };
26
26
  export declare const toMonthlyAccountBalance: (hab: HistoricalAccountBalance) => MonthlyAccountBalance;
27
- export declare const groupAccounts: (accounts: FinancialAccount[]) => AccountGroup[];
27
+ export declare const groupAccounts: (accounts: FinancialAccount[], accountTypes: AccountsCopy["account_types"]) => AccountGroup[];