mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
12 changed files with 258 additions and 144 deletions
@ -0,0 +1,12 @@ |
|||
import { NgModule } from '@angular/core'; |
|||
import { RouterModule, Routes } from '@angular/router'; |
|||
|
|||
import { PricingPageComponent } from './pricing-page.component'; |
|||
|
|||
const routes: Routes = [{ path: '', component: PricingPageComponent }]; |
|||
|
|||
@NgModule({ |
|||
imports: [RouterModule.forChild(routes)], |
|||
exports: [RouterModule] |
|||
}) |
|||
export class PricingPageRoutingModule {} |
@ -0,0 +1,53 @@ |
|||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; |
|||
import { baseCurrency } from '@ghostfolio/helper'; |
|||
import { Subject } from 'rxjs'; |
|||
import { User } from '@ghostfolio/api/app/user/interfaces/user.interface'; |
|||
import { takeUntil } from 'rxjs/operators'; |
|||
import { DataService } from '@ghostfolio/client/services/data.service'; |
|||
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; |
|||
|
|||
@Component({ |
|||
selector: 'gf-pricing-page', |
|||
templateUrl: './pricing-page.html', |
|||
styleUrls: ['./pricing-page.scss'] |
|||
}) |
|||
export class PricingPageComponent implements OnInit { |
|||
public baseCurrency = baseCurrency; |
|||
public isLoggedIn: boolean; |
|||
public user: User; |
|||
|
|||
private unsubscribeSubject = new Subject<void>(); |
|||
|
|||
/** |
|||
* @constructor |
|||
*/ |
|||
public constructor( |
|||
private cd: ChangeDetectorRef, |
|||
private dataService: DataService, |
|||
private tokenStorageService: TokenStorageService |
|||
) {} |
|||
|
|||
/** |
|||
* Initializes the controller |
|||
*/ |
|||
public ngOnInit() { |
|||
this.isLoggedIn = !!this.tokenStorageService.getToken(); |
|||
|
|||
if (this.isLoggedIn) |
|||
this.tokenStorageService |
|||
.onChangeHasToken() |
|||
.pipe(takeUntil(this.unsubscribeSubject)) |
|||
.subscribe(() => { |
|||
this.dataService.fetchUser().subscribe((user) => { |
|||
this.user = user; |
|||
|
|||
this.cd.markForCheck(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.unsubscribeSubject.next(); |
|||
this.unsubscribeSubject.complete(); |
|||
} |
|||
} |
@ -0,0 +1,102 @@ |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col"> |
|||
<h3 class="d-flex justify-content-center mb-3" i18n>Pricing Plans</h3> |
|||
<div class="row"> |
|||
<div class="col-xs-12 col-md-6"> |
|||
<mat-card class="mb-3"> |
|||
<h4 i18n>Open Source</h4> |
|||
<p>Host your <strong>Ghostfolio</strong> instance by yourself.</p> |
|||
<ul class="list-unstyled mb-3"> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Portfolio Performance</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Portfolio Summary</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Unlimited Transactions</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Advanced Insights</span> |
|||
</li> |
|||
</ul> |
|||
<p class="h5 text-right"> |
|||
<span>Free</span> |
|||
</p> |
|||
</mat-card> |
|||
</div> |
|||
<div class="col-xs-12 col-md-6"> |
|||
<mat-card |
|||
class="mb-3" |
|||
[ngClass]="{ 'active': user?.subscription?.type === 'Trial' }" |
|||
> |
|||
<h4 class="align-items-center d-flex" i18n> |
|||
Diamond |
|||
<ion-icon |
|||
class="ml-1 text-muted" |
|||
name="diamond-outline" |
|||
></ion-icon> |
|||
</h4> |
|||
<p> |
|||
Get a fully managed <strong>Ghostfolio</strong> cloud offering. |
|||
</p> |
|||
<ul class="list-unstyled mb-3"> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Portfolio Performance</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Portfolio Summary</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Unlimited Transactions</span> |
|||
</li> |
|||
<li class="align-items-center d-flex mb-1"> |
|||
<ion-icon |
|||
class="mr-1 text-muted" |
|||
name="checkmark-circle-outline" |
|||
></ion-icon> |
|||
<span>Advanced Insights</span> |
|||
</li> |
|||
</ul> |
|||
<p class="h5 text-right"> |
|||
<span class="font-weight-normal" |
|||
>{{ user?.settings.baseCurrency || baseCurrency }} |
|||
<strong>2.99</strong> |
|||
<del class="ml-1 text-muted">3.99</del> / Month</span |
|||
> |
|||
</p> |
|||
</mat-card> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
@ -0,0 +1,15 @@ |
|||
import { CommonModule } from '@angular/common'; |
|||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; |
|||
import { MatCardModule } from '@angular/material/card'; |
|||
|
|||
import { PricingPageRoutingModule } from './pricing-page-routing.module'; |
|||
import { PricingPageComponent } from './pricing-page.component'; |
|||
|
|||
@NgModule({ |
|||
declarations: [PricingPageComponent], |
|||
exports: [], |
|||
imports: [CommonModule, MatCardModule, PricingPageRoutingModule], |
|||
providers: [], |
|||
schemas: [CUSTOM_ELEMENTS_SCHEMA] |
|||
}) |
|||
export class PricingPageModule {} |
@ -0,0 +1,14 @@ |
|||
:host { |
|||
color: rgb(var(--dark-primary-text)); |
|||
display: block; |
|||
|
|||
.mat-card { |
|||
&.active { |
|||
border-color: rgba(var(--palette-primary-500), 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
:host-context(.is-dark-theme) { |
|||
color: rgb(var(--light-primary-text)); |
|||
} |
Loading…
Reference in new issue