diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 92371fb26..0dda4dd3b 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -412,6 +412,14 @@ export class PortfolioController { filterByTags }); + const { performance } = await this.portfolioService.getPerformance({ + dateRange, + filters, + impersonationId, + withExcludedAccounts: false, + userId: this.request.user.id + }); + const { holdings } = await this.portfolioService.getDetails({ dateRange, filters, @@ -419,7 +427,7 @@ export class PortfolioController { userId: this.request.user.id }); - return { holdings: Object.values(holdings) }; + return { holdings: Object.values(holdings), performance }; } @Get('investments') diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index dd411f6cc..476aa9592 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -4,6 +4,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { AssetProfileIdentifier, PortfolioPosition, + PortfolioPerformance, ToggleOption, User } from '@ghostfolio/common/interfaces'; @@ -31,6 +32,7 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { public hasPermissionToAccessHoldingsChart: boolean; public hasPermissionToCreateOrder: boolean; public holdings: PortfolioPosition[]; + public performance: PortfolioPerformance; public holdingType: HoldingType = 'ACTIVE'; public holdingTypeOptions: ToggleOption[] = [ { label: $localize`Active`, value: 'ACTIVE' }, @@ -162,8 +164,9 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { this.fetchHoldings() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ holdings }) => { + .subscribe(({ holdings, performance }) => { this.holdings = holdings; + this.performance = performance; this.changeDetectorRef.markForCheck(); }); diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index f981e50a1..fe0dc6ec3 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -50,6 +50,7 @@ [deviceType]="deviceType" [holdings]="holdings" [locale]="user?.settings?.locale" + [performance]="performance" (holdingClicked)="onHoldingClicked($event)" /> @if (hasPermissionToCreateOrder && holdings?.length > 0) { diff --git a/libs/common/src/lib/interfaces/responses/portfolio-holdings-response.interface.ts b/libs/common/src/lib/interfaces/responses/portfolio-holdings-response.interface.ts index d2cf38f55..68a6934d4 100644 --- a/libs/common/src/lib/interfaces/responses/portfolio-holdings-response.interface.ts +++ b/libs/common/src/lib/interfaces/responses/portfolio-holdings-response.interface.ts @@ -1,5 +1,9 @@ -import { PortfolioPosition } from '@ghostfolio/common/interfaces'; +import { + PortfolioPosition, + PortfolioPerformance +} from '@ghostfolio/common/interfaces'; export interface PortfolioHoldingsResponse { holdings: PortfolioPosition[]; + performance: PortfolioPerformance; } diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.html b/libs/ui/src/lib/holdings-table/holdings-table.component.html index d187d7dc7..33376a317 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.html +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -252,7 +252,7 @@ diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.ts b/libs/ui/src/lib/holdings-table/holdings-table.component.ts index beb2f62d1..498df72c5 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.ts +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.ts @@ -3,7 +3,8 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, - PortfolioPosition + PortfolioPosition, + PortfolioPerformance } from '@ghostfolio/common/interfaces'; import { GfValueComponent } from '@ghostfolio/ui/value'; @@ -55,6 +56,7 @@ export class GfHoldingsTableComponent implements OnChanges, OnDestroy { @Input() holdings: PortfolioPosition[]; @Input() locale = getLocale(); @Input() pageSize = Number.MAX_SAFE_INTEGER; + @Input() performance: PortfolioPerformance; @Output() holdingClicked = new EventEmitter(); @@ -94,16 +96,10 @@ export class GfHoldingsTableComponent implements OnChanges, OnDestroy { this.dataSource = new MatTableDataSource(this.holdings); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; - this.totalValue = this.dataSource.data.reduce( - (sum, current) => (sum += current.valueInBaseCurrency), - 0 - ); - this.totalChange = this.dataSource.data.reduce( - (sum, current) => (sum += current.netPerformanceWithCurrencyEffect), - 0 - ); + this.totalValue = this.performance.currentValueInBaseCurrency; + this.totalChange = this.performance.netPerformanceWithCurrencyEffect; this.totalChangePercentage = - this.totalChange / (this.totalValue - this.totalChange); + this.performance.netPerformancePercentageWithCurrencyEffect; if (this.holdings) { this.isLoading = false;