fixed several outstanding issues with the membership selection
parent
953c1caeda
commit
037f9376c1
|
@ -7,7 +7,7 @@
|
|||
<account-membership-options
|
||||
[accountMembership]="accountMembership"
|
||||
[membershipTypes]="membershipTypes"
|
||||
(membershipChange)="onMembershipChange($event)"
|
||||
(membershipChange)="updateAccount($event)"
|
||||
>
|
||||
</account-membership-options>
|
||||
<span *ngIf="accountMembership && accountMembership.duration" id="subscription-date" class="mat-body">
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import { Component, Input, OnDestroy } from '@angular/core';
|
||||
import { MediaChange, MediaObserver } from '@angular/flex-layout';
|
||||
import { MatBottomSheet } from '@angular/material';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { AccountMembership } from '@account/models/account-membership.model';
|
||||
import { MembershipType } from '@account/models/membership.model';
|
||||
import { MembershipUpdate } from '@account/models/membership-update.model';
|
||||
import { ProfileService } from '@account/http/profile.service';
|
||||
import { PaymentComponent } from '../../views/payment/payment.component';
|
||||
|
||||
const twoSeconds = 2000;
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'account-membership-edit',
|
||||
|
@ -15,14 +18,14 @@ import { PaymentComponent } from '../../views/payment/payment.component';
|
|||
})
|
||||
export class MembershipComponent implements OnDestroy {
|
||||
@Input() accountMembership: AccountMembership;
|
||||
public alignVertical: boolean;
|
||||
@Input() membershipTypes: MembershipType[];
|
||||
public alignVertical: boolean;
|
||||
private mediaWatcher: Subscription;
|
||||
|
||||
constructor(
|
||||
public bottomSheet: MatBottomSheet,
|
||||
public mediaObserver: MediaObserver,
|
||||
private profileService: ProfileService,
|
||||
private snackbar: MatSnackBar
|
||||
) {
|
||||
this.mediaWatcher = mediaObserver.media$.subscribe(
|
||||
(change: MediaChange) => {
|
||||
|
@ -35,43 +38,15 @@ export class MembershipComponent implements OnDestroy {
|
|||
this.mediaWatcher.unsubscribe();
|
||||
}
|
||||
|
||||
onMembershipChange(membershipType: string) {
|
||||
const selectedMembership = this.membershipTypes.find(
|
||||
(membership) => membership.type === membershipType
|
||||
);
|
||||
if (selectedMembership) {
|
||||
if (this.accountMembership) {
|
||||
// We have the user's credit card info but they decide to change plans
|
||||
this.profileService.updateAccount(
|
||||
{membership: {paymentMethod: 'Stripe', newMembership: false, membershipType: membershipType}}
|
||||
);
|
||||
} else {
|
||||
// No credit card info. Go to payment screen to collect
|
||||
this.openBottomSheet(membershipType);
|
||||
}
|
||||
} else {
|
||||
// Membership termination
|
||||
this.profileService.updateAccount(
|
||||
{membership: {paymentMethod: 'Stripe', newMembership: false, membershipType: null}}
|
||||
updateAccount(membershipUpdate: MembershipUpdate) {
|
||||
const accountUpdate = {membership: membershipUpdate};
|
||||
this.profileService.updateAccount(accountUpdate).subscribe(
|
||||
() => {
|
||||
this.snackbar.open(
|
||||
'Membership updated',
|
||||
null,
|
||||
{panelClass: 'mycroft-no-action-snackbar', duration: twoSeconds}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
openBottomSheet(membershipType: string) {
|
||||
const bottomSheetConfig = {
|
||||
data: {newAccount: false, membershipType: membershipType},
|
||||
disableClose: true,
|
||||
restoreFocus: true
|
||||
};
|
||||
const bottomSheetRef = this.bottomSheet.open(PaymentComponent, bottomSheetConfig);
|
||||
bottomSheetRef.afterDismissed().subscribe(
|
||||
(dismissValue) => {
|
||||
if (dismissValue === 'cancel') {
|
||||
this.profileService.setSelectedMembershipType(
|
||||
this.accountMembership,
|
||||
this.membershipTypes
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import { MediaChange, MediaObserver } from '@angular/flex-layout';
|
||||
import { MatButtonToggleChange } from '@angular/material';
|
||||
import { MatButtonToggleChange, MatDialog, MatDialogConfig, MatSnackBar } from '@angular/material';
|
||||
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { AccountMembership } from '../../../../../shared/models/account-membership.model';
|
||||
import { MembershipType } from '../../../../../shared/models/membership.model';
|
||||
import { ProfileService } from '../../../../../core/http/profile.service';
|
||||
import { AccountMembership } from '@account/models/account-membership.model';
|
||||
import { MembershipType } from '@account/models/membership.model';
|
||||
import { ProfileService } from '@account/http/profile.service';
|
||||
import { PaymentComponent } from '@account/app/modules/profile/components/views/payment/payment.component';
|
||||
import { MembershipUpdate } from '@account/models/membership-update.model';
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -16,13 +18,18 @@ import { ProfileService } from '../../../../../core/http/profile.service';
|
|||
})
|
||||
export class MembershipOptionsComponent implements OnInit, OnDestroy {
|
||||
@Input() accountMembership: AccountMembership;
|
||||
public alignVertical: boolean;
|
||||
@Input() membershipTypes: MembershipType[];
|
||||
@Output() membershipChange = new EventEmitter<MembershipUpdate>();
|
||||
public alignVertical: boolean;
|
||||
public mediaWatcher: Subscription;
|
||||
@Output() membershipChange = new EventEmitter<string>();
|
||||
public selectedMembershipType: string;
|
||||
|
||||
constructor(public mediaObserver: MediaObserver, private profileService: ProfileService) {
|
||||
constructor(
|
||||
public mediaObserver: MediaObserver,
|
||||
private profileService: ProfileService,
|
||||
public paymentDialog: MatDialog,
|
||||
private snackbar: MatSnackBar
|
||||
) {
|
||||
this.mediaWatcher = mediaObserver.media$.subscribe(
|
||||
(change: MediaChange) => {
|
||||
this.alignVertical = ['xs', 'sm'].includes(change.mqAlias);
|
||||
|
@ -45,9 +52,49 @@ export class MembershipOptionsComponent implements OnInit, OnDestroy {
|
|||
this.mediaWatcher.unsubscribe();
|
||||
}
|
||||
|
||||
onMembershipSelect(newMembershipType: MatButtonToggleChange) {
|
||||
this.profileService.selectedMembershipType.next(newMembershipType.value);
|
||||
this.membershipChange.emit(newMembershipType.value);
|
||||
onMembershipSelect(membershipType: MatButtonToggleChange) {
|
||||
const selectedMembership = this.membershipTypes.find(
|
||||
(membership) => membership.type === membershipType.value
|
||||
);
|
||||
let membershipUpdate;
|
||||
if (selectedMembership) {
|
||||
if (this.accountMembership) {
|
||||
// We have the user's credit card info but they decide to change plans
|
||||
membershipUpdate = {
|
||||
paymentMethod: 'Stripe',
|
||||
newMembership: false,
|
||||
membershipType: membershipType
|
||||
};
|
||||
this.membershipChange.emit(membershipUpdate);
|
||||
} else {
|
||||
// No credit card info. Go to payment dialog to collect
|
||||
this.openPaymentDialog(membershipType.value);
|
||||
}
|
||||
} else {
|
||||
// Membership termination
|
||||
membershipUpdate = {newMembership: false, membershipType: null};
|
||||
this.membershipChange.emit(membershipUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
openPaymentDialog(membershipType: string) {
|
||||
const dialogConfig = new MatDialogConfig();
|
||||
dialogConfig.data = {newAccount: false, membershipType: membershipType};
|
||||
dialogConfig.disableClose = true;
|
||||
dialogConfig.restoreFocus = true;
|
||||
const dialogRef = this.paymentDialog.open(PaymentComponent, dialogConfig);
|
||||
dialogRef.afterClosed().subscribe(
|
||||
(stripeToken) => {
|
||||
if (stripeToken) {
|
||||
const membershipUpdate: MembershipUpdate = {
|
||||
newMembership: true,
|
||||
membershipType: membershipType,
|
||||
paymentMethod: 'Stripe',
|
||||
paymentToken: stripeToken
|
||||
};
|
||||
this.membershipChange.emit(membershipUpdate);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</mat-card>
|
||||
</mat-card-content>
|
||||
<mat-card-actions align="right">
|
||||
<button mat-button id="cancel-button" (click)="onCancel()">CANCEL</button>
|
||||
<button mat-button id="submit-button" (click)="submitPayment()">SUBMIT</button>
|
||||
<button mat-button (click)="onCancel()">CANCEL</button>
|
||||
<button mat-button (click)="submitPaymentInfo()" class="submit-button">SUBMIT</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
@import "../../../../../../../../../node_modules/@angular/material/theming";
|
||||
@import "~@angular/material/theming";
|
||||
@import "mycroft-colors";
|
||||
@import "../../../../../../../../../src/stylesheets/components/buttons";
|
||||
@import "components/buttons";
|
||||
|
||||
mat-card {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
margin-bottom: 16px;
|
||||
max-width: 500px;
|
||||
padding: 32px;
|
||||
padding: 0;
|
||||
|
||||
mat-card-title {
|
||||
color: mat-color($mycroft-primary, 700);
|
||||
|
@ -28,12 +27,18 @@ mat-card {
|
|||
border-width: 1px;
|
||||
border-color: mat-color($mycroft-accent, 200);
|
||||
padding: 16px;
|
||||
margin-bottom: 40px;
|
||||
width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
#submit-button {
|
||||
@include action-button-primary;
|
||||
margin-top: 16px
|
||||
.mat-card-actions.mat-card-actions {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.submit-button {
|
||||
@include action-button-primary;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
|
||||
import {
|
||||
MatBottomSheetRef,
|
||||
MatDialog,
|
||||
MAT_DIALOG_DATA,
|
||||
MatDialogRef,
|
||||
MatSnackBar
|
||||
} from '@angular/material';
|
||||
|
@ -9,7 +8,6 @@ import {
|
|||
import { ElementOptions, StripeCardComponent, StripeService } from 'ngx-stripe';
|
||||
|
||||
import { ProfileService } from '@account/http/profile.service';
|
||||
import { VerifyCardDialogComponent } from './verify-card-dialog.component';
|
||||
|
||||
const twoSeconds = 2000;
|
||||
|
||||
|
@ -32,14 +30,13 @@ export class PaymentComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
};
|
||||
private dialogRef: MatDialogRef<VerifyCardDialogComponent>;
|
||||
|
||||
constructor(
|
||||
private bottomSheetRef: MatBottomSheetRef<PaymentComponent>,
|
||||
private paymentSnackbar: MatSnackBar,
|
||||
public dialogRef: MatDialogRef<PaymentComponent>,
|
||||
private snackbar: MatSnackBar,
|
||||
private profileService: ProfileService,
|
||||
private stripeService: StripeService,
|
||||
public verifyCardDialog: MatDialog
|
||||
@Inject(MAT_DIALOG_DATA) public dialogData: any
|
||||
|
||||
) {
|
||||
}
|
||||
|
@ -47,60 +44,23 @@ export class PaymentComponent implements OnInit {
|
|||
ngOnInit() {
|
||||
}
|
||||
|
||||
submitPayment() {
|
||||
this.openDialog();
|
||||
submitPaymentInfo() {
|
||||
this.stripeService.createToken(this.card.getCard(), {}).subscribe(
|
||||
result => {
|
||||
if (result.token) {
|
||||
const configData = this.bottomSheetRef.containerInstance.bottomSheetConfig.data;
|
||||
if (configData.newAccount) {
|
||||
this.showStripeSuccess(result.token.id);
|
||||
} else {
|
||||
this.updateAccount(configData.membershipType, result.token.id);
|
||||
}
|
||||
this.dialogRef.close(result.token.id);
|
||||
} else if (result.error) {
|
||||
this.showStripeError(result.error.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
(result) => { this.showStripeError(result.toString()); }
|
||||
);
|
||||
}
|
||||
|
||||
openDialog(): void {
|
||||
this.dialogRef = this.verifyCardDialog.open(
|
||||
VerifyCardDialogComponent,
|
||||
{width: '250px'}
|
||||
);
|
||||
}
|
||||
|
||||
updateAccount(membershipType: string, stripeToken: string) {
|
||||
const newMembership = {
|
||||
membership: {
|
||||
newMembership: true,
|
||||
membershipType: membershipType,
|
||||
paymentMethod: 'Stripe',
|
||||
paymentToken: stripeToken
|
||||
}
|
||||
};
|
||||
this.profileService.updateAccount(newMembership).subscribe(
|
||||
() => { this.showStripeSuccess(stripeToken); }
|
||||
);
|
||||
}
|
||||
|
||||
showStripeSuccess(stripeToken: string) {
|
||||
this.dialogRef.close();
|
||||
const paymentSnackbarRef = this.paymentSnackbar.open(
|
||||
'Card verification successful',
|
||||
null,
|
||||
{panelClass: 'mycroft-no-action-snackbar', duration: twoSeconds}
|
||||
);
|
||||
paymentSnackbarRef.afterDismissed().subscribe(
|
||||
() => { this.bottomSheetRef.dismiss(stripeToken); }
|
||||
);
|
||||
}
|
||||
|
||||
showStripeError(errorMessage: string) {
|
||||
this.dialogRef.close();
|
||||
this.paymentSnackbar.open(
|
||||
this.snackbar.open(
|
||||
errorMessage,
|
||||
null,
|
||||
{panelClass: 'mycroft-no-action-snackbar', duration: twoSeconds}
|
||||
|
@ -108,6 +68,6 @@ export class PaymentComponent implements OnInit {
|
|||
}
|
||||
|
||||
onCancel() {
|
||||
this.bottomSheetRef.dismiss('cancel');
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</p>
|
||||
<account-membership-options
|
||||
[membershipTypes]="membershipTypes"
|
||||
(membershipChange)="onMembershipSelection($event)"
|
||||
(membershipChange)="updateNewAccountForm($event)"
|
||||
>
|
||||
</account-membership-options>
|
||||
</mat-card>
|
||||
|
|
|
@ -2,8 +2,9 @@ import { Component, Input, OnInit } from '@angular/core';
|
|||
import { FormGroup } from '@angular/forms';
|
||||
import { MatBottomSheet } from '@angular/material';
|
||||
|
||||
import { MembershipType } from '../../../../../shared/models/membership.model';
|
||||
import { ProfileService } from '../../../../../core/http/profile.service';
|
||||
import { MembershipType } from '@account/models/membership.model';
|
||||
import { MembershipUpdate } from '@account/models/membership-update.model';
|
||||
import { ProfileService } from '@account/http/profile.service';
|
||||
import { PaymentComponent } from '../payment/payment.component';
|
||||
|
||||
@Component({
|
||||
|
@ -17,9 +18,9 @@ export class SupportStepComponent implements OnInit {
|
|||
public openDatasetDescription: string[];
|
||||
public membershipDescription: string[];
|
||||
|
||||
constructor(public bottomSheet: MatBottomSheet, private profileService: ProfileService) { }
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
this.openDatasetDescription = [
|
||||
'Mycroft\'s voices and services can only improve with your help. ' +
|
||||
'By joining our open dataset, you agree to allow Mycroft AI to collect data related ' +
|
||||
|
@ -48,51 +49,21 @@ export class SupportStepComponent implements OnInit {
|
|||
];
|
||||
}
|
||||
|
||||
onOptIn() {
|
||||
onOptIn(): void {
|
||||
this.newAcctForm.patchValue({support: {openDataset: true}});
|
||||
}
|
||||
|
||||
onOptOut() {
|
||||
onOptOut(): void {
|
||||
this.newAcctForm.patchValue({support: {openDataset: false}});
|
||||
}
|
||||
|
||||
onMembershipSelection(membershipType: string) {
|
||||
const selectedMembership = this.membershipTypes.find(
|
||||
(membership) => membership.type === membershipType
|
||||
);
|
||||
if (selectedMembership) {
|
||||
this.openBottomSheet(selectedMembership.type);
|
||||
} else {
|
||||
this.newAcctForm.patchValue({support: {membership: null}});
|
||||
}
|
||||
}
|
||||
|
||||
openBottomSheet(selectedMembership: string) {
|
||||
const bottomSheetConfig = {
|
||||
data: {newAccount: true},
|
||||
disableClose: true,
|
||||
restoreFocus: true
|
||||
};
|
||||
const bottomSheetRef = this.bottomSheet.open(PaymentComponent, bottomSheetConfig);
|
||||
bottomSheetRef.afterDismissed().subscribe(
|
||||
(dismissValue) => {
|
||||
if (dismissValue === 'cancel') {
|
||||
this.profileService.selectedMembershipType.next('Maybe Later');
|
||||
} else {
|
||||
this.updateNewAccountForm(selectedMembership, dismissValue);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
updateNewAccountForm(selectedMembership: string, stripeToken: string) {
|
||||
console.log(stripeToken);
|
||||
updateNewAccountForm(membershipUpdate: MembershipUpdate): void {
|
||||
this.newAcctForm.patchValue(
|
||||
{
|
||||
support: {
|
||||
membership: selectedMembership,
|
||||
paymentMethod: 'Stripe',
|
||||
paymentToken: stripeToken
|
||||
membership: membershipUpdate.membershipType,
|
||||
paymentMethod: membershipUpdate.paymentMethod,
|
||||
paymentToken: membershipUpdate.paymentToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export interface MembershipUpdate {
|
||||
membershipType?: string;
|
||||
newMembership: boolean;
|
||||
paymentMethod?: string;
|
||||
paymentToken?: string;
|
||||
}
|
Loading…
Reference in New Issue