diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts index e3bc2ba3d..eeeed515f 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts +++ b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -2,6 +2,7 @@ import { getCountryName } from '@ghostfolio/common/helper'; import { Product } from '@ghostfolio/common/interfaces'; import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { ProductCategory, ProductPlatform } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { DataService } from '@ghostfolio/ui/services'; @@ -91,39 +92,52 @@ export class GfProductPageComponent { const product1 = this.product1(); const product2 = this.product2(); - return [ - product1.name, - product1.origin, - product2.name, - product2.origin, - $localize`Alternative`, - $localize`App`, - $localize`Budgeting`, - $localize`Community`, - $localize`Family Office`, - `Fintech`, - $localize`Investment`, - $localize`Investor`, - $localize`Open Source`, - `OSS`, - $localize`Personal Finance`, - $localize`Privacy`, - $localize`Portfolio`, - $localize`Software`, - $localize`Tool`, - $localize`User Experience`, - $localize`Wealth`, - $localize`Wealth Management`, - `WealthTech` - ] - .filter((item): item is string => { - return !!item; - }) - .sort((a, b) => { - return a.localeCompare(b, undefined, { sensitivity: 'base' }); - }); + return Array.from( + new Set( + [ + ...(product1.categories ?? []).map((category: ProductCategory) => { + return translate(category); + }), + product1.name, + product1.origin, + ...(product1.platforms ?? []).map((platform: ProductPlatform) => { + return translate(platform); + }), + ...(product2.categories ?? []).map((category: ProductCategory) => { + return translate(category); + }), + product2.name, + product2.origin, + ...(product2.platforms ?? []).map((platform: ProductPlatform) => { + return translate(platform); + }), + $localize`Alternative`, + $localize`App`, + $localize`Community`, + `Fintech`, + $localize`Investment`, + $localize`Investor`, + $localize`Open Source`, + `OSS`, + $localize`Personal Finance`, + $localize`Portfolio`, + $localize`Privacy`, + $localize`Software`, + $localize`Tool`, + $localize`User Experience`, + $localize`Wealth`, + `WealthTech` + ].filter((item): item is string => { + return !!item; + }) + ) + ).sort((a, b) => { + return a.localeCompare(b, undefined, { sensitivity: 'base' }); + }); }); + protected readonly translate = translate; + private readonly dataService = inject(DataService); private readonly route = inject(ActivatedRoute); } diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.html b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.html index d86d88621..9a89c941f 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.html +++ b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -73,6 +73,27 @@ {{ product1().slogan }} {{ product2().slogan }} + + Category + + @for ( + category of product1().categories; + track category; + let isLast = $last + ) { + {{ translate(category) }}{{ isLast ? '' : ', ' }} + } + + + @for ( + category of product2().categories; + track category; + let isLast = $last + ) { + {{ translate(category) }}{{ isLast ? '' : ', ' }} + } + + Founded {{ product1().founded }} @@ -104,6 +125,29 @@ } + + + Available on + + + @for ( + platform of product1().platforms; + track platform; + let isLast = $last + ) { + {{ translate(platform) }}{{ isLast ? '' : ', ' }} + } + + + @for ( + platform of product2().platforms; + track platform; + let isLast = $last + ) { + {{ translate(platform) }}{{ isLast ? '' : ', ' }} + } + + Available in diff --git a/libs/ui/src/lib/i18n.ts b/libs/ui/src/lib/i18n.ts index 2c037c7d1..e8c5d7ae2 100644 --- a/libs/ui/src/lib/i18n.ts +++ b/libs/ui/src/lib/i18n.ts @@ -1,4 +1,8 @@ -import type { SectorName } from '@ghostfolio/common/types'; +import type { + ProductCategory, + ProductPlatform, + SectorName +} from '@ghostfolio/common/types'; import '@angular/localize/init'; @@ -94,8 +98,31 @@ const locales = { Other: $localize`Other`, 'Real Estate': $localize`Real Estate`, Technology: $localize`Technology`, - Utilities: $localize`Utilities` -} satisfies Record & Record; + Utilities: $localize`Utilities`, + + // Product categories (CRYPTOCURRENCY is defined above under AssetSubClass) + BUDGETING: $localize`Budgeting`, + DIVIDEND_TRACKING: $localize`Dividend Tracking`, + ETF_TRACKING: $localize`ETF Tracking`, + FAMILY_OFFICE: $localize`Family Office`, + FINANCIAL_PLANNING: $localize`Financial Planning`, + INVESTMENT_RESEARCH: $localize`Investment Research`, + NET_WORTH_TRACKING: $localize`Net Worth Tracking`, + STOCK_TRACKING: $localize`Stock Tracking`, + TAX_REPORTING: $localize`Tax Reporting`, + WEALTH_MANAGEMENT: $localize`Wealth Management`, + + // Product platforms + ANDROID: $localize`Android`, + IOS: $localize`iOS`, + LINUX: $localize`Linux`, + MACOS: $localize`macOS`, + WEB: $localize`Web`, + WINDOWS: $localize`Windows` +} satisfies Record & + Record & + Record & + Record; export function translate(aKey: string): string { return locales[aKey] ?? aKey;