@mx-cartographer/experiences 9.6.7 → 9.6.9
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/common/components/Banner.es.js +66 -26
- package/dist/common/components/Banner.es.js.map +1 -1
- package/dist/common/components/ConnectDrawer.d.ts +2 -0
- package/dist/common/components/ConnectDrawer.es.js +15 -14
- package/dist/common/components/ConnectDrawer.es.js.map +1 -1
- package/dist/common/components/ConnectWidgetPanel.d.ts +2 -0
- package/dist/common/components/ConnectWidgetPanel.es.js +48 -39
- package/dist/common/components/ConnectWidgetPanel.es.js.map +1 -1
- package/dist/common/constants/Analytics.d.ts +6 -0
- package/dist/common/constants/Analytics.es.js +7 -1
- package/dist/common/constants/Analytics.es.js.map +1 -1
- package/dist/common/constants/Connect.d.ts +7 -0
- package/dist/common/constants/Connect.es.js +6 -4
- package/dist/common/constants/Connect.es.js.map +1 -1
- package/dist/common/constants/index.d.ts +2 -1
- package/dist/common/index.es.js +95 -93
- package/dist/core/api/BannerApi.d.ts +1 -0
- package/dist/core/api/BannerApi.es.js +4 -2
- package/dist/core/api/BannerApi.es.js.map +1 -1
- package/dist/core/stores/AppDataStore.d.ts +1 -0
- package/dist/core/stores/AppDataStore.es.js +9 -2
- package/dist/core/stores/AppDataStore.es.js.map +1 -1
- package/dist/core/types/AppData.d.ts +2 -0
- package/dist/core/types/localization/InsightsFeedCopy.d.ts +1 -1
- package/dist/insights-v2/actionBlocks/MakeTransferActionBlock/layout.es.js +6 -6
- package/dist/insights-v2/actionBlocks/MakeTransferActionBlock/layout.es.js.map +1 -1
- package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/layout.d.ts +2 -2
- package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/layout.es.js +15 -15
- package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/layout.es.js.map +1 -1
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.d.ts +1 -1
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js +1 -1
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js.map +1 -1
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.d.ts +1 -1
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.es.js +16 -16
- package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.es.js.map +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js +6 -7
- package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js.map +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/layout.d.ts +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/layout.es.js +14 -30
- package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/layout.es.js.map +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/layout.d.ts +8 -8
- package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/layout.es.js +14 -14
- package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/layout.es.js.map +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js.map +1 -1
- package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.d.ts +4 -3
- package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.es.js +2 -2
- package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.es.js.map +1 -1
- package/package.json +1 -1
package/dist/common/index.es.js
CHANGED
|
@@ -4,9 +4,9 @@ import a from "./components/charts/StatusBar.es.js";
|
|
|
4
4
|
import p from "./components/charts/Donut.es.js";
|
|
5
5
|
import u from "./hooks/useAccountDisplayName.es.js";
|
|
6
6
|
import { useCombineEvents as C, useCombinePageviews as S } from "./hooks/useCombineEvents.es.js";
|
|
7
|
-
import { GlobalDataContext as c, GlobalDataProvider as
|
|
8
|
-
import { WidgetContainerContext as
|
|
9
|
-
import { useAccountStore as I, useActionContext as N, useAppConfig as P, useBudgetsStore as y, useCashflowStore as A, useCategoryStore as
|
|
7
|
+
import { GlobalDataContext as c, GlobalDataProvider as T } from "./context/GlobalDataProvider.es.js";
|
|
8
|
+
import { WidgetContainerContext as d, WidgetContainerProvider as D } from "./context/WidgetContainerProvider.es.js";
|
|
9
|
+
import { useAccountStore as I, useActionContext as N, useAppConfig as P, useBudgetsStore as y, useCashflowStore as A, useCategoryStore as O, useDebtStore as b, useError as W, useEvent as G, useFinstrongStore as L, useGlobalCopyStore as R, useGlobalStore as U, useGlobalUiStore as v, useGoalStore as B, useHelpStore as h, useHoldingStore as w, useInsightsV2Store as x, useLoad as M, useMerchantStore as Y, useNetWorthStore as H, useNotificationStore as F, usePageView as z, useRecurringTransactionsStore as V, useSettingsStore as Z, useTransactionStore as K, useTrendsStore as k, useUserStore as q, useWidgetContainerProvider as j } from "./context/hooks.es.js";
|
|
10
10
|
import { useInsightsEnabled as Q } from "./hooks/useInsightsEnabled.es.js";
|
|
11
11
|
import { useScreenSize as $ } from "./hooks/useScreenSize.es.js";
|
|
12
12
|
import ro from "./hooks/usePrevious.es.js";
|
|
@@ -18,112 +18,114 @@ import co from "./components/dialog/Dialog.es.js";
|
|
|
18
18
|
import Eo from "./components/drawer/Drawer.es.js";
|
|
19
19
|
import _o from "./components/daterangeselector/DateRangeSelector.es.js";
|
|
20
20
|
import { ANALYTICS_EVENTS as No } from "./constants/Analytics.es.js";
|
|
21
|
-
import { CONNECTIONS_WIDGET_ID as yo, CONNECT_WIDGET_ID as Ao,
|
|
22
|
-
import { GlobalStore as
|
|
23
|
-
import { INCOME_ACCOUNT_TYPES as
|
|
24
|
-
import { RECURRENCE_COPY as
|
|
25
|
-
import { LOADING_STATUS as
|
|
26
|
-
import { DEFAULT_DONUT_SIZE as
|
|
27
|
-
import { Sizes as
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
import { GlobalAccountFilter as
|
|
35
|
-
import
|
|
36
|
-
import { WidgetContainer as
|
|
37
|
-
import
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
import
|
|
21
|
+
import { CONNECTIONS_WIDGET_ID as yo, CONNECT_WIDGET_ID as Ao, CONNECT_WIDGET_SOURCES as Oo, DEEP_LINK_TYPE as bo, MemberConnectionStatus as Wo } from "./constants/Connect.es.js";
|
|
22
|
+
import { GlobalStore as Lo } from "../core/stores/GlobalStore.es.js";
|
|
23
|
+
import { INCOME_ACCOUNT_TYPES as Uo, PAYMENT_ACCOUNT_TYPES as vo, SPENDING_ACCOUNT_TYPES as Bo } from "./constants/Account.es.js";
|
|
24
|
+
import { RECURRENCE_COPY as wo } from "./constants/ScheduledPayment.es.js";
|
|
25
|
+
import { LOADING_STATUS as Mo } from "./constants/SpendingPlan.es.js";
|
|
26
|
+
import { DEFAULT_DONUT_SIZE as Ho, DEFAULT_STROKE_WIDTH as Fo } from "./constants/Donut.es.js";
|
|
27
|
+
import { Sizes as Vo, TOUCH_TARGET as Zo } from "./constants/Sizes.es.js";
|
|
28
|
+
import ko from "./components/donuts/MultiSegmentDonut.es.js";
|
|
29
|
+
import jo from "./components/donuts/SingleSegmentDonut.es.js";
|
|
30
|
+
import Qo from "./components/ErrorBoundary.es.js";
|
|
31
|
+
import $o from "./components/Error.es.js";
|
|
32
|
+
import rr from "./components/MicroWidgetContainer.es.js";
|
|
33
|
+
import er from "./components/MiniWidgetContainer.es.js";
|
|
34
|
+
import { GlobalAccountFilter as mr } from "./components/GlobalAccountFilter.es.js";
|
|
35
|
+
import ar from "./components/Loader.es.js";
|
|
36
|
+
import { WidgetContainer as pr } from "./components/WidgetContainer.es.js";
|
|
37
|
+
import ur from "./components/ConnectWidgetPanel.es.js";
|
|
38
|
+
import Cr from "./components/ConnectDrawer.es.js";
|
|
39
|
+
import gr from "./components/CurrencyDialog.es.js";
|
|
40
|
+
import Tr from "./components/CurrencyInput.es.js";
|
|
41
41
|
import dr from "./components/ResponsiveButton.es.js";
|
|
42
|
-
import
|
|
43
|
-
import
|
|
44
|
-
import
|
|
45
|
-
import
|
|
46
|
-
import
|
|
47
|
-
import
|
|
48
|
-
import
|
|
49
|
-
import { ConnectCard as
|
|
50
|
-
import { CurrencyText as
|
|
51
|
-
import { EmptyState as
|
|
52
|
-
import { ListItemAction as
|
|
53
|
-
import { ListItemRow as
|
|
54
|
-
import { ListItemWrapper as
|
|
55
|
-
import { Select as
|
|
56
|
-
import { ToggleButtonListItem as
|
|
57
|
-
import { ToggleListItem as
|
|
58
|
-
import { analyticsSession as
|
|
59
|
-
import { getClientComponentOverrides as
|
|
42
|
+
import _r from "./components/SearchBox.es.js";
|
|
43
|
+
import Nr from "./components/SelectionBox.es.js";
|
|
44
|
+
import yr from "./components/TabContentContainer.es.js";
|
|
45
|
+
import Or from "./components/IconBacking.es.js";
|
|
46
|
+
import Wr from "./components/DataRow.es.js";
|
|
47
|
+
import Lr from "./components/ZeroState.es.js";
|
|
48
|
+
import Ur from "./components/InformationTooltip.es.js";
|
|
49
|
+
import { ConnectCard as Br } from "./components/ConnectCard.es.js";
|
|
50
|
+
import { CurrencyText as wr } from "./components/CurrencyText.es.js";
|
|
51
|
+
import { EmptyState as Mr } from "./components/EmptyState.es.js";
|
|
52
|
+
import { ListItemAction as Hr } from "./components/ListItemAction.es.js";
|
|
53
|
+
import { ListItemRow as zr } from "./components/ListItemRow.es.js";
|
|
54
|
+
import { ListItemWrapper as Zr } from "./components/ListItemWrapper.es.js";
|
|
55
|
+
import { Select as kr } from "./components/Select.es.js";
|
|
56
|
+
import { ToggleButtonListItem as jr } from "./components/listitems/ToggleButtonListItem.es.js";
|
|
57
|
+
import { ToggleListItem as Qr } from "./components/listitems/ToggleListItem.es.js";
|
|
58
|
+
import { analyticsSession as $r } from "./utils/Analytics.es.js";
|
|
59
|
+
import { getClientComponentOverrides as rt, getClientCustomizations as tt, getClientPaletteOptions as et, getClientTheme as it } from "./utils/Theme.es.js";
|
|
60
60
|
export {
|
|
61
61
|
No as ANALYTICS_EVENTS,
|
|
62
62
|
yo as CONNECTIONS_WIDGET_ID,
|
|
63
63
|
Ao as CONNECT_WIDGET_ID,
|
|
64
|
+
Oo as CONNECT_WIDGET_SOURCES,
|
|
64
65
|
i as Calendar,
|
|
65
66
|
m as CalendarSelectionTypes,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
Br as ConnectCard,
|
|
68
|
+
Cr as ConnectDrawer,
|
|
69
|
+
ur as ConnectWidgetPanel,
|
|
70
|
+
gr as CurrencyDialog,
|
|
71
|
+
Tr as CurrencyInput,
|
|
72
|
+
wr as CurrencyText,
|
|
73
|
+
bo as DEEP_LINK_TYPE,
|
|
74
|
+
Ho as DEFAULT_DONUT_SIZE,
|
|
75
|
+
Fo as DEFAULT_STROKE_WIDTH,
|
|
76
|
+
Wr as DataRow,
|
|
75
77
|
_o as DateRangeSelector,
|
|
76
78
|
co as Dialog,
|
|
77
79
|
p as Donut,
|
|
78
80
|
Eo as Drawer,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
Mr as EmptyState,
|
|
82
|
+
$o as Error,
|
|
83
|
+
Qo as ErrorBoundary,
|
|
84
|
+
mr as GlobalAccountFilter,
|
|
83
85
|
c as GlobalDataContext,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
T as GlobalDataProvider,
|
|
87
|
+
Lo as GlobalStore,
|
|
88
|
+
Uo as INCOME_ACCOUNT_TYPES,
|
|
89
|
+
Or as IconBacking,
|
|
90
|
+
Ur as InformationTooltip,
|
|
91
|
+
Mo as LOADING_STATUS,
|
|
92
|
+
Hr as ListItemAction,
|
|
93
|
+
zr as ListItemRow,
|
|
94
|
+
Zr as ListItemWrapper,
|
|
95
|
+
ar as Loader,
|
|
96
|
+
Wo as MemberConnectionStatus,
|
|
97
|
+
rr as MicroWidgetContainer,
|
|
98
|
+
er as MiniWidgetContainer,
|
|
99
|
+
ko as MultiSegmentDonut,
|
|
100
|
+
vo as PAYMENT_ACCOUNT_TYPES,
|
|
101
|
+
wo as RECURRENCE_COPY,
|
|
100
102
|
dr as ResponsiveButton,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
Bo as SPENDING_ACCOUNT_TYPES,
|
|
104
|
+
_r as SearchBox,
|
|
105
|
+
kr as Select,
|
|
106
|
+
Nr as SelectionBox,
|
|
107
|
+
jo as SingleSegmentDonut,
|
|
108
|
+
Vo as Sizes,
|
|
107
109
|
a as StatusBar,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
Zo as TOUCH_TARGET,
|
|
111
|
+
yr as TabContentContainer,
|
|
112
|
+
jr as ToggleButtonListItem,
|
|
113
|
+
Qr as ToggleListItem,
|
|
114
|
+
pr as WidgetContainer,
|
|
115
|
+
d as WidgetContainerContext,
|
|
114
116
|
D as WidgetContainerProvider,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
Lr as ZeroState,
|
|
118
|
+
$r as analyticsSession,
|
|
117
119
|
r as buildDynamicCopy,
|
|
118
120
|
t as buildPluralCopy,
|
|
119
121
|
eo as formatCurrency,
|
|
120
122
|
io as formatOrdinal,
|
|
121
123
|
mo as formatPercentage,
|
|
122
124
|
no as generateEqualIntervals,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
rt as getClientComponentOverrides,
|
|
126
|
+
tt as getClientCustomizations,
|
|
127
|
+
et as getClientPaletteOptions,
|
|
128
|
+
it as getClientTheme,
|
|
127
129
|
ao as getCurrencyCodes,
|
|
128
130
|
so as getPluralRules,
|
|
129
131
|
u as useAccountDisplayName,
|
|
@@ -132,10 +134,10 @@ export {
|
|
|
132
134
|
P as useAppConfig,
|
|
133
135
|
y as useBudgetsStore,
|
|
134
136
|
A as useCashflowStore,
|
|
135
|
-
|
|
137
|
+
O as useCategoryStore,
|
|
136
138
|
C as useCombineEvents,
|
|
137
139
|
S as useCombinePageviews,
|
|
138
|
-
|
|
140
|
+
b as useDebtStore,
|
|
139
141
|
W as useError,
|
|
140
142
|
G as useEvent,
|
|
141
143
|
L as useFinstrongStore,
|
|
@@ -157,9 +159,9 @@ export {
|
|
|
157
159
|
fo as useRepeatingTransactionEligibility,
|
|
158
160
|
$ as useScreenSize,
|
|
159
161
|
Z as useSettingsStore,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
K as useTransactionStore,
|
|
163
|
+
k as useTrendsStore,
|
|
164
|
+
q as useUserStore,
|
|
163
165
|
j as useWidgetContainerProvider,
|
|
164
166
|
lo as useWidgetHeaderStyles,
|
|
165
167
|
So as useWidgetLoadTimer
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ApiEndpoints as c } from "../constants/ApiEndpoints.es.js";
|
|
1
2
|
import { Fetch as r } from "../utils/Fetch.es.js";
|
|
2
|
-
var
|
|
3
|
+
var s = class {
|
|
3
4
|
fetchInstance;
|
|
4
5
|
constructor(n) {
|
|
5
6
|
this.fetchInstance = new r(n, "", {
|
|
@@ -15,9 +16,10 @@ var a = class {
|
|
|
15
16
|
return console.error("Error fetching banner:", t), null;
|
|
16
17
|
}
|
|
17
18
|
};
|
|
19
|
+
markClicked = async (n) => this.fetchInstance?.put(`/${c.OFFERS}/${encodeURIComponent(n)}/clicked`, {});
|
|
18
20
|
};
|
|
19
21
|
export {
|
|
20
|
-
|
|
22
|
+
s as BannerApi
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
//# sourceMappingURL=BannerApi.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BannerApi.es.js","names":[],"sources":["../../../src/core/api/BannerApi.ts"],"sourcesContent":["import { Fetch } from '../utils'\n\nexport class BannerApi {\n fetchInstance: Fetch | null\n\n constructor(bullseyeEndpoint: string) {\n // Override headers without MD-Session-Token to avoid CORS error in bullseye\n this.fetchInstance = new Fetch(bullseyeEndpoint, '', {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n })\n }\n\n getBanner = async (userGuid: string) => {\n try {\n const path = `/banner/${userGuid}/account_widget_banner`\n return this.fetchInstance?.get(path).then((data) => data.banner) ?? {}\n } catch (error) {\n console.error('Error fetching banner:', error)\n return null\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BannerApi.es.js","names":[],"sources":["../../../src/core/api/BannerApi.ts"],"sourcesContent":["import { Fetch } from '../utils'\nimport { ApiEndpoints } from '../constants'\n\nexport class BannerApi {\n fetchInstance: Fetch | null\n\n constructor(bullseyeEndpoint: string) {\n // Override headers without MD-Session-Token to avoid CORS error in bullseye\n this.fetchInstance = new Fetch(bullseyeEndpoint, '', {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n })\n }\n\n getBanner = async (userGuid: string) => {\n try {\n const path = `/banner/${userGuid}/account_widget_banner`\n return this.fetchInstance?.get(path).then((data) => data.banner) ?? {}\n } catch (error) {\n console.error('Error fetching banner:', error)\n return null\n }\n }\n\n // Records a banner click server-side. The deep-link path needs this because it\n // never hits `redirect_url`, which is what records the click for external\n // banners. Rejections propagate so AppDataStore can report them via its\n // captureException handler instead of being silently swallowed here.\n markClicked = async (guid: string) =>\n this.fetchInstance?.put(`/${ApiEndpoints.OFFERS}/${encodeURIComponent(guid)}/clicked`, {})\n}\n"],"mappings":";;AAGA,IAAa,IAAb,MAAuB;AAAA,EACrB;AAAA,EAEA,YAAY,GAA0B;AAEpC,SAAK,gBAAgB,IAAI,EAAM,GAAkB,IAAI;AAAA,MACnD,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,OAAO,MAAqB;AACtC,QAAI;AACF,YAAM,IAAO,WAAW,CAAA;AACxB,aAAO,KAAK,eAAe,IAAI,CAAI,EAAE,KAAA,CAAM,MAAS,EAAK,MAAM,KAAK,CAAC;AAAA,IACvE,SAAS,GAAO;AACd,qBAAQ,MAAM,0BAA0B,CAAK,GACtC;AAAA,IACT;AAAA,EACF;AAAA,EAMA,cAAc,OAAO,MACnB,KAAK,eAAe,IAAI,IAAI,EAAa,MAAA,IAAU,mBAAmB,CAAI,CAAA,YAAa,CAAC,CAAC;AAC7F"}
|
|
@@ -18,6 +18,7 @@ export declare class AppDataStore {
|
|
|
18
18
|
setAppData: (appData: AppData) => void;
|
|
19
19
|
loadAppData: () => Promise<void>;
|
|
20
20
|
loadBanner: () => Promise<void>;
|
|
21
|
+
markBannerClicked: (guid: string) => Promise<void>;
|
|
21
22
|
setUser: (user: User) => User;
|
|
22
23
|
setUserCommunicationProfile: (profile: UserCommunicationProfile) => UserCommunicationProfile;
|
|
23
24
|
setUserProfile: (userProfile: UserProfile) => UserProfile;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AppDataApi as a } from "../api/AppDataApi.es.js";
|
|
2
2
|
import { BannerApi as e } from "../api/BannerApi.es.js";
|
|
3
3
|
import { makeAutoObservable as i, runInAction as o } from "mobx";
|
|
4
|
-
var
|
|
4
|
+
var c = class {
|
|
5
5
|
globalStore;
|
|
6
6
|
api = new a("/", "");
|
|
7
7
|
bannerApi = new e("/");
|
|
@@ -50,12 +50,19 @@ var l = class {
|
|
|
50
50
|
console.error("Error loading banner:", t), this.globalStore.captureException(t, { store: "AppDataStore" });
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
|
+
markBannerClicked = async (t) => {
|
|
54
|
+
try {
|
|
55
|
+
await this.bannerApi.markClicked(t);
|
|
56
|
+
} catch (r) {
|
|
57
|
+
console.error("Error marking banner clicked:", r), this.globalStore.captureException(r, { store: "AppDataStore" });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
53
60
|
setUser = (t) => this.appData.user = t;
|
|
54
61
|
setUserCommunicationProfile = (t) => this.appData.user_communication_profile = t;
|
|
55
62
|
setUserProfile = (t) => this.appData.user_profile = t;
|
|
56
63
|
};
|
|
57
64
|
export {
|
|
58
|
-
|
|
65
|
+
c as AppDataStore
|
|
59
66
|
};
|
|
60
67
|
|
|
61
68
|
//# sourceMappingURL=AppDataStore.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppDataStore.es.js","names":[],"sources":["../../../src/core/stores/AppDataStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\n\nimport { AppDataApi, BannerApi } from '../api'\nimport type {\n AppConfig,\n AppData,\n Banner,\n User,\n UserCommunicationProfile,\n UserProfile,\n} from '../types'\n\nimport { GlobalStore } from './GlobalStore'\n\nexport class AppDataStore {\n globalStore: GlobalStore\n api: AppDataApi = new AppDataApi('/', '')\n bannerApi: BannerApi = new BannerApi('/')\n\n appData: AppData = {} as AppData\n isAppDataLoaded: boolean = false\n banner: Banner = {}\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new AppDataApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n get appConfig(): AppConfig {\n return this.globalStore.appConfig\n }\n\n get clientCommunicationProfile() {\n return this.appData.client_communication_profile\n }\n\n get clientInsightProfile() {\n return this.appData.client_insight_profile\n }\n\n get user() {\n return this.appData.user\n }\n\n get userCommunicationProfile() {\n return this.appData.user_communication_profile\n }\n\n get userProfile() {\n return this.appData.user_profile\n }\n\n setAppData = (appData: AppData) => {\n this.appData = appData\n this.bannerApi = new BannerApi(appData.address?.bullseye || '/')\n this.isAppDataLoaded = true\n }\n\n loadAppData = async () => {\n try {\n const appData = await this.api.getAppData()\n this.setAppData(appData)\n } catch (error) {\n console.error('Error loading app data:', error)\n this.globalStore.captureException(error, { store: 'AppDataStore' })\n }\n }\n\n loadBanner = async () => {\n try {\n const userGuid = this.user?.guid ?? null\n const banner = userGuid ? await this.bannerApi.getBanner(userGuid) : {}\n\n runInAction(() => {\n this.banner = banner\n })\n } catch (error) {\n console.error('Error loading banner:', error)\n this.globalStore.captureException(error, { store: 'AppDataStore' })\n }\n }\n\n setUser = (user: User) => (this.appData.user = user)\n\n setUserCommunicationProfile = (profile: UserCommunicationProfile) =>\n (this.appData.user_communication_profile = profile)\n\n setUserProfile = (userProfile: UserProfile) => (this.appData.user_profile = userProfile)\n}\n"],"mappings":";;;AAcA,IAAa,IAAb,MAA0B;AAAA,EACxB;AAAA,EACA,MAAkB,IAAI,EAAW,KAAK,EAAE;AAAA,EACxC,YAAuB,IAAI,EAAU,GAAG;AAAA,EAExC,UAAmB,CAAC;AAAA,EACpB,kBAA2B;AAAA,EAC3B,SAAiB,CAAC;AAAA,EAElB,YAAY,GAA0B;AACpC,SAAK,cAAc,GACnB,KAAK,MAAM,IAAI,EAAW,EAAY,UAAU,EAAY,cAAc,EAAY,OAAO,GAE7F,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,IAAI,YAAuB;AACzB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAI,6BAA6B;AAC/B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,uBAAuB;AACzB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,2BAA2B;AAC7B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,aAAA,CAAc,MAAqB;AACjC,SAAK,UAAU,GACf,KAAK,YAAY,IAAI,EAAU,EAAQ,SAAS,YAAY,GAAG,GAC/D,KAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,cAAc,YAAY;AACxB,QAAI;AACF,YAAM,IAAU,MAAM,KAAK,IAAI,WAAW;AAC1C,WAAK,WAAW,CAAO;AAAA,IACzB,SAAS,GAAO;AACd,cAAQ,MAAM,2BAA2B,CAAK,GAC9C,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,aAAa,YAAY;AACvB,QAAI;AACF,YAAM,IAAW,KAAK,MAAM,QAAQ,MAC9B,IAAS,IAAW,MAAM,KAAK,UAAU,UAAU,CAAQ,IAAI,CAAC;AAEtE,MAAA,EAAA,MAAkB;AAChB,aAAK,SAAS;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,GAAO;AACd,cAAQ,MAAM,yBAAyB,CAAK,GAC5C,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,UAAA,CAAW,MAAgB,KAAK,QAAQ,OAAO;AAAA,EAE/C,8BAAA,CAA+B,MAC5B,KAAK,QAAQ,6BAA6B;AAAA,EAE7C,iBAAA,CAAkB,MAA8B,KAAK,QAAQ,eAAe;AAC9E"}
|
|
1
|
+
{"version":3,"file":"AppDataStore.es.js","names":[],"sources":["../../../src/core/stores/AppDataStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\n\nimport { AppDataApi, BannerApi } from '../api'\nimport type {\n AppConfig,\n AppData,\n Banner,\n User,\n UserCommunicationProfile,\n UserProfile,\n} from '../types'\n\nimport { GlobalStore } from './GlobalStore'\n\nexport class AppDataStore {\n globalStore: GlobalStore\n api: AppDataApi = new AppDataApi('/', '')\n bannerApi: BannerApi = new BannerApi('/')\n\n appData: AppData = {} as AppData\n isAppDataLoaded: boolean = false\n banner: Banner = {}\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new AppDataApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n get appConfig(): AppConfig {\n return this.globalStore.appConfig\n }\n\n get clientCommunicationProfile() {\n return this.appData.client_communication_profile\n }\n\n get clientInsightProfile() {\n return this.appData.client_insight_profile\n }\n\n get user() {\n return this.appData.user\n }\n\n get userCommunicationProfile() {\n return this.appData.user_communication_profile\n }\n\n get userProfile() {\n return this.appData.user_profile\n }\n\n setAppData = (appData: AppData) => {\n this.appData = appData\n this.bannerApi = new BannerApi(appData.address?.bullseye || '/')\n this.isAppDataLoaded = true\n }\n\n loadAppData = async () => {\n try {\n const appData = await this.api.getAppData()\n this.setAppData(appData)\n } catch (error) {\n console.error('Error loading app data:', error)\n this.globalStore.captureException(error, { store: 'AppDataStore' })\n }\n }\n\n loadBanner = async () => {\n try {\n const userGuid = this.user?.guid ?? null\n const banner = userGuid ? await this.bannerApi.getBanner(userGuid) : {}\n\n runInAction(() => {\n this.banner = banner\n })\n } catch (error) {\n console.error('Error loading banner:', error)\n this.globalStore.captureException(error, { store: 'AppDataStore' })\n }\n }\n\n // Fire-and-forget click receipt for the deep-link banner path (see BannerApi).\n markBannerClicked = async (guid: string) => {\n try {\n await this.bannerApi.markClicked(guid)\n } catch (error) {\n console.error('Error marking banner clicked:', error)\n this.globalStore.captureException(error, { store: 'AppDataStore' })\n }\n }\n\n setUser = (user: User) => (this.appData.user = user)\n\n setUserCommunicationProfile = (profile: UserCommunicationProfile) =>\n (this.appData.user_communication_profile = profile)\n\n setUserProfile = (userProfile: UserProfile) => (this.appData.user_profile = userProfile)\n}\n"],"mappings":";;;AAcA,IAAa,IAAb,MAA0B;AAAA,EACxB;AAAA,EACA,MAAkB,IAAI,EAAW,KAAK,EAAE;AAAA,EACxC,YAAuB,IAAI,EAAU,GAAG;AAAA,EAExC,UAAmB,CAAC;AAAA,EACpB,kBAA2B;AAAA,EAC3B,SAAiB,CAAC;AAAA,EAElB,YAAY,GAA0B;AACpC,SAAK,cAAc,GACnB,KAAK,MAAM,IAAI,EAAW,EAAY,UAAU,EAAY,cAAc,EAAY,OAAO,GAE7F,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,IAAI,YAAuB;AACzB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAI,6BAA6B;AAC/B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,uBAAuB;AACzB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,2BAA2B;AAC7B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,aAAA,CAAc,MAAqB;AACjC,SAAK,UAAU,GACf,KAAK,YAAY,IAAI,EAAU,EAAQ,SAAS,YAAY,GAAG,GAC/D,KAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,cAAc,YAAY;AACxB,QAAI;AACF,YAAM,IAAU,MAAM,KAAK,IAAI,WAAW;AAC1C,WAAK,WAAW,CAAO;AAAA,IACzB,SAAS,GAAO;AACd,cAAQ,MAAM,2BAA2B,CAAK,GAC9C,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,aAAa,YAAY;AACvB,QAAI;AACF,YAAM,IAAW,KAAK,MAAM,QAAQ,MAC9B,IAAS,IAAW,MAAM,KAAK,UAAU,UAAU,CAAQ,IAAI,CAAC;AAEtE,MAAA,EAAA,MAAkB;AAChB,aAAK,SAAS;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,GAAO;AACd,cAAQ,MAAM,yBAAyB,CAAK,GAC5C,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAGA,oBAAoB,OAAO,MAAiB;AAC1C,QAAI;AACF,YAAM,KAAK,UAAU,YAAY,CAAI;AAAA,IACvC,SAAS,GAAO;AACd,cAAQ,MAAM,iCAAiC,CAAK,GACpD,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,UAAA,CAAW,MAAgB,KAAK,QAAQ,OAAO;AAAA,EAE/C,8BAAA,CAA+B,MAC5B,KAAK,QAAQ,6BAA6B;AAAA,EAE7C,iBAAA,CAAkB,MAA8B,KAAK,QAAQ,eAAe;AAC9E"}
|
|
@@ -27,8 +27,10 @@ export interface AppConfig {
|
|
|
27
27
|
userFeatures: UserFeature[];
|
|
28
28
|
}
|
|
29
29
|
export interface Banner {
|
|
30
|
+
guid?: string;
|
|
30
31
|
image_url?: string;
|
|
31
32
|
redirect_url?: string;
|
|
33
|
+
deep_link_type?: number | null;
|
|
32
34
|
}
|
|
33
35
|
interface TransactionConfig {
|
|
34
36
|
selected_account_guid?: string;
|
|
@@ -86,7 +86,7 @@ export interface DismissInsightCopy {
|
|
|
86
86
|
export interface TransactionHistoryBlock {
|
|
87
87
|
category_spend_drawer_title: string;
|
|
88
88
|
monthly_spend_comparison_drawer_title: string;
|
|
89
|
-
|
|
89
|
+
account_balance_drawer_title: string;
|
|
90
90
|
upcoming_bill_drawer_title: string;
|
|
91
91
|
monthly_spend_to_income_drawer_title: string;
|
|
92
92
|
monthly_debt_to_income_drawer_title: string;
|
|
@@ -2,15 +2,15 @@ var e = {
|
|
|
2
2
|
SAVE_ENOUGH_TO_LIVE_ON: "SaveEnoughToLiveOn",
|
|
3
3
|
SAVE_AN_EXTRA_100: "SaveAnExtra100"
|
|
4
4
|
}, t = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
},
|
|
5
|
+
save_enough: e.SAVE_ENOUGH_TO_LIVE_ON,
|
|
6
|
+
save_extra: e.SAVE_AN_EXTRA_100
|
|
7
|
+
}, E = (_) => t[_ ?? ""] ?? e.SAVE_AN_EXTRA_100, n = (_, a) => {
|
|
8
8
|
const r = a.insights_feed?.make_transfer;
|
|
9
|
-
return r ?
|
|
9
|
+
return r ? E(_) === e.SAVE_ENOUGH_TO_LIVE_ON ? r.save_enough_title : r.save_extra_title : "";
|
|
10
10
|
}, A = (_) => _ == null || _ === "" ? void 0 : Number(_);
|
|
11
11
|
export {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
n as getMakeTransferDrawerTitle,
|
|
13
|
+
E as resolveMakeTransferVariant,
|
|
14
14
|
A as toNumber,
|
|
15
15
|
e as variants
|
|
16
16
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/MakeTransferActionBlock/layout.ts"],"sourcesContent":["import type { GlobalCopy, MakeTransferCopy } from '../../../core'\nimport type { SaveExtraBlockData } from '../../../core/types/InsightsInstanceSlotData'\n\n/**\n * MakeTransfer drilldown variants. The block uses the VALUE (e.g. \"SaveAnExtra100\"),\n * which is also the key each variant registers under (see ./index).\n */\nexport const variants = {\n SAVE_ENOUGH_TO_LIVE_ON: 'SaveEnoughToLiveOn',\n SAVE_AN_EXTRA_100: 'SaveAnExtra100',\n} as const\n\nexport type MakeTransferVariant = (typeof variants)[keyof typeof variants]\n\n// The beat payload sends the variant as a snake_case key; map it to the value.\nconst VARIANT_BY_KEY: Record<string, MakeTransferVariant> = {\n
|
|
1
|
+
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/MakeTransferActionBlock/layout.ts"],"sourcesContent":["import type { GlobalCopy, MakeTransferCopy } from '../../../core'\nimport type { SaveExtraBlockData } from '../../../core/types/InsightsInstanceSlotData'\n\n/**\n * MakeTransfer drilldown variants. The block uses the VALUE (e.g. \"SaveAnExtra100\"),\n * which is also the key each variant registers under (see ./index).\n */\nexport const variants = {\n SAVE_ENOUGH_TO_LIVE_ON: 'SaveEnoughToLiveOn',\n SAVE_AN_EXTRA_100: 'SaveAnExtra100',\n} as const\n\nexport type MakeTransferVariant = (typeof variants)[keyof typeof variants]\n\n// The beat payload sends the variant as a snake_case key; map it to the value. The keys are\n// behavior-named (aligning with the `save_enough_title` / `save_extra_title` copy), not beat-named.\nconst VARIANT_BY_KEY: Record<string, MakeTransferVariant> = {\n save_enough: variants.SAVE_ENOUGH_TO_LIVE_ON,\n save_extra: variants.SAVE_AN_EXTRA_100,\n}\n\n/** Props shared by every MakeTransfer variant. Each variant reads the fields it\n * needs directly off `slotData` — no per-variant key indirection. */\nexport interface MakeTransferVariantProps {\n slotData?: SaveExtraBlockData\n copy: MakeTransferCopy\n}\n\n/** Maps the payload variant key to the block's variant VALUE (defaults to save-extra). */\nexport const resolveMakeTransferVariant = (variant?: string | null): MakeTransferVariant =>\n VARIANT_BY_KEY[variant ?? ''] ?? variants.SAVE_AN_EXTRA_100\n\n/** Variant-specific, localized drawer title from `insights_feed.make_transfer`. */\nexport const getMakeTransferDrawerTitle = (\n variant: string | null | undefined,\n copy: GlobalCopy,\n): string => {\n const makeTransfer = copy.insights_feed?.make_transfer\n if (!makeTransfer) return ''\n return resolveMakeTransferVariant(variant) === variants.SAVE_ENOUGH_TO_LIVE_ON\n ? makeTransfer.save_enough_title\n : makeTransfer.save_extra_title\n}\n\n/** Coerce a payload figure (number or numeric string) to a number, else undefined. */\nexport const toNumber = (value?: string | number): number | undefined =>\n value === undefined || value === null || value === '' ? undefined : Number(value)\n"],"mappings":"AAOA,IAAa,IAAW;AAAA,EACtB,wBAAwB;AAAA,EACxB,mBAAmB;AACrB,GAMM,IAAsD;AAAA,EAC1D,aAAa,EAAS;AAAA,EACtB,YAAY,EAAS;AACvB,GAUa,IAAA,CAA8B,MACzC,EAAe,KAAW,EAAA,KAAO,EAAS,mBAG/B,IAAA,CACX,GACA,MACW;AACX,QAAM,IAAe,EAAK,eAAe;AACzC,SAAK,IACE,EAA2B,CAAO,MAAM,EAAS,yBACpD,EAAa,oBACb,EAAa,mBAHS;AAI5B,GAGa,IAAA,CAAY,MACA,KAAU,QAAQ,MAAU,KAAK,SAAY,OAAO,CAAK"}
|
|
@@ -17,10 +17,10 @@ export interface DrillDownHeaderContext {
|
|
|
17
17
|
selectedDate?: string | Date;
|
|
18
18
|
}
|
|
19
19
|
export declare const DRILLDOWN_VARIANTS: {
|
|
20
|
-
readonly TRANSACTION: "
|
|
20
|
+
readonly TRANSACTION: "not_standard_amount";
|
|
21
21
|
readonly CATEGORY_SPEND: "category_spend";
|
|
22
22
|
readonly MONTHLY_SPEND: "monthly_spend_comparison";
|
|
23
|
-
readonly ACCOUNT_BALANCE: "
|
|
23
|
+
readonly ACCOUNT_BALANCE: "account_balance";
|
|
24
24
|
readonly UPCOMING_BILL: "upcoming_bill";
|
|
25
25
|
readonly SPEND_TO_INCOME: "monthly_spend_to_income";
|
|
26
26
|
readonly SAVINGS_TO_INCOME: "monthly_savings_to_income";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { buildDynamicCopy as
|
|
2
|
-
import { DATE_FORMATS_INTL as
|
|
3
|
-
import { getCategoryColor as
|
|
1
|
+
import { buildDynamicCopy as p } from "../../../core/utils/Localization.es.js";
|
|
2
|
+
import { DATE_FORMATS_INTL as u, formatDate as N } from "../../../core/constants/DateFormats.es.js";
|
|
3
|
+
import { getCategoryColor as y } from "../../../core/utils/CategoryUtil.es.js";
|
|
4
4
|
import { MerchantLogo as S } from "@mxenabled/mxui";
|
|
5
5
|
import { Icon as O } from "@mxenabled/mx-icons";
|
|
6
6
|
import { jsx as c } from "react/jsx-runtime";
|
|
7
7
|
import { endOfMonth as T, startOfMonth as f } from "date-fns";
|
|
8
8
|
var i = {
|
|
9
|
-
TRANSACTION: "
|
|
9
|
+
TRANSACTION: "not_standard_amount",
|
|
10
10
|
CATEGORY_SPEND: "category_spend",
|
|
11
11
|
MONTHLY_SPEND: "monthly_spend_comparison",
|
|
12
|
-
ACCOUNT_BALANCE: "
|
|
12
|
+
ACCOUNT_BALANCE: "account_balance",
|
|
13
13
|
UPCOMING_BILL: "upcoming_bill",
|
|
14
14
|
SPEND_TO_INCOME: "monthly_spend_to_income",
|
|
15
15
|
SAVINGS_TO_INCOME: "monthly_savings_to_income",
|
|
@@ -17,34 +17,34 @@ var i = {
|
|
|
17
17
|
COST_OF_LIVING: "cost_living_to_income",
|
|
18
18
|
NON_ESSENTIAL_CATEGORY: "non_essential_category_summary",
|
|
19
19
|
DEPOSIT_SUMMARY: "monthly_deposit_summary"
|
|
20
|
-
}, _ = (e, t) => t &&
|
|
20
|
+
}, _ = (e, t) => t && y(t, e) || e.palette.primary.main, l = (e) => ({
|
|
21
21
|
start: f(new Date(e ?? NaN)),
|
|
22
22
|
end: T(new Date(e ?? NaN))
|
|
23
23
|
}), d = (e) => e?.length ? { accounts: e } : {}, g = ({ beatTransactions: e, dataSeries: t, selectedIndex: o }) => {
|
|
24
|
-
const r = t[o], a = r?.guid,
|
|
24
|
+
const r = t[o], a = r?.guid, n = e.find((s) => s.guid === a)?.has_been_split;
|
|
25
25
|
return {
|
|
26
|
-
custom: (
|
|
26
|
+
custom: (s) => s.guid === a,
|
|
27
27
|
dateRange: l(r?.date),
|
|
28
|
-
showSplits: !
|
|
28
|
+
showSplits: !n
|
|
29
29
|
};
|
|
30
30
|
}, C = ({ dataSeries: e, selectedIndex: t, instanceSlotData: o }) => {
|
|
31
31
|
const r = e[t], a = o.category_guid ?? r?.guid;
|
|
32
32
|
return {
|
|
33
|
-
custom: (
|
|
33
|
+
custom: (n) => n.category_guid === a || n.top_level_category_guid === a,
|
|
34
34
|
dateRange: l(r?.date)
|
|
35
35
|
};
|
|
36
36
|
}, I = ({ dataSeries: e, selectedIndex: t, spendCategoryGuids: o, instanceSlotData: r }) => {
|
|
37
37
|
const a = e[t];
|
|
38
38
|
return {
|
|
39
|
-
custom: (
|
|
39
|
+
custom: (n) => !!n.top_level_category_guid && o.includes(n.top_level_category_guid),
|
|
40
40
|
dateRange: l(a?.date),
|
|
41
41
|
...d(r.account_guids)
|
|
42
42
|
};
|
|
43
43
|
}, h = ({ beat: e, dataSeries: t, selectedIndex: o, isLastTab: r, instanceSlotData: a }) => {
|
|
44
|
-
const
|
|
44
|
+
const n = t[o], { start: s, end: m } = l(n?.date);
|
|
45
45
|
return {
|
|
46
46
|
dateRange: {
|
|
47
|
-
start:
|
|
47
|
+
start: s,
|
|
48
48
|
end: r && e.created_at ? new Date(e.created_at) : m
|
|
49
49
|
},
|
|
50
50
|
...d(a.account_guids)
|
|
@@ -70,7 +70,7 @@ var i = {
|
|
|
70
70
|
};
|
|
71
71
|
},
|
|
72
72
|
tipSection: (e, t, o = "") => ({
|
|
73
|
-
message:
|
|
73
|
+
message: p(t.general.tip_section_message, /* @__PURE__ */ c("strong", { children: t.general.tip_section_title }), /* @__PURE__ */ c("strong", { children: o })),
|
|
74
74
|
onDismiss: () => e(!0)
|
|
75
75
|
})
|
|
76
76
|
},
|
|
@@ -82,7 +82,7 @@ var i = {
|
|
|
82
82
|
colors: (e, t) => [_(e, t)],
|
|
83
83
|
header: (e) => ({
|
|
84
84
|
heading: e.categoryName,
|
|
85
|
-
subHeadingText: e.selectedDate &&
|
|
85
|
+
subHeadingText: e.selectedDate && N(e.selectedDate, u.MONTH_LONG) || "",
|
|
86
86
|
icon: /* @__PURE__ */ c(O, {
|
|
87
87
|
name: "calendar_month",
|
|
88
88
|
size: 16
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionHistoryBlock/layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport type { Theme } from '@mui/material/styles'\nimport { endOfMonth, startOfMonth } from 'date-fns'\nimport { getCategoryColor } from '../../../core/utils/CategoryUtil'\nimport {\n type Beat,\n type InsightsFeedCopy,\n type Subtitle,\n type Transaction,\n buildDynamicCopy,\n} from '../../../core'\nimport type { TransactionFilter } from '../../../core/stores/TransactionStore'\nimport type { InsightsInstanceSlotData } from '../../../core/types/InsightsInstanceSlotData'\nimport { MerchantLogo } from '@mxenabled/mxui'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../core/constants'\nimport { Icon } from '@mxenabled/mx-icons'\nimport type { ChartDataSeriesItem } from '../../blocks/ChartBlocks/BarchartBlock/utils'\nimport type { TipSectionProps } from '../../../insights/components/shared/ChartDrawerTemplate/TipSection'\n\nexport interface DrillDownHeader {\n heading?: string\n subHeadingText?: string\n icon?: ReactNode\n}\n\nexport interface DrillDownHeaderContext {\n title?: string\n subHeader?: Subtitle\n categoryName: string\n selectedDate?: string | Date\n}\n\nexport const DRILLDOWN_VARIANTS = {\n TRANSACTION: 'bill_amount_not_standard',\n CATEGORY_SPEND: 'category_spend',\n MONTHLY_SPEND: 'monthly_spend_comparison',\n ACCOUNT_BALANCE: 'savings_account_balances_summary',\n UPCOMING_BILL: 'upcoming_bill',\n SPEND_TO_INCOME: 'monthly_spend_to_income',\n SAVINGS_TO_INCOME: 'monthly_savings_to_income',\n DEBT_TO_INCOME: 'monthly_debt_to_income',\n COST_OF_LIVING: 'cost_living_to_income',\n NON_ESSENTIAL_CATEGORY: 'non_essential_category_summary',\n DEPOSIT_SUMMARY: 'monthly_deposit_summary',\n} as const\n\nexport type DrillDownVariant = (typeof DRILLDOWN_VARIANTS)[keyof typeof DRILLDOWN_VARIANTS]\n\n/**\n * One row of the flattened data_series a filterStrategy indexes into: a single-bar monthly total or a\n * synthesized upcoming-bill bar. Fields are optional because the backend keys each row dynamically\n * from data_series.names and not every variant carries a guid/category. Double-bar comparison rows\n * will extend this in the next MR.\n */\n\n// Resolves the top-chart palette from the theme (and the beat's category, when relevant).\nexport type ColorKind = (theme: Theme, categoryGuid?: string) => string[]\n\n// Resolves the dynamic drawer header (heading/sub-heading/icon JSX) from the selection context.\nexport type HeaderKind = (ctx: DrillDownHeaderContext) => DrillDownHeader\n\n/**\n * Everything a filterStrategy needs to turn the currently-selected bar/sub-tab into a\n * TransactionFilter. Data-only so strategies stay pure and testable.\n */\nexport interface FilterContext {\n beat: Beat\n beatTransactions: Transaction[]\n dataSeries: ChartDataSeriesItem[]\n selectedIndex: number\n subIndex: number\n isLastTab: boolean\n instanceSlotData: InsightsInstanceSlotData\n spendCategoryGuids: string[]\n displayedDateRange: { start: Date; end: Date }\n}\n\n// Resolves the current selection into a TransactionFilter. Carried on each config row so behavior\n// lives next to the variant it belongs to (no separate strategy registry to chase).\nexport type FilterStrategy = (ctx: FilterContext) => TransactionFilter\n\nexport interface DrillDownVariantConfig {\n top: 'singleBar' | 'upcomingBill' | 'doubleBar' | 'tabsOnly'\n filterStrategy: FilterStrategy\n colors: ColorKind\n header?: HeaderKind\n tipSection?: (\n setCloseTipSection: (flag: boolean) => void,\n copy: InsightsFeedCopy,\n merchantName?: string,\n ) => TipSectionProps\n scope: 'store' | 'beat'\n filterMode: 'store' | 'local'\n}\nconst categoryColor = (theme: Theme, categoryGuid?: string): string =>\n (categoryGuid && getCategoryColor(categoryGuid, theme)) || theme.palette.primary.main\n\nconst monthRange = (date: string | number | Date | undefined) => ({\n start: startOfMonth(new Date(date ?? NaN)),\n end: endOfMonth(new Date(date ?? NaN)),\n})\n\n// Scopes a filter to the beat's accounts when the beat carries account_guids; otherwise leaves\n// accounts unset so the store default (all accounts) applies.\nconst accountScope = (accountGuids?: string[]): Pick<TransactionFilter, 'accounts'> =>\n accountGuids?.length ? { accounts: accountGuids } : {}\n\n// ── Single-bar filter strategies (this MR) ────────────────────────────────────────────────────\n\n// BillAmountNotStandard / UpcomingBill — the series carries a transaction (TRN) guid; match a single\n// transaction by guid within its month.\nconst transactionGuidStrategy: FilterStrategy = ({\n beatTransactions,\n dataSeries,\n selectedIndex,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n const seriesGuid = seriesItem?.guid\n const hasBeenSplit = beatTransactions.find((trn) => trn.guid === seriesGuid)?.has_been_split\n\n return {\n custom: (trn) => trn.guid === seriesGuid,\n dateRange: monthRange(seriesItem?.date),\n showSplits: !hasBeenSplit,\n }\n}\n\n// CategorySpendingV2 — match transactions in the beat's category (or whose top-level category is that\n// guid) within the month.\nconst categoryStrategy: FilterStrategy = ({ dataSeries, selectedIndex, instanceSlotData }) => {\n const seriesItem = dataSeries[selectedIndex]\n const categoryGuid = instanceSlotData.category_guid ?? seriesItem?.guid\n\n return {\n custom: (trn) =>\n trn.category_guid === categoryGuid || trn.top_level_category_guid === categoryGuid,\n dateRange: monthRange(seriesItem?.date),\n }\n}\n\n// MonthlySpendComparisonV2 — no per-bar guid; show all spending-category transactions\n// (income/transfers/investments excluded via spendCategoryGuids) within the month.\nconst spendCategoriesStrategy: FilterStrategy = ({\n dataSeries,\n selectedIndex,\n spendCategoryGuids,\n instanceSlotData,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n\n return {\n custom: (trn) =>\n !!trn.top_level_category_guid && spendCategoryGuids.includes(trn.top_level_category_guid),\n dateRange: monthRange(seriesItem?.date),\n ...accountScope(instanceSlotData.account_guids),\n }\n}\n\n// SavingsAccountBalancesSummary — balances, not categorized spend. Filter by month only; the most\n// recent month is capped at the beat's creation time to match the snapshot the balance was computed\n// from.\nconst accountDateStrategy: FilterStrategy = ({\n beat,\n dataSeries,\n selectedIndex,\n isLastTab,\n instanceSlotData,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n const { start, end } = monthRange(seriesItem?.date)\n\n return {\n dateRange: {\n start,\n end: isLastTab && beat.created_at ? new Date(beat.created_at) : end,\n },\n ...accountScope(instanceSlotData.account_guids),\n }\n}\n\n// ── Double-bar + tabsOnly strategies (NEXT MR) ───────────────────────────────────────────────────\n// TODO(next MR — double bar): comparisonAggregatedGuidsStrategy — month × sub-tab membership over the\n// comparison bars' precomputed subGuids. Needs comparisonBars in FilterContext.\n// TODO(next MR — tabsOnly): aggregatedGuids / depositSummary strategies for the donut-drawer beats.\n\nexport const layout: Partial<Record<DrillDownVariant, DrillDownVariantConfig>> = {\n [DRILLDOWN_VARIANTS.TRANSACTION]: {\n top: 'singleBar',\n scope: 'store',\n filterMode: 'store',\n filterStrategy: transactionGuidStrategy,\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n header: (ctx: DrillDownHeaderContext) => {\n const { title, subHeader } = ctx\n return {\n heading: title,\n subHeadingText: subHeader?.text || undefined,\n icon: (\n <MerchantLogo\n alt={subHeader?.text}\n categoryGuid={subHeader?.logo?.category_guid || ''}\n merchantGuid={subHeader?.logo?.merchant_guid || ''}\n size={16}\n />\n ),\n }\n },\n tipSection: (setCloseTipSection, copy, merchantName = '') => {\n return {\n message: buildDynamicCopy(\n copy.general.tip_section_message,\n <strong>{copy.general.tip_section_title}</strong>,\n <strong>{merchantName}</strong>,\n ),\n onDismiss: () => setCloseTipSection(true),\n } as TipSectionProps\n },\n },\n [DRILLDOWN_VARIANTS.CATEGORY_SPEND]: {\n top: 'singleBar',\n filterStrategy: categoryStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n header: (ctx: DrillDownHeaderContext) => {\n return {\n heading: ctx.categoryName,\n subHeadingText: ctx.selectedDate\n ? formatDate(ctx.selectedDate, DATE_FORMATS_INTL.MONTH_LONG) || ''\n : '',\n icon: <Icon name=\"calendar_month\" size={16} />,\n }\n },\n },\n [DRILLDOWN_VARIANTS.MONTHLY_SPEND]: {\n top: 'singleBar',\n filterStrategy: spendCategoriesStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme) => [theme.palette.chart.chart2 ?? theme.palette.primary.main],\n },\n [DRILLDOWN_VARIANTS.ACCOUNT_BALANCE]: {\n top: 'singleBar',\n filterStrategy: accountDateStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme) => [theme.palette.success.main],\n },\n [DRILLDOWN_VARIANTS.UPCOMING_BILL]: {\n top: 'upcomingBill',\n filterStrategy: transactionGuidStrategy,\n scope: 'beat',\n filterMode: 'local',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n },\n\n // ── NEXT MR: double-bar comparison beats (month tabs + spend/income sub-tabs) ────────────────\n // [DRILLDOWN_VARIANTS.SPEND_TO_INCOME]: comparison('spendVsIncome'),\n // [DRILLDOWN_VARIANTS.SAVINGS_TO_INCOME]: comparison('savingsVsIncome'),\n // [DRILLDOWN_VARIANTS.DEBT_TO_INCOME]: comparison('debtVsIncome'),\n // [DRILLDOWN_VARIANTS.COST_OF_LIVING]: comparison('costOfLiving'),\n //\n // ── NEXT MR: tabsOnly donut-drawer beats (no top chart) ───────────────────────────────────\n // [DRILLDOWN_VARIANTS.NON_ESSENTIAL_CATEGORY]: { top: 'tabsOnly', ... },\n // [DRILLDOWN_VARIANTS.DEPOSIT_SUMMARY]: { top: 'tabsOnly', ... },\n}\n\n// Fallback for a missing/typo'd backend variant: a single-bar, store-scoped drawer filtered by the\n// beat's transaction guid and colored by category, so the drawer still renders instead of crashing.\nexport const FALLBACK: DrillDownVariantConfig = {\n top: 'singleBar',\n filterStrategy: transactionGuidStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionHistoryBlock/layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport type { Theme } from '@mui/material/styles'\nimport { endOfMonth, startOfMonth } from 'date-fns'\nimport { getCategoryColor } from '../../../core/utils/CategoryUtil'\nimport {\n type Beat,\n type InsightsFeedCopy,\n type Subtitle,\n type Transaction,\n buildDynamicCopy,\n} from '../../../core'\nimport type { TransactionFilter } from '../../../core/stores/TransactionStore'\nimport type { InsightsInstanceSlotData } from '../../../core/types/InsightsInstanceSlotData'\nimport { MerchantLogo } from '@mxenabled/mxui'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../core/constants'\nimport { Icon } from '@mxenabled/mx-icons'\nimport type { ChartDataSeriesItem } from '../../blocks/ChartBlocks/BarchartBlock/utils'\nimport type { TipSectionProps } from '../../../insights/components/shared/ChartDrawerTemplate/TipSection'\n\nexport interface DrillDownHeader {\n heading?: string\n subHeadingText?: string\n icon?: ReactNode\n}\n\nexport interface DrillDownHeaderContext {\n title?: string\n subHeader?: Subtitle\n categoryName: string\n selectedDate?: string | Date\n}\n\nexport const DRILLDOWN_VARIANTS = {\n TRANSACTION: 'not_standard_amount',\n CATEGORY_SPEND: 'category_spend',\n MONTHLY_SPEND: 'monthly_spend_comparison',\n ACCOUNT_BALANCE: 'account_balance',\n UPCOMING_BILL: 'upcoming_bill',\n SPEND_TO_INCOME: 'monthly_spend_to_income',\n SAVINGS_TO_INCOME: 'monthly_savings_to_income',\n DEBT_TO_INCOME: 'monthly_debt_to_income',\n COST_OF_LIVING: 'cost_living_to_income',\n NON_ESSENTIAL_CATEGORY: 'non_essential_category_summary',\n DEPOSIT_SUMMARY: 'monthly_deposit_summary',\n} as const\n\nexport type DrillDownVariant = (typeof DRILLDOWN_VARIANTS)[keyof typeof DRILLDOWN_VARIANTS]\n\n/**\n * One row of the flattened data_series a filterStrategy indexes into: a single-bar monthly total or a\n * synthesized upcoming-bill bar. Fields are optional because the backend keys each row dynamically\n * from data_series.names and not every variant carries a guid/category. Double-bar comparison rows\n * will extend this in the next MR.\n */\n\n// Resolves the top-chart palette from the theme (and the beat's category, when relevant).\nexport type ColorKind = (theme: Theme, categoryGuid?: string) => string[]\n\n// Resolves the dynamic drawer header (heading/sub-heading/icon JSX) from the selection context.\nexport type HeaderKind = (ctx: DrillDownHeaderContext) => DrillDownHeader\n\n/**\n * Everything a filterStrategy needs to turn the currently-selected bar/sub-tab into a\n * TransactionFilter. Data-only so strategies stay pure and testable.\n */\nexport interface FilterContext {\n beat: Beat\n beatTransactions: Transaction[]\n dataSeries: ChartDataSeriesItem[]\n selectedIndex: number\n subIndex: number\n isLastTab: boolean\n instanceSlotData: InsightsInstanceSlotData\n spendCategoryGuids: string[]\n displayedDateRange: { start: Date; end: Date }\n}\n\n// Resolves the current selection into a TransactionFilter. Carried on each config row so behavior\n// lives next to the variant it belongs to (no separate strategy registry to chase).\nexport type FilterStrategy = (ctx: FilterContext) => TransactionFilter\n\nexport interface DrillDownVariantConfig {\n top: 'singleBar' | 'upcomingBill' | 'doubleBar' | 'tabsOnly'\n filterStrategy: FilterStrategy\n colors: ColorKind\n header?: HeaderKind\n tipSection?: (\n setCloseTipSection: (flag: boolean) => void,\n copy: InsightsFeedCopy,\n merchantName?: string,\n ) => TipSectionProps\n scope: 'store' | 'beat'\n filterMode: 'store' | 'local'\n}\nconst categoryColor = (theme: Theme, categoryGuid?: string): string =>\n (categoryGuid && getCategoryColor(categoryGuid, theme)) || theme.palette.primary.main\n\nconst monthRange = (date: string | number | Date | undefined) => ({\n start: startOfMonth(new Date(date ?? NaN)),\n end: endOfMonth(new Date(date ?? NaN)),\n})\n\n// Scopes a filter to the beat's accounts when the beat carries account_guids; otherwise leaves\n// accounts unset so the store default (all accounts) applies.\nconst accountScope = (accountGuids?: string[]): Pick<TransactionFilter, 'accounts'> =>\n accountGuids?.length ? { accounts: accountGuids } : {}\n\n// ── Single-bar filter strategies (this MR) ────────────────────────────────────────────────────\n\n// BillAmountNotStandard / UpcomingBill — the series carries a transaction (TRN) guid; match a single\n// transaction by guid within its month.\nconst transactionGuidStrategy: FilterStrategy = ({\n beatTransactions,\n dataSeries,\n selectedIndex,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n const seriesGuid = seriesItem?.guid\n const hasBeenSplit = beatTransactions.find((trn) => trn.guid === seriesGuid)?.has_been_split\n\n return {\n custom: (trn) => trn.guid === seriesGuid,\n dateRange: monthRange(seriesItem?.date),\n showSplits: !hasBeenSplit,\n }\n}\n\n// CategorySpendingV2 — match transactions in the beat's category (or whose top-level category is that\n// guid) within the month.\nconst categoryStrategy: FilterStrategy = ({ dataSeries, selectedIndex, instanceSlotData }) => {\n const seriesItem = dataSeries[selectedIndex]\n const categoryGuid = instanceSlotData.category_guid ?? seriesItem?.guid\n\n return {\n custom: (trn) =>\n trn.category_guid === categoryGuid || trn.top_level_category_guid === categoryGuid,\n dateRange: monthRange(seriesItem?.date),\n }\n}\n\n// MonthlySpendComparisonV2 — no per-bar guid; show all spending-category transactions\n// (income/transfers/investments excluded via spendCategoryGuids) within the month.\nconst spendCategoriesStrategy: FilterStrategy = ({\n dataSeries,\n selectedIndex,\n spendCategoryGuids,\n instanceSlotData,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n\n return {\n custom: (trn) =>\n !!trn.top_level_category_guid && spendCategoryGuids.includes(trn.top_level_category_guid),\n dateRange: monthRange(seriesItem?.date),\n ...accountScope(instanceSlotData.account_guids),\n }\n}\n\n// SavingsAccountBalancesSummary — balances, not categorized spend. Filter by month only; the most\n// recent month is capped at the beat's creation time to match the snapshot the balance was computed\n// from.\nconst accountDateStrategy: FilterStrategy = ({\n beat,\n dataSeries,\n selectedIndex,\n isLastTab,\n instanceSlotData,\n}) => {\n const seriesItem = dataSeries[selectedIndex]\n const { start, end } = monthRange(seriesItem?.date)\n\n return {\n dateRange: {\n start,\n end: isLastTab && beat.created_at ? new Date(beat.created_at) : end,\n },\n ...accountScope(instanceSlotData.account_guids),\n }\n}\n\n// ── Double-bar + tabsOnly strategies (NEXT MR) ───────────────────────────────────────────────────\n// TODO(next MR — double bar): comparisonAggregatedGuidsStrategy — month × sub-tab membership over the\n// comparison bars' precomputed subGuids. Needs comparisonBars in FilterContext.\n// TODO(next MR — tabsOnly): aggregatedGuids / depositSummary strategies for the donut-drawer beats.\n\nexport const layout: Partial<Record<DrillDownVariant, DrillDownVariantConfig>> = {\n [DRILLDOWN_VARIANTS.TRANSACTION]: {\n top: 'singleBar',\n scope: 'store',\n filterMode: 'store',\n filterStrategy: transactionGuidStrategy,\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n header: (ctx: DrillDownHeaderContext) => {\n const { title, subHeader } = ctx\n return {\n heading: title,\n subHeadingText: subHeader?.text || undefined,\n icon: (\n <MerchantLogo\n alt={subHeader?.text}\n categoryGuid={subHeader?.logo?.category_guid || ''}\n merchantGuid={subHeader?.logo?.merchant_guid || ''}\n size={16}\n />\n ),\n }\n },\n tipSection: (setCloseTipSection, copy, merchantName = '') => {\n return {\n message: buildDynamicCopy(\n copy.general.tip_section_message,\n <strong>{copy.general.tip_section_title}</strong>,\n <strong>{merchantName}</strong>,\n ),\n onDismiss: () => setCloseTipSection(true),\n } as TipSectionProps\n },\n },\n [DRILLDOWN_VARIANTS.CATEGORY_SPEND]: {\n top: 'singleBar',\n filterStrategy: categoryStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n header: (ctx: DrillDownHeaderContext) => {\n return {\n heading: ctx.categoryName,\n subHeadingText: ctx.selectedDate\n ? formatDate(ctx.selectedDate, DATE_FORMATS_INTL.MONTH_LONG) || ''\n : '',\n icon: <Icon name=\"calendar_month\" size={16} />,\n }\n },\n },\n [DRILLDOWN_VARIANTS.MONTHLY_SPEND]: {\n top: 'singleBar',\n filterStrategy: spendCategoriesStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme) => [theme.palette.chart.chart2 ?? theme.palette.primary.main],\n },\n [DRILLDOWN_VARIANTS.ACCOUNT_BALANCE]: {\n top: 'singleBar',\n filterStrategy: accountDateStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme) => [theme.palette.success.main],\n },\n [DRILLDOWN_VARIANTS.UPCOMING_BILL]: {\n top: 'upcomingBill',\n filterStrategy: transactionGuidStrategy,\n scope: 'beat',\n filterMode: 'local',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n },\n\n // ── NEXT MR: double-bar comparison beats (month tabs + spend/income sub-tabs) ────────────────\n // [DRILLDOWN_VARIANTS.SPEND_TO_INCOME]: comparison('spendVsIncome'),\n // [DRILLDOWN_VARIANTS.SAVINGS_TO_INCOME]: comparison('savingsVsIncome'),\n // [DRILLDOWN_VARIANTS.DEBT_TO_INCOME]: comparison('debtVsIncome'),\n // [DRILLDOWN_VARIANTS.COST_OF_LIVING]: comparison('costOfLiving'),\n //\n // ── NEXT MR: tabsOnly donut-drawer beats (no top chart) ───────────────────────────────────\n // [DRILLDOWN_VARIANTS.NON_ESSENTIAL_CATEGORY]: { top: 'tabsOnly', ... },\n // [DRILLDOWN_VARIANTS.DEPOSIT_SUMMARY]: { top: 'tabsOnly', ... },\n}\n\n// Fallback for a missing/typo'd backend variant: a single-bar, store-scoped drawer filtered by the\n// beat's transaction guid and colored by category, so the drawer still renders instead of crashing.\nexport const FALLBACK: DrillDownVariantConfig = {\n top: 'singleBar',\n filterStrategy: transactionGuidStrategy,\n scope: 'store',\n filterMode: 'store',\n colors: (theme: Theme, categoryGuid?: string) => [categoryColor(theme, categoryGuid)],\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nexport const getLayoutConfig = (theme: Theme) => {\n return {\n
|
|
1
|
+
{"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nexport const getLayoutConfig = (theme: Theme) => {\n return {\n account_balance: {\n color: theme.palette.success.main,\n },\n monthly_spend_comparison: {\n color: theme.palette.chart.chart2,\n },\n }\n}\n"],"mappings":"AACA,IAAa,IAAA,CAAmB,OACvB;AAAA,EACL,iBAAiB,EACf,OAAO,EAAM,QAAQ,QAAQ,KAC/B;AAAA,EACA,0BAA0B,EACxB,OAAO,EAAM,QAAQ,MAAM,OAC7B;AACF"}
|
|
@@ -4,7 +4,7 @@ import { DataSeries, InstanceSlot } from '../../../../core';
|
|
|
4
4
|
import { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData';
|
|
5
5
|
export declare const BAR_CHART_VARIANTS: {
|
|
6
6
|
CATEGORY_COLOR: string;
|
|
7
|
-
|
|
7
|
+
ACCOUNT_BALANCE: string;
|
|
8
8
|
MONTHLY_SPEND_COMPARISON: string;
|
|
9
9
|
};
|
|
10
10
|
export interface ChartDataSeriesItem {
|