mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00:00
[PM-24982] Create Cart Summary Component in Bitwarden Pricing (#16344)
* feature(billing): add cart-summary component * tests(billing): add tests for component * feature(billing): add stories and documentation for storybook * feature(billing): export component * fix: add localization and remove null coalescing for PM * fix: import localization pipe and update story for I18n Service remove service * fix(billing): add IconButtonModule and use lineitem name * fix(billing): Update story props and add Family and Premium examples * fix(billing): Add examples and table of contents do to docs * fix(billing): update aria properties * fix(billing): add figma link and description * fix(billing): update docs * fix(billing): remove optional chaining since property is already checked * fix(billing): Update fonts and button padding * fix(billing): Update bitIconButton size to small
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import { CurrencyPipe } from "@angular/common";
|
||||
import { Component, computed, input, signal } from "@angular/core";
|
||||
|
||||
import { TypographyModule, IconButtonModule } from "@bitwarden/components";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
export type LineItem = {
|
||||
quantity: number;
|
||||
name: string;
|
||||
cost: number;
|
||||
cadence: "month" | "year";
|
||||
};
|
||||
|
||||
/**
|
||||
* A reusable UI-only component that displays a cart summary with line items.
|
||||
* This component has no external dependencies and performs minimal logic -
|
||||
* it only displays data and allows expanding/collapsing of line items.
|
||||
*/
|
||||
@Component({
|
||||
selector: "billing-cart-summary",
|
||||
templateUrl: "./cart-summary.component.html",
|
||||
imports: [TypographyModule, IconButtonModule, CurrencyPipe, I18nPipe],
|
||||
})
|
||||
export class CartSummaryComponent {
|
||||
// Required inputs
|
||||
passwordManager = input.required<LineItem>();
|
||||
additionalStorage = input<LineItem>();
|
||||
secretsManager = input<{ seats: LineItem; additionalServiceAccounts?: LineItem }>();
|
||||
estimatedTax = input.required<number>();
|
||||
|
||||
// UI state
|
||||
isExpanded = signal(true);
|
||||
|
||||
/**
|
||||
* Calculates total for password manager line item
|
||||
*/
|
||||
readonly passwordManagerTotal = computed<number>(() => {
|
||||
return this.passwordManager().quantity * this.passwordManager().cost;
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates total for additional storage line item if present
|
||||
*/
|
||||
readonly additionalStorageTotal = computed<number>(() => {
|
||||
const storage = this.additionalStorage();
|
||||
return storage ? storage.quantity * storage.cost : 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates total for secrets manager seats if present
|
||||
*/
|
||||
readonly secretsManagerSeatsTotal = computed<number>(() => {
|
||||
const sm = this.secretsManager();
|
||||
return sm?.seats ? sm.seats.quantity * sm.seats.cost : 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates total for secrets manager service accounts if present
|
||||
*/
|
||||
readonly additionalServiceAccountsTotal = computed<number>(() => {
|
||||
const sm = this.secretsManager();
|
||||
return sm?.additionalServiceAccounts
|
||||
? sm.additionalServiceAccounts.quantity * sm.additionalServiceAccounts.cost
|
||||
: 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates the total of all line items
|
||||
*/
|
||||
readonly total = computed<number>(() => this.getTotalCost());
|
||||
|
||||
/**
|
||||
* Toggles the expanded/collapsed state of the cart items
|
||||
*/
|
||||
toggleExpanded(): void {
|
||||
this.isExpanded.update((value: boolean) => !value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total cost of all line items in the cart
|
||||
* @returns The total cost as a number
|
||||
*/
|
||||
private getTotalCost(): number {
|
||||
return (
|
||||
this.passwordManagerTotal() +
|
||||
this.additionalStorageTotal() +
|
||||
this.secretsManagerSeatsTotal() +
|
||||
this.additionalServiceAccountsTotal() +
|
||||
this.estimatedTax()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user