@mx-cartographer/experiences 9.4.39 → 9.4.41

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 (24) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/core/stores/GlobalStore.es.js +12 -8
  3. package/dist/core/stores/GlobalStore.es.js.map +1 -1
  4. package/dist/core/stores/RecurringTransactionsStore.d.ts +1 -0
  5. package/dist/core/stores/RecurringTransactionsStore.es.js +40 -36
  6. package/dist/core/stores/RecurringTransactionsStore.es.js.map +1 -1
  7. package/dist/core/types/Transaction.d.ts +1 -0
  8. package/dist/core/types/Transaction.es.js.map +1 -1
  9. package/dist/core/utils/TransactionUtils.d.ts +4 -2
  10. package/dist/core/utils/TransactionUtils.es.js +52 -50
  11. package/dist/core/utils/TransactionUtils.es.js.map +1 -1
  12. package/dist/transactions/components/shared/TransactionDetails.es.js +84 -82
  13. package/dist/transactions/components/shared/TransactionDetails.es.js.map +1 -1
  14. package/dist/transactions/components/shared/transactiondetails/Description.d.ts +1 -0
  15. package/dist/transactions/components/shared/transactiondetails/Description.es.js +39 -39
  16. package/dist/transactions/components/shared/transactiondetails/Description.es.js.map +1 -1
  17. package/dist/transactions/components/shared/transactiondetails/TransactionAmountHeader.es.js +18 -17
  18. package/dist/transactions/components/shared/transactiondetails/TransactionAmountHeader.es.js.map +1 -1
  19. package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js +26 -25
  20. package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js.map +1 -1
  21. package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.d.ts +2 -1
  22. package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.es.js +27 -23
  23. package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.es.js.map +1 -1
  24. package/package.json +1 -1
@@ -1,18 +1,18 @@
1
- import { CategoryGuidToName as h, CategoryGuids as y } from "../constants/Category.es.js";
1
+ import { CategoryGuidToName as y, CategoryGuids as T } from "../constants/Category.es.js";
2
2
  import { DATE_FORMATS_INTL as m, formatDate as f } from "../constants/DateFormats.es.js";
3
- import { TransactionStatus as C, TransactionType as v } from "../types/Transaction.es.js";
3
+ import { TransactionStatus as v, TransactionType as C } from "../types/Transaction.es.js";
4
4
  import { formatCurrency as A } from "./NumberFormatting.es.js";
5
- import { fromUnixUTC as b } from "./DateUtil.es.js";
6
- import { TABLE_CONST as E } from "../constants/Table.es.js";
5
+ import { fromUnixUTC as E } from "./DateUtil.es.js";
6
+ import { TABLE_CONST as S } from "../constants/Table.es.js";
7
7
  import { COLUMN_NAMES as l } from "../constants/Transaction.es.js";
8
- import { format as O } from "date-fns/format";
9
- import { startOfMonth as S } from "date-fns/startOfMonth";
8
+ import { format as b } from "date-fns/format";
9
+ import { startOfMonth as O } from "date-fns/startOfMonth";
10
10
  import { startOfToday as D } from "date-fns/startOfToday";
11
11
  import { endOfToday as M } from "date-fns/endOfToday";
12
- import { fromUnixTime as U } from "date-fns/fromUnixTime";
12
+ import { fromUnixTime as N } from "date-fns/fromUnixTime";
13
13
  import { getUnixTime as _ } from "date-fns/getUnixTime";
