1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-23 21:31:29 +01:00

[PM-16662] Fix annual pricing for billable providers (#12657)

This commit is contained in:
Jonas Hendrickx 2025-01-22 12:22:53 +01:00 committed by GitHub
parent 8784602858
commit 09748389e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 24 deletions

View File

@ -25,7 +25,7 @@
<tr bitRow *ngFor="let i of activePlans"> <tr bitRow *ngFor="let i of activePlans">
<td bitCell class="tw-pl-0 tw-py-3"> <td bitCell class="tw-pl-0 tw-py-3">
{{ getFormattedPlanName(i.planName) }} {{ "orgSeats" | i18n }} ({{ {{ getFormattedPlanName(i.planName) }} {{ "orgSeats" | i18n }} ({{
i.cadence.toLowerCase() getFormattedPlanNameCadence(i.cadence) | i18n
}}) {{ "&times;" }}{{ getFormattedSeatCount(i.seatMinimum, i.purchasedSeats) }} }}) {{ "&times;" }}{{ getFormattedSeatCount(i.seatMinimum, i.purchasedSeats) }}
&#64; &#64;
{{ {{
@ -38,12 +38,11 @@
}} }}
</td> </td>
<td bitCell class="tw-text-right tw-py-3"> <td bitCell class="tw-text-right tw-py-3">
{{ ((100 - subscription.discountPercentage) / 100) * i.cost | currency: "$" }} /{{ {{ ((100 - subscription.discountPercentage) / 100) * i.cost | currency: "$" }} /
"month" | i18n {{ getBillingCadenceLabel(i) | i18n }}
}}
<div *ngIf="subscription.discountPercentage"> <div *ngIf="subscription.discountPercentage">
<bit-hint class="tw-text-sm tw-line-through"> <bit-hint class="tw-text-sm tw-line-through">
{{ i.cost | currency: "$" }} /{{ "month" | i18n }} {{ i.cost | currency: "$" }} / {{ getBillingCadenceLabel(i) | i18n }}
</bit-hint> </bit-hint>
</div> </div>
</td> </td>
@ -52,8 +51,9 @@
<tr bitRow> <tr bitRow>
<td bitCell class="tw-pl-0 tw-py-3"></td> <td bitCell class="tw-pl-0 tw-py-3"></td>
<td bitCell class="tw-text-right"> <td bitCell class="tw-text-right">
<span class="tw-font-bold">Total:</span> {{ totalCost | currency: "$" }} /{{ <span class="tw-font-bold">Total:</span> {{ totalCost | currency: "$" }} /
"month" | i18n {{
getBillingCadenceLabel(activePlans.length > 0 ? activePlans[0] : null) | i18n
}} }}
</td> </td>
</tr> </tr>

View File

@ -19,14 +19,13 @@ import { ToastService } from "@bitwarden/components";
templateUrl: "./provider-subscription.component.html", templateUrl: "./provider-subscription.component.html",
}) })
export class ProviderSubscriptionComponent implements OnInit, OnDestroy { export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
providerId: string; private providerId: string;
subscription: ProviderSubscriptionResponse; protected subscription: ProviderSubscriptionResponse;
firstLoaded = false; protected firstLoaded = false;
loading: boolean; protected loading: boolean;
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
totalCost: number; protected totalCost: number;
currentDate = new Date();
protected readonly TaxInformation = TaxInformation; protected readonly TaxInformation = TaxInformation;
@ -50,11 +49,7 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
.subscribe(); .subscribe();
} }
get isExpired() { protected async load() {
return this.subscription.status !== "active";
}
async load() {
if (this.loading) { if (this.loading) {
return; return;
} }
@ -65,7 +60,7 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
this.loading = false; this.loading = false;
} }
updateTaxInformation = async (taxInformation: TaxInformation) => { protected updateTaxInformation = async (taxInformation: TaxInformation) => {
const request = ExpandedTaxInfoUpdateRequest.From(taxInformation); const request = ExpandedTaxInfoUpdateRequest.From(taxInformation);
await this.billingApiService.updateProviderTaxInformation(this.providerId, request); await this.billingApiService.updateProviderTaxInformation(this.providerId, request);
this.toastService.showToast({ this.toastService.showToast({
@ -75,7 +70,7 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
}); });
}; };
getFormattedCost( protected getFormattedCost(
cost: number, cost: number,
seatMinimum: number, seatMinimum: number,
purchasedSeats: number, purchasedSeats: number,
@ -85,17 +80,21 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
return costPerSeat - (costPerSeat * discountPercentage) / 100; return costPerSeat - (costPerSeat * discountPercentage) / 100;
} }
getFormattedPlanName(planName: string): string { protected getFormattedPlanName(planName: string): string {
const spaceIndex = planName.indexOf(" "); const spaceIndex = planName.indexOf(" ");
return planName.substring(0, spaceIndex); return planName.substring(0, spaceIndex);
} }
getFormattedSeatCount(seatMinimum: number, purchasedSeats: number): string { protected getFormattedSeatCount(seatMinimum: number, purchasedSeats: number): string {
const totalSeats = seatMinimum + purchasedSeats; const totalSeats = seatMinimum + purchasedSeats;
return totalSeats > 1 ? totalSeats.toString() : ""; return totalSeats > 1 ? totalSeats.toString() : "";
} }
sumCost(plans: ProviderPlanResponse[]): number { protected getFormattedPlanNameCadence(cadence: string) {
return cadence === "Annual" ? "annually" : "monthly";
}
private sumCost(plans: ProviderPlanResponse[]): number {
return plans.reduce((acc, plan) => acc + plan.cost, 0); return plans.reduce((acc, plan) => acc + plan.cost, 0);
} }
@ -104,7 +103,7 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
this.destroy$.complete(); this.destroy$.complete();
} }
get activePlans(): ProviderPlanResponse[] { protected get activePlans(): ProviderPlanResponse[] {
return this.subscription.plans.filter((plan) => { return this.subscription.plans.filter((plan) => {
if (plan.purchasedSeats === 0) { if (plan.purchasedSeats === 0) {
return plan.seatMinimum > 0; return plan.seatMinimum > 0;
@ -113,4 +112,19 @@ export class ProviderSubscriptionComponent implements OnInit, OnDestroy {
} }
}); });
} }
protected getBillingCadenceLabel(providerPlanResponse: ProviderPlanResponse): string {
if (providerPlanResponse == null || providerPlanResponse == undefined) {
return "month";
}
switch (providerPlanResponse.cadence) {
case "Monthly":
return "month";
case "Annual":
return "year";
default:
return "month";
}
}
} }