From 017d42965bb8dfde3857aea7d59e66b10486e78f Mon Sep 17 00:00:00 2001 From: KenTandrian Date: Sun, 21 Jun 2026 23:23:47 +0700 Subject: [PATCH] feat(client): implement computed signal for product2 --- .../product-page.component.ts | 39 ++++++----- .../personal-finance-tools/product-page.html | 70 +++++++++---------- 2 files changed, 56 insertions(+), 53 deletions(-) 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 2ff73fea0..342c9061f 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 @@ -47,42 +47,45 @@ export class GfProductPageComponent implements OnInit { useAnonymously: true })); - protected product2: Product; - protected readonly routerLinkAbout = publicRoutes.about.routerLink; - protected readonly routerLinkFeatures = publicRoutes.features.routerLink; - protected readonly routerLinkResourcesPersonalFinanceTools = - publicRoutes.resources.subRoutes.personalFinanceTools.routerLink; - protected tags: string[]; - - private readonly dataService = inject(DataService); - private readonly route = inject(ActivatedRoute); - - public ngOnInit() { + protected readonly product2 = computed(() => { const product = personalFinanceTools.find(({ key }) => { return key === this.route.snapshot.data['key']; }); - this.product2 = { + const mappedProduct = { key: product?.key ?? '', name: product?.name ?? '', ...product }; - if (this.product2.origin) { - this.product2.origin = getCountryName({ code: this.product2.origin }); + if (mappedProduct.origin) { + mappedProduct.origin = getCountryName({ code: mappedProduct.origin }); } - if (this.product2.regions) { - this.product2.regions = this.product2.regions.map((region) => { + if (mappedProduct.regions) { + mappedProduct.regions = mappedProduct.regions.map((region) => { return translate(region); }); } + return mappedProduct; + }); + + protected readonly routerLinkAbout = publicRoutes.about.routerLink; + protected readonly routerLinkFeatures = publicRoutes.features.routerLink; + protected readonly routerLinkResourcesPersonalFinanceTools = + publicRoutes.resources.subRoutes.personalFinanceTools.routerLink; + protected tags: string[]; + + private readonly dataService = inject(DataService); + private readonly route = inject(ActivatedRoute); + + public ngOnInit() { this.tags = [ this.product1().name, this.product1().origin, - this.product2.name, - this.product2.origin, + this.product2().name, + this.product2().origin, $localize`Alternative`, $localize`App`, $localize`Budgeting`, 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 aafafa5ca..0ff3f9df4 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 @@ -6,10 +6,10 @@

Ghostfolio: The Open Source Alternative to {{ product2.name }} + > {{ product2().name }}

- @if (product2.isArchived) { + @if (product2().isArchived) {
This page has been archived.
@@ -17,7 +17,7 @@

Are you looking for an open source alternative to - {{ product2.name }}? + {{ product2().name }}? Ghostfolio is a powerful portfolio management tool that provides individuals with a comprehensive platform to track, analyze, and optimize their @@ -31,7 +31,7 @@

Ghostfolio is an open source software (OSS), providing a - cost-effective alternative to {{ product2.name }} making it + cost-effective alternative to {{ product2().name }} making it particularly suitable for individuals on a tight budget, such as those

Let’s dive deeper into the detailed Ghostfolio vs - {{ product2.name }} comparison table below to gain a thorough + {{ product2().name }} comparison table below to gain a thorough understanding of how Ghostfolio positions itself relative to - {{ product2.name }}. We will explore various aspects such as + {{ product2().name }}. We will explore various aspects such as features, data privacy, pricing, and more, allowing you to make a well-informed choice for your personal requirements.

@@ -54,7 +54,7 @@ Ghostfolio vs {{ - product2.name + product2().name }} comparison table @@ -63,7 +63,7 @@ Ghostfolio - {{ product2.name }} + {{ product2().name }} @@ -71,17 +71,17 @@ {{ product1().slogan }} - {{ product2.slogan }} + {{ product2().slogan }} Founded {{ product1().founded }} - {{ product2.founded }} + {{ product2().founded }} Origin {{ product1().origin }} - {{ product2.origin }} + {{ product2().origin }} Region @@ -96,7 +96,7 @@ @for ( - region of product2.regions; + region of product2().regions; track region; let isLast = $last ) { @@ -119,7 +119,7 @@ @for ( - language of product2.languages; + language of product2().languages; track language; let isLast = $last ) { @@ -149,18 +149,18 @@ } - @if (product2.isOpenSource) { + @if (product2().isOpenSource) { ✅ Yes } @else { ❌ No } @@ -188,18 +188,18 @@ } - @if (product2.hasSelfHostingAbility === true) { + @if (product2().hasSelfHostingAbility === true) { ✅ Yes - } @else if (product2.hasSelfHostingAbility === false) { + } @else if (product2().hasSelfHostingAbility === false) { ❌ No } @@ -227,18 +227,18 @@ } - @if (product2.useAnonymously === true) { + @if (product2().useAnonymously === true) { ✅ Yes - } @else if (product2.useAnonymously === false) { + } @else if (product2().useAnonymously === false) { ❌ No } @@ -266,18 +266,18 @@ } - @if (product2.hasFreePlan === true) { + @if (product2().hasFreePlan === true) { ✅ Yes - } @else if (product2.hasFreePlan === false) { + } @else if (product2().hasFreePlan === false) { ❌ No } @@ -290,18 +290,18 @@ year - @if (product2.pricingPerYear) { + @if (product2().pricingPerYear) { Starting from - {{ product2.pricingPerYear }} / + {{ product2().pricingPerYear }} / year } - @if (product1().note || product2.note) { + @if (product1().note || product2().note) { Notes {{ product1().note }} - {{ product2.note }} + {{ product2().note }} } @@ -310,9 +310,9 @@

Please note that the information provided in the Ghostfolio vs - {{ product2.name }} comparison table is based on our independent + {{ product2().name }} comparison table is based on our independent research and analysis. This website is not affiliated with - {{ product2.name }} or any other product mentioned in the + {{ product2().name }} or any other product mentioned in the comparison. As the landscape of personal finance tools evolves, it is essential to verify any specific details or changes directly from the respective product page. Data needs a refresh? Help us maintain @@ -355,7 +355,7 @@ aria-current="page" class="active breadcrumb-item text-truncate" > - Ghostfolio vs {{ product2.name }} + Ghostfolio vs {{ product2().name }}