|
@ -10,6 +10,11 @@ import { |
|
|
MatSlideToggle, |
|
|
MatSlideToggle, |
|
|
MatSlideToggleChange |
|
|
MatSlideToggleChange |
|
|
} from '@angular/material/slide-toggle'; |
|
|
} from '@angular/material/slide-toggle'; |
|
|
|
|
|
import { |
|
|
|
|
|
MatSnackBar, |
|
|
|
|
|
MatSnackBarRef, |
|
|
|
|
|
TextOnlySnackBar |
|
|
|
|
|
} from '@angular/material/snack-bar'; |
|
|
import { ActivatedRoute, Router } from '@angular/router'; |
|
|
import { ActivatedRoute, Router } from '@angular/router'; |
|
|
import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; |
|
|
import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; |
|
|
import { DataService } from '@ghostfolio/client/services/data.service'; |
|
|
import { DataService } from '@ghostfolio/client/services/data.service'; |
|
@ -18,7 +23,6 @@ import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; |
|
|
import { DEFAULT_DATE_FORMAT, baseCurrency } from '@ghostfolio/common/config'; |
|
|
import { DEFAULT_DATE_FORMAT, baseCurrency } from '@ghostfolio/common/config'; |
|
|
import { Access, User } from '@ghostfolio/common/interfaces'; |
|
|
import { Access, User } from '@ghostfolio/common/interfaces'; |
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|
|
import { StatusCodes } from 'http-status-codes'; |
|
|
|
|
|
import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
import { StripeService } from 'ngx-stripe'; |
|
|
import { StripeService } from 'ngx-stripe'; |
|
|
import { EMPTY, Subject } from 'rxjs'; |
|
|
import { EMPTY, Subject } from 'rxjs'; |
|
@ -50,6 +54,7 @@ export class AccountPageComponent implements OnDestroy, OnInit { |
|
|
public hasPermissionToUpdateUserSettings: boolean; |
|
|
public hasPermissionToUpdateUserSettings: boolean; |
|
|
public price: number; |
|
|
public price: number; |
|
|
public priceId: string; |
|
|
public priceId: string; |
|
|
|
|
|
public snackBarRef: MatSnackBarRef<TextOnlySnackBar>; |
|
|
public user: User; |
|
|
public user: User; |
|
|
|
|
|
|
|
|
private unsubscribeSubject = new Subject<void>(); |
|
|
private unsubscribeSubject = new Subject<void>(); |
|
@ -62,6 +67,7 @@ export class AccountPageComponent implements OnDestroy, OnInit { |
|
|
private dataService: DataService, |
|
|
private dataService: DataService, |
|
|
private deviceService: DeviceDetectorService, |
|
|
private deviceService: DeviceDetectorService, |
|
|
private dialog: MatDialog, |
|
|
private dialog: MatDialog, |
|
|
|
|
|
private snackBar: MatSnackBar, |
|
|
private route: ActivatedRoute, |
|
|
private route: ActivatedRoute, |
|
|
private router: Router, |
|
|
private router: Router, |
|
|
private stripeService: StripeService, |
|
|
private stripeService: StripeService, |
|
@ -187,7 +193,8 @@ export class AccountPageComponent implements OnDestroy, OnInit { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onRedeemCoupon() { |
|
|
public onRedeemCoupon() { |
|
|
const couponCode = prompt('Please add your coupon code:'); |
|
|
let couponCode = prompt('Please enter your coupon code:'); |
|
|
|
|
|
couponCode = couponCode?.trim(); |
|
|
|
|
|
|
|
|
if (couponCode) { |
|
|
if (couponCode) { |
|
|
this.dataService |
|
|
this.dataService |
|
@ -195,13 +202,35 @@ export class AccountPageComponent implements OnDestroy, OnInit { |
|
|
.pipe( |
|
|
.pipe( |
|
|
takeUntil(this.unsubscribeSubject), |
|
|
takeUntil(this.unsubscribeSubject), |
|
|
catchError(() => { |
|
|
catchError(() => { |
|
|
// TODO: show error notification
|
|
|
this.snackBar.open('😞 Could not redeem coupon code', undefined, { |
|
|
|
|
|
duration: 3000 |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
return EMPTY; |
|
|
return EMPTY; |
|
|
}) |
|
|
}) |
|
|
) |
|
|
) |
|
|
.subscribe(() => { |
|
|
.subscribe(() => { |
|
|
// TODO: show success notification
|
|
|
this.snackBarRef = this.snackBar.open( |
|
|
|
|
|
'✅ Coupon code has been redeemed', |
|
|
|
|
|
'Reload', |
|
|
|
|
|
{ |
|
|
|
|
|
duration: 3000 |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
this.snackBarRef |
|
|
|
|
|
.afterDismissed() |
|
|
|
|
|
.pipe(takeUntil(this.unsubscribeSubject)) |
|
|
|
|
|
.subscribe(() => { |
|
|
|
|
|
window.location.reload(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
this.snackBarRef |
|
|
|
|
|
.onAction() |
|
|
|
|
|
.pipe(takeUntil(this.unsubscribeSubject)) |
|
|
|
|
|
.subscribe(() => { |
|
|
|
|
|
window.location.reload(); |
|
|
|
|
|
}); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|