From fcaa4f79963df42c578d82ca05649722798f3eec Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 9 Aug 2025 09:38:32 +0200 Subject: [PATCH] Feature/improve precision of values in holding detail dialog on mobile (#5337) * Improve dynamic numerical precision * Shorten date on mobile * Extend Storybook story of value component * Update changelog --- CHANGELOG.md | 2 + .../holding-detail-dialog.component.ts | 59 +++++++++++++++++-- .../holding-detail-dialog.html | 6 ++ .../home-overview/home-overview.component.ts | 4 +- libs/common/src/lib/config.ts | 4 +- .../activities-table.component.html | 7 ++- .../activities-table.component.ts | 5 +- .../src/lib/value/value.component.stories.ts | 18 +++++- libs/ui/src/lib/value/value.component.ts | 3 +- 9 files changed, 93 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd5cbd55..26878b5ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Extended the import functionality by tags +- Improved the dynamic numerical precision for various values in the holding detail dialog +- Shortened the date in the activities table on mobile - Introduced the fuzzy search for the accounts endpoint - Refactored the fuzzy search for the holdings of the assistant - Improved the language localization for Polish (`pl`) diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index 8f0e6ae68..eb32b5f8b 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -3,7 +3,11 @@ import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-foote import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { NUMERICAL_PRECISION_THRESHOLD } from '@ghostfolio/common/config'; +import { + NUMERICAL_PRECISION_THRESHOLD_3_FIGURES, + NUMERICAL_PRECISION_THRESHOLD_5_FIGURES, + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES +} from '@ghostfolio/common/config'; import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper'; import { DataProviderInfo, @@ -101,6 +105,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public assetClass: string; public assetSubClass: string; public averagePrice: number; + public averagePricePrecision = 2; public benchmarkDataItems: LineChartItem[]; public benchmarkLabel = $localize`Average Unit Price`; public countries: { @@ -122,11 +127,15 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public marketDataItems: MarketData[] = []; public marketPrice: number; public marketPriceMax: number; + public marketPriceMaxPrecision = 2; public marketPriceMin: number; + public marketPriceMinPrecision = 2; + public marketPricePrecision = 2; public netPerformance: number; public netPerformancePrecision = 2; public netPerformancePercent: number; public netPerformancePercentWithCurrencyEffect: number; + public netPerformancePercentWithCurrencyEffectPrecision = 2; public netPerformanceWithCurrencyEffect: number; public netPerformanceWithCurrencyEffectPrecision = 2; public quantity: number; @@ -274,6 +283,14 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { value }) => { this.averagePrice = averagePrice; + + if ( + this.data.deviceType === 'mobile' && + this.averagePrice >= NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.averagePricePrecision = 0; + } + this.benchmarkDataItems = []; this.countries = {}; this.dataProviderInfo = dataProviderInfo; @@ -281,7 +298,8 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { if ( this.data.deviceType === 'mobile' && - this.dividendInBaseCurrency >= NUMERICAL_PRECISION_THRESHOLD + this.dividendInBaseCurrency >= + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES ) { this.dividendInBaseCurrencyPrecision = 0; } @@ -320,19 +338,42 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { if ( this.data.deviceType === 'mobile' && this.investmentInBaseCurrencyWithCurrencyEffect >= - NUMERICAL_PRECISION_THRESHOLD + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES ) { this.investmentInBaseCurrencyWithCurrencyEffectPrecision = 0; } this.marketPrice = marketPrice; this.marketPriceMax = marketPriceMax; + + if ( + this.data.deviceType === 'mobile' && + this.marketPriceMax >= NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.marketPriceMaxPrecision = 0; + } + this.marketPriceMin = marketPriceMin; + + if ( + this.data.deviceType === 'mobile' && + this.marketPriceMin >= NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.marketPriceMinPrecision = 0; + } + + if ( + this.data.deviceType === 'mobile' && + this.marketPrice >= NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.marketPricePrecision = 0; + } + this.netPerformance = netPerformance; if ( this.data.deviceType === 'mobile' && - this.netPerformance >= NUMERICAL_PRECISION_THRESHOLD + this.netPerformance >= NUMERICAL_PRECISION_THRESHOLD_6_FIGURES ) { this.netPerformancePrecision = 0; } @@ -342,13 +383,21 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.netPerformancePercentWithCurrencyEffect = netPerformancePercentWithCurrencyEffect; + if ( + this.data.deviceType === 'mobile' && + this.netPerformancePercentWithCurrencyEffect >= + NUMERICAL_PRECISION_THRESHOLD_3_FIGURES + ) { + this.netPerformancePercentWithCurrencyEffectPrecision = 0; + } + this.netPerformanceWithCurrencyEffect = netPerformanceWithCurrencyEffect; if ( this.data.deviceType === 'mobile' && this.netPerformanceWithCurrencyEffect >= - NUMERICAL_PRECISION_THRESHOLD + NUMERICAL_PRECISION_THRESHOLD_5_FIGURES ) { this.netPerformanceWithCurrencyEffectPrecision = 0; } diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index e0673a1f5..30ce98634 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -77,6 +77,7 @@ [colorizeSign]="true" [isPercent]="true" [locale]="data.locale" + [precision]="netPerformancePercentWithCurrencyEffectPrecision" [value]="netPerformancePercentWithCurrencyEffect" > @if ( @@ -95,6 +96,7 @@ size="medium" [isCurrency]="true" [locale]="data.locale" + [precision]="averagePricePrecision" [unit]="SymbolProfile?.currency" [value]="averagePrice" >Average Unit PriceMarket PriceMinimum PriceMaximum Price= - NUMERICAL_PRECISION_THRESHOLD + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES ) { this.precision = 0; } diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 02a12cfd1..169ab80c1 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -136,7 +136,9 @@ export const HEADER_KEY_SKIP_INTERCEPTOR = 'X-Skip-Interceptor'; export const MAX_TOP_HOLDINGS = 50; -export const NUMERICAL_PRECISION_THRESHOLD = 100000; +export const NUMERICAL_PRECISION_THRESHOLD_3_FIGURES = 100; +export const NUMERICAL_PRECISION_THRESHOLD_5_FIGURES = 10000; +export const NUMERICAL_PRECISION_THRESHOLD_6_FIGURES = 100000; export const PROPERTY_API_KEY_GHOSTFOLIO = 'API_KEY_GHOSTFOLIO'; export const PROPERTY_API_KEY_OPENROUTER = 'API_KEY_OPENROUTER'; diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index 4ee7c689a..326440774 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -171,7 +171,12 @@