diff --git a/apps/web/src/app/billing/individual/individual-billing.module.ts b/apps/web/src/app/billing/individual/individual-billing.module.ts
index 35c08aa40a2..36eed6fe970 100644
--- a/apps/web/src/app/billing/individual/individual-billing.module.ts
+++ b/apps/web/src/app/billing/individual/individual-billing.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from "@angular/core";
import { BaseCardComponent } from "@bitwarden/components";
import { PricingCardComponent } from "@bitwarden/pricing";
+import { AdditionalOptionsCardComponent, StorageCardComponent } from "@bitwarden/subscription";
import {
EnterBillingAddressComponent,
EnterPaymentMethodComponent,
@@ -24,6 +25,8 @@ import { UserSubscriptionComponent } from "./user-subscription.component";
EnterBillingAddressComponent,
PricingCardComponent,
BaseCardComponent,
+ StorageCardComponent,
+ AdditionalOptionsCardComponent,
],
declarations: [SubscriptionComponent, BillingHistoryViewComponent, UserSubscriptionComponent],
})
diff --git a/apps/web/src/app/billing/individual/user-subscription.component.html b/apps/web/src/app/billing/individual/user-subscription.component.html
index 2d653ff200b..a45651bb945 100644
--- a/apps/web/src/app/billing/individual/user-subscription.component.html
+++ b/apps/web/src/app/billing/individual/user-subscription.component.html
@@ -138,47 +138,28 @@
-
{{ "storage" | i18n }}
-
- {{ "subscriptionStorage" | i18n: sub.maxStorageGb || 0 : sub.storageName || "0 MB" }}
-
-
-
-
-
-
-
-
-
-
-
{{ "additionalOptions" | i18n }}
-
{{ "additionalOptionsDesc" | i18n }}
-
-
-
+
+
+
diff --git a/libs/common/src/billing/abstractions/account/account-billing-api.service.abstraction.ts b/libs/common/src/billing/abstractions/account/account-billing-api.service.abstraction.ts
index 0f28e728ea2..cdb62f8e954 100644
--- a/libs/common/src/billing/abstractions/account/account-billing-api.service.abstraction.ts
+++ b/libs/common/src/billing/abstractions/account/account-billing-api.service.abstraction.ts
@@ -1,3 +1,4 @@
+import { StorageRequest } from "../../../models/request/storage.request";
import {
BillingInvoiceResponse,
BillingTransactionResponse,
@@ -9,4 +10,6 @@ export abstract class AccountBillingApiServiceAbstraction {
startAfter?: string,
): Promise
;
abstract getBillingTransactions(startAfter?: string): Promise;
+ abstract getUserLicense(): Promise;
+ abstract putAccountStorage(request: StorageRequest): Promise;
}
diff --git a/libs/common/src/billing/services/account/account-billing-api.service.ts b/libs/common/src/billing/services/account/account-billing-api.service.ts
index f94940ecef0..f7bb9337e61 100644
--- a/libs/common/src/billing/services/account/account-billing-api.service.ts
+++ b/libs/common/src/billing/services/account/account-billing-api.service.ts
@@ -1,4 +1,5 @@
import { ApiService } from "../../../abstractions/api.service";
+import { StorageRequest } from "../../../models/request/storage.request";
import { AccountBillingApiServiceAbstraction } from "../../abstractions/account/account-billing-api.service.abstraction";
import {
BillingInvoiceResponse,
@@ -45,4 +46,12 @@ export class AccountBillingApiService implements AccountBillingApiServiceAbstrac
);
return r?.map((i: any) => new BillingTransactionResponse(i)) || [];
}
+
+ async getUserLicense(): Promise {
+ return await this.apiService.send("GET", "/account/billing/vnext/license", null, true, true);
+ }
+
+ async putAccountStorage(request: StorageRequest): Promise {
+ return await this.apiService.send("PUT", "/account/billing/vnext/storage", request, true, true);
+ }
}
diff --git a/libs/subscription/src/components/additional-options-card/additional-options-card.component.html b/libs/subscription/src/components/additional-options-card/additional-options-card.component.html
new file mode 100644
index 00000000000..2a9be62b5d5
--- /dev/null
+++ b/libs/subscription/src/components/additional-options-card/additional-options-card.component.html
@@ -0,0 +1,27 @@
+
+ {{ "additionalOptions" | i18n }}
+ {{ "additionalOptionsDesc" | i18n }}
+
+
+
+
+
diff --git a/libs/subscription/src/components/additional-options-card/additional-options-card.component.ts b/libs/subscription/src/components/additional-options-card/additional-options-card.component.ts
new file mode 100644
index 00000000000..43e893936e0
--- /dev/null
+++ b/libs/subscription/src/components/additional-options-card/additional-options-card.component.ts
@@ -0,0 +1,29 @@
+import { CommonModule } from "@angular/common";
+import { Component, ChangeDetectionStrategy, input, output } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { CardComponent, TypographyModule, ButtonModule } from "@bitwarden/components";
+
+@Component({
+ selector: "app-additional-options-card",
+ standalone: true,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [CommonModule, CardComponent, TypographyModule, ButtonModule, JslibModule],
+ templateUrl: "./additional-options-card.component.html",
+})
+export class AdditionalOptionsCardComponent {
+ readonly showDownloadLicense = input(true);
+ readonly showCancelSubscription = input(true);
+ readonly cancelPromise = input | null>(null);
+
+ readonly downloadLicense = output();
+ readonly cancelSubscription = output();
+
+ onDownloadLicense() {
+ this.downloadLicense.emit();
+ }
+
+ onCancelSubscription() {
+ this.cancelSubscription.emit();
+ }
+}
diff --git a/libs/subscription/src/components/storage-card/storage-card.component.html b/libs/subscription/src/components/storage-card/storage-card.component.html
new file mode 100644
index 00000000000..65871c4eb42
--- /dev/null
+++ b/libs/subscription/src/components/storage-card/storage-card.component.html
@@ -0,0 +1,20 @@
+
+ {{ "storage" | i18n }}
+
+ {{ "subscriptionStorage" | i18n: maxStorageGb() || 0 : storageName() || "0 MB" }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/subscription/src/components/storage-card/storage-card.component.ts b/libs/subscription/src/components/storage-card/storage-card.component.ts
new file mode 100644
index 00000000000..17d0c7934de
--- /dev/null
+++ b/libs/subscription/src/components/storage-card/storage-card.component.ts
@@ -0,0 +1,43 @@
+import { CommonModule } from "@angular/common";
+import { Component, ChangeDetectionStrategy, input, output } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import {
+ ProgressModule,
+ CardComponent,
+ TypographyModule,
+ ButtonModule,
+} from "@bitwarden/components";
+
+@Component({
+ selector: "app-storage-card",
+ standalone: true,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [
+ CommonModule,
+ CardComponent,
+ TypographyModule,
+ ButtonModule,
+ ProgressModule,
+ JslibModule,
+ ],
+ templateUrl: "./storage-card.component.html",
+})
+export class StorageCardComponent {
+ readonly maxStorageGb = input();
+ readonly storageName = input();
+ readonly storagePercentage = input();
+ readonly showActions = input(true);
+ readonly isSubscriptionCancelled = input(false);
+
+ readonly addStorage = output();
+ readonly removeStorage = output();
+
+ onAddStorage() {
+ this.addStorage.emit();
+ }
+
+ onRemoveStorage() {
+ this.removeStorage.emit();
+ }
+}
diff --git a/libs/subscription/src/index.ts b/libs/subscription/src/index.ts
index 3deb7c89d41..9bd47b88c53 100644
--- a/libs/subscription/src/index.ts
+++ b/libs/subscription/src/index.ts
@@ -1 +1,2 @@
-export type Placeholder = unknown;
+export { StorageCardComponent } from "./components/storage-card/storage-card.component";
+export { AdditionalOptionsCardComponent } from "./components/additional-options-card/additional-options-card.component";