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";