14
- var X = (r, t, n, a = []) => {
15
- const s = t.reduce((o, e) => ({
14
+ var X = (t) => t.top_level_category_guid === T.TRANSFER, ee = (t, r, n, a = []) => {
15
+ const s = r.reduce((o, e) => ({
16
16
  ...o,
17
17
  [e.guid]: e
18
18
  }), {}), d = n.reduce((o, e) => ({
@@ -30,7 +30,7 @@ var X = (r, t, n, a = []) => {
30
30
  [u]: g
31
31
  };
32
32
  }, {});
33
- return r.map((o) => {
33
+ return t.map((o) => {
34
34
  const e = s[o.account_guid], u = o.category_guid ? d[o.category_guid] : null, c = i[o.guid] ?? [];
35
35
  return {
36
36
  ...o,
@@ -38,77 +38,79 @@ var X = (r, t, n, a = []) => {
38
38
  accountIsClosed: e?.is_closed,
39
39
  accountIsHidden: e?.is_hidden,
40
40
  category: u?.name || "Uncategorized",
41
- isIncome: o.top_level_category_guid === y.INCOME,
42
- isPending: o.feed_status === C.PENDING,
41
+ institutionName: e?.institution?.name || e?.institutionName || void 0,
42
+ isIncome: o.top_level_category_guid === T.INCOME,
43
+ isPending: o.feed_status === v.PENDING,
43
44
  number: e?.account_number || "",
44
45
  payee: o.description,
45
46
  tags: c
46
47
  };
47
48
  });
48
- }, N = "uncategorized", ee = (r, t, n, a, s, d) => {
49
- const i = I(r, s, d), o = L(i, n, a);
50
- return t.forEach((e) => {
49
+ }, U = "uncategorized", te = (t, r, n, a, s, d) => {
50
+ const i = R(t, s, d), o = I(i, n, a);
51
+ return r.forEach((e) => {
51
52
  const u = o.findIndex((g) => g.guid === e), c = d.filter((g) => g.parent_guid === e);
52
53
  o.splice(u + 1, 0, ...c);
53
54
  }), o;
54
- }, I = (r, t, n) => {
55
+ }, R = (t, r, n) => {
55
56
  const { accounts: a = [], dateRange: s = {
56
- start: S(D()),
57
+ start: O(D()),
57
58
  end: M()
58
- }, custom: d = () => !0, searchTerm: i = "", showSplits: o = !1 } = r;
59
+ }, custom: d = () => !0, searchTerm: i = "", showSplits: o = !1 } = t;
59
60
  return n.filter((e) => o ? !e.has_been_split : !e.parent_guid).filter((e) => !!a.find((u) => u === e.account_guid)).filter((e) => e.date >= _(s.start) && e.date <= _(s.end)).filter(d).filter((e) => {
60
- if (i === N && e.has_been_split) return !1;
61
+ if (i === U && e.has_been_split) return !1;
61
62
  if (/^spl/i.test(i) && (e.has_been_split || e.parent_guid)) return !0;
62
- const u = e.tags.some((g) => p(i, t.find((T) => T.guid === g)?.name)), c = U(e.date);
63
- return p(i, e.payee) || p(i, e.feed_description) || p(i, e.category) || p(i, f(c, m.MONTH)) || p(i, f(c, m.DAY)) || p(i, f(c, m.FULL_MONTH_DAY)) || p(i, f(c, m.MONTH_DAY_YEAR)) || p(i, O(c, "do")) || p(i, e.account) || p(i, A(e.amount, "0,0.00")) || p(i, e.memo) || u;
63
+ const u = e.tags.some((g) => p(i, r.find((h) => h.guid === g)?.name)), c = N(e.date);
64
+ return p(i, e.payee) || p(i, e.feed_description) || p(i, e.category) || p(i, f(c, m.MONTH)) || p(i, f(c, m.DAY)) || p(i, f(c, m.FULL_MONTH_DAY)) || p(i, f(c, m.MONTH_DAY_YEAR)) || p(i, b(c, "do")) || p(i, e.account) || p(i, A(e.amount, "0,0.00")) || p(i, e.memo) || u;
64
65
  });
65
- }, L = (r, t, n) => [...r].sort((a, s) => {
66
- const d = t, i = (a[d] || "") > (s[d] || "");
66
+ }, I = (t, r, n) => [...t].sort((a, s) => {
67
+ const d = r, i = (a[d] || "") > (s[d] || "");
67
68
  let o = i ? -1 : 1, e = i ? 1 : -1;
68
- return (t === l.DATE || t === l.AMOUNT) && (o = i ? 1 : -1, e = i ? -1 : 1), n === E.ASC ? o : e;
69
- }), p = (r, t) => {
70
- const n = r.toLowerCase().split(" "), a = t?.toString().toLowerCase() ?? "";
69
+ return (r === l.DATE || r === l.AMOUNT) && (o = i ? 1 : -1, e = i ? -1 : 1), n === S.ASC ? o : e;
70
+ }), p = (t, r) => {
71
+ const n = t.toLowerCase().split(" "), a = r?.toString().toLowerCase() ?? "";
71
72
  return n.every((s) => a.indexOf(s) > -1);
72
73
  };
73
- function R(r) {
74
- return new Set(r.filter((t) => t.parent_guid !== void 0).map((t) => t.parent_guid));
74
+ function L(t) {
75
+ return new Set(t.filter((r) => r.parent_guid !== void 0).map((r) => r.parent_guid));
75
76
  }
76
- function w(r) {
77
- return r.reduce((t, n) => (n.parent_guid && (t[n.parent_guid] || (t[n.parent_guid] = []), t[n.parent_guid].push(n)), t), {});
77
+ function w(t) {
78
+ return t.reduce((r, n) => (n.parent_guid && (r[n.parent_guid] || (r[n.parent_guid] = []), r[n.parent_guid].push(n)), r), {});
78
79
  }
79
- function te(r, t) {
80
- const n = R(t), a = w(t), s = /* @__PURE__ */ new Set(), d = [];
81
- for (const i of r) n.has(i.guid) ? (a[i.guid] ?? []).slice().sort((o, e) => Math.abs(e.amount) - Math.abs(o.amount)).forEach((o) => {
80
+ function re(t, r) {
81
+ const n = L(r), a = w(r), s = /* @__PURE__ */ new Set(), d = [];
82
+ for (const i of t) n.has(i.guid) ? (a[i.guid] ?? []).slice().sort((o, e) => Math.abs(e.amount) - Math.abs(o.amount)).forEach((o) => {
82
83
  s.has(o.guid) || (d.push(o), s.add(o.guid));
83
84
  }) : s.has(i.guid) || (d.push(i), s.add(i.guid));
84
85
  return d;
85
86
  }
86
- var re = (r, t) => {
87
- const n = P(j(r, t)), a = new Blob([n], { type: "text/csv;charset=utf-8;" }), s = document.createElement("a");
87
+ var ne = (t, r) => {
88
+ const n = P(j(t, r)), a = new Blob([n], { type: "text/csv;charset=utf-8;" }), s = document.createElement("a");
88
89
  s.href = URL.createObjectURL(a), s.setAttribute("download", "transactions.csv"), document.body.appendChild(s), s.click(), document.body.removeChild(s), URL.revokeObjectURL(s.href);
89
- }, j = (r, t) => r.map((n) => ({
90
- Date: f(b(n.date), m.YEAR_MONTH_DAY),
90
+ }, j = (t, r) => t.map((n) => ({
91
+ Date: f(E(n.date), m.YEAR_MONTH_DAY),
91
92
  Description: x(n),
92
93
  "Original Description": n.feed_description,
93
94
  Amount: `${n.amount}`,
94
- Type: n.transaction_type === v.CREDIT ? "Credit" : "Debit",
95
- "Parent Category": h[n.top_level_category_guid || ""],
95
+ Type: n.transaction_type === C.CREDIT ? "Credit" : "Debit",
96
+ "Parent Category": y[n.top_level_category_guid || ""],
96
97
  Category: n.category,
97
98
  Account: n.account,
98
- Tags: B(n, t),
99
+ Tags: F(n, r),
99
100
  Memo: n.memo,
100
101
  Pending: n.isPending ? "TRUE" : "FALSE"
101
- })), G = (r) => r ? /[,"\n\r]/.test(r) ? `"${r.replace(/"/g, '""')}"` : r : "", P = (r) => r.length === 0 ? "" : Object.keys(r[0]).join(",").concat(`\r
102
- `) + r.map((t) => Object.values(t).map(G).join(",")).join(`\r
103
- `), x = (r) => {
104
- let t = r.parent_guid ? "Split: " : "";
105
- return t += r.is_hidden ? "(Excluded) " : "", t += r.description, t;
106
- }, B = (r, t) => r.tags.map((n) => t.filter((a) => a.guid === n)[0]?.name ?? "").join(" ");
102
+ })), G = (t) => t ? /[,"\n\r]/.test(t) ? `"${t.replace(/"/g, '""')}"` : t : "", P = (t) => t.length === 0 ? "" : Object.keys(t[0]).join(",").concat(`\r
103
+ `) + t.map((r) => Object.values(r).map(G).join(",")).join(`\r
104
+ `), x = (t) => {
105
+ let r = t.parent_guid ? "Split: " : "";
106
+ return r += t.is_hidden ? "(Excluded) " : "", r += t.description, r;
107
+ }, F = (t, r) => t.tags.map((n) => r.filter((a) => a.guid === n)[0]?.name ?? "").join(" ");
107
108
  export {
108
- X as buildDetailedTransactions,
109
- re as exportTransactionsToCSV,
110
- te as flattenTransactionsWithSplits,
111
- ee as sortAndFilterTransactions
109
+ ee as buildDetailedTransactions,
110
+ ne as exportTransactionsToCSV,
111
+ re as flattenTransactionsWithSplits,
112
+ X as isTransferTransaction,
113
+ te as sortAndFilterTransactions
112
114
  };
113
115
 
114
116
  //# sourceMappingURL=TransactionUtils.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionUtils.es.js","names":[],"sources":["../../../src/core/utils/TransactionUtils.ts"],"sourcesContent":["import { endOfToday } from 'date-fns/endOfToday'\nimport { format } from 'date-fns/format'\nimport { fromUnixTime } from 'date-fns/fromUnixTime'\nimport { getUnixTime } from 'date-fns/getUnixTime'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\n\nimport { TABLE_CONST } from '../constants/Table'\nimport {\n CategoryGuids,\n CategoryGuidToName,\n DATE_FORMATS_INTL,\n formatDate,\n ORDINAL_DATE_FORMAT,\n} from '../constants'\nimport { COLUMN_NAMES } from '../constants/Transaction'\nimport { TransactionStatus, TransactionType } from '../types'\nimport type { Account, Category, Tag, Tagging, Transaction } from '../types'\n\nimport { type TransactionFilter } from '../stores/TransactionStore'\n\nimport { fromUnixUTC } from './DateUtil'\nimport { formatCurrency } from './NumberFormatting'\n\ninterface AccountsMap {\n [key: string]: Account\n}\n\ninterface CategoriesMap {\n [key: string]: Category\n}\n\ninterface TaggingsMap {\n [key: string]: string[]\n}\n\nexport const buildDetailedTransactions = (\n transactions: Transaction[],\n accounts: Account[],\n categories: Category[],\n taggings: Tagging[] = [],\n) => {\n const accountsMap = accounts.reduce((acc: AccountsMap, account: Account) => {\n return { ...acc, [account.guid]: account }\n }, {})\n\n const categoriesMap = categories.reduce((acc: CategoriesMap, category: Category) => {\n return { ...acc, [category.guid]: category }\n }, {})\n\n const taggingsMap = taggings.reduce((acc: TaggingsMap, tagging: Tagging) => {\n const { transaction_guid, tag_guid } = tagging\n\n if (!acc[transaction_guid]) {\n return {\n ...acc,\n [transaction_guid]: [tag_guid],\n }\n }\n const tags = [...acc[transaction_guid], tag_guid] as string[]\n\n return {\n ...acc,\n [transaction_guid]: tags,\n }\n }, {})\n\n return transactions.map((transaction: Transaction) => {\n const account = accountsMap[transaction.account_guid]\n const category = transaction.category_guid ? categoriesMap[transaction.category_guid] : null\n const tags = taggingsMap[transaction.guid] ?? []\n\n return {\n ...transaction,\n account: account?.user_name || 'Unknown',\n accountIsClosed: account?.is_closed,\n accountIsHidden: account?.is_hidden,\n category: category?.name || 'Uncategorized',\n isIncome: transaction.top_level_category_guid === CategoryGuids.INCOME,\n isPending: transaction.feed_status === TransactionStatus.PENDING,\n number: account?.account_number || '',\n payee: transaction.description,\n tags,\n }\n })\n}\n\nconst UNCATEGORIZED_TERM = 'uncategorized'\n\nexport const sortAndFilterTransactions = (\n filter: TransactionFilter,\n expandedSplits: string[],\n sortColumn: string,\n sortDirection: string,\n tags: Tag[],\n transactions: Transaction[],\n) => {\n const filteredTransactions = filterTransactions(filter, tags, transactions)\n\n const sortedTransactions = sortTransactions(filteredTransactions, sortColumn, sortDirection)\n\n expandedSplits.forEach((guid) => {\n const index = sortedTransactions.findIndex((t) => t.guid === guid)\n const children = transactions.filter((t) => t.parent_guid === guid)\n sortedTransactions.splice(index + 1, 0, ...children)\n })\n return sortedTransactions\n}\n\nconst filterTransactions = (\n filter: TransactionFilter,\n tags: Tag[],\n transactions: Transaction[],\n) => {\n const {\n accounts = [],\n dateRange = { start: startOfMonth(startOfToday()), end: endOfToday() },\n custom = () => true,\n searchTerm: searchFilter = '',\n showSplits = false,\n } = filter\n\n return (\n transactions\n // Filters out parent of split transactions when showSplits is true and filters out split\n // transaction children when showSplits is false\n .filter((t) => (showSplits ? !t.has_been_split : !t.parent_guid))\n // Filter for selected accounts\n .filter((t) => Boolean(accounts.find((guid) => guid === t.account_guid)))\n // Filter for Date Range.\n // NOTE: bounds are local-midnight (getUnixTime of a local Date) while dates\n // are rendered/exported on the UTC calendar day (fromUnixUTC). For a\n // midnight-UTC row near a month boundary in a negative-offset browser the\n // two can disagree by a day. Left as-is here to keep this fix low-risk;\n // unifying range + search on UTC is tracked with the core-data ISO\n // migration (MEW-3961 follow-up).\n .filter((t) => t.date >= getUnixTime(dateRange.start) && t.date <= getUnixTime(dateRange.end))\n // Custom filter\n .filter(custom)\n // Search filter\n .filter((transaction) => {\n // Don't return uncategorized split transactions\n if (searchFilter === UNCATEGORIZED_TERM && transaction.has_been_split) {\n return false\n }\n\n // Split check - When searching for \"Splits\" and transaction is a split or is a parent of a split(s)\n const splitPattern = /^spl/i\n if (\n splitPattern.test(searchFilter) &&\n (transaction.has_been_split || Boolean(transaction.parent_guid))\n ) {\n return true\n }\n\n // Check transactions tags\n const isTagIncludedInSearch = transaction.tags.some((guid) =>\n isIncludedInSearch(searchFilter, tags.find((tag) => tag.guid === guid)?.name),\n )\n const date = fromUnixTime(transaction.date)\n return (\n isIncludedInSearch(searchFilter, transaction.payee) ||\n isIncludedInSearch(searchFilter, transaction.feed_description) ||\n isIncludedInSearch(searchFilter, transaction.category) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.MONTH)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.DAY)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.FULL_MONTH_DAY)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.MONTH_DAY_YEAR)) ||\n isIncludedInSearch(searchFilter, format(date, ORDINAL_DATE_FORMAT)) ||\n isIncludedInSearch(searchFilter, transaction.account) ||\n isIncludedInSearch(searchFilter, formatCurrency(transaction.amount, '0,0.00')) ||\n isIncludedInSearch(searchFilter, transaction.memo) ||\n isTagIncludedInSearch\n )\n })\n )\n}\n\nconst sortTransactions = (\n transactions: Transaction[],\n sortColumn: string,\n sortDirection: string,\n) => {\n return [...transactions].sort((a: Transaction, b: Transaction) => {\n const column = sortColumn as keyof Transaction\n const sortCompare = (a[column] || '') > (b[column] || '')\n\n let sortASC = sortCompare ? -1 : 1\n let sortDESC = sortCompare ? 1 : -1\n\n if (sortColumn === COLUMN_NAMES.DATE || sortColumn === COLUMN_NAMES.AMOUNT) {\n sortASC = sortCompare ? 1 : -1\n sortDESC = sortCompare ? -1 : 1\n }\n\n return sortDirection === TABLE_CONST.ASC ? sortASC : sortDESC\n })\n}\n\n/**\n * Determines if a value is included within the terms set in the search bar\n */\nconst isIncludedInSearch = (searchFilter: string, value: string | null | undefined) => {\n const lowerCasedTerms = searchFilter.toLowerCase().split(' ')\n const lowerCasedValue = value?.toString().toLowerCase() ?? ''\n\n return lowerCasedTerms.every((filter) => lowerCasedValue.indexOf(filter) > -1)\n}\n\n// TODO: Change the way formatting data is exported in order to handle localization\ntype FormattedTransaction = {\n Date: string\n Description: string\n 'Original Description': string\n Amount: string\n Type: string\n 'Parent Category': string\n Category: string\n Account: string\n Tags: string\n Memo: string\n Pending: string\n}\n\n/**\n * Collects the GUIDs of all transactions that act as parents\n * to one or more split (child) transactions.\n */\nfunction extractParentTransactionGuids(transactions: Transaction[]): Set<string> {\n return new Set(\n transactions.filter((tx) => tx.parent_guid !== undefined).map((tx) => tx.parent_guid!),\n )\n}\n\n/**\n * Organizes child transactions by their parent transaction GUID.\n * Returns a map from parent GUID to an array of its child transactions.\n */\nfunction mapChildTransactionsByParent(transactions: Transaction[]): Record<string, Transaction[]> {\n return transactions.reduce<Record<string, Transaction[]>>((accumulator, tx) => {\n if (tx.parent_guid) {\n if (!accumulator[tx.parent_guid]) accumulator[tx.parent_guid] = []\n accumulator[tx.parent_guid].push(tx)\n }\n return accumulator\n }, {})\n}\n\n/**\n * Produces a list of transactions based on the given sorted transactions,\n * where parent transactions that have split children are replaced by those\n * children sorted by descending absolute amount. All other transactions\n * are included as-is, with duplicates removed.\n */\nexport function flattenTransactionsWithSplits(\n sortedTransactions: Transaction[],\n allTransactions: Transaction[],\n): Transaction[] {\n // Set of parent transaction GUIDs that have split child transactions\n const parentTransactionGuidsWithSplits = extractParentTransactionGuids(allTransactions)\n\n // Map from parent GUID to array of its child split transactions\n const childTransactionsGroupedByParent = mapChildTransactionsByParent(allTransactions)\n\n // Track GUIDs of transactions already included in the result to avoid duplicates\n const processedTransactionGuids = new Set<string>()\n\n // Resulting list of transactions with parents replaced by their split children\n const flattenedTransactionList: Transaction[] = []\n\n for (const transaction of sortedTransactions) {\n if (parentTransactionGuidsWithSplits.has(transaction.guid)) {\n // This transaction is a parent with splits, so replace it with its children\n const splitChildTransactions = childTransactionsGroupedByParent[transaction.guid] ?? []\n\n splitChildTransactions\n .slice()\n .sort((a, b) => Math.abs(b.amount) - Math.abs(a.amount))\n .forEach((childTransaction) => {\n if (!processedTransactionGuids.has(childTransaction.guid)) {\n flattenedTransactionList.push(childTransaction)\n processedTransactionGuids.add(childTransaction.guid)\n }\n })\n } else if (!processedTransactionGuids.has(transaction.guid)) {\n // Normal transaction (no splits), add as-is if not already added\n flattenedTransactionList.push(transaction)\n processedTransactionGuids.add(transaction.guid)\n }\n }\n\n return flattenedTransactionList\n}\n\nexport const exportTransactionsToCSV = (transactions: Transaction[], tags: Tag[]) => {\n const csvContent = structureCSVData(formatTransactions(transactions, tags))\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })\n const link = document.createElement('a')\n link.href = URL.createObjectURL(blob)\n link.setAttribute('download', 'transactions.csv')\n\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n\n URL.revokeObjectURL(link.href)\n}\n\n/**\n * Formats a list of transactions into a list that will be used when\n * downloaded to a CSV file.\n */\nconst formatTransactions = (transactions: Transaction[], tags: Tag[]) => {\n return transactions.map((transaction) => ({\n // Post dates are calendar days; format on the UTC day so the export can't\n // shift to the prior day in a Western-offset browser.\n Date: formatDate(fromUnixUTC(transaction.date), DATE_FORMATS_INTL.YEAR_MONTH_DAY),\n Description: getDescription(transaction),\n 'Original Description': transaction.feed_description,\n Amount: `${transaction.amount}`,\n Type: transaction.transaction_type === TransactionType.CREDIT ? 'Credit' : 'Debit',\n 'Parent Category': CategoryGuidToName[transaction.top_level_category_guid || ''],\n Category: transaction.category,\n Account: transaction.account,\n Tags: getTags(transaction, tags),\n Memo: transaction.memo,\n Pending: transaction.isPending ? 'TRUE' : 'FALSE',\n })) as FormattedTransaction[]\n}\n\n/**\n * Escapes a value for safe CSV output\n */\nconst escapeCsvField = (field?: string | null): string => {\n if (!field) return ''\n return /[,\"\\n\\r]/.test(field) ? `\"${field.replace(/\"/g, '\"\"')}\"` : field\n}\n\n/**\n * Structures the CSV file data using the formatted transactions\n */\nconst structureCSVData = (formattedTransactions: FormattedTransaction[]) => {\n // Guard the empty export: Object.keys(undefined) would throw for a zero-row\n // list (e.g. an over-filtered range), so emit an empty file instead.\n if (formattedTransactions.length === 0) return ''\n\n const csvHeader = Object.keys(formattedTransactions[0]).join(',').concat('\\r\\n')\n const csvRows = formattedTransactions\n .map((transaction) => Object.values(transaction).map(escapeCsvField).join(','))\n .join('\\r\\n')\n\n return csvHeader + csvRows\n}\n\n/**\n * Get the description for a transaction that will be used within the CSV copy.\n * We want to highlight that split transactions are a split as well as\n * hidden transactions are hidden.\n */\nconst getDescription = (transaction: Transaction) => {\n let description = transaction.parent_guid ? 'Split: ' : ''\n description += transaction.is_hidden ? '(Excluded) ' : ''\n description += transaction.description\n\n return description\n}\n\nconst getTags = (transaction: Transaction, tags: Tag[]) => {\n return transaction.tags\n .map((tagGuid) => {\n const tag = tags.filter((t) => t.guid === tagGuid)[0]\n\n return tag?.name ?? ''\n })\n .join(' ')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionUtils.es.js","names":[],"sources":["../../../src/core/utils/TransactionUtils.ts"],"sourcesContent":["import { endOfToday } from 'date-fns/endOfToday'\nimport { format } from 'date-fns/format'\nimport { fromUnixTime } from 'date-fns/fromUnixTime'\nimport { getUnixTime } from 'date-fns/getUnixTime'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\n\nimport { TABLE_CONST } from '../constants/Table'\nimport {\n CategoryGuids,\n CategoryGuidToName,\n DATE_FORMATS_INTL,\n formatDate,\n ORDINAL_DATE_FORMAT,\n} from '../constants'\nimport { COLUMN_NAMES } from '../constants/Transaction'\nimport { TransactionStatus, TransactionType } from '../types'\nimport type { Category, DetailedAccount, Tag, Tagging, Transaction } from '../types'\n\nimport { type TransactionFilter } from '../stores/TransactionStore'\n\nimport { fromUnixUTC } from './DateUtil'\nimport { formatCurrency } from './NumberFormatting'\n\ninterface AccountsMap {\n [key: string]: DetailedAccount\n}\n\n// True for account-to-account transfers (top-level Transfer category). Used to\n// swap the payee/description for the institution name in the transaction detail\n// header, the table Payee column, and the mobile list.\nexport const isTransferTransaction = (\n transaction: Pick<Transaction, 'top_level_category_guid'>,\n): boolean => transaction.top_level_category_guid === CategoryGuids.TRANSFER\n\ninterface CategoriesMap {\n [key: string]: Category\n}\n\ninterface TaggingsMap {\n [key: string]: string[]\n}\n\nexport const buildDetailedTransactions = (\n transactions: Transaction[],\n accounts: DetailedAccount[],\n categories: Category[],\n taggings: Tagging[] = [],\n) => {\n const accountsMap = accounts.reduce((acc: AccountsMap, account: DetailedAccount) => {\n return { ...acc, [account.guid]: account }\n }, {})\n\n const categoriesMap = categories.reduce((acc: CategoriesMap, category: Category) => {\n return { ...acc, [category.guid]: category }\n }, {})\n\n const taggingsMap = taggings.reduce((acc: TaggingsMap, tagging: Tagging) => {\n const { transaction_guid, tag_guid } = tagging\n\n if (!acc[transaction_guid]) {\n return {\n ...acc,\n [transaction_guid]: [tag_guid],\n }\n }\n const tags = [...acc[transaction_guid], tag_guid] as string[]\n\n return {\n ...acc,\n [transaction_guid]: tags,\n }\n }, {})\n\n return transactions.map((transaction: Transaction) => {\n const account = accountsMap[transaction.account_guid]\n const category = transaction.category_guid ? categoriesMap[transaction.category_guid] : null\n const tags = taggingsMap[transaction.guid] ?? []\n\n return {\n ...transaction,\n account: account?.user_name || 'Unknown',\n accountIsClosed: account?.is_closed,\n accountIsHidden: account?.is_hidden,\n category: category?.name || 'Uncategorized',\n institutionName: account?.institution?.name || account?.institutionName || undefined,\n isIncome: transaction.top_level_category_guid === CategoryGuids.INCOME,\n isPending: transaction.feed_status === TransactionStatus.PENDING,\n number: account?.account_number || '',\n payee: transaction.description,\n tags,\n }\n })\n}\n\nconst UNCATEGORIZED_TERM = 'uncategorized'\n\nexport const sortAndFilterTransactions = (\n filter: TransactionFilter,\n expandedSplits: string[],\n sortColumn: string,\n sortDirection: string,\n tags: Tag[],\n transactions: Transaction[],\n) => {\n const filteredTransactions = filterTransactions(filter, tags, transactions)\n\n const sortedTransactions = sortTransactions(filteredTransactions, sortColumn, sortDirection)\n\n expandedSplits.forEach((guid) => {\n const index = sortedTransactions.findIndex((t) => t.guid === guid)\n const children = transactions.filter((t) => t.parent_guid === guid)\n sortedTransactions.splice(index + 1, 0, ...children)\n })\n return sortedTransactions\n}\n\nconst filterTransactions = (\n filter: TransactionFilter,\n tags: Tag[],\n transactions: Transaction[],\n) => {\n const {\n accounts = [],\n dateRange = { start: startOfMonth(startOfToday()), end: endOfToday() },\n custom = () => true,\n searchTerm: searchFilter = '',\n showSplits = false,\n } = filter\n\n return (\n transactions\n // Filters out parent of split transactions when showSplits is true and filters out split\n // transaction children when showSplits is false\n .filter((t) => (showSplits ? !t.has_been_split : !t.parent_guid))\n // Filter for selected accounts\n .filter((t) => Boolean(accounts.find((guid) => guid === t.account_guid)))\n // Filter for Date Range.\n // NOTE: bounds are local-midnight (getUnixTime of a local Date) while dates\n // are rendered/exported on the UTC calendar day (fromUnixUTC). For a\n // midnight-UTC row near a month boundary in a negative-offset browser the\n // two can disagree by a day. Left as-is here to keep this fix low-risk;\n // unifying range + search on UTC is tracked with the core-data ISO\n // migration (MEW-3961 follow-up).\n .filter((t) => t.date >= getUnixTime(dateRange.start) && t.date <= getUnixTime(dateRange.end))\n // Custom filter\n .filter(custom)\n // Search filter\n .filter((transaction) => {\n // Don't return uncategorized split transactions\n if (searchFilter === UNCATEGORIZED_TERM && transaction.has_been_split) {\n return false\n }\n\n // Split check - When searching for \"Splits\" and transaction is a split or is a parent of a split(s)\n const splitPattern = /^spl/i\n if (\n splitPattern.test(searchFilter) &&\n (transaction.has_been_split || Boolean(transaction.parent_guid))\n ) {\n return true\n }\n\n // Check transactions tags\n const isTagIncludedInSearch = transaction.tags.some((guid) =>\n isIncludedInSearch(searchFilter, tags.find((tag) => tag.guid === guid)?.name),\n )\n const date = fromUnixTime(transaction.date)\n return (\n isIncludedInSearch(searchFilter, transaction.payee) ||\n isIncludedInSearch(searchFilter, transaction.feed_description) ||\n isIncludedInSearch(searchFilter, transaction.category) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.MONTH)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.DAY)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.FULL_MONTH_DAY)) ||\n isIncludedInSearch(searchFilter, formatDate(date, DATE_FORMATS_INTL.MONTH_DAY_YEAR)) ||\n isIncludedInSearch(searchFilter, format(date, ORDINAL_DATE_FORMAT)) ||\n isIncludedInSearch(searchFilter, transaction.account) ||\n isIncludedInSearch(searchFilter, formatCurrency(transaction.amount, '0,0.00')) ||\n isIncludedInSearch(searchFilter, transaction.memo) ||\n isTagIncludedInSearch\n )\n })\n )\n}\n\nconst sortTransactions = (\n transactions: Transaction[],\n sortColumn: string,\n sortDirection: string,\n) => {\n return [...transactions].sort((a: Transaction, b: Transaction) => {\n const column = sortColumn as keyof Transaction\n const sortCompare = (a[column] || '') > (b[column] || '')\n\n let sortASC = sortCompare ? -1 : 1\n let sortDESC = sortCompare ? 1 : -1\n\n if (sortColumn === COLUMN_NAMES.DATE || sortColumn === COLUMN_NAMES.AMOUNT) {\n sortASC = sortCompare ? 1 : -1\n sortDESC = sortCompare ? -1 : 1\n }\n\n return sortDirection === TABLE_CONST.ASC ? sortASC : sortDESC\n })\n}\n\n/**\n * Determines if a value is included within the terms set in the search bar\n */\nconst isIncludedInSearch = (searchFilter: string, value: string | null | undefined) => {\n const lowerCasedTerms = searchFilter.toLowerCase().split(' ')\n const lowerCasedValue = value?.toString().toLowerCase() ?? ''\n\n return lowerCasedTerms.every((filter) => lowerCasedValue.indexOf(filter) > -1)\n}\n\n// TODO: Change the way formatting data is exported in order to handle localization\ntype FormattedTransaction = {\n Date: string\n Description: string\n 'Original Description': string\n Amount: string\n Type: string\n 'Parent Category': string\n Category: string\n Account: string\n Tags: string\n Memo: string\n Pending: string\n}\n\n/**\n * Collects the GUIDs of all transactions that act as parents\n * to one or more split (child) transactions.\n */\nfunction extractParentTransactionGuids(transactions: Transaction[]): Set<string> {\n return new Set(\n transactions.filter((tx) => tx.parent_guid !== undefined).map((tx) => tx.parent_guid!),\n )\n}\n\n/**\n * Organizes child transactions by their parent transaction GUID.\n * Returns a map from parent GUID to an array of its child transactions.\n */\nfunction mapChildTransactionsByParent(transactions: Transaction[]): Record<string, Transaction[]> {\n return transactions.reduce<Record<string, Transaction[]>>((accumulator, tx) => {\n if (tx.parent_guid) {\n if (!accumulator[tx.parent_guid]) accumulator[tx.parent_guid] = []\n accumulator[tx.parent_guid].push(tx)\n }\n return accumulator\n }, {})\n}\n\n/**\n * Produces a list of transactions based on the given sorted transactions,\n * where parent transactions that have split children are replaced by those\n * children sorted by descending absolute amount. All other transactions\n * are included as-is, with duplicates removed.\n */\nexport function flattenTransactionsWithSplits(\n sortedTransactions: Transaction[],\n allTransactions: Transaction[],\n): Transaction[] {\n // Set of parent transaction GUIDs that have split child transactions\n const parentTransactionGuidsWithSplits = extractParentTransactionGuids(allTransactions)\n\n // Map from parent GUID to array of its child split transactions\n const childTransactionsGroupedByParent = mapChildTransactionsByParent(allTransactions)\n\n // Track GUIDs of transactions already included in the result to avoid duplicates\n const processedTransactionGuids = new Set<string>()\n\n // Resulting list of transactions with parents replaced by their split children\n const flattenedTransactionList: Transaction[] = []\n\n for (const transaction of sortedTransactions) {\n if (parentTransactionGuidsWithSplits.has(transaction.guid)) {\n // This transaction is a parent with splits, so replace it with its children\n const splitChildTransactions = childTransactionsGroupedByParent[transaction.guid] ?? []\n\n splitChildTransactions\n .slice()\n .sort((a, b) => Math.abs(b.amount) - Math.abs(a.amount))\n .forEach((childTransaction) => {\n if (!processedTransactionGuids.has(childTransaction.guid)) {\n flattenedTransactionList.push(childTransaction)\n processedTransactionGuids.add(childTransaction.guid)\n }\n })\n } else if (!processedTransactionGuids.has(transaction.guid)) {\n // Normal transaction (no splits), add as-is if not already added\n flattenedTransactionList.push(transaction)\n processedTransactionGuids.add(transaction.guid)\n }\n }\n\n return flattenedTransactionList\n}\n\nexport const exportTransactionsToCSV = (transactions: Transaction[], tags: Tag[]) => {\n const csvContent = structureCSVData(formatTransactions(transactions, tags))\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })\n const link = document.createElement('a')\n link.href = URL.createObjectURL(blob)\n link.setAttribute('download', 'transactions.csv')\n\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n\n URL.revokeObjectURL(link.href)\n}\n\n/**\n * Formats a list of transactions into a list that will be used when\n * downloaded to a CSV file.\n */\nconst formatTransactions = (transactions: Transaction[], tags: Tag[]) => {\n return transactions.map((transaction) => ({\n // Post dates are calendar days; format on the UTC day so the export can't\n // shift to the prior day in a Western-offset browser.\n Date: formatDate(fromUnixUTC(transaction.date), DATE_FORMATS_INTL.YEAR_MONTH_DAY),\n Description: getDescription(transaction),\n 'Original Description': transaction.feed_description,\n Amount: `${transaction.amount}`,\n Type: transaction.transaction_type === TransactionType.CREDIT ? 'Credit' : 'Debit',\n 'Parent Category': CategoryGuidToName[transaction.top_level_category_guid || ''],\n Category: transaction.category,\n Account: transaction.account,\n Tags: getTags(transaction, tags),\n Memo: transaction.memo,\n Pending: transaction.isPending ? 'TRUE' : 'FALSE',\n })) as FormattedTransaction[]\n}\n\n/**\n * Escapes a value for safe CSV output\n */\nconst escapeCsvField = (field?: string | null): string => {\n if (!field) return ''\n return /[,\"\\n\\r]/.test(field) ? `\"${field.replace(/\"/g, '\"\"')}\"` : field\n}\n\n/**\n * Structures the CSV file data using the formatted transactions\n */\nconst structureCSVData = (formattedTransactions: FormattedTransaction[]) => {\n // Guard the empty export: Object.keys(undefined) would throw for a zero-row\n // list (e.g. an over-filtered range), so emit an empty file instead.\n if (formattedTransactions.length === 0) return ''\n\n const csvHeader = Object.keys(formattedTransactions[0]).join(',').concat('\\r\\n')\n const csvRows = formattedTransactions\n .map((transaction) => Object.values(transaction).map(escapeCsvField).join(','))\n .join('\\r\\n')\n\n return csvHeader + csvRows\n}\n\n/**\n * Get the description for a transaction that will be used within the CSV copy.\n * We want to highlight that split transactions are a split as well as\n * hidden transactions are hidden.\n */\nconst getDescription = (transaction: Transaction) => {\n let description = transaction.parent_guid ? 'Split: ' : ''\n description += transaction.is_hidden ? '(Excluded) ' : ''\n description += transaction.description\n\n return description\n}\n\nconst getTags = (transaction: Transaction, tags: Tag[]) => {\n return transaction.tags\n .map((tagGuid) => {\n const tag = tags.filter((t) => t.guid === tagGuid)[0]\n\n return tag?.name ?? ''\n })\n .join(' ')\n}\n"],"mappings":"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"}
@@ -1,57 +1,58 @@
1
- import { buildDynamicCopy as F } from "../../../core/utils/Localization.es.js";
2
- import { DATE_FORMATS_INTL as re, formatDate as oe } from "../../../core/constants/DateFormats.es.js";
3
- import { useCategoryStore as ie, useEvent as ae, useGlobalCopyStore as ne, useGlobalUiStore as de, useTransactionStore as se, useUserStore as le } from "../../../common/context/hooks.es.js";
4
- import { ANALYTICS_EVENTS as me } from "../../../common/constants/Analytics.es.js";
5
- import { TransactionType as ce } from "../../../core/types/Transaction.es.js";
6
- import { isFeatureEnabled as ue } from "../../../core/utils/UserUtils.es.js";
7
- import { formatCurrency as G } from "../../../core/utils/NumberFormatting.es.js";
8
- import { fromUnixUTC as pe } from "../../../core/utils/DateUtil.es.js";
9
- import ge from "../../../common/components/Loader.es.js";
10
- import { BottomActions as m, DEFAULT_BOTTOM_ACTIONS as fe, DEFAULT_TOP_ACTIONS as he, TopActions as f } from "../../constants/Actions.es.js";
11
- import _e from "../../../insights/components/shared/ChartTransactionWithDrillDown.es.js";
12
- import { EmbeddedCard as Te } from "../../../insights/components/shared/InsightsCard/EmbeddedCard.es.js";
13
- import { AddMerchantBudgetAction as Se } from "./transactiondetails/actions/AddMerchantBudgetAction.es.js";
14
- import ye from "./transactiondetails/actions/CategoryAction.es.js";
15
- import be from "./transactiondetails/actions/DateAction.es.js";
16
- import De from "./transactiondetails/actions/DeleteAction.es.js";
17
- import Ae from "./transactiondetails/actions/DeleteLogoAction.es.js";
18
- import Ce from "./transactiondetails/actions/ExcludeAction.es.js";
19
- import ve from "./transactiondetails/actions/MemoAction.es.js";
20
- import xe from "./transactiondetails/actions/SplitAction.es.js";
21
- import we from "./transactiondetails/actions/TagsAction.es.js";
22
- import Ie from "./transactiondetails/Description.es.js";
23
- import Le from "./transactiondetails/FlagTransaction.es.js";
24
- import Ee from "./transactiondetails/TransactionDetailsView.es.js";
25
- import { getEmbeddedInstanceSlotByBeatTemplates as Me } from "./getEmbeddedInstanceSlotByBeatTemplates.es.js";
26
- import a, { useMemo as P } from "react";
27
- import { observer as Oe } from "mobx-react-lite";
1
+ import { buildDynamicCopy as G } from "../../../core/utils/Localization.es.js";
2
+ import { DATE_FORMATS_INTL as oe, formatDate as ie } from "../../../core/constants/DateFormats.es.js";
3
+ import { useCategoryStore as ae, useEvent as ne, useGlobalCopyStore as de, useGlobalUiStore as se, useTransactionStore as le, useUserStore as me } from "../../../common/context/hooks.es.js";
4
+ import { ANALYTICS_EVENTS as ce } from "../../../common/constants/Analytics.es.js";
5
+ import { TransactionType as ue } from "../../../core/types/Transaction.es.js";
6
+ import { isFeatureEnabled as pe } from "../../../core/utils/UserUtils.es.js";
7
+ import { formatCurrency as P } from "../../../core/utils/NumberFormatting.es.js";
8
+ import { fromUnixUTC as ge } from "../../../core/utils/DateUtil.es.js";
9
+ import { isTransferTransaction as fe } from "../../../core/utils/TransactionUtils.es.js";
10
+ import he from "../../../common/components/Loader.es.js";
11
+ import { BottomActions as m, DEFAULT_BOTTOM_ACTIONS as _e, DEFAULT_TOP_ACTIONS as Te, TopActions as f } from "../../constants/Actions.es.js";
12
+ import Se from "../../../insights/components/shared/ChartTransactionWithDrillDown.es.js";
13
+ import { EmbeddedCard as ye } from "../../../insights/components/shared/InsightsCard/EmbeddedCard.es.js";
14
+ import { AddMerchantBudgetAction as be } from "./transactiondetails/actions/AddMerchantBudgetAction.es.js";
15
+ import De from "./transactiondetails/actions/CategoryAction.es.js";
16
+ import Ae from "./transactiondetails/actions/DateAction.es.js";
17
+ import Ce from "./transactiondetails/actions/DeleteAction.es.js";
18
+ import ve from "./transactiondetails/actions/DeleteLogoAction.es.js";
19
+ import xe from "./transactiondetails/actions/ExcludeAction.es.js";
20
+ import we from "./transactiondetails/actions/MemoAction.es.js";
21
+ import Ie from "./transactiondetails/actions/SplitAction.es.js";
22
+ import Le from "./transactiondetails/actions/TagsAction.es.js";
23
+ import Ee from "./transactiondetails/Description.es.js";
24
+ import Me from "./transactiondetails/FlagTransaction.es.js";
25
+ import Be from "./transactiondetails/TransactionDetailsView.es.js";
26
+ import { getEmbeddedInstanceSlotByBeatTemplates as Oe } from "./getEmbeddedInstanceSlotByBeatTemplates.es.js";
27
+ import a, { useMemo as U } from "react";
28
+ import { observer as Ne } from "mobx-react-lite";
28
29
  import h from "@mui/material/Stack";
29
- import { MerchantLogo as U, P as Be, Text as b } from "@mxenabled/mxui";
30
- import { endOfMonth as Ne } from "date-fns/endOfMonth";
31
- import { isBefore as Fe } from "date-fns/isBefore";
30
+ import { MerchantLogo as V, P as Fe, Text as b } from "@mxenabled/mxui";
31
+ import { endOfMonth as Ge } from "date-fns/endOfMonth";
32
+ import { isBefore as Pe } from "date-fns/isBefore";
32
33
  import { startOfMonth as k } from "date-fns/startOfMonth";
33
34
  import D from "@mui/material/Paper";
34
35
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
35
- import { useTheme as Ge } from "@mui/material/styles";
36
- import Pe from "@mui/material/Box";
36
+ import { useTheme as Ue } from "@mui/material/styles";
37
+ import Ve from "@mui/material/Box";
37
38
  import H from "@mui/material/Divider";
38
39
  import R from "@mui/material/List";
39
- import Ue from "@mui/material/Alert";
40
- import ke from "@mui/material/Snackbar";
41
- var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = he, transaction: e }) => {
42
- const { onEvent: W } = ae(), { isCopyLoaded: j } = de(), { userFeatures: z } = le(), { accounts: q, common: X, insights_feed: d } = ne(), { detailedCategories: C } = ie(), { alert: v, associatedBeats: x, detailedTransactions: w, cachedStartDate: I, loadEmbeddedInstanceTransactions: Y, setAlert: L } = se(), [$, E] = a.useState(!1), [M, O] = a.useState(!1), [J, K] = a.useState(!1), Q = Ge(), Z = e?.number && e.number.length > 4, B = e?.transaction_type === ce.CREDIT, s = a.useMemo(() => x.find((r) => r.associated_transaction_guid === e.guid), [x, e]), o = Me(X, s), [l, T] = a.useState(o ? o.dataSeries.length - 1 : 0);
43
- a.useEffect(() => W(me.TRANSACTION_DETAILS_VIEW, { transaction_guid: e.guid }), []), a.useEffect(() => {
40
+ import ke from "@mui/material/Alert";
41
+ import He from "@mui/material/Snackbar";
42
+ var Re = ({ bottomActions: _ = _e, canFlagTransaction: W = !0, topActions: A = Te, transaction: e }) => {
43
+ const { onEvent: j } = ne(), { isCopyLoaded: z } = se(), { userFeatures: q } = me(), { accounts: X, common: Y, insights_feed: d } = de(), { detailedCategories: C } = ae(), { alert: v, associatedBeats: x, detailedTransactions: w, cachedStartDate: I, loadEmbeddedInstanceTransactions: $, setAlert: L } = le(), [J, E] = a.useState(!1), [M, B] = a.useState(!1), [K, Q] = a.useState(!1), Z = Ue(), ee = e?.number && e.number.length > 4, O = e?.transaction_type === ue.CREDIT, N = fe(e) && !!e.institutionName, s = a.useMemo(() => x.find((r) => r.associated_transaction_guid === e.guid), [x, e]), o = Oe(Y, s), [l, T] = a.useState(o ? o.dataSeries.length - 1 : 0);
44
+ a.useEffect(() => j(ce.TRANSACTION_DETAILS_VIEW, { transaction_guid: e.guid }), []), a.useEffect(() => {
44
45
  if (!o || o.dataSeries.length === 0) return;
45
46
  const { date: r } = o.dataSeries[l], i = k(r);
46
- Fe(i, I) && (O(!0), Y(i).finally(() => {
47
- O(!1);
47
+ Pe(i, I) && (B(!0), $(i).finally(() => {
48
+ B(!1);
48
49
  }));
49
50
  }, [
50
51
  l,
51
52
  o,
52
53
  I
53
54
  ]);
54
- const S = _.includes(m.MerchantBudget) && !e?.merchant_guid ? _.filter((r) => r !== m.MerchantBudget) : _, y = P(() => {
55
+ const S = _.includes(m.MerchantBudget) && !e?.merchant_guid ? _.filter((r) => r !== m.MerchantBudget) : _, y = U(() => {
55
56
  if (o) {
56
57
  const r = C.find((g) => g.guid === e.top_level_category_guid), i = s?.payload?.average_amount ?? 0, u = e.amount;
57
58
  let p = d.general.increased_text;
@@ -62,12 +63,12 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
62
63
  };
63
64
  }
64
65
  return null;
65
- }, [o, C]), ee = P(() => {
66
+ }, [o, C]), te = U(() => {
66
67
  if (!o?.dataSeries?.length) return [];
67
- const { guid: r, date: i } = o.dataSeries[l], u = k(i), p = Ne(i);
68
+ const { guid: r, date: i } = o.dataSeries[l], u = k(i), p = Ge(i);
68
69
  return w.filter((g) => {
69
- const N = pe(g.date);
70
- return N >= u && N <= p && g.guid === r;
70
+ const F = ge(g.date);
71
+ return F >= u && F <= p && g.guid === r;
71
72
  });
72
73
  }, [
73
74
  l,
@@ -75,9 +76,9 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
75
76
  w,
76
77
  M
77
78
  ]);
78
- if (!j) return /* @__PURE__ */ t(ge, {});
79
- const c = ue(z, "MX_TXN_DETAILS_VIEW_ONLY"), te = Q.palette.mode === "dark" ? "grey.800" : "grey.100";
80
- return /* @__PURE__ */ n(Pe, {
79
+ if (!z) return /* @__PURE__ */ t(he, {});
80
+ const c = pe(q, "MX_TXN_DETAILS_VIEW_ONLY"), re = Z.palette.mode === "dark" ? "grey.800" : "grey.100";
81
+ return /* @__PURE__ */ n(Ve, {
81
82
  className: "mx-txn-transaction-details",
82
83
  width: "100%",
83
84
  children: [
@@ -89,29 +90,30 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
89
90
  /* @__PURE__ */ t(D, {
90
91
  elevation: 2,
91
92
  sx: { width: 64 },
92
- children: /* @__PURE__ */ t(U, {
93
+ children: /* @__PURE__ */ t(V, {
93
94
  categoryGuid: e.top_level_category_guid || "",
94
95
  merchantGuid: e.merchant_guid || "",
95
96
  size: 64
96
97
  })
97
98
  }),
98
- /* @__PURE__ */ t(Ie, {
99
+ /* @__PURE__ */ t(Ee, {
100
+ displayValue: N ? e.institutionName : void 0,
99
101
  transaction: e,
100
- viewOnly: c
102
+ viewOnly: c || N
101
103
  }),
102
104
  /* @__PURE__ */ n(h, {
103
105
  direction: "row",
104
106
  justifyContent: "space-between",
105
107
  sx: { minHeight: 44 },
106
- children: [/* @__PURE__ */ n(Be, {
107
- color: B ? "success.main" : "text.primary",
108
+ children: [/* @__PURE__ */ n(Fe, {
109
+ color: O ? "success.main" : "text.primary",
108
110
  variant: "h1",
109
- children: [B ? "+" : "", G(e.amount, "0,0.00")]
110
- }), !c && V && /* @__PURE__ */ t(Le, { transaction: e })]
111
+ children: [O ? "+" : "", P(e.amount, "0,0.00")]
112
+ }), !c && W && /* @__PURE__ */ t(Me, { transaction: e })]
111
113
  }),
112
- o?.instanceSlot && /* @__PURE__ */ t(Te, {
114
+ o?.instanceSlot && /* @__PURE__ */ t(ye, {
113
115
  callToAction: o.callToAction,
114
- description: F(d.general.embedded_description, y.changetype, /* @__PURE__ */ t("strong", { children: y.percentageAmount })),
116
+ description: G(d.general.embedded_description, y.changetype, /* @__PURE__ */ t("strong", { children: y.percentageAmount })),
115
117
  instanceSlot: o.instanceSlot,
116
118
  onCtaClick: () => {
117
119
  E(!0);
@@ -120,7 +122,7 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
120
122
  }),
121
123
  /* @__PURE__ */ n(h, {
122
124
  sx: {
123
- bgcolor: te,
125
+ bgcolor: re,
124
126
  borderRadius: "4px",
125
127
  gap: 4,
126
128
  p: 8
@@ -128,7 +130,7 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
128
130
  children: [/* @__PURE__ */ t(b, {
129
131
  bold: !0,
130
132
  children: `${e.account}
131
- ${Z ? e.number : "•".repeat(4).concat(e.number ?? "")}`
133
+ ${ee ? e.number : "•".repeat(4).concat(e.number ?? "")}`
132
134
  }), /* @__PURE__ */ t(b, {
133
135
  bold: !0,
134
136
  truncate: !0,
@@ -141,11 +143,11 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
141
143
  /* @__PURE__ */ t(D, {
142
144
  square: !0,
143
145
  sx: { boxShadow: "none" },
144
- children: c ? /* @__PURE__ */ t(Ee, { transaction: e }) : /* @__PURE__ */ t(R, { children: A.map((r, i) => /* @__PURE__ */ n(a.Fragment, { children: [
145
- r === f.Category && /* @__PURE__ */ t(ye, { transaction: e }),
146
- r === f.Date && /* @__PURE__ */ t(be, { transaction: e }),
147
- r === f.Memo && /* @__PURE__ */ t(ve, { transaction: e }),
148
- r === f.Tags && /* @__PURE__ */ t(we, { transaction: e }),
146
+ children: c ? /* @__PURE__ */ t(Be, { transaction: e }) : /* @__PURE__ */ t(R, { children: A.map((r, i) => /* @__PURE__ */ n(a.Fragment, { children: [
147
+ r === f.Category && /* @__PURE__ */ t(De, { transaction: e }),
148
+ r === f.Date && /* @__PURE__ */ t(Ae, { transaction: e }),
149
+ r === f.Memo && /* @__PURE__ */ t(we, { transaction: e }),
150
+ r === f.Tags && /* @__PURE__ */ t(Le, { transaction: e }),
149
151
  /* @__PURE__ */ t(H, {
150
152
  component: "li",
151
153
  variant: i < A.length - 1 ? "inset" : "fullWidth"
@@ -158,28 +160,28 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
158
160
  ml: 26,
159
161
  mt: 16,
160
162
  variant: "body1",
161
- children: q.actions
163
+ children: X.actions
162
164
  }), /* @__PURE__ */ t(D, {
163
165
  square: !0,
164
166
  sx: { boxShadow: "none" },
165
167
  children: /* @__PURE__ */ n(R, { children: [S.map((r, i) => /* @__PURE__ */ n(a.Fragment, { children: [
166
- r === m.MerchantBudget && /* @__PURE__ */ t(Se, { transaction: e }),
167
- r === m.SplitTransaction && /* @__PURE__ */ t(xe, { transaction: e }),
168
- r === m.HideTransaction && /* @__PURE__ */ t(Ce, { transaction: e }),
169
- r === m.MerchantLogo && /* @__PURE__ */ t(Ae, { transaction: e }),
168
+ r === m.MerchantBudget && /* @__PURE__ */ t(be, { transaction: e }),
169
+ r === m.SplitTransaction && /* @__PURE__ */ t(Ie, { transaction: e }),
170
+ r === m.HideTransaction && /* @__PURE__ */ t(xe, { transaction: e }),
171
+ r === m.MerchantLogo && /* @__PURE__ */ t(ve, { transaction: e }),
170
172
  /* @__PURE__ */ t(H, {
171
173
  component: "li",
172
174
  variant: i < S.length - 1 ? "inset" : "fullWidth"
173
175
  })
174
- ] }, r)), e.is_manual && !e.parent_guid && !e.has_been_split && /* @__PURE__ */ t(De, { transaction: e })] })
176
+ ] }, r)), e.is_manual && !e.parent_guid && !e.has_been_split && /* @__PURE__ */ t(Ce, { transaction: e })] })
175
177
  })] })
176
178
  ] }),
177
- s && o && /* @__PURE__ */ t(_e, {
178
- ariaLabel: oe(o?.dataSeries[l]?.date, re.MONTH),
179
+ s && o && /* @__PURE__ */ t(Se, {
180
+ ariaLabel: ie(o?.dataSeries[l]?.date, oe.MONTH),
179
181
  barChartProps: {
180
182
  amounts: {
181
183
  average: s.payload.average_amount,
182
- formattedAverage: G(s.payload.average_amount, "0,0")
184
+ formattedAverage: P(s.payload.average_amount, "0,0")
183
185
  },
184
186
  color: y.category?.color || "",
185
187
  data: o.chartData,
@@ -206,31 +208,31 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
206
208
  },
207
209
  data: o.chartData,
208
210
  defaultSelectedIndex: l,
209
- icon: /* @__PURE__ */ t(U, {
211
+ icon: /* @__PURE__ */ t(V, {
210
212
  alt: e.description ?? "",
211
213
  categoryGuid: e.category_guid ?? "",
212
214
  merchantGuid: e.merchant_guid ?? "",
213
215
  size: 16
214
216
  }),
215
- isOpen: $,
217
+ isOpen: J,
216
218
  onClose: () => {
217
219
  E(!1), T(o.dataSeries.length - 1);
218
220
  },
219
221
  onTabChange: (r) => {
220
222
  T(r);
221
223
  },
222
- tipSection: J ? void 0 : {
223
- message: F(d.general.tip_section_message, /* @__PURE__ */ t("strong", { children: d.general.tip_section_title }), /* @__PURE__ */ t("strong", { children: s.primary_transaction?.description })),
224
- onDismiss: () => K(!0)
224
+ tipSection: K ? void 0 : {
225
+ message: G(d.general.tip_section_message, /* @__PURE__ */ t("strong", { children: d.general.tip_section_title }), /* @__PURE__ */ t("strong", { children: s.primary_transaction?.description })),
226
+ onDismiss: () => Q(!0)
225
227
  },
226
228
  title: d.general.transaction_history_title,
227
229
  transactionListProps: {
228
230
  showLoader: M,
229
231
  showInsights: !0,
230
- transaction: ee
232
+ transaction: te
231
233
  }
232
234
  }),
233
- /* @__PURE__ */ t(ke, {
235
+ /* @__PURE__ */ t(He, {
234
236
  anchorOrigin: {
235
237
  vertical: "bottom",
236
238
  horizontal: "right"
@@ -238,7 +240,7 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
238
240
  autoHideDuration: 3500,
239
241
  onClose: () => L(""),
240
242
  open: !!v,
241
- children: /* @__PURE__ */ t(Ue, {
243
+ children: /* @__PURE__ */ t(ke, {
242
244
  closeText: "",
243
245
  onClose: () => L(""),
244
246
  severity: "success",
@@ -248,9 +250,9 @@ var He = ({ bottomActions: _ = fe, canFlagTransaction: V = !0, topActions: A = h
248
250
  })
249
251
  ]
250
252
  });
251
- }, wt = Oe(He);
253
+ }, Et = Ne(Re);
252
254
  export {
253
- wt as default
255
+ Et as default
254
256
  };
255
257
 
256
258
  //# sourceMappingURL=TransactionDetails.es.js.map