From 1f4427b0e7b57f22dea3c74db3c73279162bf6f2 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:30:25 +0700 Subject: [PATCH] Task/improve type safety of account detail dialog (#6731) * feat(client): resolve type errors * feat(client): migrate to inject function * feat(client): tighten up encapsulation * fix(client): remove unused activities --- .../account-detail-dialog.component.ts | 97 ++++++++++--------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index 5cd501cf8..f51315e91 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -12,7 +12,6 @@ import { } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { OrderWithAccount } from '@ghostfolio/common/types'; import { GfAccountBalancesComponent } from '@ghostfolio/ui/account-balances'; import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { GfDialogFooterComponent } from '@ghostfolio/ui/dialog-footer'; @@ -27,7 +26,7 @@ import { ChangeDetectorRef, Component, DestroyRef, - Inject, + inject, OnInit } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; @@ -78,41 +77,42 @@ import { AccountDetailDialogParams } from './interfaces/interfaces'; templateUrl: 'account-detail-dialog.html' }) export class GfAccountDetailDialogComponent implements OnInit { - public accountBalances: AccountBalancesResponse['balances']; - public activities: OrderWithAccount[]; - public activitiesCount: number; - public balance: number; - public balancePrecision = 2; - public currency: string; - public dataSource: MatTableDataSource; - public dividendInBaseCurrency: number; - public dividendInBaseCurrencyPrecision = 2; - public equity: number; - public equityPrecision = 2; - public hasPermissionToDeleteAccountBalance: boolean; - public historicalDataItems: HistoricalDataItem[]; - public holdings: PortfolioPosition[]; - public interestInBaseCurrency: number; - public interestInBaseCurrencyPrecision = 2; - public isLoadingActivities: boolean; - public isLoadingChart: boolean; - public name: string; - public platformName: string; - public sortColumn = 'date'; - public sortDirection: SortDirection = 'desc'; - public totalItems: number; - public user: User; - public valueInBaseCurrency: number; - - public constructor( - private changeDetectorRef: ChangeDetectorRef, - @Inject(MAT_DIALOG_DATA) public data: AccountDetailDialogParams, - private dataService: DataService, - private destroyRef: DestroyRef, - public dialogRef: MatDialogRef, - private router: Router, - private userService: UserService - ) { + protected accountBalances: AccountBalancesResponse['balances']; + protected activitiesCount: number; + protected balance: number; + protected balancePrecision = 2; + protected currency: string | null; + protected dataSource: MatTableDataSource; + protected dividendInBaseCurrency: number; + protected dividendInBaseCurrencyPrecision = 2; + protected equity: number | null; + protected equityPrecision = 2; + protected hasPermissionToDeleteAccountBalance: boolean; + protected historicalDataItems: HistoricalDataItem[]; + protected holdings: PortfolioPosition[]; + protected interestInBaseCurrency: number; + protected interestInBaseCurrencyPrecision = 2; + protected isLoadingActivities: boolean; + protected isLoadingChart: boolean; + protected name: string | null; + protected platformName: string; + protected sortColumn = 'date'; + protected sortDirection: SortDirection = 'desc'; + protected totalItems: number; + protected user: User; + protected valueInBaseCurrency: number; + + protected readonly data = inject(MAT_DIALOG_DATA); + + private readonly changeDetectorRef = inject(ChangeDetectorRef); + private readonly dataService = inject(DataService); + private readonly destroyRef = inject(DestroyRef); + private readonly dialogRef = + inject>(MatDialogRef); + private readonly router = inject(Router); + private readonly userService = inject(UserService); + + public constructor() { this.userService.stateChanged .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { @@ -135,7 +135,7 @@ export class GfAccountDetailDialogComponent implements OnInit { this.initialize(); } - public onCloneActivity(aActivity: Activity) { + protected onCloneActivity(aActivity: Activity) { this.router.navigate( internalRoutes.portfolio.subRoutes.activities.routerLink, { @@ -146,11 +146,11 @@ export class GfAccountDetailDialogComponent implements OnInit { this.dialogRef.close(); } - public onClose() { + protected onClose() { this.dialogRef.close(); } - public onAddAccountBalance(accountBalance: CreateAccountBalanceDto) { + protected onAddAccountBalance(accountBalance: CreateAccountBalanceDto) { this.dataService .postAccountBalance(accountBalance) .pipe(takeUntilDestroyed(this.destroyRef)) @@ -159,7 +159,7 @@ export class GfAccountDetailDialogComponent implements OnInit { }); } - public onDeleteAccountBalance(aId: string) { + protected onDeleteAccountBalance(aId: string) { this.dataService .deleteAccountBalance(aId) .pipe(takeUntilDestroyed(this.destroyRef)) @@ -168,7 +168,7 @@ export class GfAccountDetailDialogComponent implements OnInit { }); } - public onExport() { + protected onExport() { const activityIds = this.dataSource.data.map(({ id }) => { return id; }); @@ -180,7 +180,7 @@ export class GfAccountDetailDialogComponent implements OnInit { downloadAsFile({ content: data, fileName: `ghostfolio-export-${this.name - .replace(/\s+/g, '-') + ?.replace(/\s+/g, '-') .toLowerCase()}-${format( parseISO(data.meta.date), 'yyyyMMddHHmm' @@ -190,14 +190,14 @@ export class GfAccountDetailDialogComponent implements OnInit { }); } - public onSortChanged({ active, direction }: Sort) { + protected onSortChanged({ active, direction }: Sort) { this.sortColumn = active; this.sortDirection = direction; this.fetchActivities(); } - public onUpdateActivity(aActivity: Activity) { + protected onUpdateActivity(aActivity: Activity) { this.router.navigate( internalRoutes.portfolio.subRoutes.activities.routerLink, { @@ -208,7 +208,7 @@ export class GfAccountDetailDialogComponent implements OnInit { this.dialogRef.close(); } - public showValuesInPercentage() { + protected showValuesInPercentage() { return ( this.data.hasImpersonationId || this.user?.settings?.isRestrictedView ); @@ -330,7 +330,10 @@ export class GfAccountDetailDialogComponent implements OnInit { next: ({ accountBalances, portfolioPerformance }) => { this.accountBalances = accountBalances.balances; - if (portfolioPerformance.chart.length > 0) { + if ( + portfolioPerformance.chart && + portfolioPerformance.chart.length > 0 + ) { this.historicalDataItems = portfolioPerformance.chart.map( ({ date, netWorth, netWorthInPercentage }) => ({ date,