Feature/move pricing section to page (#86)
* Add a dedicated pricing page * Update changelogpull/87/head
parent
42b9178d96
commit
eb09d77251
@ -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