@mx-cartographer/experiences 9.4.3 → 9.4.4
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 +5 -0
- package/dist/core/constants/Investments.d.ts +3 -0
- package/dist/core/constants/Investments.es.js +34 -11
- package/dist/core/constants/Investments.es.js.map +1 -1
- package/dist/core/stores/HoldingStore.d.ts +3 -0
- package/dist/core/stores/HoldingStore.es.js +39 -29
- package/dist/core/stores/HoldingStore.es.js.map +1 -1
- package/dist/core/utils/InvestmentUtil.d.ts +4 -0
- package/dist/core/utils/InvestmentUtil.es.js +71 -58
- package/dist/core/utils/InvestmentUtil.es.js.map +1 -1
- package/dist/investments/InvestmentsWidget.es.js +100 -66
- package/dist/investments/InvestmentsWidget.es.js.map +1 -1
- package/dist/investments/components/allocation/util/createInvestementsAllocationData.es.js +50 -59
- package/dist/investments/components/allocation/util/createInvestementsAllocationData.es.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## [9.4.4] - 08-26-2026
|
|
2
|
+
|
|
3
|
+
- **CHANGED** - Investments widget now disables (not hides) the Allocation and Analysis tabs, with an explanatory tooltip, when the selected accounts have no data to render; the active tab resets to Overview if it becomes disabled
|
|
4
|
+
- **FIXED** - The Analysis tab now stays disabled for partially-enriched holdings whose style weights fall outside the render band, so it no longer enables onto an all-zero grid
|
|
5
|
+
|
|
1
6
|
## [9.4.3] - 08-26-2026
|
|
2
7
|
|
|
3
8
|
- **ADDED** - Pass category_guid and main_class_guid when creating repeating transactions (MEW-4051)
|
|
@@ -2,6 +2,9 @@ export declare enum AnalysisType {
|
|
|
2
2
|
Stocks = "stocks",
|
|
3
3
|
Bonds = "bonds"
|
|
4
4
|
}
|
|
5
|
+
export declare const ALLOCATION_KEYS: readonly ["allocations_cash", "allocations_convertible", "allocations_foreign_bond", "allocations_foreign_stock", "allocations_other", "allocations_preferred", "allocations_us_bond", "allocations_us_stock", "allocations_unknown"];
|
|
6
|
+
export type AllocationKey = (typeof ALLOCATION_KEYS)[number];
|
|
7
|
+
export declare const STYLE_WEIGHT_KEYS: readonly ["large_core_weight", "large_growth_weight", "large_value_weight", "mid_core_weight", "mid_growth_weight", "mid_value_weight", "small_core_weight", "small_growth_weight", "small_value_weight", "unknown_weight"];
|
|
5
8
|
export declare const EquityClassificationTypes: {
|
|
6
9
|
UNKNOWN: number;
|
|
7
10
|
LARGE_VALUE: number;
|
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
var
|
|
2
|
-
return
|
|
3
|
-
})({}),
|
|
1
|
+
var E = /* @__PURE__ */ (function(_) {
|
|
2
|
+
return _.Stocks = "stocks", _.Bonds = "bonds", _;
|
|
3
|
+
})({}), o = [
|
|
4
|
+
"allocations_cash",
|
|
5
|
+
"allocations_convertible",
|
|
6
|
+
"allocations_foreign_bond",
|
|
7
|
+
"allocations_foreign_stock",
|
|
8
|
+
"allocations_other",
|
|
9
|
+
"allocations_preferred",
|
|
10
|
+
"allocations_us_bond",
|
|
11
|
+
"allocations_us_stock",
|
|
12
|
+
"allocations_unknown"
|
|
13
|
+
], a = [
|
|
14
|
+
"large_core_weight",
|
|
15
|
+
"large_growth_weight",
|
|
16
|
+
"large_value_weight",
|
|
17
|
+
"mid_core_weight",
|
|
18
|
+
"mid_growth_weight",
|
|
19
|
+
"mid_value_weight",
|
|
20
|
+
"small_core_weight",
|
|
21
|
+
"small_growth_weight",
|
|
22
|
+
"small_value_weight",
|
|
23
|
+
"unknown_weight"
|
|
24
|
+
], i = {
|
|
4
25
|
UNKNOWN: 0,
|
|
5
26
|
LARGE_VALUE: 1,
|
|
6
27
|
LARGE_CORE: 2,
|
|
@@ -11,7 +32,7 @@ var I = /* @__PURE__ */ (function(E) {
|
|
|
11
32
|
SMALL_VALUE: 7,
|
|
12
33
|
SMALL_CORE: 8,
|
|
13
34
|
SMALL_GROWTH: 9
|
|
14
|
-
},
|
|
35
|
+
}, I = {
|
|
15
36
|
0: "UNKNOWN",
|
|
16
37
|
1: "LARGE_VALUE",
|
|
17
38
|
2: "LARGE_CORE",
|
|
@@ -22,7 +43,7 @@ var I = /* @__PURE__ */ (function(E) {
|
|
|
22
43
|
7: "SMALL_VALUE",
|
|
23
44
|
8: "SMALL_CORE",
|
|
24
45
|
9: "SMALL_GROWTH"
|
|
25
|
-
},
|
|
46
|
+
}, L = {
|
|
26
47
|
UNKNOWN: 0,
|
|
27
48
|
HIGH_LIMITED: 1,
|
|
28
49
|
HIGH_MODERATE: 2,
|
|
@@ -33,7 +54,7 @@ var I = /* @__PURE__ */ (function(E) {
|
|
|
33
54
|
LOW_LIMITED: 7,
|
|
34
55
|
LOW_MODERATE: 8,
|
|
35
56
|
LOW_EXTENSIVE: 9
|
|
36
|
-
},
|
|
57
|
+
}, t = {
|
|
37
58
|
0: "UNKNOWN",
|
|
38
59
|
1: "HIGH_LIMITED",
|
|
39
60
|
2: "HIGH_MODERATE",
|
|
@@ -46,11 +67,13 @@ var I = /* @__PURE__ */ (function(E) {
|
|
|
46
67
|
9: "LOW_EXTENSIVE"
|
|
47
68
|
};
|
|
48
69
|
export {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
o as ALLOCATION_KEYS,
|
|
71
|
+
E as AnalysisType,
|
|
72
|
+
i as EquityClassificationTypes,
|
|
73
|
+
I as EquityClassificationValues,
|
|
74
|
+
L as FixedIncomeClassificationTypes,
|
|
75
|
+
t as FixedIncomeClassificationValues,
|
|
76
|
+
a as STYLE_WEIGHT_KEYS
|
|
54
77
|
};
|
|
55
78
|
|
|
56
79
|
//# sourceMappingURL=Investments.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Investments.es.js","names":[],"sources":["../../../src/core/constants/Investments.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Investments.es.js","names":[],"sources":["../../../src/core/constants/Investments.ts"],"sourcesContent":["import type { Holding } from '../types/Holding'\n\nexport enum AnalysisType {\n Stocks = 'stocks',\n Bonds = 'bonds',\n}\n\n// The nine Morningstar allocation weights on a holding. Order is significant:\n// it maps positionally to the `allocations_list` copy display names.\nexport const ALLOCATION_KEYS = [\n 'allocations_cash',\n 'allocations_convertible',\n 'allocations_foreign_bond',\n 'allocations_foreign_stock',\n 'allocations_other',\n 'allocations_preferred',\n 'allocations_us_bond',\n 'allocations_us_stock',\n 'allocations_unknown',\n] as const satisfies readonly (keyof Holding)[]\n\nexport type AllocationKey = (typeof ALLOCATION_KEYS)[number]\n\n// The ten style-box weights (equity + fixed-income share the same buckets).\nexport const STYLE_WEIGHT_KEYS = [\n 'large_core_weight',\n 'large_growth_weight',\n 'large_value_weight',\n 'mid_core_weight',\n 'mid_growth_weight',\n 'mid_value_weight',\n 'small_core_weight',\n 'small_growth_weight',\n 'small_value_weight',\n 'unknown_weight',\n] as const satisfies readonly (keyof Holding)[]\n\nexport const EquityClassificationTypes = {\n UNKNOWN: 0,\n LARGE_VALUE: 1,\n LARGE_CORE: 2,\n LARGE_GROWTH: 3,\n MID_VALUE: 4,\n MID_CORE: 5,\n MID_GROWTH: 6,\n SMALL_VALUE: 7,\n SMALL_CORE: 8,\n SMALL_GROWTH: 9,\n}\n\nexport const EquityClassificationValues = {\n 0: 'UNKNOWN',\n 1: 'LARGE_VALUE',\n 2: 'LARGE_CORE',\n 3: 'LARGE_GROWTH',\n 4: 'MID_VALUE',\n 5: 'MID_CORE',\n 6: 'MID_GROWTH',\n 7: 'SMALL_VALUE',\n 8: 'SMALL_CORE',\n 9: 'SMALL_GROWTH',\n}\n\nexport const FixedIncomeClassificationTypes = {\n UNKNOWN: 0,\n HIGH_LIMITED: 1,\n HIGH_MODERATE: 2,\n HIGH_EXTENSIVE: 3,\n MEDIUM_LIMITED: 4,\n MEDIUM_MODERATE: 5,\n MEDIUM_EXTENSIVE: 6,\n LOW_LIMITED: 7,\n LOW_MODERATE: 8,\n LOW_EXTENSIVE: 9,\n}\n\nexport const FixedIncomeClassificationValues = {\n 0: 'UNKNOWN',\n 1: 'HIGH_LIMITED',\n 2: 'HIGH_MODERATE',\n 3: 'HIGH_EXTENSIVE',\n 4: 'MEDIUM_LIMITED',\n 5: 'MEDIUM_MODERATE',\n 6: 'MEDIUM_EXTENSIVE',\n 7: 'LOW_LIMITED',\n 8: 'LOW_MODERATE',\n 9: 'LOW_EXTENSIVE',\n}\n"],"mappings":"AAEA,IAAY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,SAAA,UACA,EAAA,QAAA;AACF,GAAA,CAAA,CAAA,GAIa,IAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKa,IAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAA4B;AAAA,EACvC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAChB,GAEa,IAA6B;AAAA,EACxC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL,GAEa,IAAiC;AAAA,EAC5C,SAAS;AAAA,EACT,cAAc;AAAA,EACd,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,eAAe;AACjB,GAEa,IAAkC;AAAA,EAC7C,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL"}
|
|
@@ -15,6 +15,9 @@ export declare class HoldingStore {
|
|
|
15
15
|
[x: string]: number;
|
|
16
16
|
};
|
|
17
17
|
get visibleHoldings(): Holding[];
|
|
18
|
+
get hasAllocationData(): boolean;
|
|
19
|
+
get hasAnalysisData(): boolean;
|
|
20
|
+
get selectedInvestmentAccounts(): import('..').DetailedAccount[];
|
|
18
21
|
setHoldings: (holdings: Holding[]) => void;
|
|
19
22
|
setShowConnectionsWidget: (value: boolean) => void;
|
|
20
23
|
loadHoldings: () => Promise<void>;
|
|
@@ -1,60 +1,70 @@
|
|
|
1
|
-
import { HoldingApi as
|
|
1
|
+
import { HoldingApi as o } from "../api/HoldingApi.es.js";
|
|
2
2
|
import { AnalysisType as n } from "../constants/Investments.es.js";
|
|
3
|
-
import { analysisChartData as a, analysisDetailsData as r, mapDataToPercentageGrid as
|
|
4
|
-
import { makeAutoObservable as
|
|
5
|
-
var
|
|
3
|
+
import { analysisChartData as a, analysisDetailsData as l, holdingHasAllocationData as r, holdingHasStyleData as d, mapDataToPercentageGrid as h } from "../utils/InvestmentUtil.es.js";
|
|
4
|
+
import { makeAutoObservable as c, runInAction as g } from "mobx";
|
|
5
|
+
var m = class {
|
|
6
6
|
analysisType = n.Stocks;
|
|
7
|
-
api = new
|
|
7
|
+
api = new o("/", "");
|
|
8
8
|
holdings = [];
|
|
9
9
|
holdingsLoaded = !1;
|
|
10
10
|
globalStore;
|
|
11
11
|
showConnectionsWidget = !1;
|
|
12
|
-
constructor(
|
|
13
|
-
this.globalStore =
|
|
12
|
+
constructor(s) {
|
|
13
|
+
this.globalStore = s, this.api = new o(s.endpoint, s.sessionToken, s.onError), c(this);
|
|
14
14
|
}
|
|
15
15
|
get analysisChartData() {
|
|
16
|
-
return
|
|
16
|
+
return h(a(this.visibleHoldings), this.analysisType);
|
|
17
17
|
}
|
|
18
18
|
get analysisDetails() {
|
|
19
|
-
return
|
|
19
|
+
return l(this.visibleHoldings)[this.analysisType] || {};
|
|
20
20
|
}
|
|
21
21
|
get visibleHoldings() {
|
|
22
|
-
return this.holdings.filter((
|
|
22
|
+
return this.holdings.filter((s) => this.globalStore.globalUiStore.selectedAccountGuids.includes(s.account_guid));
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
this.
|
|
24
|
+
get hasAllocationData() {
|
|
25
|
+
return this.visibleHoldings.some(r) ? !0 : this.selectedInvestmentAccounts.some((s) => (s.cash_balance ?? 0) > 0);
|
|
26
|
+
}
|
|
27
|
+
get hasAnalysisData() {
|
|
28
|
+
return this.visibleHoldings.some(d);
|
|
29
|
+
}
|
|
30
|
+
get selectedInvestmentAccounts() {
|
|
31
|
+
const { selectedAccountGuids: s } = this.globalStore.globalUiStore;
|
|
32
|
+
return this.globalStore.accountStore.visibleInvestmentAccounts.filter((t) => s.includes(t.guid));
|
|
33
|
+
}
|
|
34
|
+
setHoldings = (s) => {
|
|
35
|
+
this.holdings = s, this.holdingsLoaded = !0;
|
|
26
36
|
};
|
|
27
|
-
setShowConnectionsWidget = (
|
|
28
|
-
this.showConnectionsWidget =
|
|
37
|
+
setShowConnectionsWidget = (s) => {
|
|
38
|
+
this.showConnectionsWidget = s;
|
|
29
39
|
};
|
|
30
40
|
loadHoldings = async () => {
|
|
31
41
|
try {
|
|
32
|
-
const
|
|
33
|
-
this.setHoldings(
|
|
34
|
-
} catch (
|
|
35
|
-
console.error("Error occurred while getting holdings:",
|
|
42
|
+
const s = await this.api.getHoldings();
|
|
43
|
+
this.setHoldings(s);
|
|
44
|
+
} catch (s) {
|
|
45
|
+
console.error("Error occurred while getting holdings:", s), this.globalStore.captureException(s, { store: "HoldingStore" });
|
|
36
46
|
}
|
|
37
47
|
};
|
|
38
|
-
setAnalysisType = (
|
|
39
|
-
this.analysisType =
|
|
48
|
+
setAnalysisType = (s) => {
|
|
49
|
+
this.analysisType = s;
|
|
40
50
|
};
|
|
41
|
-
updateHoldings = async (
|
|
51
|
+
updateHoldings = async (s) => {
|
|
42
52
|
this.holdingsLoaded = !1;
|
|
43
53
|
try {
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
this.holdings =
|
|
54
|
+
const t = await this.api.updateHoldings(s), e = this.holdings.findIndex(({ guid: i }) => i === s.guid);
|
|
55
|
+
if (e >= 0) {
|
|
56
|
+
const i = [...this.holdings];
|
|
57
|
+
i[e] = t, g(() => {
|
|
58
|
+
this.holdings = i, this.holdingsLoaded = !0;
|
|
49
59
|
});
|
|
50
60
|
}
|
|
51
|
-
} catch (
|
|
52
|
-
console.error("Error occurred while updating holding:",
|
|
61
|
+
} catch (t) {
|
|
62
|
+
console.error("Error occurred while updating holding:", t), this.globalStore.captureException(t, { store: "HoldingStore" });
|
|
53
63
|
}
|
|
54
64
|
};
|
|
55
65
|
};
|
|
56
66
|
export {
|
|
57
|
-
|
|
67
|
+
m as HoldingStore
|
|
58
68
|
};
|
|
59
69
|
|
|
60
70
|
//# sourceMappingURL=HoldingStore.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HoldingStore.es.js","names":[],"sources":["../../../src/core/stores/HoldingStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\n\nimport { HoldingApi } from '../api'\nimport { AnalysisType } from '../constants/Investments'\nimport { type Holding } from '../types'\nimport {\n analysisChartData,\n analysisDetailsData,\n mapDataToPercentageGrid,\n} from '../utils/InvestmentUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nexport class HoldingStore {\n analysisType: AnalysisType = AnalysisType.Stocks\n api = new HoldingApi('/', '')\n holdings: Holding[] = []\n holdingsLoaded = false\n globalStore: GlobalStore\n showConnectionsWidget = false\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new HoldingApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n get analysisChartData() {\n return mapDataToPercentageGrid(analysisChartData(this.visibleHoldings), this.analysisType)\n }\n\n get analysisDetails() {\n return analysisDetailsData(this.visibleHoldings)[this.analysisType] || {}\n }\n\n get visibleHoldings() {\n return this.holdings.filter((holding) =>\n this.globalStore.globalUiStore.selectedAccountGuids.includes(holding.account_guid),\n )\n }\n\n setHoldings = (holdings: Holding[]) => {\n this.holdings = holdings\n this.holdingsLoaded = true\n }\n\n setShowConnectionsWidget = (value: boolean) => {\n this.showConnectionsWidget = value\n }\n\n loadHoldings = async () => {\n try {\n const holdings = await this.api.getHoldings()\n this.setHoldings(holdings)\n } catch (error) {\n console.error('Error occurred while getting holdings:', error)\n this.globalStore.captureException(error, { store: 'HoldingStore' })\n }\n }\n\n setAnalysisType = (analysisType: AnalysisType) => {\n this.analysisType = analysisType\n }\n\n updateHoldings = async (holding: Holding) => {\n this.holdingsLoaded = false\n try {\n const updatedHolding = await this.api.updateHoldings(holding)\n const updatedIndex = this.holdings.findIndex(({ guid }) => guid === holding.guid)\n\n if (updatedIndex >= 0) {\n const holdings = [...this.holdings]\n holdings[updatedIndex] = updatedHolding\n\n runInAction(() => {\n this.holdings = holdings\n this.holdingsLoaded = true\n })\n }\n } catch (error) {\n console.error('Error occurred while updating holding:', error)\n this.globalStore.captureException(error, { store: 'HoldingStore' })\n }\n }\n}\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"HoldingStore.es.js","names":[],"sources":["../../../src/core/stores/HoldingStore.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from 'mobx'\n\nimport { HoldingApi } from '../api'\nimport { AnalysisType } from '../constants/Investments'\nimport { type Holding } from '../types'\nimport {\n analysisChartData,\n analysisDetailsData,\n holdingHasAllocationData,\n holdingHasStyleData,\n mapDataToPercentageGrid,\n} from '../utils/InvestmentUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nexport class HoldingStore {\n analysisType: AnalysisType = AnalysisType.Stocks\n api = new HoldingApi('/', '')\n holdings: Holding[] = []\n holdingsLoaded = false\n globalStore: GlobalStore\n showConnectionsWidget = false\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new HoldingApi(globalStore.endpoint, globalStore.sessionToken, globalStore.onError)\n\n makeAutoObservable(this)\n }\n\n get analysisChartData() {\n return mapDataToPercentageGrid(analysisChartData(this.visibleHoldings), this.analysisType)\n }\n\n get analysisDetails() {\n return analysisDetailsData(this.visibleHoldings)[this.analysisType] || {}\n }\n\n get visibleHoldings() {\n return this.holdings.filter((holding) =>\n this.globalStore.globalUiStore.selectedAccountGuids.includes(holding.account_guid),\n )\n }\n\n // Cash counts because a cash balance renders as a synthetic donut slice.\n get hasAllocationData() {\n if (this.visibleHoldings.some(holdingHasAllocationData)) return true\n\n return this.selectedInvestmentAccounts.some((account) => (account.cash_balance ?? 0) > 0)\n }\n\n get hasAnalysisData() {\n return this.visibleHoldings.some(holdingHasStyleData)\n }\n\n get selectedInvestmentAccounts() {\n const { selectedAccountGuids } = this.globalStore.globalUiStore\n return this.globalStore.accountStore.visibleInvestmentAccounts.filter((account) =>\n selectedAccountGuids.includes(account.guid),\n )\n }\n\n setHoldings = (holdings: Holding[]) => {\n this.holdings = holdings\n this.holdingsLoaded = true\n }\n\n setShowConnectionsWidget = (value: boolean) => {\n this.showConnectionsWidget = value\n }\n\n loadHoldings = async () => {\n try {\n const holdings = await this.api.getHoldings()\n this.setHoldings(holdings)\n } catch (error) {\n console.error('Error occurred while getting holdings:', error)\n this.globalStore.captureException(error, { store: 'HoldingStore' })\n }\n }\n\n setAnalysisType = (analysisType: AnalysisType) => {\n this.analysisType = analysisType\n }\n\n updateHoldings = async (holding: Holding) => {\n this.holdingsLoaded = false\n try {\n const updatedHolding = await this.api.updateHoldings(holding)\n const updatedIndex = this.holdings.findIndex(({ guid }) => guid === holding.guid)\n\n if (updatedIndex >= 0) {\n const holdings = [...this.holdings]\n holdings[updatedIndex] = updatedHolding\n\n runInAction(() => {\n this.holdings = holdings\n this.holdingsLoaded = true\n })\n }\n } catch (error) {\n console.error('Error occurred while updating holding:', error)\n this.globalStore.captureException(error, { store: 'HoldingStore' })\n }\n }\n}\n"],"mappings":";;;;AAeA,IAAa,IAAb,MAA0B;AAAA,EACxB,eAA6B,EAAa;AAAA,EAC1C,MAAM,IAAI,EAAW,KAAK,EAAE;AAAA,EAC5B,WAAsB,CAAC;AAAA,EACvB,iBAAiB;AAAA,EACjB;AAAA,EACA,wBAAwB;AAAA,EAExB,YAAY,GAA0B;AACpC,SAAK,cAAc,GACnB,KAAK,MAAM,IAAI,EAAW,EAAY,UAAU,EAAY,cAAc,EAAY,OAAO,GAE7F,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,IAAI,oBAAoB;AACtB,WAAO,EAAwB,EAAkB,KAAK,eAAe,GAAG,KAAK,YAAY;AAAA,EAC3F;AAAA,EAEA,IAAI,kBAAkB;AACpB,WAAO,EAAoB,KAAK,eAAe,EAAE,KAAK,YAAA,KAAiB,CAAC;AAAA,EAC1E;AAAA,EAEA,IAAI,kBAAkB;AACpB,WAAO,KAAK,SAAS,OAAA,CAAQ,MAC3B,KAAK,YAAY,cAAc,qBAAqB,SAAS,EAAQ,YAAY,CACnF;AAAA,EACF;AAAA,EAGA,IAAI,oBAAoB;AACtB,WAAI,KAAK,gBAAgB,KAAK,CAAwB,IAAU,KAEzD,KAAK,2BAA2B,KAAA,CAAM,OAAa,EAAQ,gBAAgB,KAAK,CAAC;AAAA,EAC1F;AAAA,EAEA,IAAI,kBAAkB;AACpB,WAAO,KAAK,gBAAgB,KAAK,CAAmB;AAAA,EACtD;AAAA,EAEA,IAAI,6BAA6B;AAC/B,UAAM,EAAE,sBAAA,EAAA,IAAyB,KAAK,YAAY;AAClD,WAAO,KAAK,YAAY,aAAa,0BAA0B,OAAA,CAAQ,MACrE,EAAqB,SAAS,EAAQ,IAAI,CAC5C;AAAA,EACF;AAAA,EAEA,cAAA,CAAe,MAAwB;AACrC,SAAK,WAAW,GAChB,KAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,2BAAA,CAA4B,MAAmB;AAC7C,SAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEA,eAAe,YAAY;AACzB,QAAI;AACF,YAAM,IAAW,MAAM,KAAK,IAAI,YAAY;AAC5C,WAAK,YAAY,CAAQ;AAAA,IAC3B,SAAS,GAAO;AACd,cAAQ,MAAM,0CAA0C,CAAK,GAC7D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,kBAAA,CAAmB,MAA+B;AAChD,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,iBAAiB,OAAO,MAAqB;AAC3C,SAAK,iBAAiB;AACtB,QAAI;AACF,YAAM,IAAiB,MAAM,KAAK,IAAI,eAAe,CAAO,GACtD,IAAe,KAAK,SAAS,UAAA,CAAW,EAAE,MAAA,EAAA,MAAW,MAAS,EAAQ,IAAI;AAEhF,UAAI,KAAgB,GAAG;AACrB,cAAM,IAAW,CAAC,GAAG,KAAK,QAAQ;AAClC,QAAA,EAAS,CAAA,IAAgB,GAEzB,EAAA,MAAkB;AAChB,eAAK,WAAW,GAChB,KAAK,iBAAiB;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF,SAAS,GAAO;AACd,cAAQ,MAAM,0CAA0C,CAAK,GAC7D,KAAK,YAAY,iBAAiB,GAAO,EAAE,OAAO,eAAe,CAAC;AAAA,IACpE;AAAA,EACF;AACF"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Holding } from '../types';
|
|
2
2
|
import { AnalysisType } from '../constants/Investments';
|
|
3
3
|
type WeightMap = Record<string, number>;
|
|
4
|
+
export declare const isMeaningfulNumber: (value: unknown) => boolean;
|
|
5
|
+
export declare const isValidClassification: (value: unknown) => boolean;
|
|
6
|
+
export declare const holdingHasStyleData: (holding: Holding) => boolean;
|
|
7
|
+
export declare const holdingHasAllocationData: (holding: Holding) => boolean;
|
|
4
8
|
export declare const createGroups: (classificationObj: Record<number, string>, groupSize?: number) => string[][];
|
|
5
9
|
export declare const bondGroups: string[][];
|
|
6
10
|
export declare const stockGroups: string[][];
|
|
@@ -1,80 +1,93 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
var
|
|
4
|
-
const
|
|
5
|
-
|
|
1
|
+
import { ALLOCATION_KEYS as V, AnalysisType as k, EquityClassificationTypes as A, EquityClassificationValues as m, FixedIncomeClassificationTypes as G, FixedIncomeClassificationValues as f, STYLE_WEIGHT_KEYS as T } from "../constants/Investments.es.js";
|
|
2
|
+
import W from "numeral";
|
|
3
|
+
var S = 80, x = 120, h = (e) => e > S && e < x, C = (e) => {
|
|
4
|
+
const t = Number(e);
|
|
5
|
+
return Number.isFinite(t) && t !== 0;
|
|
6
|
+
}, d = (e) => {
|
|
7
|
+
const t = Number(e);
|
|
8
|
+
return Number.isFinite(t) && t >= 1 && t <= 9;
|
|
9
|
+
}, F = (e) => {
|
|
10
|
+
const t = T.reduce((r, s) => r + (Number(e[s]) || 0), 0);
|
|
11
|
+
return h(t) || t === 0 && (d(e.equity_classification) || d(e.fixed_income_classification));
|
|
12
|
+
}, q = (e) => V.some((t) => C(e[t])), E = (e, t = 3) => {
|
|
13
|
+
const r = Object.keys(e).map(Number).filter((a) => a !== 0).sort((a, i) => a - i), s = [];
|
|
14
|
+
for (let a = 0; a < r.length; a += t) s.push(r.slice(a, a + t).map((i) => e[i]));
|
|
6
15
|
return s;
|
|
7
|
-
},
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const l = i(
|
|
11
|
-
return Object.keys(l).forEach((_) =>
|
|
16
|
+
}, I = E(f), D = E(m), K = (e) => {
|
|
17
|
+
const t = p(e, w), r = p(e, y), s = (a, i) => {
|
|
18
|
+
const o = a.reduce((n, c) => n + N(c), 0), u = a.reduce((n, c) => {
|
|
19
|
+
const l = i(c);
|
|
20
|
+
return Object.keys(l).forEach((_) => n[_] = (n[_] || 0) + l[_]), n;
|
|
12
21
|
}, {});
|
|
13
|
-
return Object.fromEntries(Object.entries(u).map(([
|
|
22
|
+
return Object.fromEntries(Object.entries(u).map(([n, c]) => [n, c / o * 100]));
|
|
14
23
|
};
|
|
15
24
|
return {
|
|
16
|
-
stocks: s(
|
|
17
|
-
bonds: s(r,
|
|
25
|
+
stocks: s(t, L),
|
|
26
|
+
bonds: s(r, b)
|
|
18
27
|
};
|
|
19
|
-
},
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
return Object.keys(
|
|
23
|
-
u[l] = (u[l] || 0) + (
|
|
28
|
+
}, U = (e) => {
|
|
29
|
+
const t = e.filter((a) => !isNaN(a.equity_classification)), r = e.filter((a) => !isNaN(a.fixed_income_classification)), s = (a, i, o) => a.reduce((u, n) => {
|
|
30
|
+
const c = i(n);
|
|
31
|
+
return Object.keys(o).forEach((l) => {
|
|
32
|
+
u[l] = (u[l] || 0) + (c[l] || 0);
|
|
24
33
|
}), u;
|
|
25
34
|
}, {});
|
|
26
35
|
return {
|
|
27
|
-
stocks: s(
|
|
28
|
-
bonds: s(r,
|
|
36
|
+
stocks: s(t, L, A),
|
|
37
|
+
bonds: s(r, b, G)
|
|
29
38
|
};
|
|
30
|
-
},
|
|
31
|
-
const
|
|
32
|
-
return { [f[
|
|
33
|
-
},
|
|
34
|
-
const { large_core_weight:
|
|
35
|
-
LARGE_CORE:
|
|
39
|
+
}, H = (e, t) => Object.fromEntries(Object.entries(e).map(([r, s]) => [r, s * t / 100])), b = (e) => O(e, y, f), y = (e) => {
|
|
40
|
+
const t = e.fixed_income_classification;
|
|
41
|
+
return { [f[t]]: 100 };
|
|
42
|
+
}, L = (e) => O(e, w, m), w = (e) => {
|
|
43
|
+
const { large_core_weight: t, large_growth_weight: r, large_value_weight: s, mid_core_weight: a, mid_growth_weight: i, mid_value_weight: o, small_core_weight: u, small_growth_weight: n, small_value_weight: c, unknown_weight: l, equity_classification: _ } = e, g = {
|
|
44
|
+
LARGE_CORE: t ?? 0,
|
|
36
45
|
LARGE_GROWTH: r ?? 0,
|
|
37
46
|
LARGE_VALUE: s ?? 0,
|
|
38
|
-
MID_CORE:
|
|
47
|
+
MID_CORE: a ?? 0,
|
|
39
48
|
MID_GROWTH: i ?? 0,
|
|
40
|
-
MID_VALUE:
|
|
49
|
+
MID_VALUE: o ?? 0,
|
|
41
50
|
SMALL_CORE: u ?? 0,
|
|
42
|
-
SMALL_GROWTH:
|
|
43
|
-
SMALL_VALUE:
|
|
51
|
+
SMALL_GROWTH: n ?? 0,
|
|
52
|
+
SMALL_VALUE: c ?? 0,
|
|
44
53
|
UNKNOWN: l ?? 0
|
|
45
54
|
};
|
|
46
|
-
return g
|
|
47
|
-
},
|
|
48
|
-
const s =
|
|
49
|
-
if (
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
console.error(`Invalid classification key: ${
|
|
55
|
+
return v(g) === 0 && _ !== void 0 ? { [m[_]]: 100 } : g;
|
|
56
|
+
}, O = (e, t, r) => {
|
|
57
|
+
const s = t(e), a = N(e), i = H(s, a);
|
|
58
|
+
if (v(i) === 0) {
|
|
59
|
+
const o = String(e.equity_classification ?? e.fixed_income_classification);
|
|
60
|
+
if (o in r) return { [r[o]]: a };
|
|
61
|
+
console.error(`Invalid classification key: ${o}`);
|
|
53
62
|
}
|
|
54
63
|
return i;
|
|
55
|
-
},
|
|
56
|
-
const s =
|
|
57
|
-
return
|
|
58
|
-
}),
|
|
59
|
-
const r =
|
|
60
|
-
return !s || Object.keys(s).length === 0 ? r.map((
|
|
61
|
-
},
|
|
64
|
+
}, Y = (e) => e.split("_").map((t) => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase()).join(" "), j = (e) => e >= 1 ? `${W(e).format("0")}%` : "< 1%", N = (e) => e.calculated_market_value ?? e.market_value, p = (e, t) => e.filter((r) => {
|
|
65
|
+
const s = t(r);
|
|
66
|
+
return h(v(s));
|
|
67
|
+
}), B = (e, t) => {
|
|
68
|
+
const r = t === k.Stocks ? D : I, s = e[t];
|
|
69
|
+
return !s || Object.keys(s).length === 0 ? r.map((a) => a.map(() => "0%")) : r.map((a) => a.map((i) => j(s[i] ?? 0)));
|
|
70
|
+
}, v = (e) => Object.values(e).reduce((t, r) => t + r, 0);
|
|
62
71
|
export {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
K as analysisChartData,
|
|
73
|
+
U as analysisDetailsData,
|
|
74
|
+
I as bondGroups,
|
|
75
|
+
H as calculateWeightedValue,
|
|
76
|
+
E as createGroups,
|
|
77
|
+
y as extractBondWeight,
|
|
78
|
+
w as extractStockWeight,
|
|
79
|
+
O as extractValueFromWeight,
|
|
80
|
+
Y as formatKey,
|
|
81
|
+
j as formatPercent,
|
|
82
|
+
N as getHoldingValue,
|
|
74
83
|
p as getValidHoldings,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
q as holdingHasAllocationData,
|
|
85
|
+
F as holdingHasStyleData,
|
|
86
|
+
C as isMeaningfulNumber,
|
|
87
|
+
d as isValidClassification,
|
|
88
|
+
B as mapDataToPercentageGrid,
|
|
89
|
+
D as stockGroups,
|
|
90
|
+
v as sumValues
|
|
78
91
|
};
|
|
79
92
|
|
|
80
93
|
//# sourceMappingURL=InvestmentUtil.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvestmentUtil.es.js","names":[],"sources":["../../../src/core/utils/InvestmentUtil.ts"],"sourcesContent":["import numeral from 'numeral'\n\nimport type { Holding } from '../types'\n\nimport {\n AnalysisType,\n EquityClassificationTypes,\n EquityClassificationValues,\n FixedIncomeClassificationTypes,\n FixedIncomeClassificationValues,\n} from '../constants/Investments'\n\ntype WeightMap = Record<string, number>\n\nexport const createGroups = (classificationObj: Record<number, string>, groupSize = 3) => {\n const keys = Object.keys(classificationObj)\n .map(Number)\n .filter((k) => k !== 0)\n .sort((a, b) => a - b)\n\n const groups = []\n for (let i = 0; i < keys.length; i += groupSize) {\n groups.push(keys.slice(i, i + groupSize).map((key) => classificationObj[key]))\n }\n return groups\n}\n\nexport const bondGroups = createGroups(FixedIncomeClassificationValues)\nexport const stockGroups = createGroups(EquityClassificationValues)\n\nexport const analysisChartData = (holdings: Holding[]) => {\n const stocks = getValidHoldings(holdings, extractStockWeight)\n const bonds = getValidHoldings(holdings, extractBondWeight)\n\n const processGroupData = (group: Holding[], extractValueFn: (holding: Holding) => WeightMap) => {\n const totalValue = group.reduce((acc, holding) => acc + getHoldingValue(holding), 0)\n const groupValues = group.reduce((acc, holding) => {\n const value = extractValueFn(holding)\n Object.keys(value).forEach((key) => (acc[key] = (acc[key] || 0) + value[key]))\n return acc\n }, {} as WeightMap)\n\n return Object.fromEntries(\n Object.entries(groupValues).map(([key, value]) => [key, (value / totalValue) * 100]),\n )\n }\n\n const data = {\n stocks: processGroupData(stocks, extractStockValueFromWeight),\n bonds: processGroupData(bonds, extractBondValueFromWeight),\n }\n\n return data\n}\n\nexport const analysisDetailsData = (holdings: Holding[]) => {\n const stocks = holdings.filter((holding) => !isNaN(holding.equity_classification))\n const bonds = holdings.filter((holding) => !isNaN(holding.fixed_income_classification))\n\n const aggregateValues = (\n holdings: Holding[],\n extractValueFn: (holding: Holding) => WeightMap,\n classificationTypes: Record<string, number>,\n ) => {\n return holdings.reduce((acc, holding) => {\n const values = extractValueFn(holding)\n Object.keys(classificationTypes).forEach((sector) => {\n acc[sector] = (acc[sector] || 0) + (values[sector] || 0)\n })\n return acc\n }, {} as WeightMap)\n }\n\n return {\n stocks: aggregateValues(stocks, extractStockValueFromWeight, EquityClassificationTypes),\n bonds: aggregateValues(bonds, extractBondValueFromWeight, FixedIncomeClassificationTypes),\n }\n}\n\nexport const calculateWeightedValue = (weights: WeightMap, value: number): WeightMap => {\n return Object.fromEntries(\n Object.entries(weights).map(([key, weight]) => [key, (weight * value) / 100]),\n )\n}\n\nconst extractBondValueFromWeight = (bond: Holding) =>\n extractValueFromWeight(bond, extractBondWeight, FixedIncomeClassificationValues)\n\nexport const extractBondWeight = (bond: Holding): WeightMap => {\n const classificationKey = bond.fixed_income_classification\n return {\n [FixedIncomeClassificationValues[\n classificationKey as keyof typeof FixedIncomeClassificationValues\n ]]: 100,\n }\n}\n\nconst extractStockValueFromWeight = (stock: Holding) =>\n extractValueFromWeight(stock, extractStockWeight, EquityClassificationValues)\n\nexport const extractStockWeight = (stock: Holding): WeightMap => {\n const {\n large_core_weight,\n large_growth_weight,\n large_value_weight,\n mid_core_weight,\n mid_growth_weight,\n mid_value_weight,\n small_core_weight,\n small_growth_weight,\n small_value_weight,\n unknown_weight,\n equity_classification,\n } = stock\n\n const data: WeightMap = {\n LARGE_CORE: large_core_weight ?? 0,\n LARGE_GROWTH: large_growth_weight ?? 0,\n LARGE_VALUE: large_value_weight ?? 0,\n MID_CORE: mid_core_weight ?? 0,\n MID_GROWTH: mid_growth_weight ?? 0,\n MID_VALUE: mid_value_weight ?? 0,\n SMALL_CORE: small_core_weight ?? 0,\n SMALL_GROWTH: small_growth_weight ?? 0,\n SMALL_VALUE: small_value_weight ?? 0,\n UNKNOWN: unknown_weight ?? 0,\n }\n\n if (sumValues(data) === 0 && equity_classification !== undefined) {\n const key =\n EquityClassificationValues[equity_classification as keyof typeof EquityClassificationValues]\n return { [key]: 100 }\n }\n\n return data\n}\n\nexport const extractValueFromWeight = (\n holding: Holding,\n extractWeightFn: (h: Holding) => WeightMap,\n classificationValues: Record<string, string>,\n): WeightMap => {\n const weights = extractWeightFn(holding)\n const value = getHoldingValue(holding)\n const weightedValues = calculateWeightedValue(weights, value)\n\n if (sumValues(weightedValues) === 0) {\n const classificationKey = String(\n holding.equity_classification ?? holding.fixed_income_classification,\n )\n\n if (classificationKey in classificationValues) {\n return { [classificationValues[classificationKey]]: value }\n } else {\n console.error(`Invalid classification key: ${classificationKey}`)\n }\n }\n\n return weightedValues\n}\n\nexport const formatKey = (key: string): string =>\n key\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n\nexport const formatPercent = (value: number): string =>\n value >= 1 ? `${numeral(value).format('0')}%` : '< 1%'\n\nexport const getHoldingValue = (holding: Holding): number =>\n holding.calculated_market_value ?? holding.market_value\n\nexport const getValidHoldings = (\n holdings: Holding[],\n extractWeightFn: (holding: Holding) => WeightMap,\n): Holding[] => {\n return holdings.filter((holding) => {\n const weight = extractWeightFn(holding)\n const total = sumValues(weight)\n return total > 80 && total < 120\n })\n}\n\nexport const mapDataToPercentageGrid = (\n data: Record<AnalysisType, Record<string, number>>,\n analysisType: AnalysisType,\n): string[][] => {\n const groups = analysisType === AnalysisType.Stocks ? stockGroups : bondGroups\n\n const selected = data[analysisType]\n if (!selected || Object.keys(selected).length === 0)\n return groups.map((group) => group.map(() => '0%'))\n\n return groups.map((group) => group.map((key) => formatPercent(selected[key] ?? 0)))\n}\n\nexport const sumValues = (obj: WeightMap): number =>\n Object.values(obj).reduce((acc, val) => acc + val, 0)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InvestmentUtil.es.js","names":[],"sources":["../../../src/core/utils/InvestmentUtil.ts"],"sourcesContent":["import numeral from 'numeral'\n\nimport type { Holding } from '../types'\n\nimport {\n ALLOCATION_KEYS,\n AnalysisType,\n EquityClassificationTypes,\n EquityClassificationValues,\n FixedIncomeClassificationTypes,\n FixedIncomeClassificationValues,\n STYLE_WEIGHT_KEYS,\n} from '../constants/Investments'\n\ntype WeightMap = Record<string, number>\n\n// The render band getValidHoldings keeps; the analysis gate reuses it so the\n// tab never enables onto an all-zero grid.\nconst STYLE_WEIGHT_MIN = 80\nconst STYLE_WEIGHT_MAX = 120\nconst isInStyleWeightBand = (total: number): boolean =>\n total > STYLE_WEIGHT_MIN && total < STYLE_WEIGHT_MAX\n\n// Coerces so a stringified number counts; null/\"\"/\"0\"/NaN/0 all mean \"no data\".\nexport const isMeaningfulNumber = (value: unknown): boolean => {\n const n = Number(value)\n return Number.isFinite(n) && n !== 0\n}\n\n// Classification 0 is UNKNOWN; only 1..9 represent real data.\nexport const isValidClassification = (value: unknown): boolean => {\n const n = Number(value)\n return Number.isFinite(n) && n >= 1 && n <= 9\n}\n\n// Classification only counts when style weights sum to 0, matching\n// extractWeight's fallback — otherwise a partial (out-of-band) total that\n// getValidHoldings drops would wrongly enable the tab onto an empty grid.\nexport const holdingHasStyleData = (holding: Holding): boolean => {\n const styleTotal = STYLE_WEIGHT_KEYS.reduce((sum, key) => sum + (Number(holding[key]) || 0), 0)\n return (\n isInStyleWeightBand(styleTotal) ||\n (styleTotal === 0 &&\n (isValidClassification(holding.equity_classification) ||\n isValidClassification(holding.fixed_income_classification)))\n )\n}\n\nexport const holdingHasAllocationData = (holding: Holding): boolean =>\n ALLOCATION_KEYS.some((key) => isMeaningfulNumber(holding[key]))\n\nexport const createGroups = (classificationObj: Record<number, string>, groupSize = 3) => {\n const keys = Object.keys(classificationObj)\n .map(Number)\n .filter((k) => k !== 0)\n .sort((a, b) => a - b)\n\n const groups = []\n for (let i = 0; i < keys.length; i += groupSize) {\n groups.push(keys.slice(i, i + groupSize).map((key) => classificationObj[key]))\n }\n return groups\n}\n\nexport const bondGroups = createGroups(FixedIncomeClassificationValues)\nexport const stockGroups = createGroups(EquityClassificationValues)\n\nexport const analysisChartData = (holdings: Holding[]) => {\n const stocks = getValidHoldings(holdings, extractStockWeight)\n const bonds = getValidHoldings(holdings, extractBondWeight)\n\n const processGroupData = (group: Holding[], extractValueFn: (holding: Holding) => WeightMap) => {\n const totalValue = group.reduce((acc, holding) => acc + getHoldingValue(holding), 0)\n const groupValues = group.reduce((acc, holding) => {\n const value = extractValueFn(holding)\n Object.keys(value).forEach((key) => (acc[key] = (acc[key] || 0) + value[key]))\n return acc\n }, {} as WeightMap)\n\n return Object.fromEntries(\n Object.entries(groupValues).map(([key, value]) => [key, (value / totalValue) * 100]),\n )\n }\n\n const data = {\n stocks: processGroupData(stocks, extractStockValueFromWeight),\n bonds: processGroupData(bonds, extractBondValueFromWeight),\n }\n\n return data\n}\n\nexport const analysisDetailsData = (holdings: Holding[]) => {\n const stocks = holdings.filter((holding) => !isNaN(holding.equity_classification))\n const bonds = holdings.filter((holding) => !isNaN(holding.fixed_income_classification))\n\n const aggregateValues = (\n holdings: Holding[],\n extractValueFn: (holding: Holding) => WeightMap,\n classificationTypes: Record<string, number>,\n ) => {\n return holdings.reduce((acc, holding) => {\n const values = extractValueFn(holding)\n Object.keys(classificationTypes).forEach((sector) => {\n acc[sector] = (acc[sector] || 0) + (values[sector] || 0)\n })\n return acc\n }, {} as WeightMap)\n }\n\n return {\n stocks: aggregateValues(stocks, extractStockValueFromWeight, EquityClassificationTypes),\n bonds: aggregateValues(bonds, extractBondValueFromWeight, FixedIncomeClassificationTypes),\n }\n}\n\nexport const calculateWeightedValue = (weights: WeightMap, value: number): WeightMap => {\n return Object.fromEntries(\n Object.entries(weights).map(([key, weight]) => [key, (weight * value) / 100]),\n )\n}\n\nconst extractBondValueFromWeight = (bond: Holding) =>\n extractValueFromWeight(bond, extractBondWeight, FixedIncomeClassificationValues)\n\nexport const extractBondWeight = (bond: Holding): WeightMap => {\n const classificationKey = bond.fixed_income_classification\n return {\n [FixedIncomeClassificationValues[\n classificationKey as keyof typeof FixedIncomeClassificationValues\n ]]: 100,\n }\n}\n\nconst extractStockValueFromWeight = (stock: Holding) =>\n extractValueFromWeight(stock, extractStockWeight, EquityClassificationValues)\n\nexport const extractStockWeight = (stock: Holding): WeightMap => {\n const {\n large_core_weight,\n large_growth_weight,\n large_value_weight,\n mid_core_weight,\n mid_growth_weight,\n mid_value_weight,\n small_core_weight,\n small_growth_weight,\n small_value_weight,\n unknown_weight,\n equity_classification,\n } = stock\n\n const data: WeightMap = {\n LARGE_CORE: large_core_weight ?? 0,\n LARGE_GROWTH: large_growth_weight ?? 0,\n LARGE_VALUE: large_value_weight ?? 0,\n MID_CORE: mid_core_weight ?? 0,\n MID_GROWTH: mid_growth_weight ?? 0,\n MID_VALUE: mid_value_weight ?? 0,\n SMALL_CORE: small_core_weight ?? 0,\n SMALL_GROWTH: small_growth_weight ?? 0,\n SMALL_VALUE: small_value_weight ?? 0,\n UNKNOWN: unknown_weight ?? 0,\n }\n\n if (sumValues(data) === 0 && equity_classification !== undefined) {\n const key =\n EquityClassificationValues[equity_classification as keyof typeof EquityClassificationValues]\n return { [key]: 100 }\n }\n\n return data\n}\n\nexport const extractValueFromWeight = (\n holding: Holding,\n extractWeightFn: (h: Holding) => WeightMap,\n classificationValues: Record<string, string>,\n): WeightMap => {\n const weights = extractWeightFn(holding)\n const value = getHoldingValue(holding)\n const weightedValues = calculateWeightedValue(weights, value)\n\n if (sumValues(weightedValues) === 0) {\n const classificationKey = String(\n holding.equity_classification ?? holding.fixed_income_classification,\n )\n\n if (classificationKey in classificationValues) {\n return { [classificationValues[classificationKey]]: value }\n } else {\n console.error(`Invalid classification key: ${classificationKey}`)\n }\n }\n\n return weightedValues\n}\n\nexport const formatKey = (key: string): string =>\n key\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n\nexport const formatPercent = (value: number): string =>\n value >= 1 ? `${numeral(value).format('0')}%` : '< 1%'\n\nexport const getHoldingValue = (holding: Holding): number =>\n holding.calculated_market_value ?? holding.market_value\n\nexport const getValidHoldings = (\n holdings: Holding[],\n extractWeightFn: (holding: Holding) => WeightMap,\n): Holding[] => {\n return holdings.filter((holding) => {\n const weight = extractWeightFn(holding)\n return isInStyleWeightBand(sumValues(weight))\n })\n}\n\nexport const mapDataToPercentageGrid = (\n data: Record<AnalysisType, Record<string, number>>,\n analysisType: AnalysisType,\n): string[][] => {\n const groups = analysisType === AnalysisType.Stocks ? stockGroups : bondGroups\n\n const selected = data[analysisType]\n if (!selected || Object.keys(selected).length === 0)\n return groups.map((group) => group.map(() => '0%'))\n\n return groups.map((group) => group.map((key) => formatPercent(selected[key] ?? 0)))\n}\n\nexport const sumValues = (obj: WeightMap): number =>\n Object.values(obj).reduce((acc, val) => acc + val, 0)\n"],"mappings":";;AAkBA,IAAM,IAAmB,IACnB,IAAmB,KACnB,IAAA,CAAuB,MAC3B,IAAQ,KAAoB,IAAQ,GAGzB,IAAA,CAAsB,MAA4B;AAC7D,QAAM,IAAI,OAAO,CAAK;AACtB,SAAO,OAAO,SAAS,CAAC,KAAK,MAAM;AACrC,GAGa,IAAA,CAAyB,MAA4B;AAChE,QAAM,IAAI,OAAO,CAAK;AACtB,SAAO,OAAO,SAAS,CAAC,KAAK,KAAK,KAAK,KAAK;AAC9C,GAKa,IAAA,CAAuB,MAA8B;AAChE,QAAM,IAAa,EAAkB,OAAA,CAAQ,GAAK,MAAQ,KAAO,OAAO,EAAQ,CAAA,CAAI,KAAK,IAAI,CAAC;AAC9F,SACE,EAAoB,CAAU,KAC7B,MAAe,MACb,EAAsB,EAAQ,qBAAqB,KAClD,EAAsB,EAAQ,2BAA2B;AAEjE,GAEa,IAAA,CAA4B,MACvC,EAAgB,KAAA,CAAM,MAAQ,EAAmB,EAAQ,CAAA,CAAI,CAAC,GAEnD,IAAA,CAAgB,GAA2C,IAAY,MAAM;AACxF,QAAM,IAAO,OAAO,KAAK,CAAiB,EACvC,IAAI,MAAM,EACV,OAAA,CAAQ,MAAM,MAAM,CAAC,EACrB,KAAA,CAAM,GAAG,MAAM,IAAI,CAAC,GAEjB,IAAS,CAAC;AAChB,WAAS,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,EACpC,CAAA,EAAO,KAAK,EAAK,MAAM,GAAG,IAAI,CAAS,EAAE,IAAA,CAAK,MAAQ,EAAkB,CAAA,CAAI,CAAC;AAE/E,SAAO;AACT,GAEa,IAAa,EAAa,CAA+B,GACzD,IAAc,EAAa,CAA0B,GAErD,IAAA,CAAqB,MAAwB;AACxD,QAAM,IAAS,EAAiB,GAAU,CAAkB,GACtD,IAAQ,EAAiB,GAAU,CAAiB,GAEpD,IAAA,CAAoB,GAAkB,MAAoD;AAC9F,UAAM,IAAa,EAAM,OAAA,CAAQ,GAAK,MAAY,IAAM,EAAgB,CAAO,GAAG,CAAC,GAC7E,IAAc,EAAM,OAAA,CAAQ,GAAK,MAAY;AACjD,YAAM,IAAQ,EAAe,CAAO;AACpC,oBAAO,KAAK,CAAK,EAAE,QAAA,CAAS,MAAS,EAAI,CAAA,KAAQ,EAAI,CAAA,KAAQ,KAAK,EAAM,CAAA,CAAK,GACtE;AAAA,IACT,GAAG,CAAC,CAAc;AAElB,WAAO,OAAO,YACZ,OAAO,QAAQ,CAAW,EAAE,IAAA,CAAK,CAAC,GAAK,CAAA,MAAW,CAAC,GAAM,IAAQ,IAAc,GAAG,CAAC,CACrF;AAAA,EACF;AAOA,SAAO;AAAA,IAJL,QAAQ,EAAiB,GAAQ,CAA2B;AAAA,IAC5D,OAAO,EAAiB,GAAO,CAA0B;AAAA,EAGpD;AACT,GAEa,IAAA,CAAuB,MAAwB;AAC1D,QAAM,IAAS,EAAS,OAAA,CAAQ,MAAY,CAAC,MAAM,EAAQ,qBAAqB,CAAC,GAC3E,IAAQ,EAAS,OAAA,CAAQ,MAAY,CAAC,MAAM,EAAQ,2BAA2B,CAAC,GAEhF,IAAA,CACJ,GACA,GACA,MAEO,EAAS,OAAA,CAAQ,GAAK,MAAY;AACvC,UAAM,IAAS,EAAe,CAAO;AACrC,kBAAO,KAAK,CAAmB,EAAE,QAAA,CAAS,MAAW;AACnD,MAAA,EAAI,CAAA,KAAW,EAAI,CAAA,KAAW,MAAM,EAAO,CAAA,KAAW;AAAA,IACxD,CAAC,GACM;AAAA,EACT,GAAG,CAAC,CAAc;AAGpB,SAAO;AAAA,IACL,QAAQ,EAAgB,GAAQ,GAA6B,CAAyB;AAAA,IACtF,OAAO,EAAgB,GAAO,GAA4B,CAA8B;AAAA,EAC1F;AACF,GAEa,IAAA,CAA0B,GAAoB,MAClD,OAAO,YACZ,OAAO,QAAQ,CAAO,EAAE,IAAA,CAAK,CAAC,GAAK,CAAA,MAAY,CAAC,GAAM,IAAS,IAAS,GAAG,CAAC,CAC9E,GAGI,IAAA,CAA8B,MAClC,EAAuB,GAAM,GAAmB,CAA+B,GAEpE,IAAA,CAAqB,MAA6B;AAC7D,QAAM,IAAoB,EAAK;AAC/B,SAAO,EAAA,CACJ,EACC,CAAA,CAAA,GACE,IACN;AACF,GAEM,IAAA,CAA+B,MACnC,EAAuB,GAAO,GAAoB,CAA0B,GAEjE,IAAA,CAAsB,MAA8B;AAC/D,QAAM,EACJ,mBAAA,GACA,qBAAA,GACA,oBAAA,GACA,iBAAA,GACA,mBAAA,GACA,kBAAA,GACA,mBAAA,GACA,qBAAA,GACA,oBAAA,GACA,gBAAA,GACA,uBAAA,EAAA,IACE,GAEE,IAAkB;AAAA,IACtB,YAAY,KAAqB;AAAA,IACjC,cAAc,KAAuB;AAAA,IACrC,aAAa,KAAsB;AAAA,IACnC,UAAU,KAAmB;AAAA,IAC7B,YAAY,KAAqB;AAAA,IACjC,WAAW,KAAoB;AAAA,IAC/B,YAAY,KAAqB;AAAA,IACjC,cAAc,KAAuB;AAAA,IACrC,aAAa,KAAsB;AAAA,IACnC,SAAS,KAAkB;AAAA,EAC7B;AAEA,SAAI,EAAU,CAAI,MAAM,KAAK,MAA0B,SAG9C,EAAA,CADL,EAA2B,CAAA,CAAA,GACb,IAAI,IAGf;AACT,GAEa,IAAA,CACX,GACA,GACA,MACc;AACd,QAAM,IAAU,EAAgB,CAAO,GACjC,IAAQ,EAAgB,CAAO,GAC/B,IAAiB,EAAuB,GAAS,CAAK;AAE5D,MAAI,EAAU,CAAc,MAAM,GAAG;AACnC,UAAM,IAAoB,OACxB,EAAQ,yBAAyB,EAAQ,2BAC3C;AAEA,QAAI,KAAqB,EACvB,QAAO,EAAA,CAAG,EAAqB,CAAA,CAAA,GAAqB,EAAM;AAE1D,YAAQ,MAAM,+BAA+B,CAAA,EAAmB;AAAA,EAEpE;AAEA,SAAO;AACT,GAEa,IAAA,CAAa,MACxB,EACG,MAAM,GAAG,EACT,IAAA,CAAK,MAAS,EAAK,OAAO,CAAC,EAAE,YAAY,IAAI,EAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,GAAG,GAEA,IAAA,CAAiB,MAC5B,KAAS,IAAI,GAAG,EAAQ,CAAK,EAAE,OAAO,GAAG,CAAA,MAAO,QAErC,IAAA,CAAmB,MAC9B,EAAQ,2BAA2B,EAAQ,cAEhC,IAAA,CACX,GACA,MAEO,EAAS,OAAA,CAAQ,MAAY;AAClC,QAAM,IAAS,EAAgB,CAAO;AACtC,SAAO,EAAoB,EAAU,CAAM,CAAC;AAC9C,CAAC,GAGU,IAAA,CACX,GACA,MACe;AACf,QAAM,IAAS,MAAiB,EAAa,SAAS,IAAc,GAE9D,IAAW,EAAK,CAAA;AACtB,SAAI,CAAC,KAAY,OAAO,KAAK,CAAQ,EAAE,WAAW,IACzC,EAAO,IAAA,CAAK,MAAU,EAAM,IAAA,MAAU,IAAI,CAAC,IAE7C,EAAO,IAAA,CAAK,MAAU,EAAM,IAAA,CAAK,MAAQ,EAAc,EAAS,CAAA,KAAQ,CAAC,CAAC,CAAC;AACpF,GAEa,IAAA,CAAa,MACxB,OAAO,OAAO,CAAG,EAAE,OAAA,CAAQ,GAAK,MAAQ,IAAM,GAAK,CAAC"}
|
|
@@ -1,72 +1,106 @@
|
|
|
1
|
-
import { useAccountStore as
|
|
2
|
-
import { useScreenSize as
|
|
3
|
-
import { useWidgetLoadTimer as
|
|
4
|
-
import { ANALYTICS_EVENTS as
|
|
5
|
-
import { AccountType as
|
|
6
|
-
import
|
|
7
|
-
import { WidgetContainer as
|
|
8
|
-
import { EmptyState as
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { TabTitle as
|
|
14
|
-
import
|
|
15
|
-
import { observer as
|
|
16
|
-
import
|
|
17
|
-
import { Fragment as
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
import { useAccountStore as O, useEvent as k, useGlobalCopyStore as F, useGlobalUiStore as K, useHoldingStore as y } from "../common/context/hooks.es.js";
|
|
2
|
+
import { useScreenSize as V } from "../common/hooks/useScreenSize.es.js";
|
|
3
|
+
import { useWidgetLoadTimer as H } from "../common/hooks/useWidgetLoadTimer.es.js";
|
|
4
|
+
import { ANALYTICS_EVENTS as s } from "../common/constants/Analytics.es.js";
|
|
5
|
+
import { AccountType as U } from "../core/types/Account.es.js";
|
|
6
|
+
import j from "../common/components/Loader.es.js";
|
|
7
|
+
import { WidgetContainer as z } from "../common/components/WidgetContainer.es.js";
|
|
8
|
+
import { EmptyState as B } from "../common/components/EmptyState.es.js";
|
|
9
|
+
import R from "../accounts/components/ConnectionsDrawer.es.js";
|
|
10
|
+
import Y from "./components/Allocation.es.js";
|
|
11
|
+
import $ from "./components/Analysis.es.js";
|
|
12
|
+
import q from "./components/Overview.es.js";
|
|
13
|
+
import { TabTitle as J } from "./components/TabTitle.es.js";
|
|
14
|
+
import l from "react";
|
|
15
|
+
import { observer as P } from "mobx-react-lite";
|
|
16
|
+
import Q from "@mui/material/Stack";
|
|
17
|
+
import { Fragment as X, jsx as t, jsxs as T } from "react/jsx-runtime";
|
|
18
|
+
import Z from "@mui/material/Tab";
|
|
19
|
+
import tt from "@mui/material/Tabs";
|
|
20
|
+
import et from "@mui/material/Tooltip";
|
|
21
|
+
var It = P(({ onBackClick: I, onMenuClick: S, sx: g }) => {
|
|
22
|
+
const { onEvent: c } = k(), { isMobile: v } = V(), { isAccountDataLoaded: A, loadAccountData: N, visibleInvestmentAccounts: L } = O(), { visibleHoldings: x, hasAllocationData: m, hasAnalysisData: d, setShowConnectionsWidget: _, showConnectionsWidget: D } = y(), { investments: e, accounts: W } = F(), { isInitialized: p } = K(), [o, f] = l.useState(0), { loadHoldings: w, holdingsLoaded: n } = y();
|
|
23
|
+
H({
|
|
23
24
|
widgetName: "InvestmentsWidget",
|
|
24
|
-
isLoaded:
|
|
25
|
-
}),
|
|
26
|
-
|
|
27
|
-
}, []),
|
|
28
|
-
|
|
29
|
-
}, [
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
isLoaded: n
|
|
26
|
+
}), l.useEffect(() => {
|
|
27
|
+
A || N().finally();
|
|
28
|
+
}, []), l.useEffect(() => {
|
|
29
|
+
p && w().finally();
|
|
30
|
+
}, [p]), l.useEffect(() => {
|
|
31
|
+
n && (o === 1 && !m && f(0), o === 2 && !d && f(0));
|
|
32
|
+
}, [
|
|
33
|
+
o,
|
|
34
|
+
m,
|
|
35
|
+
d,
|
|
36
|
+
n
|
|
37
|
+
]);
|
|
38
|
+
const M = () => {
|
|
39
|
+
c(s.INVESTMENT_WIDGET_ACCOUNT_FILTER_CLICK);
|
|
32
40
|
};
|
|
33
|
-
if (!
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
],
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
if (!p || !n) return /* @__PURE__ */ t(j, {});
|
|
42
|
+
const G = [
|
|
43
|
+
s.INVESTMENT_WIDGET_DETAILS_CLICK,
|
|
44
|
+
s.INVESTMENT_WIDGET_ALLOCATION_CLICK,
|
|
45
|
+
s.INVESTMENT_WIDGET_ANALYSIS_CLICK
|
|
46
|
+
], i = L.length === 0 && x.length === 0, b = [
|
|
47
|
+
{
|
|
48
|
+
title: e.tab_overview_title,
|
|
49
|
+
disabled: !1,
|
|
50
|
+
tooltip: ""
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: e.tab_allocation_title,
|
|
54
|
+
disabled: !m,
|
|
55
|
+
tooltip: e.allocation.empty_data
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
title: e.tab_analysis_title,
|
|
59
|
+
disabled: !d,
|
|
60
|
+
tooltip: e.analysis.empty_data
|
|
61
|
+
}
|
|
42
62
|
];
|
|
43
|
-
return /* @__PURE__ */
|
|
44
|
-
allowedAccountTypes: [
|
|
45
|
-
onAccountsFilterClick:
|
|
46
|
-
onBackClick:
|
|
47
|
-
onMenuClick:
|
|
48
|
-
sx:
|
|
63
|
+
return /* @__PURE__ */ T(z, {
|
|
64
|
+
allowedAccountTypes: [U.INVESTMENT],
|
|
65
|
+
onAccountsFilterClick: M,
|
|
66
|
+
onBackClick: I,
|
|
67
|
+
onMenuClick: S,
|
|
68
|
+
sx: g,
|
|
49
69
|
title: e.title,
|
|
50
|
-
children: [/* @__PURE__ */
|
|
51
|
-
mx:
|
|
70
|
+
children: [/* @__PURE__ */ T(Q, {
|
|
71
|
+
mx: v ? 0 : 48,
|
|
52
72
|
my: 24,
|
|
53
|
-
children: [/* @__PURE__ */ t(
|
|
54
|
-
onChange: (
|
|
55
|
-
|
|
73
|
+
children: [/* @__PURE__ */ t(tt, {
|
|
74
|
+
onChange: (r, a) => {
|
|
75
|
+
i || b[a]?.disabled || (f(a), c(G[a]));
|
|
56
76
|
},
|
|
57
77
|
sx: { bgcolor: "background.paper" },
|
|
58
78
|
textColor: "primary",
|
|
59
|
-
value:
|
|
79
|
+
value: i ? !1 : o,
|
|
60
80
|
variant: "fullWidth",
|
|
61
|
-
children:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
81
|
+
children: b.map(({ title: r, disabled: a, tooltip: C }) => {
|
|
82
|
+
const u = i || a, E = u && !i && !!C, h = /* @__PURE__ */ t(Z, {
|
|
83
|
+
"aria-disabled": u || void 0,
|
|
84
|
+
label: /* @__PURE__ */ t(J, { title: r }),
|
|
85
|
+
sx: {
|
|
86
|
+
...E && { flex: 1 },
|
|
87
|
+
...u && {
|
|
88
|
+
opacity: 0.38,
|
|
89
|
+
cursor: "default"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}, r);
|
|
93
|
+
return E ? /* @__PURE__ */ t(et, {
|
|
94
|
+
describeChild: !0,
|
|
95
|
+
title: C,
|
|
96
|
+
children: h
|
|
97
|
+
}, r) : h;
|
|
98
|
+
})
|
|
99
|
+
}), i ? /* @__PURE__ */ t(B, {
|
|
66
100
|
header: e.empty_state_header,
|
|
67
101
|
icon: "bid_landscape",
|
|
68
102
|
onClick: () => {
|
|
69
|
-
|
|
103
|
+
_(!0), c(s.ACCOUNTS_CLICK_CONNECT);
|
|
70
104
|
},
|
|
71
105
|
primaryButton: e.overview.connect_accounts,
|
|
72
106
|
subText: e.empty_state_description,
|
|
@@ -79,20 +113,20 @@ var ut = R(({ onBackClick: u, onMenuClick: T, sx: _ }) => {
|
|
|
79
113
|
},
|
|
80
114
|
px: 16
|
|
81
115
|
}
|
|
82
|
-
}) : /* @__PURE__ */
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
116
|
+
}) : /* @__PURE__ */ T(X, { children: [
|
|
117
|
+
o === 0 && /* @__PURE__ */ t(q, {}),
|
|
118
|
+
o === 1 && /* @__PURE__ */ t(Y, {}),
|
|
119
|
+
o === 2 && /* @__PURE__ */ t($, {})
|
|
86
120
|
] })]
|
|
87
|
-
}), /* @__PURE__ */ t(
|
|
88
|
-
onClose: () =>
|
|
89
|
-
showConnectionsWidget:
|
|
90
|
-
title:
|
|
121
|
+
}), /* @__PURE__ */ t(R, {
|
|
122
|
+
onClose: () => _(!1),
|
|
123
|
+
showConnectionsWidget: D,
|
|
124
|
+
title: W.manage_connections
|
|
91
125
|
})]
|
|
92
126
|
});
|
|
93
127
|
});
|
|
94
128
|
export {
|
|
95
|
-
|
|
129
|
+
It as InvestmentsWidget
|
|
96
130
|
};
|
|
97
131
|
|
|
98
132
|
//# sourceMappingURL=InvestmentsWidget.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvestmentsWidget.es.js","names":[],"sources":["../../src/investments/InvestmentsWidget.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\n\nimport {\n ANALYTICS_EVENTS,\n EmptyState,\n Loader,\n useAccountStore,\n useEvent,\n useGlobalCopyStore,\n useGlobalUiStore,\n useHoldingStore,\n useScreenSize,\n useWidgetLoadTimer,\n WidgetContainer,\n} from '../common'\nimport { AccountType, WidgetProps } from '../core'\n\nimport ConnectionsDrawer from '../accounts/components/ConnectionsDrawer'\nimport Allocation from './components/Allocation'\nimport Analysis from './components/Analysis'\nimport Overview from './components/Overview'\nimport { TabTitle } from './components/TabTitle'\n\nexport const InvestmentsWidget = observer(({ onBackClick, onMenuClick, sx }: WidgetProps) => {\n const { onEvent } = useEvent()\n const { isMobile } = useScreenSize()\n const {\n isAccountDataLoaded,\n loadAccountData,\n visibleInvestmentAccounts: accounts,\n } = useAccountStore()\n const {\n visibleHoldings: holdings,\n setShowConnectionsWidget,\n showConnectionsWidget,\n } = useHoldingStore()\n const { investments: copy, accounts: accountsCopy } = useGlobalCopyStore()\n\n const { isInitialized } = useGlobalUiStore()\n\n const [selectedTab, setSelectedTab] = React.useState(0)\n\n const { loadHoldings, holdingsLoaded } = useHoldingStore()\n\n useWidgetLoadTimer({\n widgetName: 'InvestmentsWidget',\n isLoaded: holdingsLoaded,\n })\n\n React.useEffect(() => {\n if (!isAccountDataLoaded) {\n loadAccountData().finally()\n }\n }, [])\n\n React.useEffect(() => {\n if (isInitialized) {\n loadHoldings().finally()\n }\n }, [isInitialized])\n\n const handleAccountFilterClick = () => {\n onEvent(ANALYTICS_EVENTS.INVESTMENT_WIDGET_ACCOUNT_FILTER_CLICK)\n }\n\n if (!isInitialized || !holdingsLoaded) return <Loader />\n\n const events = [\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_DETAILS_CLICK,\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_ALLOCATION_CLICK,\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_ANALYSIS_CLICK,\n ]\n const isEmptyState = accounts.length === 0 && holdings.length === 0\n const investmentTabs = [\n copy.tab_overview_title,\n copy.tab_allocation_title,\n copy.tab_analysis_title,\n ]\n return (\n <WidgetContainer\n allowedAccountTypes={[AccountType.INVESTMENT]}\n onAccountsFilterClick={handleAccountFilterClick}\n onBackClick={onBackClick}\n onMenuClick={onMenuClick}\n sx={sx}\n title={copy.title}\n >\n <Stack mx={isMobile ? 0 : 48} my={24}>\n <Tabs\n onChange={(_, newValue) => {\n setSelectedTab(newValue)\n onEvent(events[newValue])\n }}\n sx={{ bgcolor: 'background.paper' }}\n textColor=\"primary\"\n value={!isEmptyState ? selectedTab : false}\n variant=\"fullWidth\"\n >\n {investmentTabs.map((title) => (\n <Tab
|
|
1
|
+
{"version":3,"file":"InvestmentsWidget.es.js","names":[],"sources":["../../src/investments/InvestmentsWidget.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\nimport Tooltip from '@mui/material/Tooltip'\n\nimport {\n ANALYTICS_EVENTS,\n EmptyState,\n Loader,\n useAccountStore,\n useEvent,\n useGlobalCopyStore,\n useGlobalUiStore,\n useHoldingStore,\n useScreenSize,\n useWidgetLoadTimer,\n WidgetContainer,\n} from '../common'\nimport { AccountType, WidgetProps } from '../core'\n\nimport ConnectionsDrawer from '../accounts/components/ConnectionsDrawer'\nimport Allocation from './components/Allocation'\nimport Analysis from './components/Analysis'\nimport Overview from './components/Overview'\nimport { TabTitle } from './components/TabTitle'\n\nexport const InvestmentsWidget = observer(({ onBackClick, onMenuClick, sx }: WidgetProps) => {\n const { onEvent } = useEvent()\n const { isMobile } = useScreenSize()\n const {\n isAccountDataLoaded,\n loadAccountData,\n visibleInvestmentAccounts: accounts,\n } = useAccountStore()\n const {\n visibleHoldings: holdings,\n hasAllocationData,\n hasAnalysisData,\n setShowConnectionsWidget,\n showConnectionsWidget,\n } = useHoldingStore()\n const { investments: copy, accounts: accountsCopy } = useGlobalCopyStore()\n\n const { isInitialized } = useGlobalUiStore()\n\n const [selectedTab, setSelectedTab] = React.useState(0)\n\n const { loadHoldings, holdingsLoaded } = useHoldingStore()\n\n useWidgetLoadTimer({\n widgetName: 'InvestmentsWidget',\n isLoaded: holdingsLoaded,\n })\n\n React.useEffect(() => {\n if (!isAccountDataLoaded) {\n loadAccountData().finally()\n }\n }, [])\n\n React.useEffect(() => {\n if (isInitialized) {\n loadHoldings().finally()\n }\n }, [isInitialized])\n\n // Reset to Overview if the active tab becomes disabled. Only act once holdings\n // are loaded so a mid-refetch (getters briefly false) doesn't eject the user.\n // Depend only on the boolean getters, never `visibleHoldings` (new array each\n // access → render loop).\n React.useEffect(() => {\n if (!holdingsLoaded) return\n if (selectedTab === 1 && !hasAllocationData) setSelectedTab(0)\n if (selectedTab === 2 && !hasAnalysisData) setSelectedTab(0)\n }, [selectedTab, hasAllocationData, hasAnalysisData, holdingsLoaded])\n\n const handleAccountFilterClick = () => {\n onEvent(ANALYTICS_EVENTS.INVESTMENT_WIDGET_ACCOUNT_FILTER_CLICK)\n }\n\n if (!isInitialized || !holdingsLoaded) return <Loader />\n\n const events = [\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_DETAILS_CLICK,\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_ALLOCATION_CLICK,\n ANALYTICS_EVENTS.INVESTMENT_WIDGET_ANALYSIS_CLICK,\n ]\n const isEmptyState = accounts.length === 0 && holdings.length === 0\n const investmentTabs = [\n { title: copy.tab_overview_title, disabled: false, tooltip: '' },\n {\n title: copy.tab_allocation_title,\n disabled: !hasAllocationData,\n tooltip: copy.allocation.empty_data,\n },\n {\n title: copy.tab_analysis_title,\n disabled: !hasAnalysisData,\n tooltip: copy.analysis.empty_data,\n },\n ]\n return (\n <WidgetContainer\n allowedAccountTypes={[AccountType.INVESTMENT]}\n onAccountsFilterClick={handleAccountFilterClick}\n onBackClick={onBackClick}\n onMenuClick={onMenuClick}\n sx={sx}\n title={copy.title}\n >\n <Stack mx={isMobile ? 0 : 48} my={24}>\n <Tabs\n onChange={(_, newValue) => {\n // aria-disabled tabs stay clickable; block their selection here.\n if (isEmptyState || investmentTabs[newValue]?.disabled) return\n setSelectedTab(newValue)\n onEvent(events[newValue])\n }}\n sx={{ bgcolor: 'background.paper' }}\n textColor=\"primary\"\n value={!isEmptyState ? selectedTab : false}\n variant=\"fullWidth\"\n >\n {investmentTabs.map(({ title, disabled, tooltip }) => {\n const isDisabled = isEmptyState || disabled\n const isTooltipTab = isDisabled && !isEmptyState && Boolean(tooltip)\n // aria-disabled (not native disabled) keeps the Tab focusable and in\n // the a11y tree; describeChild adds the reason without stealing the name.\n const tab = (\n <Tab\n aria-disabled={isDisabled || undefined}\n key={title}\n label={<TabTitle title={title} />}\n sx={{\n ...(isTooltipTab && { flex: 1 }),\n ...(isDisabled && {\n opacity: 0.38,\n cursor: 'default',\n }),\n }}\n />\n )\n\n return isTooltipTab ? (\n <Tooltip describeChild key={title} title={tooltip}>\n {tab}\n </Tooltip>\n ) : (\n tab\n )\n })}\n </Tabs>\n {isEmptyState ? (\n <EmptyState\n header={copy.empty_state_header}\n icon=\"bid_landscape\"\n onClick={() => {\n setShowConnectionsWidget(true)\n onEvent(ANALYTICS_EVENTS.ACCOUNTS_CLICK_CONNECT)\n }}\n primaryButton={copy.overview.connect_accounts}\n subText={copy.empty_state_description}\n sx={{\n width: { sm: 432 },\n '.buttons-footer': {\n width: 167,\n },\n '.MuiTypography-h2': {\n mt: 20,\n mb: 4,\n },\n px: 16,\n }}\n />\n ) : (\n <>\n {selectedTab === 0 && <Overview />}\n {selectedTab === 1 && <Allocation />}\n {selectedTab === 2 && <Analysis />}\n </>\n )}\n </Stack>\n <ConnectionsDrawer\n onClose={() => setShowConnectionsWidget(false)}\n showConnectionsWidget={showConnectionsWidget}\n title={accountsCopy.manage_connections}\n />\n </WidgetContainer>\n )\n})\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { formatCurrency as
|
|
2
|
-
|
|
1
|
+
import { formatCurrency as L, formatPercentage as k } from "../../../../core/utils/NumberFormatting.es.js";
|
|
2
|
+
import { ALLOCATION_KEYS as B } from "../../../../core/constants/Investments.es.js";
|
|
3
|
+
var C = {
|
|
3
4
|
allocations_cash: "#AEDCCC",
|
|
4
5
|
allocations_convertible: "#80CAD0",
|
|
5
6
|
allocations_foreign_bond: "#51B9D4",
|
|
@@ -9,95 +10,85 @@ var L = {
|
|
|
9
10
|
allocations_unknown: "#161D6A",
|
|
10
11
|
allocations_us_bond: "#254995",
|
|
11
12
|
allocations_us_stock: "#1E2D84"
|
|
12
|
-
}, y =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
], C = (e, l, c) => {
|
|
23
|
-
const i = c === void 0 ? 0 : l, t = c === void 0 ? l : c;
|
|
24
|
-
return e >= Math.min(i, t) && e < Math.max(i, t);
|
|
25
|
-
}, h = (e, l, c) => {
|
|
26
|
-
const i = [...new Set(e.map((r) => r.name.toLowerCase()))];
|
|
27
|
-
let t;
|
|
28
|
-
return i.map((r) => {
|
|
29
|
-
const _ = e.reduce((m, o) => {
|
|
30
|
-
const p = o.name;
|
|
31
|
-
return p.toLowerCase() === r ? (t = p, v(o) * o[l] / 100 + m) : m;
|
|
13
|
+
}, y = B.map((t) => ({ name: t })), V = (t, l, r) => {
|
|
14
|
+
const i = r === void 0 ? 0 : l, e = r === void 0 ? l : r;
|
|
15
|
+
return t >= Math.min(i, e) && t < Math.max(i, e);
|
|
16
|
+
}, h = (t, l, r) => {
|
|
17
|
+
const i = [...new Set(t.map((c) => c.name.toLowerCase()))];
|
|
18
|
+
let e;
|
|
19
|
+
return i.map((c) => {
|
|
20
|
+
const _ = t.reduce((m, s) => {
|
|
21
|
+
const p = s.name;
|
|
22
|
+
return p.toLowerCase() === c ? (e = p, d(s) * s[l] / 100 + m) : m;
|
|
32
23
|
}, 0);
|
|
33
24
|
return {
|
|
34
|
-
displayName:
|
|
35
|
-
name:
|
|
25
|
+
displayName: e,
|
|
26
|
+
name: e,
|
|
36
27
|
value: _,
|
|
37
|
-
percentage: _ /
|
|
28
|
+
percentage: _ / r
|
|
38
29
|
};
|
|
39
30
|
});
|
|
40
|
-
},
|
|
41
|
-
const i = Object.values(l.allocations_list),
|
|
42
|
-
let
|
|
43
|
-
const _ =
|
|
31
|
+
}, d = (t) => t.calculated_market_value ? t.calculated_market_value : t.market_value, E = (t, l, r) => {
|
|
32
|
+
const i = Object.values(l.allocations_list), e = [];
|
|
33
|
+
let c = 0;
|
|
34
|
+
const _ = new Set(t.map(({ guid: a }) => a)), m = r.filter(({ account_guid: a }) => _.has(a)).map((a) => ({
|
|
44
35
|
...a,
|
|
45
36
|
name: a.symbol || a.description,
|
|
46
|
-
gainLoss: a.cost_basis || a.cost_basis === 0 ?
|
|
47
|
-
})), { cashBalance:
|
|
37
|
+
gainLoss: a.cost_basis || a.cost_basis === 0 ? d(a) - a.cost_basis : 0
|
|
38
|
+
})), { cashBalance: s, totalAccountBalance: p } = t.reduce((a, n) => ({
|
|
48
39
|
cashBalance: a.cashBalance + (n.cash_balance || 0),
|
|
49
40
|
totalAccountBalance: a.totalAccountBalance + (n.balance || 0)
|
|
50
41
|
}), {
|
|
51
42
|
cashBalance: 0,
|
|
52
43
|
totalAccountBalance: 0
|
|
53
|
-
}), { marketValue:
|
|
54
|
-
marketValue: a.marketValue +
|
|
44
|
+
}), { marketValue: b, totalGainLoss: A } = m.reduce((a, n) => ({
|
|
45
|
+
marketValue: a.marketValue + d(n),
|
|
55
46
|
totalGainLoss: a.totalGainLoss + n.gainLoss
|
|
56
47
|
}), {
|
|
57
48
|
marketValue: 0,
|
|
58
49
|
totalGainLoss: 0
|
|
59
|
-
}), f =
|
|
50
|
+
}), f = b + s;
|
|
60
51
|
return y.forEach((a, n) => {
|
|
61
|
-
const
|
|
62
|
-
let
|
|
63
|
-
const
|
|
64
|
-
if (a.name === "allocations_cash" &&
|
|
65
|
-
|
|
52
|
+
const v = m.filter((u) => !!u[a.name]);
|
|
53
|
+
let o = v.reduce((u, g) => u + d(g) * g[a.name] / 100, 0);
|
|
54
|
+
const D = h(v, a.name, o);
|
|
55
|
+
if (a.name === "allocations_cash" && s > 0) {
|
|
56
|
+
o += s;
|
|
66
57
|
const u = {
|
|
67
58
|
displayName: l.cash_balance_display_name,
|
|
68
59
|
name: "allocations_name",
|
|
69
|
-
value:
|
|
70
|
-
percentage:
|
|
60
|
+
value: s,
|
|
61
|
+
percentage: s / f
|
|
71
62
|
};
|
|
72
|
-
|
|
63
|
+
D.push(u);
|
|
73
64
|
}
|
|
74
|
-
|
|
65
|
+
o > 0 && (e.push({
|
|
75
66
|
name: a.name,
|
|
76
67
|
displayName: i[n],
|
|
77
68
|
guid: `${a.name}-${n}`,
|
|
78
|
-
holdings:
|
|
79
|
-
percentage:
|
|
80
|
-
value:
|
|
81
|
-
color:
|
|
82
|
-
}),
|
|
69
|
+
holdings: D,
|
|
70
|
+
percentage: o / f,
|
|
71
|
+
value: o,
|
|
72
|
+
color: C[a.name]
|
|
73
|
+
}), c += o);
|
|
83
74
|
}), {
|
|
84
|
-
investmentsData:
|
|
85
|
-
donutData:
|
|
75
|
+
investmentsData: e,
|
|
76
|
+
donutData: e.map(({ displayName: a, guid: n, color: v, value: o }) => ({
|
|
86
77
|
id: n,
|
|
87
|
-
color:
|
|
78
|
+
color: v,
|
|
88
79
|
label: a,
|
|
89
|
-
value:
|
|
80
|
+
value: o / c * 100
|
|
90
81
|
})),
|
|
91
|
-
totalAmount:
|
|
92
|
-
totalGainLoss:
|
|
82
|
+
totalAmount: c,
|
|
83
|
+
totalGainLoss: A,
|
|
93
84
|
totalMarketValue: f,
|
|
94
|
-
totalGainLossPercentage:
|
|
85
|
+
totalGainLossPercentage: A / p
|
|
95
86
|
};
|
|
96
|
-
},
|
|
87
|
+
}, N = (t) => t < 1e-3 ? "< 0.1%" : k(t), S = (t) => t === 0 ? L(t, "0,0.00") : V(t, -0.01, 0.01) ? "< $0.01" : L(t, "0,0.00");
|
|
97
88
|
export {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
E as createInvestmentsAllocationData,
|
|
90
|
+
S as currencyDisplay,
|
|
91
|
+
N as percentageDisplay
|
|
101
92
|
};
|
|
102
93
|
|
|
103
94
|
//# sourceMappingURL=createInvestementsAllocationData.es.js.map
|
package/dist/investments/components/allocation/util/createInvestementsAllocationData.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createInvestementsAllocationData.es.js","names":[],"sources":["../../../../../src/investments/components/allocation/util/createInvestementsAllocationData.tsx"],"sourcesContent":["import { Account, Holding } from '../../../../core'\nimport { InvestmentAllocationCopy } from '../../../../core/types/localization/InvestmentsCopy'\nimport type { DonutData } from '../InvestmentsAllocationChart'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\n\nexport interface InvestmentsAllocationData {\n name: string\n displayName: string\n guid: string\n holdings: InvestmentAllocationTotals[]\n percentage: number\n value: number\n color: string\n}\nexport interface InvestmentAllocationTotals {\n displayName: string\n name: string\n value: number\n percentage: number\n}\n\nconst allocationColors = {\n allocations_cash: '#AEDCCC',\n allocations_convertible: '#80CAD0',\n allocations_foreign_bond: '#51B9D4',\n allocations_foreign_stock: '#3DA0C9',\n allocations_other: '#3583B8',\n allocations_preferred: '#2D66A7',\n allocations_unknown: '#161D6A',\n allocations_us_bond: '#254995',\n allocations_us_stock: '#1E2D84',\n}\nconst allocationsList = [\n {\n name: 'allocations_cash',\n },\n {\n name: 'allocations_convertible',\n },\n {\n name: 'allocations_foreign_bond',\n },\n {\n name: 'allocations_foreign_stock',\n },\n {\n name: 'allocations_other',\n },\n {\n name: 'allocations_preferred',\n },\n {\n name: 'allocations_us_bond',\n },\n {\n name: 'allocations_us_stock',\n },\n {\n name: 'allocations_unknown',\n },\n]\n\nconst inRange = (n: number, start: number, end?: number) => {\n const rangeStart = end === undefined ? 0 : start\n const rangeEnd = end === undefined ? start : end\n return n >= Math.min(rangeStart, rangeEnd) && n < Math.max(rangeStart, rangeEnd)\n}\n\nconst createHoldingsData = (\n holdings: Holding[],\n allocationName: string,\n allocationValue: number,\n) => {\n const uniqueHoldings = [\n ...new Set(holdings.map((holding: Holding) => holding.name.toLowerCase())),\n ]\n let displayName: string\n const investmentAllocationTotals = uniqueHoldings.map((holdingName) => {\n // sum all the holdings with the same \"name\"\n const holdingsTotalValue = holdings.reduce((acc, hold: Holding) => {\n const name = hold.name\n\n if (name.toLowerCase() === holdingName) {\n // Since we lose the capitalization with the unique names, we take it from the last match.\n displayName = name\n return (\n (getHoldingValue(hold) * hold[allocationName as keyof typeof allocationColors]) / 100 +\n acc\n )\n }\n\n return acc\n }, 0)\n\n return {\n displayName,\n name: displayName,\n value: holdingsTotalValue,\n percentage: holdingsTotalValue / allocationValue,\n }\n })\n return investmentAllocationTotals\n}\n\nconst getHoldingValue = (holding: Holding) =>\n holding.calculated_market_value ? holding.calculated_market_value : holding.market_value\n\nexport const createInvestmentsAllocationData = (\n accounts: Account[],\n copy: InvestmentAllocationCopy,\n holdings: Holding[],\n) => {\n const allocationListDisplayNames = Object.values(copy.allocations_list)\n const investementAllocationData: InvestmentsAllocationData[] = []\n\n let totalAmount = 0\n\n const accountGuids = accounts.map(({ guid }) => guid)\n const updatedHoldings: Holding[] = holdings\n .filter(({ account_guid }) => accountGuids.includes(account_guid))\n .map((eachHolding) => {\n return {\n ...eachHolding,\n name: eachHolding.symbol || eachHolding.description,\n gainLoss:\n eachHolding.cost_basis || eachHolding.cost_basis === 0\n ? getHoldingValue(eachHolding) - eachHolding.cost_basis\n : 0,\n }\n })\n\n const { cashBalance, totalAccountBalance } = accounts.reduce(\n (sum, account) => {\n return {\n cashBalance: sum.cashBalance + (account.cash_balance || 0),\n totalAccountBalance: sum.totalAccountBalance + (account.balance || 0),\n }\n },\n { cashBalance: 0, totalAccountBalance: 0 },\n )\n const { marketValue, totalGainLoss } = updatedHoldings.reduce(\n (acc, holding) => {\n return {\n marketValue: acc.marketValue + getHoldingValue(holding),\n totalGainLoss: acc.totalGainLoss + holding.gainLoss,\n }\n },\n { marketValue: 0, totalGainLoss: 0 },\n )\n const totalMarketValue = marketValue + cashBalance\n\n allocationsList.forEach((allocation, index) => {\n const filteredHoldings = updatedHoldings.filter(\n (eachHolding) => !!eachHolding[allocation.name as keyof typeof allocationColors],\n )\n let holdingsTotal = filteredHoldings.reduce(\n (sum, holding) =>\n sum +\n (getHoldingValue(holding) * holding[allocation.name as keyof typeof allocationColors]) /\n 100,\n 0,\n )\n const investmentAllocationTotals = createHoldingsData(\n filteredHoldings,\n allocation.name,\n holdingsTotal,\n )\n if (allocation.name === 'allocations_cash' && cashBalance > 0) {\n // Updating holdingsTotal to include cash balance\n // This affects the holdingsTotal and percentage for this allocation\n holdingsTotal += cashBalance\n\n // Creating a holding item for cash balance\n const cashBalanceHolding = {\n displayName: copy.cash_balance_display_name,\n name: 'allocations_name',\n value: cashBalance,\n percentage: cashBalance / totalMarketValue,\n }\n\n investmentAllocationTotals.push(cashBalanceHolding)\n }\n\n // Shows allocation if holdingsTotal is greater than zero\n if (holdingsTotal > 0) {\n investementAllocationData.push({\n name: allocation.name,\n displayName: allocationListDisplayNames[index],\n guid: `${allocation.name}-${index}`,\n holdings: investmentAllocationTotals,\n percentage: holdingsTotal / totalMarketValue,\n value: holdingsTotal,\n color: allocationColors[allocation.name as keyof typeof allocationColors],\n })\n totalAmount += holdingsTotal\n }\n })\n const donutData: DonutData[] = investementAllocationData.map(\n ({ displayName, guid, color, value }) => ({\n id: guid,\n color: color,\n label: displayName,\n value: (value / totalAmount) * 100,\n }),\n )\n\n return {\n investmentsData: investementAllocationData,\n donutData,\n totalAmount,\n totalGainLoss,\n totalMarketValue,\n totalGainLossPercentage: totalGainLoss / totalAccountBalance,\n }\n}\n\nexport const percentageDisplay = (value: number) =>\n value < 0.001 ? '< 0.1%' : formatPercentage(value)\n\nexport const currencyDisplay = (value: number) => {\n if (value === 0) return formatCurrency(value, '0,0.00')\n return inRange(value, -0.01, 0.01) ? '< $0.01' : formatCurrency(value, '0,0.00')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createInvestementsAllocationData.es.js","names":[],"sources":["../../../../../src/investments/components/allocation/util/createInvestementsAllocationData.tsx"],"sourcesContent":["import { Account, Holding } from '../../../../core'\nimport { ALLOCATION_KEYS, type AllocationKey } from '../../../../core/constants/Investments'\nimport { InvestmentAllocationCopy } from '../../../../core/types/localization/InvestmentsCopy'\nimport type { DonutData } from '../InvestmentsAllocationChart'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\n\nexport interface InvestmentsAllocationData {\n name: string\n displayName: string\n guid: string\n holdings: InvestmentAllocationTotals[]\n percentage: number\n value: number\n color: string\n}\nexport interface InvestmentAllocationTotals {\n displayName: string\n name: string\n value: number\n percentage: number\n}\n\nconst allocationColors: Record<AllocationKey, string> = {\n allocations_cash: '#AEDCCC',\n allocations_convertible: '#80CAD0',\n allocations_foreign_bond: '#51B9D4',\n allocations_foreign_stock: '#3DA0C9',\n allocations_other: '#3583B8',\n allocations_preferred: '#2D66A7',\n allocations_unknown: '#161D6A',\n allocations_us_bond: '#254995',\n allocations_us_stock: '#1E2D84',\n}\nconst allocationsList = ALLOCATION_KEYS.map((name) => ({ name }))\n\nconst inRange = (n: number, start: number, end?: number) => {\n const rangeStart = end === undefined ? 0 : start\n const rangeEnd = end === undefined ? start : end\n return n >= Math.min(rangeStart, rangeEnd) && n < Math.max(rangeStart, rangeEnd)\n}\n\nconst createHoldingsData = (\n holdings: Holding[],\n allocationName: string,\n allocationValue: number,\n) => {\n const uniqueHoldings = [\n ...new Set(holdings.map((holding: Holding) => holding.name.toLowerCase())),\n ]\n let displayName: string\n const investmentAllocationTotals = uniqueHoldings.map((holdingName) => {\n // sum all the holdings with the same \"name\"\n const holdingsTotalValue = holdings.reduce((acc, hold: Holding) => {\n const name = hold.name\n\n if (name.toLowerCase() === holdingName) {\n // Since we lose the capitalization with the unique names, we take it from the last match.\n displayName = name\n return (\n (getHoldingValue(hold) * hold[allocationName as keyof typeof allocationColors]) / 100 +\n acc\n )\n }\n\n return acc\n }, 0)\n\n return {\n displayName,\n name: displayName,\n value: holdingsTotalValue,\n percentage: holdingsTotalValue / allocationValue,\n }\n })\n return investmentAllocationTotals\n}\n\nconst getHoldingValue = (holding: Holding) =>\n holding.calculated_market_value ? holding.calculated_market_value : holding.market_value\n\nexport const createInvestmentsAllocationData = (\n accounts: Account[],\n copy: InvestmentAllocationCopy,\n holdings: Holding[],\n) => {\n const allocationListDisplayNames = Object.values(copy.allocations_list)\n const investementAllocationData: InvestmentsAllocationData[] = []\n\n let totalAmount = 0\n\n const accountGuids = new Set(accounts.map(({ guid }) => guid))\n const updatedHoldings: Holding[] = holdings\n .filter(({ account_guid }) => accountGuids.has(account_guid))\n .map((eachHolding) => {\n return {\n ...eachHolding,\n name: eachHolding.symbol || eachHolding.description,\n gainLoss:\n eachHolding.cost_basis || eachHolding.cost_basis === 0\n ? getHoldingValue(eachHolding) - eachHolding.cost_basis\n : 0,\n }\n })\n\n const { cashBalance, totalAccountBalance } = accounts.reduce(\n (sum, account) => {\n return {\n cashBalance: sum.cashBalance + (account.cash_balance || 0),\n totalAccountBalance: sum.totalAccountBalance + (account.balance || 0),\n }\n },\n { cashBalance: 0, totalAccountBalance: 0 },\n )\n const { marketValue, totalGainLoss } = updatedHoldings.reduce(\n (acc, holding) => {\n return {\n marketValue: acc.marketValue + getHoldingValue(holding),\n totalGainLoss: acc.totalGainLoss + holding.gainLoss,\n }\n },\n { marketValue: 0, totalGainLoss: 0 },\n )\n const totalMarketValue = marketValue + cashBalance\n\n allocationsList.forEach((allocation, index) => {\n const filteredHoldings = updatedHoldings.filter(\n (eachHolding) => !!eachHolding[allocation.name as keyof typeof allocationColors],\n )\n let holdingsTotal = filteredHoldings.reduce(\n (sum, holding) =>\n sum +\n (getHoldingValue(holding) * holding[allocation.name as keyof typeof allocationColors]) /\n 100,\n 0,\n )\n const investmentAllocationTotals = createHoldingsData(\n filteredHoldings,\n allocation.name,\n holdingsTotal,\n )\n if (allocation.name === 'allocations_cash' && cashBalance > 0) {\n // Updating holdingsTotal to include cash balance\n // This affects the holdingsTotal and percentage for this allocation\n holdingsTotal += cashBalance\n\n // Creating a holding item for cash balance\n const cashBalanceHolding = {\n displayName: copy.cash_balance_display_name,\n name: 'allocations_name',\n value: cashBalance,\n percentage: cashBalance / totalMarketValue,\n }\n\n investmentAllocationTotals.push(cashBalanceHolding)\n }\n\n // Shows allocation if holdingsTotal is greater than zero\n if (holdingsTotal > 0) {\n investementAllocationData.push({\n name: allocation.name,\n displayName: allocationListDisplayNames[index],\n guid: `${allocation.name}-${index}`,\n holdings: investmentAllocationTotals,\n percentage: holdingsTotal / totalMarketValue,\n value: holdingsTotal,\n color: allocationColors[allocation.name as keyof typeof allocationColors],\n })\n totalAmount += holdingsTotal\n }\n })\n const donutData: DonutData[] = investementAllocationData.map(\n ({ displayName, guid, color, value }) => ({\n id: guid,\n color: color,\n label: displayName,\n value: (value / totalAmount) * 100,\n }),\n )\n\n return {\n investmentsData: investementAllocationData,\n donutData,\n totalAmount,\n totalGainLoss,\n totalMarketValue,\n totalGainLossPercentage: totalGainLoss / totalAccountBalance,\n }\n}\n\nexport const percentageDisplay = (value: number) =>\n value < 0.001 ? '< 0.1%' : formatPercentage(value)\n\nexport const currencyDisplay = (value: number) => {\n if (value === 0) return formatCurrency(value, '0,0.00')\n return inRange(value, -0.01, 0.01) ? '< $0.01' : formatCurrency(value, '0,0.00')\n}\n"],"mappings":"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"}
|