1
0
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:
KiruthigaManivannan
2024-06-26 19:36:25 +05:30
committed by GitHub
parent c85429ab4f
commit 5e9e095b40
2 changed files with 84 additions and 119 deletions

View File

@@ -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>

View File

@@ -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;