Browse Source

Task/improve type safety in portfolio proportion chart component (#6491)

* Improve type safety in portfolio proportion chart component
pull/6521/head
Kenrick Tandrian 1 week ago
committed by GitHub
parent
commit
8bca0f5830
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 92
      libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts

92
libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts

@ -13,12 +13,11 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
ElementRef, ElementRef,
EventEmitter,
Input, Input,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
Output, output,
ViewChild viewChild
} from '@angular/core'; } from '@angular/core';
import { DataSource } from '@prisma/client'; import { DataSource } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
@ -81,15 +80,16 @@ export class GfPortfolioProportionChartComponent
@Input() maxItems?: number; @Input() maxItems?: number;
@Input() showLabels = false; @Input() showLabels = false;
@Output() proportionChartClicked = new EventEmitter<AssetProfileIdentifier>();
@ViewChild('chartCanvas') chartCanvas: ElementRef<HTMLCanvasElement>;
public chart: Chart<'doughnut'>; public chart: Chart<'doughnut'>;
public isLoading = true; public isLoading = true;
protected readonly proportionChartClicked = output<AssetProfileIdentifier>();
private readonly OTHER_KEY = 'OTHER'; private readonly OTHER_KEY = 'OTHER';
private readonly chartCanvas =
viewChild.required<ElementRef<HTMLCanvasElement>>('chartCanvas');
private colorMap: { private colorMap: {
[symbol: string]: string; [symbol: string]: string;
} = {}; } = {};
@ -130,45 +130,45 @@ export class GfPortfolioProportionChartComponent
}; };
if (this.keys.length > 0) { if (this.keys.length > 0) {
const primaryKey = this.keys[0];
const secondaryKey = this.keys[1];
Object.keys(this.data).forEach((symbol) => { Object.keys(this.data).forEach((symbol) => {
if (this.data[symbol][this.keys[0]]?.toUpperCase()) { const asset = this.data[symbol];
if (chartData[this.data[symbol][this.keys[0]].toUpperCase()]) { const assetValue = asset.value || 0;
chartData[this.data[symbol][this.keys[0]].toUpperCase()].value = const primaryKeyValue = (asset[primaryKey] as string)?.toUpperCase();
chartData[ const secondaryKeyValue = asset[secondaryKey] as string;
this.data[symbol][this.keys[0]].toUpperCase()
].value.plus(this.data[symbol].value || 0); if (primaryKeyValue) {
if (chartData[primaryKeyValue]) {
if ( chartData[primaryKeyValue].value =
chartData[this.data[symbol][this.keys[0]].toUpperCase()] chartData[primaryKeyValue].value.plus(assetValue);
.subCategory[this.data[symbol][this.keys[1]]]
) { const targetSubCategory =
chartData[ chartData[primaryKeyValue].subCategory?.[secondaryKeyValue];
this.data[symbol][this.keys[0]].toUpperCase() if (targetSubCategory) {
].subCategory[this.data[symbol][this.keys[1]]].value = chartData[ targetSubCategory.value =
this.data[symbol][this.keys[0]].toUpperCase() targetSubCategory.value.plus(assetValue);
].subCategory[this.data[symbol][this.keys[1]]].value.plus(
this.data[symbol].value || 0
);
} else { } else {
chartData[ if (chartData[primaryKeyValue].subCategory) {
this.data[symbol][this.keys[0]].toUpperCase() chartData[primaryKeyValue].subCategory[
].subCategory[this.data[symbol][this.keys[1]] ?? UNKNOWN_KEY] = { secondaryKeyValue ?? UNKNOWN_KEY
value: new Big(this.data[symbol].value || 0) ] = {
value: new Big(assetValue)
}; };
} }
}
} else { } else {
chartData[this.data[symbol][this.keys[0]].toUpperCase()] = { chartData[primaryKeyValue] = {
name: this.data[symbol][this.keys[0]], name: asset[primaryKey] as string,
subCategory: {}, subCategory: {},
value: new Big(this.data[symbol].value || 0) value: new Big(assetValue)
}; };
if (this.data[symbol][this.keys[1]]) { if (secondaryKeyValue) {
chartData[ chartData[primaryKeyValue].subCategory = {
this.data[symbol][this.keys[0]].toUpperCase() [secondaryKeyValue]: {
].subCategory = { value: new Big(assetValue)
[this.data[symbol][this.keys[1]]]: {
value: new Big(this.data[symbol].value || 0)
} }
}; };
} }
@ -181,10 +181,10 @@ export class GfPortfolioProportionChartComponent
} else { } else {
chartData[UNKNOWN_KEY] = { chartData[UNKNOWN_KEY] = {
name: this.data[symbol].name, name: this.data[symbol].name,
subCategory: this.keys[1] subCategory: secondaryKey
? { [this.keys[1]]: { value: new Big(0) } } ? { [secondaryKey]: { value: new Big(0) } }
: undefined, : undefined,
value: new Big(this.data[symbol].value || 0) value: new Big(assetValue)
}; };
} }
} }
@ -278,13 +278,15 @@ export class GfPortfolioProportionChartComponent
Object.keys(item.subCategory ?? {}).forEach((subCategory) => { Object.keys(item.subCategory ?? {}).forEach((subCategory) => {
if (item.name === UNKNOWN_KEY) { if (item.name === UNKNOWN_KEY) {
backgroundColorSubCategory.push(item.color); backgroundColorSubCategory.push(item.color ?? '');
} else { } else {
backgroundColorSubCategory.push( backgroundColorSubCategory.push(
Color(item.color).lighten(lightnessRatio).hex() Color(item.color).lighten(lightnessRatio).hex()
); );
} }
dataSubCategory.push(item.subCategory[subCategory].value.toNumber()); dataSubCategory.push(
item.subCategory?.[subCategory].value.toNumber() ?? 0
);
labelSubCategory.push(subCategory); labelSubCategory.push(subCategory);
lightnessRatio += 0.1; lightnessRatio += 0.1;
@ -334,7 +336,7 @@ export class GfPortfolioProportionChartComponent
labels labels
}; };
if (this.chartCanvas) { if (this.chartCanvas()) {
if (this.chart) { if (this.chart) {
this.chart.data = data; this.chart.data = data;
this.chart.options.plugins ??= {}; this.chart.options.plugins ??= {};
@ -343,7 +345,7 @@ export class GfPortfolioProportionChartComponent
this.chart.update(); this.chart.update();
} else { } else {
this.chart = new Chart<'doughnut'>(this.chartCanvas.nativeElement, { this.chart = new Chart<'doughnut'>(this.chartCanvas().nativeElement, {
data, data,
options: { options: {
animation: false, animation: false,

Loading…
Cancel
Save