@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.
- package/CHANGELOG.md +8 -0
- package/dist/core/stores/GlobalStore.es.js +12 -8
- package/dist/core/stores/GlobalStore.es.js.map +1 -1
- package/dist/core/stores/RecurringTransactionsStore.d.ts +1 -0
- package/dist/core/stores/RecurringTransactionsStore.es.js +40 -36
- package/dist/core/stores/RecurringTransactionsStore.es.js.map +1 -1
- package/dist/core/types/Transaction.d.ts +1 -0
- package/dist/core/types/Transaction.es.js.map +1 -1
- package/dist/core/utils/TransactionUtils.d.ts +4 -2
- package/dist/core/utils/TransactionUtils.es.js +52 -50
- package/dist/core/utils/TransactionUtils.es.js.map +1 -1
- package/dist/transactions/components/shared/TransactionDetails.es.js +84 -82
- package/dist/transactions/components/shared/TransactionDetails.es.js.map +1 -1
- package/dist/transactions/components/shared/transactiondetails/Description.d.ts +1 -0
- package/dist/transactions/components/shared/transactiondetails/Description.es.js +39 -39
- package/dist/transactions/components/shared/transactiondetails/Description.es.js.map +1 -1
- package/dist/transactions/components/shared/transactiondetails/TransactionAmountHeader.es.js +18 -17
- package/dist/transactions/components/shared/transactiondetails/TransactionAmountHeader.es.js.map +1 -1
- package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js +26 -25
- package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js.map +1 -1
- package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.d.ts +2 -1
- package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.es.js +27 -23
- package/dist/transactions/components/shared/transactiontable/cells/PayeeCell.es.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { CategoryGuidToName as
|
|
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
|
|
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
|
|
6
|
-
import { TABLE_CONST as
|
|
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
|
|
9
|
-
import { startOfMonth as
|
|
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
|
|
12
|
+
import { fromUnixTime as N } from "date-fns/fromUnixTime";
|
|
13
13
|
import { getUnixTime as _ } from "date-fns/getUnixTime";
|
|
14
|
-
var X = (
|
|
15
|
-
const s =
|
|
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
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
},
|
|
49
|
-
const i =
|
|
50
|
-
return
|
|
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
|
-
},
|
|
55
|
+
}, R = (t, r, n) => {
|
|
55
56
|
const { accounts: a = [], dateRange: s = {
|
|
56
|
-
start:
|
|
57
|
+
start: O(D()),
|
|
57
58
|
end: M()
|
|
58
|
-
}, custom: d = () => !0, searchTerm: i = "", showSplits: o = !1 } =
|
|
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 ===
|
|
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,
|
|
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,
|
|
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
|
-
},
|
|
66
|
-
const 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 (
|
|
69
|
-
}), p = (
|
|
70
|
-
const n =
|
|
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
|
|
74
|
-
return new Set(
|
|
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(
|
|
77
|
-
return
|
|
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
|
|
80
|
-
const n =
|
|
81
|
-
for (const i of
|
|
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
|
|
87
|
-
const n = P(j(
|
|
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 = (
|
|
90
|
-
Date: f(
|
|
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 ===
|
|
95
|
-
"Parent Category":
|
|
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:
|
|
99
|
+
Tags: F(n, r),
|
|
99
100
|
Memo: n.memo,
|
|
100
101
|
Pending: n.isPending ? "TRUE" : "FALSE"
|
|
101
|
-
})), G = (
|
|
102
|
-
`) +
|
|
103
|
-
`), x = (
|
|
104
|
-
let
|
|
105
|
-
return
|
|
106
|
-
},
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
2
|
-
import { DATE_FORMATS_INTL as
|
|
3
|
-
import { useCategoryStore as
|
|
4
|
-
import { ANALYTICS_EVENTS as
|
|
5
|
-
import { TransactionType as
|
|
6
|
-
import { isFeatureEnabled as
|
|
7
|
-
import { formatCurrency as
|
|
8
|
-
import { fromUnixUTC as
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import _e from "
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import {
|
|
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
|
|
30
|
-
import { endOfMonth as
|
|
31
|
-
import { isBefore as
|
|
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
|
|
36
|
-
import
|
|
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
|
|
40
|
-
import
|
|
41
|
-
var
|
|
42
|
-
const { onEvent:
|
|
43
|
-
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
|
-
|
|
47
|
-
|
|
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 =
|
|
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]),
|
|
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 =
|
|
68
|
+
const { guid: r, date: i } = o.dataSeries[l], u = k(i), p = Ge(i);
|
|
68
69
|
return w.filter((g) => {
|
|
69
|
-
const
|
|
70
|
-
return
|
|
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 (!
|
|
79
|
-
const c =
|
|
80
|
-
return /* @__PURE__ */ n(
|
|
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(
|
|
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(
|
|
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(
|
|
107
|
-
color:
|
|
108
|
+
children: [/* @__PURE__ */ n(Fe, {
|
|
109
|
+
color: O ? "success.main" : "text.primary",
|
|
108
110
|
variant: "h1",
|
|
109
|
-
children: [
|
|
110
|
-
}), !c &&
|
|
111
|
+
children: [O ? "+" : "", P(e.amount, "0,0.00")]
|
|
112
|
+
}), !c && W && /* @__PURE__ */ t(Me, { transaction: e })]
|
|
111
113
|
}),
|
|
112
|
-
o?.instanceSlot && /* @__PURE__ */ t(
|
|
114
|
+
o?.instanceSlot && /* @__PURE__ */ t(ye, {
|
|
113
115
|
callToAction: o.callToAction,
|
|
114
|
-
description:
|
|
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:
|
|
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
|
-
${
|
|
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(
|
|
145
|
-
r === f.Category && /* @__PURE__ */ t(
|
|
146
|
-
r === f.Date && /* @__PURE__ */ t(
|
|
147
|
-
r === f.Memo && /* @__PURE__ */ t(
|
|
148
|
-
r === f.Tags && /* @__PURE__ */ t(
|
|
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:
|
|
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(
|
|
167
|
-
r === m.SplitTransaction && /* @__PURE__ */ t(
|
|
168
|
-
r === m.HideTransaction && /* @__PURE__ */ t(
|
|
169
|
-
r === m.MerchantLogo && /* @__PURE__ */ t(
|
|
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(
|
|
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(
|
|
178
|
-
ariaLabel:
|
|
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:
|
|
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(
|
|
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:
|
|
223
|
-
message:
|
|
224
|
-
onDismiss: () =>
|
|
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:
|
|
232
|
+
transaction: te
|
|
231
233
|
}
|
|
232
234
|
}),
|
|
233
|
-
/* @__PURE__ */ t(
|
|
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(
|
|
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
|
-
},
|
|
253
|
+
}, Et = Ne(Re);
|
|
252
254
|
export {
|
|
253
|
-
|
|
255
|
+
Et as default
|
|
254
256
|
};
|
|
255
257
|
|
|
256
258
|
//# sourceMappingURL=TransactionDetails.es.js.map
|