1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-11 22:13:32 +00:00

feat(billing): improves premium org upgrade dialog

Adds a close button to the premium organization upgrade dialog.

Updates the success toast message after upgrading to teams.

Hides the formatted amount for credit discounts.

Sets the change detection strategy to OnPush for improved performance.
This commit is contained in:
Stephon Brown
2026-01-28 17:49:43 -05:00
parent 28e63d564a
commit 2eaff7a8fa
5 changed files with 36 additions and 6 deletions

View File

@@ -337,7 +337,7 @@ describe("PremiumOrgUpgradePaymentComponent", () => {
expect(mockToastService.showToast).toHaveBeenCalledWith({
variant: "success",
message: "organizationUpdated",
message: "plansUpdated",
});
expect(completeSpy).toHaveBeenCalledWith({
status: PremiumOrgUpgradePaymentStatus.UpgradedToTeams,

View File

@@ -177,7 +177,7 @@ export class PremiumOrgUpgradePaymentComponent implements OnInit, AfterViewInit
type: "amount-off",
value: this.estimatedInvoice().credit,
translationKey: "premiumMembershipDiscount",
quantity: 1,
hideFormattedAmount: true,
},
};
});

View File

@@ -4,6 +4,17 @@
cdkTrapFocus
cdkTrapFocusAutoCapture
>
<header class="tw-flex tw-items-center tw-justify-end tw-pl-6 tw-pt-3 tw-pr-2">
<button
cdkFocusInitial
type="button"
bitIconButton="bwi-close"
buttonType="main"
size="default"
[label]="'close' | i18n"
(click)="closeClicked.emit(closedStatus)"
></button>
</header>
<div class="tw-px-14 tw-py-8">
<div class="tw-flex tw-text-center tw-flex-col tw-pb-4">
<h1 class="tw-font-medium tw-text-[32px]">

View File

@@ -1,6 +1,13 @@
import { CdkTrapFocus } from "@angular/cdk/a11y";
import { CommonModule } from "@angular/common";
import { Component, DestroyRef, OnInit, output, signal } from "@angular/core";
import {
Component,
DestroyRef,
OnInit,
output,
signal,
ChangeDetectionStrategy,
} from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { combineLatest, catchError, of } from "rxjs";
@@ -16,15 +23,21 @@ import {
SubscriptionCadenceIds,
} from "@bitwarden/common/billing/types/subscription-pricing-tier";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { UnionOfValues } from "@bitwarden/common/vault/types/union-of-values";
import { ButtonType, DialogModule, ToastService } from "@bitwarden/components";
import { PricingCardComponent } from "@bitwarden/pricing";
import { SharedModule } from "../../../../shared";
import { BillingServicesModule } from "../../../services";
export const PremiumOrgUpgradeStatus = {
Closed: "closed",
ProceededToPayment: "proceeded-to-payment",
} as const;
export type PremiumOrgUpgradeStatus = UnionOfValues<typeof PremiumOrgUpgradeStatus>;
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-premium-org-upgrade",
imports: [
CommonModule,
@@ -38,6 +51,9 @@ import { BillingServicesModule } from "../../../services";
})
export class PremiumOrgUpgradeComponent implements OnInit {
planSelected = output<PersonalSubscriptionPricingTierId | BusinessSubscriptionPricingTierId>();
closeClicked = output<PremiumOrgUpgradeStatus>();
protected closedStatus = PremiumOrgUpgradeStatus.Closed;
protected readonly loading = signal(true);
protected familiesCardDetails!: SubscriptionPricingCardDetails;
protected teamsCardDetails!: SubscriptionPricingCardDetails;
@@ -129,11 +145,13 @@ export class PremiumOrgUpgradeComponent implements OnInit {
}
let priceAmount: number | undefined;
let shouldShowPerUser = false;
if ("annualPrice" in tier.passwordManager) {
priceAmount = tier.passwordManager.annualPrice;
} else if ("annualPricePerUser" in tier.passwordManager) {
priceAmount = tier.passwordManager.annualPricePerUser;
shouldShowPerUser = true;
}
return {
@@ -144,6 +162,7 @@ export class PremiumOrgUpgradeComponent implements OnInit {
? {
amount: priceAmount / 12,
cadence: SubscriptionCadenceIds.Monthly,
showPerUser: shouldShowPerUser,
}
: undefined,
button: {

View File

@@ -4,7 +4,7 @@ import { ButtonType } from "@bitwarden/components";
export type SubscriptionPricingCardDetails = {
title: string;
tagline: string;
price?: { amount: number; cadence: SubscriptionCadence };
price?: { amount: number; cadence: SubscriptionCadence; showPerUser?: boolean };
button: { text: string; type: ButtonType; icon?: { type: string; position: "before" | "after" } };
features: string[];
};