mirror of
https://github.com/bitwarden/browser.git
synced 2024-08-27 23:31:41 +02:00
[PM 5023] migrate payment component (#8345)
* payment component migration * payment component migration * payment component migration
This commit is contained in:
parent
6fadee7cb4
commit
c06211829f
|
@ -1,163 +1,113 @@
|
||||||
<div class="mb-4 text-lg" *ngIf="showOptions && showMethods">
|
<div [formGroup]="paymentForm">
|
||||||
<div class="form-check form-check-inline mr-4">
|
<div class="tw-mb-4 tw-text-lg" *ngIf="showOptions && showMethods">
|
||||||
<input
|
<bit-radio-group formControlName="method">
|
||||||
class="form-check-input"
|
<bit-radio-button id="method-card" [value]="paymentMethodType.Card">
|
||||||
type="radio"
|
<bit-label>
|
||||||
name="Method"
|
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>
|
||||||
id="method-card"
|
{{ "creditCard" | i18n }}</bit-label
|
||||||
[value]="paymentMethodType.Card"
|
|
||||||
[(ngModel)]="method"
|
|
||||||
(change)="changeMethod()"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label" for="method-card">
|
|
||||||
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i> {{ "creditCard" | i18n }}</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline mr-4" *ngIf="!hideBank">
|
|
||||||
<input
|
|
||||||
class="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
name="Method"
|
|
||||||
id="method-bank"
|
|
||||||
[value]="paymentMethodType.BankAccount"
|
|
||||||
[(ngModel)]="method"
|
|
||||||
(change)="changeMethod()"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label" for="method-bank">
|
|
||||||
<i class="bwi bwi-fw bwi-bank" aria-hidden="true"></i> {{ "bankAccount" | i18n }}</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline" *ngIf="!hidePaypal">
|
|
||||||
<input
|
|
||||||
class="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
name="Method"
|
|
||||||
id="method-paypal"
|
|
||||||
[value]="paymentMethodType.PayPal"
|
|
||||||
[(ngModel)]="method"
|
|
||||||
(change)="changeMethod()"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label" for="method-paypal">
|
|
||||||
<i class="bwi bwi-fw bwi-paypal" aria-hidden="true"></i> PayPal</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline" *ngIf="!hideCredit">
|
|
||||||
<input
|
|
||||||
class="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
name="Method"
|
|
||||||
id="method-credit"
|
|
||||||
[value]="paymentMethodType.Credit"
|
|
||||||
[(ngModel)]="method"
|
|
||||||
(change)="changeMethod()"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label" for="method-credit">
|
|
||||||
<i class="bwi bwi-fw bwi-dollar" aria-hidden="true"></i> {{ "accountCredit" | i18n }}</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="showMethods && method === paymentMethodType.Card">
|
|
||||||
<div class="row">
|
|
||||||
<div [ngClass]="trialFlow ? 'col-5' : 'col-4'" class="form-group">
|
|
||||||
<label for="stripe-card-number-element">{{ "number" | i18n }}</label>
|
|
||||||
<div id="stripe-card-number-element" class="form-control stripe-form-control"></div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="!trialFlow" class="form-group col-8 d-flex align-items-end">
|
|
||||||
<img
|
|
||||||
src="../../images/cards.png"
|
|
||||||
alt="Visa, MasterCard, Discover, AmEx, JCB, Diners Club, UnionPay"
|
|
||||||
width="323"
|
|
||||||
height="32"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div [ngClass]="trialFlow ? 'col-3' : 'col-4'" class="form-group">
|
|
||||||
<label for="stripe-card-expiry-element">{{ "expiration" | i18n }}</label>
|
|
||||||
<div id="stripe-card-expiry-element" class="form-control stripe-form-control"></div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-4">
|
|
||||||
<div class="d-flex">
|
|
||||||
<label for="stripe-card-cvc-element">
|
|
||||||
{{ "securityCode" | i18n }}
|
|
||||||
</label>
|
|
||||||
<a
|
|
||||||
href="https://www.cvvnumber.com/cvv.html"
|
|
||||||
tabindex="-1"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
class="ml-auto"
|
|
||||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
</bit-radio-button>
|
||||||
</a>
|
<bit-radio-button id="method-bank" [value]="paymentMethodType.BankAccount" *ngIf="!hideBank">
|
||||||
|
<bit-label>
|
||||||
|
<i class="bwi bwi-fw bwi-bank" aria-hidden="true"></i>
|
||||||
|
{{ "bankAccount" | i18n }}</bit-label
|
||||||
|
>
|
||||||
|
</bit-radio-button>
|
||||||
|
<bit-radio-button id="method-paypal" [value]="paymentMethodType.PayPal" *ngIf="!hidePaypal">
|
||||||
|
<bit-label> <i class="bwi bwi-fw bwi-paypal" aria-hidden="true"></i> PayPal</bit-label>
|
||||||
|
</bit-radio-button>
|
||||||
|
<bit-radio-button id="method-credit" [value]="paymentMethodType.Credit" *ngIf="!hideCredit">
|
||||||
|
<bit-label>
|
||||||
|
<i class="bwi bwi-fw bwi-dollar" aria-hidden="true"></i>
|
||||||
|
{{ "accountCredit" | i18n }}</bit-label
|
||||||
|
>
|
||||||
|
</bit-radio-button>
|
||||||
|
</bit-radio-group>
|
||||||
|
</div>
|
||||||
|
<ng-container *ngIf="showMethods && method === paymentMethodType.Card">
|
||||||
|
<div class="tw-grid tw-grid-cols-12 tw-gap-4 tw-mb-4">
|
||||||
|
<div [ngClass]="trialFlow ? 'tw-col-span-5' : 'tw-col-span-4'">
|
||||||
|
<label for="stripe-card-number-element">{{ "number" | i18n }}</label>
|
||||||
|
<div id="stripe-card-number-element" class="form-control stripe-form-control"></div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!trialFlow" class="tw-col-span-8 tw-flex tw-items-end">
|
||||||
|
<img
|
||||||
|
src="../../images/cards.png"
|
||||||
|
alt="Visa, MasterCard, Discover, AmEx, JCB, Diners Club, UnionPay"
|
||||||
|
width="323"
|
||||||
|
height="32"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div [ngClass]="trialFlow ? 'tw-col-span-3' : 'tw-col-span-4'">
|
||||||
|
<label for="stripe-card-expiry-element">{{ "expiration" | i18n }}</label>
|
||||||
|
<div id="stripe-card-expiry-element" class="form-control stripe-form-control"></div>
|
||||||
|
</div>
|
||||||
|
<div class="tw-col-span-4">
|
||||||
|
<div class="tw-flex">
|
||||||
|
<label for="stripe-card-cvc-element">
|
||||||
|
{{ "securityCode" | i18n }}
|
||||||
|
</label>
|
||||||
|
<a
|
||||||
|
href="https://www.cvvnumber.com/cvv.html"
|
||||||
|
tabindex="-1"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
class="ml-auto"
|
||||||
|
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div id="stripe-card-cvc-element" class="form-control stripe-form-control"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="stripe-card-cvc-element" class="form-control stripe-form-control"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
</ng-container>
|
<ng-container *ngIf="showMethods && method === paymentMethodType.BankAccount">
|
||||||
<ng-container *ngIf="showMethods && method === paymentMethodType.BankAccount">
|
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
|
||||||
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
|
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
|
||||||
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
|
</app-callout>
|
||||||
</app-callout>
|
<div class="tw-grid tw-grid-cols-12 tw-gap-4" formGroupName="bank">
|
||||||
<div class="row">
|
<bit-form-field class="tw-col-span-6">
|
||||||
<div class="form-group col-6">
|
<bit-label>{{ "routingNumber" | i18n }}</bit-label>
|
||||||
<label for="routing_number">{{ "routingNumber" | i18n }}</label>
|
<input bitInput type="text" formControlName="routing_number" required appInputVerbatim />
|
||||||
<input
|
</bit-form-field>
|
||||||
id="routing_number"
|
<bit-form-field class="tw-col-span-6">
|
||||||
class="form-control"
|
<bit-label>{{ "accountNumber" | i18n }}</bit-label>
|
||||||
type="text"
|
<input bitInput type="text" formControlName="account_number" required appInputVerbatim />
|
||||||
name="routing_number"
|
</bit-form-field>
|
||||||
[(ngModel)]="bank.routing_number"
|
<bit-form-field class="tw-col-span-6">
|
||||||
required
|
<bit-label>{{ "accountHolderName" | i18n }}</bit-label>
|
||||||
appInputVerbatim
|
<input
|
||||||
/>
|
bitInput
|
||||||
|
type="text"
|
||||||
|
formControlName="account_holder_name"
|
||||||
|
required
|
||||||
|
appInputVerbatim
|
||||||
|
/>
|
||||||
|
</bit-form-field>
|
||||||
|
|
||||||
|
<bit-form-field class="tw-col-span-6">
|
||||||
|
<bit-label>{{ "bankAccountType" | i18n }}</bit-label>
|
||||||
|
<bit-select formControlName="account_holder_type" required>
|
||||||
|
<bit-option value="" label="-- {{ 'select' | i18n }} --"></bit-option>
|
||||||
|
<bit-option value="company" label="{{ 'bankAccountTypeCompany' | i18n }}"></bit-option>
|
||||||
|
<bit-option
|
||||||
|
value="individual"
|
||||||
|
label="{{ 'bankAccountTypeIndividual' | i18n }}"
|
||||||
|
></bit-option>
|
||||||
|
</bit-select>
|
||||||
|
</bit-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-6">
|
</ng-container>
|
||||||
<label for="account_number">{{ "accountNumber" | i18n }}</label>
|
<ng-container *ngIf="showMethods && method === paymentMethodType.PayPal">
|
||||||
<input
|
<div class="tw-mb-3">
|
||||||
id="account_number"
|
<div id="bt-dropin-container" class="tw-mb-1"></div>
|
||||||
class="form-control"
|
<small class="tw-text-muted">{{ "paypalClickSubmit" | i18n }}</small>
|
||||||
type="text"
|
|
||||||
name="account_number"
|
|
||||||
[(ngModel)]="bank.account_number"
|
|
||||||
required
|
|
||||||
appInputVerbatim
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-6">
|
</ng-container>
|
||||||
<label for="account_holder_name">{{ "accountHolderName" | i18n }}</label>
|
<ng-container *ngIf="showMethods && method === paymentMethodType.Credit">
|
||||||
<input
|
<app-callout type="note">
|
||||||
id="account_holder_name"
|
{{ "makeSureEnoughCredit" | i18n }}
|
||||||
class="form-control"
|
</app-callout>
|
||||||
type="text"
|
</ng-container>
|
||||||
name="account_holder_name"
|
</div>
|
||||||
[(ngModel)]="bank.account_holder_name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-6">
|
|
||||||
<label for="account_holder_type">{{ "bankAccountType" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="account_holder_type"
|
|
||||||
class="form-control"
|
|
||||||
name="account_holder_type"
|
|
||||||
[(ngModel)]="bank.account_holder_type"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<option value="">-- {{ "select" | i18n }} --</option>
|
|
||||||
<option value="company">{{ "bankAccountTypeCompany" | i18n }}</option>
|
|
||||||
<option value="individual">{{ "bankAccountTypeIndividual" | i18n }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="showMethods && method === paymentMethodType.PayPal">
|
|
||||||
<div class="mb-3">
|
|
||||||
<div id="bt-dropin-container" class="mb-1"></div>
|
|
||||||
<small class="text-muted">{{ "paypalClickSubmit" | i18n }}</small>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="showMethods && method === paymentMethodType.Credit">
|
|
||||||
<app-callout type="note">
|
|
||||||
{{ "makeSureEnoughCredit" | i18n }}
|
|
||||||
</app-callout>
|
|
||||||
</ng-container>
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
|
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction";
|
import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction";
|
||||||
|
@ -17,23 +18,34 @@ import { SharedModule } from "../../shared";
|
||||||
export class PaymentComponent implements OnInit, OnDestroy {
|
export class PaymentComponent implements OnInit, OnDestroy {
|
||||||
@Input() showMethods = true;
|
@Input() showMethods = true;
|
||||||
@Input() showOptions = true;
|
@Input() showOptions = true;
|
||||||
@Input() method = PaymentMethodType.Card;
|
|
||||||
@Input() hideBank = false;
|
@Input() hideBank = false;
|
||||||
@Input() hidePaypal = false;
|
@Input() hidePaypal = false;
|
||||||
@Input() hideCredit = false;
|
@Input() hideCredit = false;
|
||||||
@Input() trialFlow = false;
|
@Input() trialFlow = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set method(value: PaymentMethodType) {
|
||||||
|
this._method = value;
|
||||||
|
this.paymentForm?.controls.method.setValue(value, { emitEvent: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
get method(): PaymentMethodType {
|
||||||
|
return this._method;
|
||||||
|
}
|
||||||
|
private _method: PaymentMethodType = PaymentMethodType.Card;
|
||||||
|
|
||||||
private destroy$ = new Subject<void>();
|
private destroy$ = new Subject<void>();
|
||||||
|
protected paymentForm = new FormGroup({
|
||||||
bank: any = {
|
method: new FormControl(this.method),
|
||||||
routing_number: null,
|
bank: new FormGroup({
|
||||||
account_number: null,
|
routing_number: new FormControl(null, [Validators.required]),
|
||||||
account_holder_name: null,
|
account_number: new FormControl(null, [Validators.required]),
|
||||||
account_holder_type: "",
|
account_holder_name: new FormControl(null, [Validators.required]),
|
||||||
currency: "USD",
|
account_holder_type: new FormControl("", [Validators.required]),
|
||||||
country: "US",
|
currency: new FormControl("USD"),
|
||||||
};
|
country: new FormControl("US"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
paymentMethodType = PaymentMethodType;
|
paymentMethodType = PaymentMethodType;
|
||||||
|
|
||||||
private btScript: HTMLScriptElement;
|
private btScript: HTMLScriptElement;
|
||||||
|
@ -85,7 +97,6 @@ export class PaymentComponent implements OnInit, OnDestroy {
|
||||||
invalid: "is-invalid",
|
invalid: "is-invalid",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
if (!this.showOptions) {
|
if (!this.showOptions) {
|
||||||
this.hidePaypal = this.method !== PaymentMethodType.PayPal;
|
this.hidePaypal = this.method !== PaymentMethodType.PayPal;
|
||||||
|
@ -97,6 +108,13 @@ export class PaymentComponent implements OnInit, OnDestroy {
|
||||||
if (!this.hidePaypal) {
|
if (!this.hidePaypal) {
|
||||||
window.document.head.appendChild(this.btScript);
|
window.document.head.appendChild(this.btScript);
|
||||||
}
|
}
|
||||||
|
this.paymentForm
|
||||||
|
.get("method")
|
||||||
|
.valueChanges.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((v) => {
|
||||||
|
this.method = v;
|
||||||
|
this.changeMethod();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -140,7 +158,6 @@ export class PaymentComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
changeMethod() {
|
changeMethod() {
|
||||||
this.btInstance = null;
|
this.btInstance = null;
|
||||||
|
|
||||||
if (this.method === PaymentMethodType.PayPal) {
|
if (this.method === PaymentMethodType.PayPal) {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
(window as any).braintree.dropin.create(
|
(window as any).braintree.dropin.create(
|
||||||
|
@ -209,15 +226,17 @@ export class PaymentComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.stripe.createToken("bank_account", this.bank).then((result: any) => {
|
this.stripe
|
||||||
if (result.error) {
|
.createToken("bank_account", this.paymentForm.get("bank").value)
|
||||||
reject(result.error.message);
|
.then((result: any) => {
|
||||||
} else if (result.token && result.token.id != null) {
|
if (result.error) {
|
||||||
resolve([result.token.id, this.method]);
|
reject(result.error.message);
|
||||||
} else {
|
} else if (result.token && result.token.id != null) {
|
||||||
reject();
|
resolve([result.token.id, this.method]);
|
||||||
}
|
} else {
|
||||||
});
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user