mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 15:53:27 +00:00
PM-5022 Migrate Payment Method component (#8397)
* PM-5022 Migrated Payment Method component * PM-5022 Addressed review comments * PM-5022 Addressed review comments on CSS * PM-5022 Addressed the css comment and fixed build issues * PM-5022 Changed app-callout to bit-callout --------- Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
c85429ab4f
commit
5e9e095b40
@@ -3,7 +3,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
bitButton
|
bitButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
(click)="load()"
|
[bitAction]="load"
|
||||||
class="tw-ml-auto"
|
class="tw-ml-auto"
|
||||||
*ngIf="firstLoaded"
|
*ngIf="firstLoaded"
|
||||||
[disabled]="loading"
|
[disabled]="loading"
|
||||||
@@ -14,115 +14,93 @@
|
|||||||
</app-header>
|
</app-header>
|
||||||
|
|
||||||
<bit-container>
|
<bit-container>
|
||||||
<div class="tabbed-header" *ngIf="!organizationId">
|
<!-- TODO: Organization and individual should use different "page" components -->
|
||||||
<!--TODO: Organization and individual should use different "page" components -->
|
<h2 bitTypography="h1" *ngIf="!organizationId">{{ "paymentMethod" | i18n }}</h2>
|
||||||
<h1>{{ "paymentMethod" | i18n }}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-container *ngIf="!firstLoaded && loading">
|
<ng-container *ngIf="!firstLoaded && loading">
|
||||||
<i
|
<i
|
||||||
class="bwi bwi-spinner bwi-spin text-muted"
|
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||||
title="{{ 'loading' | i18n }}"
|
title="{{ 'loading' | i18n }}"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="billing">
|
<ng-container *ngIf="billing">
|
||||||
<h2>{{ (isCreditBalance ? "accountCredit" : "accountBalance") | i18n }}</h2>
|
<bit-section>
|
||||||
<p class="text-lg">
|
<h2 bitTypography="h2">
|
||||||
<strong>{{ creditOrBalance | currency: "$" }}</strong>
|
{{ (isCreditBalance ? "accountCredit" : "accountBalance") | i18n }}
|
||||||
</p>
|
</h2>
|
||||||
<p>{{ "creditAppliedDesc" | i18n }}</p>
|
<p class="tw-text-lg tw-font-bold">{{ creditOrBalance | currency: "$" }}</p>
|
||||||
<button type="button" bitButton buttonType="secondary" [bitAction]="addCredit">
|
<p bitTypography="body1">{{ "creditAppliedDesc" | i18n }}</p>
|
||||||
{{ "addCredit" | i18n }}
|
<button type="button" bitButton buttonType="secondary" [bitAction]="addCredit">
|
||||||
</button>
|
{{ "addCredit" | i18n }}
|
||||||
<h2 class="spaced-header">{{ "paymentMethod" | i18n }}</h2>
|
</button>
|
||||||
<p *ngIf="!paymentSource">{{ "noPaymentMethod" | i18n }}</p>
|
</bit-section>
|
||||||
<ng-container *ngIf="paymentSource">
|
<bit-section>
|
||||||
<app-callout
|
<h2 bitTypography="h2">{{ "paymentMethod" | i18n }}</h2>
|
||||||
type="warning"
|
<p *ngIf="!paymentSource" bitTypography="body1">{{ "noPaymentMethod" | i18n }}</p>
|
||||||
title="{{ 'verifyBankAccount' | i18n }}"
|
<ng-container *ngIf="paymentSource">
|
||||||
*ngIf="
|
<bit-callout
|
||||||
forOrganization &&
|
type="warning"
|
||||||
paymentSource.type === paymentMethodType.BankAccount &&
|
title="{{ 'verifyBankAccount' | i18n }}"
|
||||||
paymentSource.needsVerification
|
*ngIf="
|
||||||
"
|
forOrganization &&
|
||||||
>
|
paymentSource.type === paymentMethodType.BankAccount &&
|
||||||
<p>{{ "verifyBankAccountDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}</p>
|
paymentSource.needsVerification
|
||||||
<form
|
"
|
||||||
#verifyForm
|
|
||||||
class="form-inline"
|
|
||||||
(ngSubmit)="verifyBank()"
|
|
||||||
[formGroup]="verifyBankForm"
|
|
||||||
[appApiAction]="verifyBankPromise"
|
|
||||||
ngNativeValidate
|
|
||||||
>
|
>
|
||||||
<bit-form-field class="tw-mr-2 tw-w-40">
|
<p bitTypography="body1">
|
||||||
<bit-label>{{ "amountX" | i18n: "1" }}</bit-label>
|
{{ "verifyBankAccountDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
|
||||||
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount1" />
|
</p>
|
||||||
<span bitPrefix>$0.</span>
|
<form
|
||||||
</bit-form-field>
|
[formGroup]="verifyBankForm"
|
||||||
<bit-form-field class="tw-mr-2 tw-w-40">
|
[bitSubmit]="verifyBank"
|
||||||
<bit-label>{{ "amountX" | i18n: "2" }}</bit-label>
|
class="tw-flex tw-flex-wrap tw-items-center tw-space-x-2"
|
||||||
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount2" />
|
|
||||||
<span bitPrefix>$0.</span>
|
|
||||||
</bit-form-field>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitButton
|
|
||||||
buttonType="primary"
|
|
||||||
type="submit"
|
|
||||||
class="btn-submit"
|
|
||||||
[disabled]="verifyForm.loading"
|
|
||||||
>
|
>
|
||||||
<i
|
<bit-form-field class="tw-w-40">
|
||||||
class="bwi bwi-spinner bwi-spin"
|
<bit-label>{{ "amountX" | i18n: "1" }}</bit-label>
|
||||||
title="{{ 'loading' | i18n }}"
|
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount1" />
|
||||||
aria-hidden="true"
|
<span bitPrefix>$0.</span>
|
||||||
></i>
|
</bit-form-field>
|
||||||
<span>{{ "verifyBankAccount" | i18n }}</span>
|
<bit-form-field class="tw-w-40">
|
||||||
</button>
|
<bit-label>{{ "amountX" | i18n: "2" }}</bit-label>
|
||||||
</form>
|
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount2" />
|
||||||
</app-callout>
|
<span bitPrefix>$0.</span>
|
||||||
<p>
|
</bit-form-field>
|
||||||
<i class="bwi bwi-fw" [ngClass]="paymentSourceClasses"></i>
|
<button bitButton bitFormButton buttonType="primary" type="submit">
|
||||||
{{ paymentSource.description }}
|
{{ "verifyBankAccount" | i18n }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</bit-callout>
|
||||||
|
<p>
|
||||||
|
<i class="bwi bwi-fw" [ngClass]="paymentSourceClasses"></i>
|
||||||
|
{{ paymentSource.description }}
|
||||||
|
</p>
|
||||||
|
</ng-container>
|
||||||
|
<button type="button" bitButton buttonType="secondary" [bitAction]="changePayment">
|
||||||
|
{{ (paymentSource ? "changePaymentMethod" : "addPaymentMethod") | i18n }}
|
||||||
|
</button>
|
||||||
|
<p *ngIf="isUnpaid" bitTypography="body1">
|
||||||
|
{{ "paymentChargedWithUnpaidSubscription" | i18n }}
|
||||||
</p>
|
</p>
|
||||||
</ng-container>
|
</bit-section>
|
||||||
<button type="button" bitButton buttonType="secondary" [bitAction]="changePayment">
|
<bit-section *ngIf="forOrganization">
|
||||||
{{ (paymentSource ? "changePaymentMethod" : "addPaymentMethod") | i18n }}
|
<h2 bitTypography="h2">{{ "taxInformation" | i18n }}</h2>
|
||||||
</button>
|
<p bitTypography="body1">{{ "taxInformationDesc" | i18n }}</p>
|
||||||
<p *ngIf="isUnpaid">{{ "paymentChargedWithUnpaidSubscription" | i18n }}</p>
|
|
||||||
<ng-container *ngIf="forOrganization">
|
|
||||||
<h2 class="spaced-header">{{ "taxInformation" | i18n }}</h2>
|
|
||||||
<p>{{ "taxInformationDesc" | i18n }}</p>
|
|
||||||
<div *ngIf="!org || loading">
|
<div *ngIf="!org || loading">
|
||||||
<i
|
<i
|
||||||
class="bwi bwi-spinner bwi-spin text-muted"
|
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||||
title="{{ 'loading' | i18n }}"
|
title="{{ 'loading' | i18n }}"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||||
</div>
|
</div>
|
||||||
<form
|
<form *ngIf="org && !loading" [formGroup]="taxForm" [bitSubmit]="submitTaxInfo">
|
||||||
*ngIf="org && !loading"
|
|
||||||
#formTax
|
|
||||||
(ngSubmit)="submitTaxInfo()"
|
|
||||||
[appApiAction]="taxFormPromise"
|
|
||||||
ngNativeValidate
|
|
||||||
>
|
|
||||||
<app-tax-info></app-tax-info>
|
<app-tax-info></app-tax-info>
|
||||||
<button
|
<button bitButton bitFormButton buttonType="primary" type="submit">
|
||||||
bitButton
|
{{ "save" | i18n }}
|
||||||
buttonType="primary"
|
|
||||||
type="submit"
|
|
||||||
class="btn-submit"
|
|
||||||
[disabled]="formTax.loading"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
|
||||||
<span>{{ "save" | i18n }}</span>
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
</bit-section>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</bit-container>
|
</bit-container>
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ export class PaymentMethodComponent implements OnInit {
|
|||||||
organizationId: string;
|
organizationId: string;
|
||||||
isUnpaid = false;
|
isUnpaid = false;
|
||||||
|
|
||||||
verifyBankPromise: Promise<any>;
|
|
||||||
taxFormPromise: Promise<any>;
|
|
||||||
|
|
||||||
verifyBankForm = this.formBuilder.group({
|
verifyBankForm = this.formBuilder.group({
|
||||||
amount1: new FormControl<number>(null, [
|
amount1: new FormControl<number>(null, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
@@ -54,6 +51,8 @@ export class PaymentMethodComponent implements OnInit {
|
|||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
taxForm = this.formBuilder.group({});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected apiService: ApiService,
|
protected apiService: ApiService,
|
||||||
protected organizationApiService: OrganizationApiServiceAbstraction,
|
protected organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
@@ -83,7 +82,7 @@ export class PaymentMethodComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
load = async () => {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -109,7 +108,7 @@ export class PaymentMethodComponent implements OnInit {
|
|||||||
this.isUnpaid = this.subscription?.status === "unpaid" ?? false;
|
this.isUnpaid = this.subscription?.status === "unpaid" ?? false;
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
addCredit = async () => {
|
addCredit = async () => {
|
||||||
const dialogRef = openAddCreditDialog(this.dialogService, {
|
const dialogRef = openAddCreditDialog(this.dialogService, {
|
||||||
@@ -136,35 +135,23 @@ export class PaymentMethodComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async verifyBank() {
|
verifyBank = async () => {
|
||||||
if (this.loading || !this.forOrganization) {
|
if (this.loading || !this.forOrganization) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const request = new VerifyBankRequest();
|
||||||
const request = new VerifyBankRequest();
|
request.amount1 = this.verifyBankForm.value.amount1;
|
||||||
request.amount1 = this.verifyBankForm.value.amount1;
|
request.amount2 = this.verifyBankForm.value.amount2;
|
||||||
request.amount2 = this.verifyBankForm.value.amount2;
|
await this.organizationApiService.verifyBank(this.organizationId, request);
|
||||||
this.verifyBankPromise = this.organizationApiService.verifyBank(this.organizationId, request);
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("verifiedBankAccount"));
|
||||||
await this.verifyBankPromise;
|
await this.load();
|
||||||
this.platformUtilsService.showToast(
|
};
|
||||||
"success",
|
|
||||||
null,
|
|
||||||
this.i18nService.t("verifiedBankAccount"),
|
|
||||||
);
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.load();
|
|
||||||
} catch (e) {
|
|
||||||
this.logService.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async submitTaxInfo() {
|
submitTaxInfo = async () => {
|
||||||
this.taxFormPromise = this.taxInfo.submitTaxInfo();
|
await this.taxInfo.submitTaxInfo();
|
||||||
await this.taxFormPromise;
|
|
||||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("taxInfoUpdated"));
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("taxInfoUpdated"));
|
||||||
}
|
};
|
||||||
|
|
||||||
get isCreditBalance() {
|
get isCreditBalance() {
|
||||||
return this.billing == null || this.billing.balance <= 0;
|
return this.billing == null || this.billing.balance <= 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user