@mx-cartographer/experiences 6.26.0-alpha.sms7 → 6.26.1-alpha.mega1
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 +31 -1
- package/dist/AccountStore-DkL93tXL.mjs +317 -0
- package/dist/AccountStore-DkL93tXL.mjs.map +1 -0
- package/dist/BudgetUtil-CVqAdv-j.mjs +187 -0
- package/dist/BudgetUtil-CVqAdv-j.mjs.map +1 -0
- package/dist/CashflowStore-gPEEBiXo.mjs +53 -0
- package/dist/CashflowStore-gPEEBiXo.mjs.map +1 -0
- package/dist/CategoryStore-m7oieLzP.mjs +260 -0
- package/dist/CategoryStore-m7oieLzP.mjs.map +1 -0
- package/dist/ConnectMiniWidget-CQWafYtQ.mjs +22966 -0
- package/dist/ConnectMiniWidget-CQWafYtQ.mjs.map +1 -0
- package/dist/DebtsStore-cUhIgJx6.mjs +145 -0
- package/dist/DebtsStore-cUhIgJx6.mjs.map +1 -0
- package/dist/Donut-CGNFni9y.mjs +58 -0
- package/dist/Donut-CGNFni9y.mjs.map +1 -0
- package/dist/FinstrongStore-BDG7l0nI.mjs +183 -0
- package/dist/FinstrongStore-BDG7l0nI.mjs.map +1 -0
- package/dist/GoalStore-o2waGeyf.mjs +293 -0
- package/dist/GoalStore-o2waGeyf.mjs.map +1 -0
- package/dist/Loader-CwdK8lfx.mjs +147 -0
- package/dist/Loader-CwdK8lfx.mjs.map +1 -0
- package/dist/MerchantStore-Cck9IGIH.mjs +125 -0
- package/dist/MerchantStore-Cck9IGIH.mjs.map +1 -0
- package/dist/NetWorthStore-D5eUfGQt.mjs +66 -0
- package/dist/NetWorthStore-D5eUfGQt.mjs.map +1 -0
- package/dist/NotificationStore-DCxw8W7u.mjs +141 -0
- package/dist/NotificationStore-DCxw8W7u.mjs.map +1 -0
- package/dist/RecurringTransactionsStore-Bijrgllq.mjs +337 -0
- package/dist/RecurringTransactionsStore-Bijrgllq.mjs.map +1 -0
- package/dist/SettingsStore-BhOYgUOa.mjs +352 -0
- package/dist/SettingsStore-BhOYgUOa.mjs.map +1 -0
- package/dist/TransactionApi-Dnbyi1JL.mjs +175 -0
- package/dist/TransactionApi-Dnbyi1JL.mjs.map +1 -0
- package/dist/TransactionStore-CiEtt5XJ.mjs +417 -0
- package/dist/TransactionStore-CiEtt5XJ.mjs.map +1 -0
- package/dist/TrendsStore-Idq3QfoA.mjs +131 -0
- package/dist/TrendsStore-Idq3QfoA.mjs.map +1 -0
- package/dist/accounts/index.es.js +18 -0
- package/dist/accounts/index.es.js.map +1 -0
- package/dist/analytics/index.es.js +170 -0
- package/dist/analytics/index.es.js.map +1 -0
- package/dist/budgets/index.es.js +1116 -0
- package/dist/budgets/index.es.js.map +1 -0
- package/dist/cashflow/index.es.js +118 -0
- package/dist/cashflow/index.es.js.map +1 -0
- package/dist/categories/index.es.js +10 -0
- package/dist/categories/index.es.js.map +1 -0
- package/dist/categories/util/CategoryUtil.d.ts +3 -2
- package/dist/common/components/charts/StackedLineChart.d.ts +2 -2
- package/dist/common/components/charts/stackedlinechart/CustomLegend.d.ts +1 -0
- package/dist/common/context/hooks.d.ts +13 -13
- package/dist/common/index.es.js +1549 -0
- package/dist/common/index.es.js.map +1 -0
- package/dist/common/types/AppData.d.ts +2 -0
- package/dist/common/types/Category.d.ts +2 -8
- package/dist/common/types/index.d.ts +1 -1
- package/dist/dashboard/index.es.js +257 -0
- package/dist/dashboard/index.es.js.map +1 -0
- package/dist/debts/index.es.js +9 -0
- package/dist/debts/index.es.js.map +1 -0
- package/dist/finstrong/index.es.js +11 -0
- package/dist/finstrong/index.es.js.map +1 -0
- package/dist/goals/index.es.js +9 -0
- package/dist/goals/index.es.js.map +1 -0
- package/dist/help/components/content/section/index.d.ts +15 -15
- package/dist/help/index.es.js +6 -0
- package/dist/help/index.es.js.map +1 -0
- package/dist/investments/index.es.js +1694 -0
- package/dist/investments/index.es.js.map +1 -0
- package/dist/merchants/index.es.js +7 -0
- package/dist/merchants/index.es.js.map +1 -0
- package/dist/microinsights/index.es.js +21 -0
- package/dist/microinsights/index.es.js.map +1 -0
- package/dist/networth/index.es.js +11 -0
- package/dist/networth/index.es.js.map +1 -0
- package/dist/notifications/index.es.js +116 -0
- package/dist/notifications/index.es.js.map +1 -0
- package/dist/recurringtransactions/index.es.js +14 -0
- package/dist/recurringtransactions/index.es.js.map +1 -0
- package/dist/settings/index.es.js +112 -0
- package/dist/settings/index.es.js.map +1 -0
- package/dist/spending/index.es.js +632 -0
- package/dist/spending/index.es.js.map +1 -0
- package/dist/transactions/index.es.js +19 -0
- package/dist/transactions/index.es.js.map +1 -0
- package/dist/trends/components/CategoriesList.d.ts +5 -5
- package/dist/trends/components/CategoriesListItem.d.ts +7 -4
- package/dist/trends/components/CategoryDetailChart.d.ts +5 -1
- package/dist/trends/index.es.js +10 -0
- package/dist/trends/index.es.js.map +1 -0
- package/dist/trends/stores/TrendsStore.d.ts +11 -16
- package/package.json +91 -3
- package/dist/index.d.ts +0 -22
- package/dist/index.es.js +0 -29873
- package/dist/index.es.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
## [6.26.0] - 08-27-2025
|
|
2
|
+
|
|
3
|
+
- **CHANGED** - `GlobalStore` now accepts props for data
|
|
4
|
+
|
|
5
|
+
## [6.25.11] - 08-26-2025
|
|
6
|
+
|
|
7
|
+
- **ADDED** - New Trends Widget | Add tooltip to category details chart
|
|
8
|
+
|
|
9
|
+
## [6.25.10] - 08-26-2025
|
|
10
|
+
|
|
11
|
+
- **ADDED** - Respect Deep link params for `Spending` Widget.
|
|
12
|
+
|
|
13
|
+
## [6.25.9] - 08-25-2025
|
|
14
|
+
|
|
15
|
+
- **FIXED** - Debts table showing available balance instead of current balance
|
|
16
|
+
|
|
17
|
+
## [6.25.8] - 08-25-2025
|
|
18
|
+
|
|
19
|
+
- **FIXED** - Spending widget so that it displays all income categories
|
|
20
|
+
- **FIXED** - Spending widget so that it exlucdes investment categories
|
|
21
|
+
- **FIXED** - Transaction list on Spending widget so that it displays the correct transactions
|
|
22
|
+
|
|
23
|
+
## [6.25.7] - 08-25-2025
|
|
24
|
+
|
|
25
|
+
- **UPDATED** - StackedLineChart to have responsive height based on widget and legend dimensions
|
|
26
|
+
|
|
27
|
+
## [6.25.6] - 08-25-2025
|
|
28
|
+
|
|
29
|
+
- **CHANGED** - new Trends Widget to use Detailed Categories
|
|
30
|
+
|
|
1
31
|
## [6.25.5] - 08-25-2025
|
|
2
32
|
|
|
3
33
|
- **ADDED** - `Mini Goals Widget` | Padding updated for empty state
|
|
@@ -18,7 +48,7 @@
|
|
|
18
48
|
|
|
19
49
|
- **ADDED** - `Profile` drawer with API for `Finstrong` widget
|
|
20
50
|
|
|
21
|
-
## [6.25.
|
|
51
|
+
## [6.25.0] - 08-20-2025
|
|
22
52
|
|
|
23
53
|
- **ADDED** - (new) TrendsWidget, TrendsStore, TrendsChartTotals, TrendsInsights
|
|
24
54
|
- **ADDED** - CategoryList, CategoryDetailDrawer, CategoryDetailChart
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { makeAutoObservable as d, runInAction as a } from "mobx";
|
|
2
|
+
import "bowser";
|
|
3
|
+
import "date-fns/getUnixTime";
|
|
4
|
+
import "date-fns/intlFormat";
|
|
5
|
+
import { ae as l, af as n, aS as s, aT as u, aU as _, aV as A, aW as g } from "./ConnectMiniWidget-CQWafYtQ.mjs";
|
|
6
|
+
import "date-fns/addMonths";
|
|
7
|
+
import "date-fns/addQuarters";
|
|
8
|
+
import "date-fns/addWeeks";
|
|
9
|
+
import "date-fns/addYears";
|
|
10
|
+
import "date-fns/getDay";
|
|
11
|
+
import "date-fns/isBefore";
|
|
12
|
+
import "date-fns/nextDay";
|
|
13
|
+
import "date-fns/setDate";
|
|
14
|
+
import "date-fns/startOfToday";
|
|
15
|
+
import "date-fns/fromUnixTime";
|
|
16
|
+
import "react";
|
|
17
|
+
import "numeral";
|
|
18
|
+
import "@mui/material";
|
|
19
|
+
import "react/jsx-runtime";
|
|
20
|
+
import "@mui/material/Button";
|
|
21
|
+
import "@mxenabled/mxui";
|
|
22
|
+
import "@mui/material/Tooltip";
|
|
23
|
+
import "@mui/material/Box";
|
|
24
|
+
import "@mui/material/IconButton";
|
|
25
|
+
import "./Loader-CwdK8lfx.mjs";
|
|
26
|
+
import "@mui/material/styles/useTheme";
|
|
27
|
+
import "@mui/material/useMediaQuery";
|
|
28
|
+
import "@mxenabled/cssinjs";
|
|
29
|
+
import "date-fns/addDays";
|
|
30
|
+
import "date-fns/eachDayOfInterval";
|
|
31
|
+
import "date-fns/eachWeekOfInterval";
|
|
32
|
+
import "date-fns/endOfMonth";
|
|
33
|
+
import "date-fns/format";
|
|
34
|
+
import "date-fns/isSameMonth";
|
|
35
|
+
import "date-fns/startOfMonth";
|
|
36
|
+
import "date-fns/subMonths";
|
|
37
|
+
import "@mui/material/Paper";
|
|
38
|
+
import "@mxenabled/mx-icons";
|
|
39
|
+
import "date-fns/isSameDay";
|
|
40
|
+
import "date-fns/isWithinInterval";
|
|
41
|
+
import "d3";
|
|
42
|
+
import "@mui/material/styles";
|
|
43
|
+
import "@mui/x-charts";
|
|
44
|
+
import "@mui/x-charts/ChartsTooltip";
|
|
45
|
+
import "@mui/material/Stack";
|
|
46
|
+
import "date-fns/differenceInCalendarDays";
|
|
47
|
+
import "date-fns/endOfToday";
|
|
48
|
+
import "date-fns/endOfYear";
|
|
49
|
+
import "date-fns/startOfYear";
|
|
50
|
+
import "date-fns/subDays";
|
|
51
|
+
import "date-fns/subYears";
|
|
52
|
+
import "@mui/material/ButtonGroup";
|
|
53
|
+
import "@mui/material/Tab";
|
|
54
|
+
import "@mui/material/Tabs";
|
|
55
|
+
import "@mui/material/ToggleButton";
|
|
56
|
+
import "@mui/material/ToggleButtonGroup";
|
|
57
|
+
import "@mui/material/Dialog";
|
|
58
|
+
import "@mui/material/DialogContent";
|
|
59
|
+
import "@mui/material/Card";
|
|
60
|
+
import "@mui/material/CardContent";
|
|
61
|
+
import "@mui/material/CardHeader";
|
|
62
|
+
import "uuid";
|
|
63
|
+
import "@mui/material/CircularProgress";
|
|
64
|
+
import "@mui/material/FormControlLabel";
|
|
65
|
+
import "@mui/material/Radio";
|
|
66
|
+
import "@mui/material/Avatar";
|
|
67
|
+
import "@mui/material/ListItem";
|
|
68
|
+
import "@mui/material/ListItemAvatar";
|
|
69
|
+
import "@mui/material/ListItemButton";
|
|
70
|
+
import "@mui/material/ListItemText";
|
|
71
|
+
import "@mui/material/ListItemIcon";
|
|
72
|
+
import "@mui/material/MenuItem";
|
|
73
|
+
import "@mui/material/TextField";
|
|
74
|
+
import "@mui/material/Switch";
|
|
75
|
+
import "posthog-js";
|
|
76
|
+
import "date-fns/differenceInDays";
|
|
77
|
+
import "@mui/x-data-grid-pro";
|
|
78
|
+
import "date-fns";
|
|
79
|
+
import "@mui/material/Divider";
|
|
80
|
+
import "@mui/material/List";
|
|
81
|
+
import "date-fns/formatISO";
|
|
82
|
+
import "date-fns/isAfter";
|
|
83
|
+
import "date-fns/parseISO";
|
|
84
|
+
import "date-fns/subQuarters";
|
|
85
|
+
import "date-fns/lastDayOfMonth";
|
|
86
|
+
import "date-fns/setDayOfYear";
|
|
87
|
+
import "date-fns/addSeconds";
|
|
88
|
+
import "date-fns/differenceInCalendarMonths";
|
|
89
|
+
import "date-fns/getMonth";
|
|
90
|
+
class p {
|
|
91
|
+
fetchInstance;
|
|
92
|
+
constructor(t, e) {
|
|
93
|
+
this.fetchInstance = new l(t, e);
|
|
94
|
+
}
|
|
95
|
+
createAccount = async (t) => this.fetchInstance.post(n.ACCOUNTS, t).then((e) => e.account).catch((e) => e);
|
|
96
|
+
deleteAccount = async (t) => this.fetchInstance.delete(`${n.ACCOUNTS}/${t}`).catch((e) => e);
|
|
97
|
+
getAccounts = async () => this.fetchInstance.get(n.ACCOUNTS).then((t) => t.accounts).catch((t) => t);
|
|
98
|
+
getInstitutions = async () => this.fetchInstance.get(n.INSTITUTIONS).then((t) => t).catch((t) => t);
|
|
99
|
+
getMembers = async () => this.fetchInstance.get(n.MEMBERS).then((t) => t.members).catch((t) => t);
|
|
100
|
+
getMonthlyAccountBalances = async (t) => this.fetchInstance.get(`${n.ACCOUNTS}/${t}/monthly_account_balances`).then((e) => e.monthly_account_balances).catch((e) => e);
|
|
101
|
+
mergeAccounts = async (t) => this.fetchInstance.put(`${n.ACCOUNTS}/merge`, { accounts: t }).then((e) => e).catch((e) => e);
|
|
102
|
+
refreshAllMembers = async () => this.fetchInstance.get(`${n.MEMBERS}/refresh_all`).then((t) => t).catch((t) => t);
|
|
103
|
+
updateAccount = async (t) => this.fetchInstance.put(`${n.ACCOUNTS}/${t.guid}`, t).then((e) => e.account).catch((e) => e);
|
|
104
|
+
}
|
|
105
|
+
class f {
|
|
106
|
+
isLoading = !1;
|
|
107
|
+
selectedAccount = {};
|
|
108
|
+
selectedMember = {};
|
|
109
|
+
constructor() {
|
|
110
|
+
d(this);
|
|
111
|
+
}
|
|
112
|
+
setIsLoading = (t) => this.isLoading = t;
|
|
113
|
+
setSelectedAccount = (t) => this.selectedAccount = t;
|
|
114
|
+
setSelectedMember = (t) => this.selectedMember = t;
|
|
115
|
+
}
|
|
116
|
+
class te {
|
|
117
|
+
globalStore;
|
|
118
|
+
api = new p("/", "");
|
|
119
|
+
accounts = [];
|
|
120
|
+
institutions = [];
|
|
121
|
+
members = [];
|
|
122
|
+
uiStore;
|
|
123
|
+
constructor(t) {
|
|
124
|
+
this.globalStore = t, this.uiStore = new f(), this.api = new p(t.endpoint, t.sessionToken), d(this);
|
|
125
|
+
}
|
|
126
|
+
loadAccountData = async ({
|
|
127
|
+
accounts: t,
|
|
128
|
+
institutions: e
|
|
129
|
+
} = {}) => {
|
|
130
|
+
await Promise.all([this.loadAccounts(t), this.loadInstitutions(e)]);
|
|
131
|
+
};
|
|
132
|
+
get cashAccounts() {
|
|
133
|
+
return this.accounts.filter(
|
|
134
|
+
(t) => t.account_type === s.CASH || t.account_type === s.CHECKING || t.account_type === s.PREPAID || t.account_type === s.SAVINGS || t.account_type === s.CHECKING_LINE_OF_CREDIT
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
get cashBalance() {
|
|
138
|
+
return this.cashAccounts.reduce((t, e) => t + (e?.balance || 0), 0);
|
|
139
|
+
}
|
|
140
|
+
get checkingAccounts() {
|
|
141
|
+
return this.accounts.filter((t) => t.account_type === s.CHECKING);
|
|
142
|
+
}
|
|
143
|
+
get debtAccounts() {
|
|
144
|
+
return this.accounts.filter(
|
|
145
|
+
(t) => t.account_type === s.CREDIT_CARD || t.account_type === s.LOAN || t.account_type === s.MORTGAGE || t.account_type === s.LINE_OF_CREDIT || t.account_type === s.CHECKING_LINE_OF_CREDIT
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
get finstrongAccounts() {
|
|
149
|
+
const t = /* @__PURE__ */ new Set([
|
|
150
|
+
s.CHECKING,
|
|
151
|
+
s.SAVINGS,
|
|
152
|
+
s.CREDIT_CARD,
|
|
153
|
+
s.INVESTMENT
|
|
154
|
+
]);
|
|
155
|
+
return this.accounts.filter((e) => t.has(e.account_type));
|
|
156
|
+
}
|
|
157
|
+
get investmentAccounts() {
|
|
158
|
+
return this.accounts.filter(
|
|
159
|
+
(t) => t.account_type === s.INVESTMENT
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
get savingsAccounts() {
|
|
163
|
+
return this.accounts.filter((t) => t.account_type === s.SAVINGS);
|
|
164
|
+
}
|
|
165
|
+
get visibleAccounts() {
|
|
166
|
+
return this.accounts.filter((t) => !t.is_hidden);
|
|
167
|
+
}
|
|
168
|
+
get visibleCashAccounts() {
|
|
169
|
+
return this.cashAccounts.filter((t) => !t.is_hidden);
|
|
170
|
+
}
|
|
171
|
+
get visibleCashBalance() {
|
|
172
|
+
return this.visibleCashAccounts.reduce((t, e) => t + (e?.balance || 0), 0);
|
|
173
|
+
}
|
|
174
|
+
get visibleCheckingAccounts() {
|
|
175
|
+
return this.checkingAccounts.filter((t) => !t.is_hidden);
|
|
176
|
+
}
|
|
177
|
+
get visibleDebtAccounts() {
|
|
178
|
+
return this.debtAccounts.filter((t) => !t.is_hidden);
|
|
179
|
+
}
|
|
180
|
+
get visibleFinstrongAccounts() {
|
|
181
|
+
return this.finstrongAccounts.filter(
|
|
182
|
+
(t) => !(t.is_closed || t.is_deleted || t.is_hidden)
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
get visibleInvestmentAccounts() {
|
|
186
|
+
return this.investmentAccounts.filter((t) => !t.is_hidden);
|
|
187
|
+
}
|
|
188
|
+
get visibleSavingsAccounts() {
|
|
189
|
+
return this.savingsAccounts.filter((t) => !t.is_hidden);
|
|
190
|
+
}
|
|
191
|
+
addAccount = async (t) => {
|
|
192
|
+
try {
|
|
193
|
+
const e = await this.api.createAccount(t);
|
|
194
|
+
a(() => {
|
|
195
|
+
this.accounts = [...this.accounts, e];
|
|
196
|
+
});
|
|
197
|
+
} catch (e) {
|
|
198
|
+
console.error(`Error occurred while adding an account: ${e}`);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
augmentAccounts = (t = this.accounts) => {
|
|
202
|
+
const e = [];
|
|
203
|
+
return t.forEach((c) => {
|
|
204
|
+
const r = this.members.findIndex(
|
|
205
|
+
(o) => o.guid === c.member_guid
|
|
206
|
+
);
|
|
207
|
+
if (r > -1) {
|
|
208
|
+
let o = u.Connected;
|
|
209
|
+
const i = this.members[r];
|
|
210
|
+
_.includes(i.connection_status) ? o = u.Error : A.includes(i.connection_status) ? o = u.Processing : g.includes(i.connection_status) && (o = u.RequiresMfa);
|
|
211
|
+
let m = c.user_name || c.feed_name || "";
|
|
212
|
+
c.account_number && (m = `${m} *${c.account_number}`), e.push({
|
|
213
|
+
...c,
|
|
214
|
+
institutionName: m,
|
|
215
|
+
memberName: i.name,
|
|
216
|
+
connectionStatus: o
|
|
217
|
+
}), this.members[r].connectionStatus = o;
|
|
218
|
+
}
|
|
219
|
+
}), e;
|
|
220
|
+
};
|
|
221
|
+
loadAccounts = async (t) => {
|
|
222
|
+
await this.loadMembers();
|
|
223
|
+
try {
|
|
224
|
+
const e = t || await this.api.getAccounts();
|
|
225
|
+
a(() => {
|
|
226
|
+
this.accounts = this.sortAccounts(this.augmentAccounts(e));
|
|
227
|
+
});
|
|
228
|
+
} catch (e) {
|
|
229
|
+
console.error(`Error occurred while loading accounts: ${e}`);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
loadInstitutions = async (t) => {
|
|
233
|
+
try {
|
|
234
|
+
const e = t || await this.api.getInstitutions();
|
|
235
|
+
a(() => {
|
|
236
|
+
this.institutions = e;
|
|
237
|
+
});
|
|
238
|
+
} catch (e) {
|
|
239
|
+
console.error(`Error occurred while loading institutions: ${e}`);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
loadMembers = async () => {
|
|
243
|
+
try {
|
|
244
|
+
const t = await this.api.getMembers();
|
|
245
|
+
a(() => {
|
|
246
|
+
this.members = t;
|
|
247
|
+
});
|
|
248
|
+
} catch (t) {
|
|
249
|
+
console.error(`Error occurred while loading members: ${t}`);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
mergeAccounts = async (t) => {
|
|
253
|
+
try {
|
|
254
|
+
const e = await this.api.mergeAccounts(t), c = e[Object.keys(e)[0]];
|
|
255
|
+
a(() => {
|
|
256
|
+
const r = this.accounts.findIndex((i) => i.guid === t[1]);
|
|
257
|
+
this.accounts.splice(r, 1);
|
|
258
|
+
const o = this.accounts.findIndex((i) => i.guid === t[0]);
|
|
259
|
+
this.accounts.splice(o, 1, c);
|
|
260
|
+
});
|
|
261
|
+
} catch (e) {
|
|
262
|
+
console.error(`Error occurred while merging accounts: ${e}`);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
sortAccounts = (t = this.accounts) => t.sort((e, c) => e.account_type > c.account_type ? 1 : e.account_type < c.account_type ? -1 : (e.name || "") > (c.name || "") ? 1 : (e.name || "") < (c.name || "") ? -1 : 0);
|
|
266
|
+
refreshAccounts = async () => {
|
|
267
|
+
this.uiStore.setIsLoading(!0), await Promise.all([this.loadAccounts(), this.loadInstitutions()]), this.uiStore.setIsLoading(!1);
|
|
268
|
+
};
|
|
269
|
+
refreshMembers = async () => {
|
|
270
|
+
try {
|
|
271
|
+
await this.api.refreshAllMembers(), await this.loadMembers();
|
|
272
|
+
} catch (t) {
|
|
273
|
+
console.error(`Error occurredwhile refreshing members: ${t}`);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
removeAccount = async (t) => {
|
|
277
|
+
try {
|
|
278
|
+
await this.api.deleteAccount(t), a(() => {
|
|
279
|
+
const e = this.accounts.findIndex((c) => c.guid === t);
|
|
280
|
+
this.accounts.splice(e, 1);
|
|
281
|
+
});
|
|
282
|
+
} catch (e) {
|
|
283
|
+
console.error(`Error occurred while removing an account: ${e}`);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
updateAccount = async (t) => {
|
|
287
|
+
try {
|
|
288
|
+
const e = await this.api.updateAccount(t);
|
|
289
|
+
a(() => {
|
|
290
|
+
const c = this.accounts.findIndex(
|
|
291
|
+
(r) => r.guid === e.guid
|
|
292
|
+
);
|
|
293
|
+
this.accounts.splice(c, 1, e), this.accounts = this.augmentAccounts(this.accounts);
|
|
294
|
+
});
|
|
295
|
+
} catch (e) {
|
|
296
|
+
console.error(`Error occurred while updating account: ${e}`);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
updateAccountFiltering = async (t, e) => {
|
|
300
|
+
for (const c of t) {
|
|
301
|
+
const r = this.accounts.find((o) => o.guid === c);
|
|
302
|
+
if (r) {
|
|
303
|
+
r.is_excluded_from_accounts = e, r.is_excluded_from_budgets = e, r.is_excluded_from_cash_flow = e, r.is_excluded_from_debts = e, r.is_excluded_from_goals = e, r.is_excluded_from_investments = e, r.is_excluded_from_net_worth = e, r.is_excluded_from_spending = e, r.is_excluded_from_transactions = e, r.is_excluded_from_trends = e;
|
|
304
|
+
try {
|
|
305
|
+
this.updateAccount(r);
|
|
306
|
+
} catch (o) {
|
|
307
|
+
console.error(`Failed to update account ${c} (added):`, o);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
export {
|
|
314
|
+
p as A,
|
|
315
|
+
te as a
|
|
316
|
+
};
|
|
317
|
+
//# sourceMappingURL=AccountStore-DkL93tXL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountStore-DkL93tXL.mjs","sources":["../src/accounts/api/AccountApi.ts","../src/accounts/stores/UiStore.ts","../src/accounts/stores/AccountStore.ts"],"sourcesContent":["import Fetch from '../../common/utils/Fetch'\n\nimport { ApiEndpoints } from '../../common/constants'\nimport type { Account } from '../../common'\n\nexport class AccountApi {\n fetchInstance: Fetch\n\n constructor(endpoint: string, token: string) {\n this.fetchInstance = new Fetch(endpoint, token)\n }\n\n createAccount = async (account: Account) => {\n return this.fetchInstance\n .post(ApiEndpoints.ACCOUNTS, account)\n .then((data) => data.account)\n .catch((error) => error)\n }\n\n deleteAccount = async (accountGuid: string) => {\n return this.fetchInstance\n .delete(`${ApiEndpoints.ACCOUNTS}/${accountGuid}`)\n .catch((error) => error)\n }\n\n getAccounts = async () => {\n return this.fetchInstance\n .get(ApiEndpoints.ACCOUNTS)\n .then((data) => data.accounts)\n .catch((error) => error)\n }\n\n getInstitutions = async () => {\n return this.fetchInstance\n .get(ApiEndpoints.INSTITUTIONS)\n .then((data) => data)\n .catch((error) => error)\n }\n\n getMembers = async () => {\n return this.fetchInstance\n .get(ApiEndpoints.MEMBERS)\n .then((data) => data.members)\n .catch((error) => error)\n }\n\n getMonthlyAccountBalances = async (guid: string) => {\n return this.fetchInstance\n .get(`${ApiEndpoints.ACCOUNTS}/${guid}/monthly_account_balances`)\n .then((data) => data.monthly_account_balances)\n .catch((error) => error)\n }\n\n mergeAccounts = async (accountGuids: string[]) => {\n return this.fetchInstance\n .put(`${ApiEndpoints.ACCOUNTS}/merge`, { accounts: accountGuids })\n .then((data) => data)\n .catch((error) => error)\n }\n\n refreshAllMembers = async () => {\n return this.fetchInstance\n .get(`${ApiEndpoints.MEMBERS}/refresh_all`)\n .then((data) => data)\n .catch((error) => error)\n }\n\n updateAccount = async (account: Account) => {\n return this.fetchInstance\n .put(`${ApiEndpoints.ACCOUNTS}/${account.guid}`, account)\n .then((data) => data.account)\n .catch((error) => error)\n }\n}\n","import { makeAutoObservable } from 'mobx'\nimport { Account, Member } from '../../common'\n\nexport class UiStore {\n isLoading = false\n\n selectedAccount: Account = {} as Account\n selectedMember: Member = {} as Member\n\n constructor() {\n makeAutoObservable(this)\n }\n\n setIsLoading = (isLoading: boolean) => (this.isLoading = isLoading)\n\n setSelectedAccount = (account: Account) => (this.selectedAccount = account)\n setSelectedMember = (member: Member) => (this.selectedMember = member)\n}\n","import { makeAutoObservable, runInAction } from 'mobx'\n\nimport {\n AccountType,\n ErrorStatuses,\n MfaStatuses,\n ConnectionStatus,\n ProcessingStatuses,\n} from '../../common'\n\nimport type { Account, GlobalStore, Institution, Member } from '../../common'\n\nimport { AccountApi } from '../api/AccountApi'\nimport { UiStore } from './UiStore'\n\nexport class AccountStore {\n globalStore: GlobalStore\n api: AccountApi = new AccountApi('/', '')\n\n accounts: Account[] = []\n institutions: Institution[] = []\n members: Member[] = []\n uiStore: UiStore\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.uiStore = new UiStore()\n this.api = new AccountApi(globalStore.endpoint, globalStore.sessionToken)\n\n makeAutoObservable(this)\n }\n\n loadAccountData = async ({\n accounts,\n institutions,\n }: {\n accounts?: Account[]\n institutions?: Institution[]\n } = {}) => {\n await Promise.all([this.loadAccounts(accounts), this.loadInstitutions(institutions)])\n }\n\n get cashAccounts(): Account[] {\n return this.accounts.filter(\n (account: Account) =>\n account.account_type === AccountType.CASH ||\n account.account_type === AccountType.CHECKING ||\n account.account_type === AccountType.PREPAID ||\n account.account_type === AccountType.SAVINGS ||\n account.account_type === AccountType.CHECKING_LINE_OF_CREDIT,\n )\n }\n\n get cashBalance(): number {\n return this.cashAccounts.reduce((total, account) => total + (account?.balance || 0), 0)\n }\n\n get checkingAccounts(): Account[] {\n return this.accounts.filter((a: Account) => a.account_type === AccountType.CHECKING)\n }\n\n get debtAccounts(): Account[] {\n return this.accounts.filter(\n (account: Account) =>\n account.account_type === AccountType.CREDIT_CARD ||\n account.account_type === AccountType.LOAN ||\n account.account_type === AccountType.MORTGAGE ||\n account.account_type === AccountType.LINE_OF_CREDIT ||\n account.account_type === AccountType.CHECKING_LINE_OF_CREDIT,\n )\n }\n\n get finstrongAccounts(): Account[] {\n const eligibleTypes = new Set([\n AccountType.CHECKING,\n AccountType.SAVINGS,\n AccountType.CREDIT_CARD,\n AccountType.INVESTMENT,\n ])\n\n return this.accounts.filter((account) => eligibleTypes.has(account.account_type))\n }\n\n get investmentAccounts(): Account[] {\n return this.accounts.filter(\n (account: Account) => account.account_type === AccountType.INVESTMENT,\n )\n }\n\n get savingsAccounts(): Account[] {\n return this.accounts.filter((a: Account) => a.account_type === AccountType.SAVINGS)\n }\n\n get visibleAccounts(): Account[] {\n return this.accounts.filter((a: Account) => !a.is_hidden)\n }\n\n get visibleCashAccounts(): Account[] {\n return this.cashAccounts.filter((account: Account) => !account.is_hidden)\n }\n\n get visibleCashBalance(): number {\n return this.visibleCashAccounts.reduce((total, account) => total + (account?.balance || 0), 0)\n }\n\n get visibleCheckingAccounts(): Account[] {\n return this.checkingAccounts.filter((account: Account) => !account.is_hidden)\n }\n\n get visibleDebtAccounts(): Account[] {\n return this.debtAccounts.filter((account: Account) => !account.is_hidden)\n }\n\n get visibleFinstrongAccounts(): Account[] {\n return this.finstrongAccounts.filter(\n (account: Account) => !(account.is_closed || account.is_deleted || account.is_hidden),\n )\n }\n\n get visibleInvestmentAccounts(): Account[] {\n return this.investmentAccounts.filter((account: Account) => !account.is_hidden)\n }\n\n get visibleSavingsAccounts(): Account[] {\n return this.savingsAccounts.filter((account: Account) => !account.is_hidden)\n }\n\n addAccount = async (account: Account) => {\n try {\n const newAccount = await this.api.createAccount(account)\n\n runInAction(() => {\n this.accounts = [...this.accounts, newAccount]\n })\n } catch (error) {\n console.error(`Error occurred while adding an account: ${error}`)\n }\n }\n\n augmentAccounts = (accounts: Account[] = this.accounts) => {\n const augmentedAccounts: Account[] = []\n\n accounts.forEach((account: Account) => {\n const memberLocation = this.members.findIndex(\n (member: Member) => member.guid === account.member_guid,\n )\n if (memberLocation > -1) {\n let connectionStatus = ConnectionStatus.Connected\n const member = this.members[memberLocation]\n if (ErrorStatuses.includes(member.connection_status)) {\n connectionStatus = ConnectionStatus.Error\n } else if (ProcessingStatuses.includes(member.connection_status)) {\n connectionStatus = ConnectionStatus.Processing\n } else if (MfaStatuses.includes(member.connection_status)) {\n connectionStatus = ConnectionStatus.RequiresMfa\n }\n\n let institutionName = account.user_name || account.feed_name || ''\n if (account.account_number) {\n institutionName = `${institutionName} *${account.account_number}`\n }\n\n augmentedAccounts.push({\n ...account,\n institutionName,\n memberName: member.name,\n connectionStatus,\n })\n\n this.members[memberLocation].connectionStatus = connectionStatus\n }\n })\n\n return augmentedAccounts\n }\n\n loadAccounts = async (accountsOverride?: Account[]) => {\n await this.loadMembers()\n\n try {\n const accounts = accountsOverride || (await this.api.getAccounts())\n\n runInAction(() => {\n this.accounts = this.sortAccounts(this.augmentAccounts(accounts))\n })\n } catch (error) {\n console.error(`Error occurred while loading accounts: ${error}`)\n }\n }\n\n loadInstitutions = async (institutionsOverride?: Institution[]) => {\n try {\n const institutions = institutionsOverride || (await this.api.getInstitutions())\n\n runInAction(() => {\n this.institutions = institutions\n })\n } catch (error) {\n console.error(`Error occurred while loading institutions: ${error}`)\n }\n }\n\n loadMembers = async () => {\n try {\n const members = await this.api.getMembers()\n\n runInAction(() => {\n this.members = members\n })\n } catch (error) {\n console.error(`Error occurred while loading members: ${error}`)\n }\n }\n\n mergeAccounts = async (accountGuids: string[]) => {\n try {\n const response = await this.api.mergeAccounts(accountGuids)\n // the response from the api is a funky database key here, so this is essentially just getting the first item in the returned object\n // to prevent making multiple api calls here\n const mergedAccount = response[Object.keys(response)[0]]\n\n runInAction(() => {\n const account2Index = this.accounts.findIndex((account) => account.guid === accountGuids[1])\n this.accounts.splice(account2Index, 1)\n\n const account1Index = this.accounts.findIndex((account) => account.guid === accountGuids[0])\n this.accounts.splice(account1Index, 1, mergedAccount)\n })\n } catch (error) {\n console.error(`Error occurred while merging accounts: ${error}`)\n }\n }\n\n sortAccounts = (accounts: Account[] = this.accounts) => {\n return accounts.sort((a: Account, b: Account) => {\n // orders by account type descending (Checking -> Savings -> Credit card)\n if (a.account_type > b.account_type) return 1\n if (a.account_type < b.account_type) return -1\n // orders by name (Emergency Savings -> Health Savings -> Rainy Day Savings)\n if ((a.name || '') > (b.name || '')) return 1\n if ((a.name || '') < (b.name || '')) return -1\n return 0\n })\n }\n\n refreshAccounts = async () => {\n this.uiStore.setIsLoading(true)\n await Promise.all([this.loadAccounts(), this.loadInstitutions()])\n this.uiStore.setIsLoading(false)\n }\n\n refreshMembers = async () => {\n try {\n await this.api.refreshAllMembers()\n await this.loadMembers()\n } catch (error) {\n console.error(`Error occurredwhile refreshing members: ${error}`)\n }\n }\n\n removeAccount = async (accountGuid: string) => {\n try {\n await this.api.deleteAccount(accountGuid)\n\n runInAction(() => {\n const deletedIndex = this.accounts.findIndex((account) => account.guid === accountGuid)\n this.accounts.splice(deletedIndex, 1)\n })\n } catch (error) {\n console.error(`Error occurred while removing an account: ${error}`)\n }\n }\n\n updateAccount = async (account: Account) => {\n try {\n const updatedAccount = await this.api.updateAccount(account)\n\n runInAction(() => {\n const updatedAccountIndex = this.accounts.findIndex(\n (account) => account.guid === updatedAccount.guid,\n )\n\n this.accounts.splice(updatedAccountIndex, 1, updatedAccount)\n\n this.accounts = this.augmentAccounts(this.accounts)\n })\n } catch (error) {\n console.error(`Error occurred while updating account: ${error}`)\n }\n }\n\n updateAccountFiltering = async (guids: string[], isExcluded: boolean) => {\n for (const guid of guids) {\n const account = this.accounts.find((acc) => acc.guid === guid)\n\n if (account) {\n account.is_excluded_from_accounts = isExcluded\n account.is_excluded_from_budgets = isExcluded\n account.is_excluded_from_cash_flow = isExcluded\n account.is_excluded_from_debts = isExcluded\n account.is_excluded_from_goals = isExcluded\n account.is_excluded_from_investments = isExcluded\n account.is_excluded_from_net_worth = isExcluded\n account.is_excluded_from_spending = isExcluded\n account.is_excluded_from_transactions = isExcluded\n account.is_excluded_from_trends = isExcluded\n\n try {\n this.updateAccount(account)\n } catch (error) {\n console.error(`Failed to update account ${guid} (added):`, error)\n }\n }\n }\n }\n}\n"],"names":["AccountApi","endpoint","token","Fetch","account","ApiEndpoints","data","error","accountGuid","guid","accountGuids","UiStore","makeAutoObservable","isLoading","member","AccountStore","globalStore","accounts","institutions","AccountType","total","a","eligibleTypes","newAccount","runInAction","augmentedAccounts","memberLocation","connectionStatus","ConnectionStatus","ErrorStatuses","ProcessingStatuses","MfaStatuses","institutionName","accountsOverride","institutionsOverride","members","response","mergedAccount","account2Index","account1Index","b","deletedIndex","updatedAccount","updatedAccountIndex","guids","isExcluded","acc"],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import "bowser";
|
|
2
|
+
import "date-fns/getUnixTime";
|
|
3
|
+
import "date-fns/intlFormat";
|
|
4
|
+
import "react";
|
|
5
|
+
import "react/jsx-runtime";
|
|
6
|
+
import "@mui/material/Button";
|
|
7
|
+
import "@mxenabled/mxui";
|
|
8
|
+
import "@mui/material/Tooltip";
|
|
9
|
+
import "@mui/material/Box";
|
|
10
|
+
import "@mui/material/IconButton";
|
|
11
|
+
import { aK as g, aL as c, aM as d } from "./ConnectMiniWidget-CQWafYtQ.mjs";
|
|
12
|
+
import { u as _ } from "./Loader-CwdK8lfx.mjs";
|
|
13
|
+
import "@mui/material/styles/useTheme";
|
|
14
|
+
import "@mui/material/useMediaQuery";
|
|
15
|
+
import "@mxenabled/cssinjs";
|
|
16
|
+
import "date-fns/addDays";
|
|
17
|
+
import "date-fns/addMonths";
|
|
18
|
+
import "date-fns/eachDayOfInterval";
|
|
19
|
+
import "date-fns/eachWeekOfInterval";
|
|
20
|
+
import "date-fns/endOfMonth";
|
|
21
|
+
import "date-fns/format";
|
|
22
|
+
import "date-fns/isBefore";
|
|
23
|
+
import "date-fns/isSameMonth";
|
|
24
|
+
import "date-fns/startOfMonth";
|
|
25
|
+
import "date-fns/startOfToday";
|
|
26
|
+
import "date-fns/subMonths";
|
|
27
|
+
import "@mui/material/Paper";
|
|
28
|
+
import "@mxenabled/mx-icons";
|
|
29
|
+
import "date-fns/isSameDay";
|
|
30
|
+
import "date-fns/isWithinInterval";
|
|
31
|
+
import "d3";
|
|
32
|
+
import "@mui/material/styles";
|
|
33
|
+
import "@mui/x-charts";
|
|
34
|
+
import "@mui/material";
|
|
35
|
+
import "@mui/x-charts/ChartsTooltip";
|
|
36
|
+
import "@mui/material/Stack";
|
|
37
|
+
import "date-fns/addYears";
|
|
38
|
+
import "date-fns/differenceInCalendarDays";
|
|
39
|
+
import "date-fns/endOfToday";
|
|
40
|
+
import "date-fns/endOfYear";
|
|
41
|
+
import "date-fns/startOfYear";
|
|
42
|
+
import "date-fns/subDays";
|
|
43
|
+
import "date-fns/subYears";
|
|
44
|
+
import "@mui/material/ButtonGroup";
|
|
45
|
+
import "@mui/material/Tab";
|
|
46
|
+
import "@mui/material/Tabs";
|
|
47
|
+
import "@mui/material/ToggleButton";
|
|
48
|
+
import "@mui/material/ToggleButtonGroup";
|
|
49
|
+
import "@mui/material/Dialog";
|
|
50
|
+
import "@mui/material/DialogContent";
|
|
51
|
+
import "@mui/material/Card";
|
|
52
|
+
import "@mui/material/CardContent";
|
|
53
|
+
import "@mui/material/CardHeader";
|
|
54
|
+
import "uuid";
|
|
55
|
+
import "numeral";
|
|
56
|
+
import "@mui/material/CircularProgress";
|
|
57
|
+
import "@mui/material/FormControlLabel";
|
|
58
|
+
import "@mui/material/Radio";
|
|
59
|
+
import "@mui/material/Avatar";
|
|
60
|
+
import "@mui/material/ListItem";
|
|
61
|
+
import "@mui/material/ListItemAvatar";
|
|
62
|
+
import "@mui/material/ListItemButton";
|
|
63
|
+
import "@mui/material/ListItemText";
|
|
64
|
+
import "@mui/material/ListItemIcon";
|
|
65
|
+
import "@mui/material/MenuItem";
|
|
66
|
+
import "@mui/material/TextField";
|
|
67
|
+
import "@mui/material/Switch";
|
|
68
|
+
import "mobx";
|
|
69
|
+
import "posthog-js";
|
|
70
|
+
import "date-fns/differenceInDays";
|
|
71
|
+
import "@mui/x-data-grid-pro";
|
|
72
|
+
import "date-fns";
|
|
73
|
+
import "@mui/material/Divider";
|
|
74
|
+
import "@mui/material/List";
|
|
75
|
+
import "date-fns/fromUnixTime";
|
|
76
|
+
import "date-fns/formatISO";
|
|
77
|
+
import "date-fns/isAfter";
|
|
78
|
+
import "date-fns/addQuarters";
|
|
79
|
+
import "date-fns/nextDay";
|
|
80
|
+
import "date-fns/parseISO";
|
|
81
|
+
import "date-fns/setDate";
|
|
82
|
+
import "date-fns/subQuarters";
|
|
83
|
+
import "date-fns/lastDayOfMonth";
|
|
84
|
+
import "date-fns/setDayOfYear";
|
|
85
|
+
import "date-fns/addWeeks";
|
|
86
|
+
import "date-fns/getDay";
|
|
87
|
+
import "date-fns/addSeconds";
|
|
88
|
+
import "date-fns/differenceInCalendarMonths";
|
|
89
|
+
import "date-fns/getMonth";
|
|
90
|
+
const f = (o, r) => o.find((t) => t.guid === r), B = (o, r) => o.find((t) => t.guid === r), T = (o, r) => {
|
|
91
|
+
const t = o.find((i) => i.subCategories.find((n) => n.guid === r));
|
|
92
|
+
if (t)
|
|
93
|
+
return t.subCategories.find((i) => i.guid === r);
|
|
94
|
+
}, ir = (o, r) => {
|
|
95
|
+
const t = [];
|
|
96
|
+
for (const i of r) {
|
|
97
|
+
const n = f(o, i.category_guid);
|
|
98
|
+
if (!n) continue;
|
|
99
|
+
const e = n.parent_guid ?? n.guid, a = f(o, e);
|
|
100
|
+
if (!a) continue;
|
|
101
|
+
const p = {
|
|
102
|
+
amount: i.total,
|
|
103
|
+
category: n,
|
|
104
|
+
guid: n.guid,
|
|
105
|
+
subCategoryTotals: []
|
|
106
|
+
}, m = t.find((s) => s.guid === e);
|
|
107
|
+
m ? (m.amount += i.total, m.subCategoryTotals.push(p)) : t.push({
|
|
108
|
+
amount: i.total,
|
|
109
|
+
category: a,
|
|
110
|
+
guid: e,
|
|
111
|
+
subCategoryTotals: [p]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return t;
|
|
115
|
+
}, er = (o, r) => {
|
|
116
|
+
const t = o.find((i) => i.guid === r);
|
|
117
|
+
return t ? t.guid === g.INCOME || t.parent_guid === g.INCOME : !1;
|
|
118
|
+
}, l = (o, r) => !o && !r ? 0 : !o && r ? 101 : r / o * 100, y = (o, r) => {
|
|
119
|
+
const t = {
|
|
120
|
+
background: r.palette.success.main,
|
|
121
|
+
description: o <= 100 ? r.palette.text.secondary : r.palette.error.main,
|
|
122
|
+
text: r.palette.common.white,
|
|
123
|
+
mercury: r.palette.success.lighter
|
|
124
|
+
};
|
|
125
|
+
return o > 100 ? (t.background = r.palette.error.main, t.mercury = r.palette.error.lighter) : o > 80 && (t.background = r.palette.warning.main, t.text = r.palette.grey[900], t.mercury = r.palette.warning.lighter), t;
|
|
126
|
+
}, nr = () => {
|
|
127
|
+
const { detailedBudgets: o } = _();
|
|
128
|
+
return o.map((t) => {
|
|
129
|
+
const i = t.transaction_total;
|
|
130
|
+
return t.amount - i;
|
|
131
|
+
}).reduce((t, i) => t + i, 0);
|
|
132
|
+
}, ar = (o, r, t, i) => {
|
|
133
|
+
const n = [];
|
|
134
|
+
for (const e of o) {
|
|
135
|
+
const a = B(r, e.category_guid);
|
|
136
|
+
if (!a) continue;
|
|
137
|
+
const p = a.totalAmount, m = l(e.amount, p), s = e.amount - p;
|
|
138
|
+
n.push({
|
|
139
|
+
...e,
|
|
140
|
+
budgetColors: y(m, i),
|
|
141
|
+
category: a,
|
|
142
|
+
description: c(
|
|
143
|
+
s < 0 ? t.budget_remaining_over : t.budget_remaining_left,
|
|
144
|
+
d(Math.abs(s), "0,0")
|
|
145
|
+
),
|
|
146
|
+
percentage: m,
|
|
147
|
+
subBudgets: [],
|
|
148
|
+
transaction_total: p
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
for (const e of o) {
|
|
152
|
+
const a = T(r, e.category_guid);
|
|
153
|
+
if (!a) continue;
|
|
154
|
+
const p = a.currentAmount, m = n.find((C) => C.category_guid === a.parent_guid);
|
|
155
|
+
if (!m) continue;
|
|
156
|
+
const s = e.amount - p, u = l(e.amount, p);
|
|
157
|
+
m && m.subBudgets.push({
|
|
158
|
+
...e,
|
|
159
|
+
budgetColors: y(u, i),
|
|
160
|
+
category: a,
|
|
161
|
+
description: c(
|
|
162
|
+
s < 0 ? t.budget_remaining_over : t.budget_remaining_left,
|
|
163
|
+
d(Math.abs(s), "0,0")
|
|
164
|
+
),
|
|
165
|
+
percentage: u,
|
|
166
|
+
subBudgets: [],
|
|
167
|
+
transaction_total: p
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return n;
|
|
171
|
+
}, b = (o, r) => o.find((t) => t.guid === r), pr = (o, r, t) => {
|
|
172
|
+
const i = b(o, t);
|
|
173
|
+
if (i)
|
|
174
|
+
return b(i.subBudgets, r);
|
|
175
|
+
};
|
|
176
|
+
export {
|
|
177
|
+
pr as a,
|
|
178
|
+
ar as b,
|
|
179
|
+
B as c,
|
|
180
|
+
T as d,
|
|
181
|
+
ir as e,
|
|
182
|
+
b as f,
|
|
183
|
+
f as g,
|
|
184
|
+
er as i,
|
|
185
|
+
nr as u
|
|
186
|
+
};
|
|
187
|
+
//# sourceMappingURL=BudgetUtil-CVqAdv-j.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BudgetUtil-CVqAdv-j.mjs","sources":["../src/common/utils/Categories.ts","../src/budgets/utils/BudgetUtil.ts"],"sourcesContent":["import type { Category, CategoryTotal, DateRangeCategoryTotals, DetailedCategory } from '../types'\nimport { CategoryGuids } from '../constants'\n\nexport const getCategory = (\n categories: Category[],\n categoryGuid: string | undefined,\n): Category | undefined => {\n return categories.find((c) => c.guid === categoryGuid)\n}\n\nexport const getDetailedCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n return detailedCategories.find((dc) => dc.guid === guid)\n}\n\nexport const getDetailedSubCategory = (\n detailedCategories: DetailedCategory[],\n guid: string | undefined,\n): DetailedCategory | undefined => {\n const parent = detailedCategories.find((dc) => dc.subCategories.find((sc) => sc.guid === guid))\n if (!parent) return undefined\n\n return parent.subCategories.find((sc) => sc.guid === guid)\n}\n\nexport const getCategoryTotalsByParent = (\n categories: Category[],\n dateRangeTotals: DateRangeCategoryTotals[],\n): CategoryTotal[] => {\n const categoryTotals = [] as CategoryTotal[]\n\n // Iterate over the category data from BE and roll up all categories into parent categories\n // acc is the accumulated category totals of type CategoryTotal that is initialized as an empty []\n // curr is the current DateRangeCategoryTotal\n\n for (const dateRangeTotal of dateRangeTotals) {\n const category = getCategory(categories, dateRangeTotal.category_guid)\n if (!category) continue\n\n const parentGuid = category.parent_guid ?? category.guid\n const parentCategory = getCategory(categories, parentGuid)\n if (!parentCategory) continue\n\n const categoryTotal = {\n amount: dateRangeTotal.total,\n category,\n guid: category.guid,\n subCategoryTotals: [],\n }\n\n const parentCategoryTotal = categoryTotals.find((ct) => ct.guid === parentGuid)\n if (parentCategoryTotal) {\n parentCategoryTotal.amount += dateRangeTotal.total\n parentCategoryTotal.subCategoryTotals.push(categoryTotal)\n } else {\n categoryTotals.push({\n amount: dateRangeTotal.total,\n category: parentCategory,\n guid: parentGuid,\n subCategoryTotals: [categoryTotal],\n })\n }\n }\n\n return categoryTotals\n}\n\nexport const isIncome = (categories: Category[], guid: string) => {\n const category = categories.find((c) => c.guid === guid)\n if (!category) return false\n\n return category.guid === CategoryGuids.INCOME || category.parent_guid === CategoryGuids.INCOME\n}\n","import type { Theme } from '@mui/system'\n\nimport {\n type Budget,\n type BudgetColors,\n type BudgetsCopy,\n type DetailedCategory,\n type DetailedBudget,\n buildDynamicCopy,\n formatCurrency,\n getDetailedCategory,\n getDetailedSubCategory,\n useBudgetsStore,\n} from '../../common'\n\nexport const getBudgetPercentage = (budgetAmount: number, totalAmount: number) => {\n // No budget amount and nothing spent results in zero percent and green bubble\n if (!budgetAmount && !totalAmount) {\n return 0\n }\n\n // No budget amount and money spent results in 101 percent and red bubble\n if (!budgetAmount && totalAmount) {\n return 101\n }\n\n // Budget amount and money spent results in calculating percentage for color\n return (totalAmount / budgetAmount) * 100\n}\n\nexport const getBudgetColors = (percentage: number, theme: Theme) => {\n const budgetColors: BudgetColors = {\n background: theme.palette.success.main,\n description: percentage <= 100 ? theme.palette.text.secondary : theme.palette.error.main,\n text: theme.palette.common.white,\n mercury: theme.palette.success.lighter,\n }\n\n if (percentage > 100) {\n budgetColors.background = theme.palette.error.main\n budgetColors.mercury = theme.palette.error.lighter\n } else if (percentage > 80) {\n budgetColors.background = theme.palette.warning.main\n budgetColors.text = theme.palette.grey['900']\n budgetColors.mercury = theme.palette.warning.lighter\n }\n\n return budgetColors\n}\n\nexport const useGetBudgetDifference = () => {\n const { detailedBudgets: budgets } = useBudgetsStore()\n\n const differences = budgets.map((budget) => {\n const currentAmount = budget.transaction_total\n const totalAmount = budget.amount\n return totalAmount - currentAmount\n })\n\n return differences.reduce((total, difference) => total + difference, 0)\n}\n\nexport const augmentBudgets = (\n budgets: Budget[],\n categories: DetailedCategory[],\n copy: BudgetsCopy,\n theme: Theme,\n): DetailedBudget[] => {\n const detailedBudgets = [] as DetailedBudget[]\n\n // Top-level Categories\n for (const budget of budgets) {\n const category = getDetailedCategory(categories, budget.category_guid)\n if (!category) continue\n\n const spent = category.totalAmount\n\n const percentage = getBudgetPercentage(budget.amount, spent)\n const difference = budget.amount - spent\n\n detailedBudgets.push({\n ...budget,\n budgetColors: getBudgetColors(percentage, theme),\n category,\n description: buildDynamicCopy(\n difference < 0 ? copy.budget_remaining_over : copy.budget_remaining_left,\n formatCurrency(Math.abs(difference), '0,0'),\n ) as string,\n percentage,\n subBudgets: [],\n transaction_total: spent,\n })\n }\n\n // Sub categories\n for (const budget of budgets) {\n const category = getDetailedSubCategory(categories, budget.category_guid)\n if (!category) continue\n\n const spent = category.currentAmount\n\n const parentBudget = detailedBudgets.find((b) => b.category_guid === category.parent_guid)\n if (!parentBudget) continue\n\n const difference = budget.amount - spent\n const percentage = getBudgetPercentage(budget.amount, spent)\n\n if (parentBudget) {\n parentBudget.subBudgets.push({\n ...budget,\n budgetColors: getBudgetColors(percentage, theme),\n category,\n description: buildDynamicCopy(\n difference < 0 ? copy.budget_remaining_over : copy.budget_remaining_left,\n formatCurrency(Math.abs(difference), '0,0'),\n ) as string,\n percentage,\n subBudgets: [],\n transaction_total: spent,\n })\n }\n }\n\n return detailedBudgets\n}\n\nexport const findBudget = (budgets: DetailedBudget[], guid: string): DetailedBudget | undefined => {\n return budgets.find((budget) => budget.guid === guid)\n}\n\nexport const findSubBudget = (\n budgets: DetailedBudget[],\n guid: string,\n parentGuid: string,\n): DetailedBudget | undefined => {\n const parent = findBudget(budgets, parentGuid)\n if (!parent) return undefined\n\n return findBudget(parent.subBudgets, guid)\n}\n"],"names":["getCategory","categories","categoryGuid","c","getDetailedCategory","detailedCategories","guid","dc","getDetailedSubCategory","parent","sc","getCategoryTotalsByParent","dateRangeTotals","categoryTotals","dateRangeTotal","category","parentGuid","parentCategory","categoryTotal","parentCategoryTotal","ct","isIncome","CategoryGuids","getBudgetPercentage","budgetAmount","totalAmount","getBudgetColors","percentage","theme","budgetColors","useGetBudgetDifference","budgets","useBudgetsStore","budget","currentAmount","total","difference","augmentBudgets","copy","detailedBudgets","spent","buildDynamicCopy","formatCurrency","parentBudget","b","findBudget","findSubBudget"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { makeAutoObservable as o } from "mobx";
|
|
2
|
+
import { addDays as r } from "date-fns/addDays";
|
|
3
|
+
import { differenceInDays as n } from "date-fns/differenceInDays";
|
|
4
|
+
import { endOfMonth as i } from "date-fns/endOfMonth";
|
|
5
|
+
import { isBefore as a } from "date-fns/isBefore";
|
|
6
|
+
import { startOfToday as t } from "date-fns/startOfToday";
|
|
7
|
+
class c {
|
|
8
|
+
// Cashflow is hard-coded to display 30 days starting from today
|
|
9
|
+
dateRange = { start: t(), end: r(t(), 30) };
|
|
10
|
+
isDirty = !1;
|
|
11
|
+
nextIncome = void 0;
|
|
12
|
+
upcomingExpenses = [];
|
|
13
|
+
selectedCashAccounts = [];
|
|
14
|
+
constructor() {
|
|
15
|
+
o(this);
|
|
16
|
+
}
|
|
17
|
+
// Returns the number of days until the next income activity or 0 if there is no income activity
|
|
18
|
+
get daysUntilNextIncome() {
|
|
19
|
+
return this.nextIncome ? Math.abs(n(t(), this.nextIncome.expectedDate)) : 0;
|
|
20
|
+
}
|
|
21
|
+
// Returns the expenses (Activities) until the next income activity or the end of the month
|
|
22
|
+
// if there is no income activity
|
|
23
|
+
get expensesTilNextIncome() {
|
|
24
|
+
return this.upcomingExpenses.filter(
|
|
25
|
+
(e) => a(e.expectedDate, this.nextIncome?.expectedDate || i(/* @__PURE__ */ new Date()))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
setNextIncome = (e) => {
|
|
29
|
+
this.nextIncome = e;
|
|
30
|
+
};
|
|
31
|
+
setUpcomingExpenses = (e) => {
|
|
32
|
+
this.upcomingExpenses = e;
|
|
33
|
+
};
|
|
34
|
+
setSelectedCashAccounts = (e) => this.selectedCashAccounts = e;
|
|
35
|
+
}
|
|
36
|
+
class f {
|
|
37
|
+
globalStore;
|
|
38
|
+
uiStore;
|
|
39
|
+
constructor(e) {
|
|
40
|
+
this.globalStore = e, this.uiStore = new c(), o(this);
|
|
41
|
+
}
|
|
42
|
+
completeOnboarding = async () => {
|
|
43
|
+
const e = {
|
|
44
|
+
...this.globalStore.userStore.userProfile,
|
|
45
|
+
has_completed_cash_flow_onboarding: !0
|
|
46
|
+
};
|
|
47
|
+
await this.globalStore.userStore.updateUserProfile(e);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
f as C
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=CashflowStore-gPEEBiXo.mjs.map
|