1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-07-17 14:06:49 +02:00

[PM 5023] migrate payment component (#8345)

* payment component migration

* payment component migration

* payment component migration
This commit is contained in:
vinith-kovan 2024-06-06 19:29:54 +05:30 committed by GitHub
parent 6fadee7cb4
commit c06211829f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 149 additions and 180 deletions

View File

@ -1,163 +1,113 @@
<div class="mb-4 text-lg" *ngIf="showOptions && showMethods">
<div class="form-check form-check-inline mr-4">
<input
class="form-check-input"
type="radio"
name="Method"
id="method-card"
[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 }}"
<div [formGroup]="paymentForm">
<div class="tw-mb-4 tw-text-lg" *ngIf="showOptions && showMethods">
<bit-radio-group formControlName="method">
<bit-radio-button id="method-card" [value]="paymentMethodType.Card">
<bit-label>
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>
{{ "creditCard" | i18n }}</bit-label
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</bit-radio-button>
<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 id="stripe-card-cvc-element" class="form-control stripe-form-control"></div>
</div>
</div>
</ng-container>
<ng-container *ngIf="showMethods && method === paymentMethodType.BankAccount">
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
</app-callout>
<div class="row">
<div class="form-group col-6">
<label for="routing_number">{{ "routingNumber" | i18n }}</label>
<input
id="routing_number"
class="form-control"
type="text"
name="routing_number"
[(ngModel)]="bank.routing_number"
required
appInputVerbatim
/>
</ng-container>
<ng-container *ngIf="showMethods && method === paymentMethodType.BankAccount">
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
</app-callout>
<div class="tw-grid tw-grid-cols-12 tw-gap-4" formGroupName="bank">
<bit-form-field class="tw-col-span-6">
<bit-label>{{ "routingNumber" | i18n }}</bit-label>
<input bitInput type="text" formControlName="routing_number" required appInputVerbatim />
</bit-form-field>
<bit-form-field class="tw-col-span-6">
<bit-label>{{ "accountNumber" | i18n }}</bit-label>
<input bitInput type="text" formControlName="account_number" required appInputVerbatim />
</bit-form-field>
<bit-form-field class="tw-col-span-6">
<bit-label>{{ "accountHolderName" | i18n }}</bit-label>
<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 class="form-group col-6">
<label for="account_number">{{ "accountNumber" | i18n }}</label>
<input
id="account_number"
class="form-control"
type="text"
name="account_number"
[(ngModel)]="bank.account_number"
required
appInputVerbatim
/>
</ng-container>
<ng-container *ngIf="showMethods && method === paymentMethodType.PayPal">
<div class="tw-mb-3">
<div id="bt-dropin-container" class="tw-mb-1"></div>
<small class="tw-text-muted">{{ "paypalClickSubmit" | i18n }}</small>
</div>
<div class="form-group col-6">
<label for="account_holder_name">{{ "accountHolderName" | i18n }}</label>
<input
id="account_holder_name"
class="form-control"
type="text"
name="account_holder_name"
[(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>
</ng-container>
<ng-container *ngIf="showMethods && method === paymentMethodType.Credit">
<app-callout type="note">
{{ "makeSureEnoughCredit" | i18n }}
</app-callout>
</ng-container>
</div>

View File

@ -1,4 +1,5 @@
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { Subject, takeUntil } from "rxjs";
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 {
@Input() showMethods = true;
@Input() showOptions = true;
@Input() method = PaymentMethodType.Card;
@Input() hideBank = false;
@Input() hidePaypal = false;
@Input() hideCredit = 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>();
bank: any = {
routing_number: null,
account_number: null,
account_holder_name: null,
account_holder_type: "",
currency: "USD",
country: "US",
};
protected paymentForm = new FormGroup({
method: new FormControl(this.method),
bank: new FormGroup({
routing_number: new FormControl(null, [Validators.required]),
account_number: new FormControl(null, [Validators.required]),
account_holder_name: new FormControl(null, [Validators.required]),
account_holder_type: new FormControl("", [Validators.required]),
currency: new FormControl("USD"),
country: new FormControl("US"),
}),
});
paymentMethodType = PaymentMethodType;
private btScript: HTMLScriptElement;
@ -85,7 +97,6 @@ export class PaymentComponent implements OnInit, OnDestroy {
invalid: "is-invalid",
};
}
async ngOnInit() {
if (!this.showOptions) {
this.hidePaypal = this.method !== PaymentMethodType.PayPal;
@ -97,6 +108,13 @@ export class PaymentComponent implements OnInit, OnDestroy {
if (!this.hidePaypal) {
window.document.head.appendChild(this.btScript);
}
this.paymentForm
.get("method")
.valueChanges.pipe(takeUntil(this.destroy$))
.subscribe((v) => {
this.method = v;
this.changeMethod();
});
}
ngOnDestroy() {
@ -140,7 +158,6 @@ export class PaymentComponent implements OnInit, OnDestroy {
changeMethod() {
this.btInstance = null;
if (this.method === PaymentMethodType.PayPal) {
window.setTimeout(() => {
(window as any).braintree.dropin.create(
@ -209,15 +226,17 @@ export class PaymentComponent implements OnInit, OnDestroy {
}
});
} else {
this.stripe.createToken("bank_account", this.bank).then((result: any) => {
if (result.error) {
reject(result.error.message);
} else if (result.token && result.token.id != null) {
resolve([result.token.id, this.method]);
} else {
reject();
}
});
this.stripe
.createToken("bank_account", this.paymentForm.get("bank").value)
.then((result: any) => {
if (result.error) {
reject(result.error.message);
} else if (result.token && result.token.id != null) {
resolve([result.token.id, this.method]);
} else {
reject();
}
});
}
}
});