diff --git a/apps/web/src/app/billing/organizations/adjust-subscription.component.html b/apps/web/src/app/billing/organizations/adjust-subscription.component.html index f0200da638..9fe8d20540 100644 --- a/apps/web/src/app/billing/organizations/adjust-subscription.component.html +++ b/apps/web/src/app/billing/organizations/adjust-subscription.component.html @@ -1,65 +1,57 @@ -
-
-
-
- - - + +
+
+ + {{ "subscriptionSeats" | i18n }} + + {{ "total" | i18n }}: {{ additionalSeatCount || 0 }} × {{ seatPrice | currency: "$" }} = {{ adjustedSeatTotal | currency: "$" }} / - {{ interval | i18n }} - -
+ {{ interval | i18n }} +
-
-
-
- - -
- {{ "limitSubscriptionDesc" | i18n }} -
-
-
-
- +
+
+ + + {{ "limitSubscription" | i18n }} + {{ "limitSubscriptionDesc" | i18n }} + +
+
+
+ + {{ "maxSeatLimit" | i18n }} - + {{ "maxSeatCost" | i18n }}: {{ additionalMaxSeatCount || 0 }} × {{ seatPrice | currency: "$" }} = {{ maxSeatTotal | currency: "$" }} / - {{ interval | i18n }} - -
+ {{ interval | i18n }} +
-
+ diff --git a/apps/web/src/app/billing/organizations/adjust-subscription.component.ts b/apps/web/src/app/billing/organizations/adjust-subscription.component.ts index 4290a1281b..b843c79cb9 100644 --- a/apps/web/src/app/billing/organizations/adjust-subscription.component.ts +++ b/apps/web/src/app/billing/organizations/adjust-subscription.component.ts @@ -1,77 +1,102 @@ -import { Component, EventEmitter, Input, Output } from "@angular/core"; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core"; +import { FormBuilder, Validators } from "@angular/forms"; +import { Subject, takeUntil } from "rxjs"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @Component({ selector: "app-adjust-subscription", templateUrl: "adjust-subscription.component.html", }) -export class AdjustSubscription { +export class AdjustSubscription implements OnInit, OnDestroy { @Input() organizationId: string; @Input() maxAutoscaleSeats: number; @Input() currentSeatCount: number; @Input() seatPrice = 0; @Input() interval = "year"; @Output() onAdjusted = new EventEmitter(); + private destroy$ = new Subject(); - formPromise: Promise; - limitSubscription: boolean; - newSeatCount: number; - newMaxSeats: number; - + adjustSubscriptionForm = this.formBuilder.group({ + newSeatCount: [0, [Validators.min(0)]], + limitSubscription: [false], + newMaxSeats: [0, [Validators.min(0)]], + }); + get limitSubscription(): boolean { + return this.adjustSubscriptionForm.value.limitSubscription; + } constructor( private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private logService: LogService, private organizationApiService: OrganizationApiServiceAbstraction, + private formBuilder: FormBuilder, ) {} ngOnInit() { - this.limitSubscription = this.maxAutoscaleSeats != null; - this.newSeatCount = this.currentSeatCount; - this.newMaxSeats = this.maxAutoscaleSeats; + this.adjustSubscriptionForm.patchValue({ + newSeatCount: this.currentSeatCount, + limitSubscription: this.maxAutoscaleSeats != null, + newMaxSeats: this.maxAutoscaleSeats, + }); + this.adjustSubscriptionForm + .get("limitSubscription") + .valueChanges.pipe(takeUntil(this.destroy$)) + .subscribe((value: boolean) => { + if (value) { + this.adjustSubscriptionForm + .get("newMaxSeats") + .addValidators([ + Validators.min( + this.adjustSubscriptionForm.value.newSeatCount == null + ? 1 + : this.adjustSubscriptionForm.value.newSeatCount, + ), + Validators.required, + ]); + } + this.adjustSubscriptionForm.get("newMaxSeats").updateValueAndValidity(); + }); } - async submit() { - try { - const request = new OrganizationSubscriptionUpdateRequest( - this.additionalSeatCount, - this.newMaxSeats, - ); - this.formPromise = this.organizationApiService.updatePasswordManagerSeats( - this.organizationId, - request, - ); - - await this.formPromise; - - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("subscriptionUpdated"), - ); - } catch (e) { - this.logService.error(e); + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + submit = async () => { + this.adjustSubscriptionForm.markAllAsTouched(); + if (this.adjustSubscriptionForm.invalid) { + return; } + const request = new OrganizationSubscriptionUpdateRequest( + this.additionalSeatCount, + this.adjustSubscriptionForm.value.newMaxSeats, + ); + await this.organizationApiService.updatePasswordManagerSeats(this.organizationId, request); + + this.platformUtilsService.showToast("success", null, this.i18nService.t("subscriptionUpdated")); + this.onAdjusted.emit(); - } + }; limitSubscriptionChanged() { - if (!this.limitSubscription) { - this.newMaxSeats = null; + if (!this.adjustSubscriptionForm.value.limitSubscription) { + this.adjustSubscriptionForm.value.newMaxSeats = null; } } get additionalSeatCount(): number { - return this.newSeatCount ? this.newSeatCount - this.currentSeatCount : 0; + return this.adjustSubscriptionForm.value.newSeatCount + ? this.adjustSubscriptionForm.value.newSeatCount - this.currentSeatCount + : 0; } get additionalMaxSeatCount(): number { - return this.newMaxSeats ? this.newMaxSeats - this.currentSeatCount : 0; + return this.adjustSubscriptionForm.value.newMaxSeats + ? this.adjustSubscriptionForm.value.newMaxSeats - this.currentSeatCount + : 0; } get adjustedSeatTotal(): number {