diff --git a/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.test.tsx b/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.test.tsx index efc04fbd3a4..5dc599348ed 100644 --- a/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.test.tsx +++ b/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.test.tsx @@ -1,19 +1,18 @@ import React from "react"; -import { mount } from "enzyme"; import { QueryClient, QueryClientProvider } from "react-query"; - -import DetailsContent from "./DetailsContent"; +import { mount } from "enzyme"; +import { CodeSnippet } from "@canonical/react-components"; +import { + UserSubscriptionMarketplace, + UserSubscriptionPeriod, +} from "advantage/api/enum"; import { contractTokenFactory, freeSubscriptionFactory, userSubscriptionFactory, userSubscriptionStatusesFactory, } from "advantage/tests/factories/api"; -import { - UserSubscriptionPeriod, - UserSubscriptionMarketplace, -} from "advantage/api/enum"; -import { CodeSnippet } from "@canonical/react-components"; +import DetailsContent from "./DetailsContent"; describe("DetailsContent", () => { let queryClient: QueryClient; @@ -35,7 +34,6 @@ describe("DetailsContent", () => { ); expect(wrapper.find("[data-test='expires-col']").text()).toBe("Never"); expect(wrapper.find("[data-test='billing-col']").text()).toBe("None"); - expect(wrapper.find("[data-test='cost-col']").text()).toBe("Free"); }); it("displays ua subscription specific details", () => { @@ -58,7 +56,6 @@ describe("DetailsContent", () => { "09 Jul 2022" ); expect(wrapper.find("[data-test='billing-col']").text()).toBe("Yearly"); - expect(wrapper.find("[data-test='cost-col']").text()).toBe("$1,500 USD/yr"); }); it("displays a spinner while loading the contract token", () => { @@ -120,21 +117,6 @@ describe("DetailsContent", () => { ); }); - it("hides the cost column if there is no cost provided", () => { - const contract = userSubscriptionFactory.build(); - contract.price = null; - queryClient.setQueryData("userSubscriptions", [contract]); - const wrapper = mount( - - - - ); - expect(wrapper.find("[data-test='cost-col']").exists()).toBe(false); - }); - it("displays correctly for blender subscription", () => { const contract = userSubscriptionFactory.build({ marketplace: UserSubscriptionMarketplace.Blender, diff --git a/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.tsx b/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.tsx index 288b0fc24ae..b003db59f27 100644 --- a/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.tsx +++ b/static/js/src/advantage/react/components/Subscriptions/SubscriptionDetails/DetailsContent/DetailsContent.tsx @@ -17,7 +17,6 @@ import { formatDate, getMachineTypeDisplay, getPeriodDisplay, - getSubscriptionCost, isBlenderSubscription, isFreeSubscription, } from "advantage/react/utils"; @@ -93,16 +92,6 @@ const DetailsContent = ({ selectedId, setHasUnsavedChanges }: Props) => { : getPeriodDisplay(subscription.period), }; - const cost = getSubscriptionCost(subscription); - const costCol: Feature = { - // When a legacy subscription is being displayed then stretch this - // column to take up the space where the billing column would - // otherwise be. - size: subscription.type === UserSubscriptionType.Legacy ? 5 : 3, - title: "Cost", - value: cost, - }; - const tokenBlock = token?.contract_token ? ( { ? // Don't show the billing column for legacy subscriptions. [] : [billingCol]), - ...(cost && subscription.type !== UserSubscriptionType.Legacy - ? // Don't show the cost column if it's empty. - [costCol] - : []), ...(isBlender ? // Don't show the column for Blender subscriptions. [] diff --git a/static/js/src/advantage/react/components/Subscriptions/SubscriptionEdit/SubscriptionEdit.tsx b/static/js/src/advantage/react/components/Subscriptions/SubscriptionEdit/SubscriptionEdit.tsx index 5365bc3a043..b3da349f0b8 100644 --- a/static/js/src/advantage/react/components/Subscriptions/SubscriptionEdit/SubscriptionEdit.tsx +++ b/static/js/src/advantage/react/components/Subscriptions/SubscriptionEdit/SubscriptionEdit.tsx @@ -10,7 +10,10 @@ import { NotificationProps, Spinner, } from "@canonical/react-components"; -import { UserSubscriptionPeriod } from "advantage/api/enum"; +import { + UserSubscriptionMarketplace, + UserSubscriptionPeriod, +} from "advantage/api/enum"; import { UserSubscription } from "advantage/api/types"; import { usePreviewResizeContract, @@ -19,7 +22,10 @@ import { } from "advantage/react/hooks"; import { PreviewResizeContractResponse } from "advantage/react/hooks/usePreviewResizeContract"; import { ResizeContractResponse } from "advantage/react/hooks/useResizeContract"; -import { selectSubscriptionById } from "advantage/react/hooks/useUserSubscriptions"; +import { + selectAutoRenewableSubscriptionsByMarketplace, + selectSubscriptionById, +} from "advantage/react/hooks/useUserSubscriptions"; import { currencyFormatter, formatDate, @@ -96,6 +102,7 @@ type ResizeSummaryProps = { nextCycle: Date | null; preview?: PreviewResizeContractResponse; isPreviewLoading: boolean; + totalCost: number; }; const ResizeSummary = ({ @@ -108,6 +115,7 @@ const ResizeSummary = ({ nextCycle, preview, isPreviewLoading, + totalCost, }: ResizeSummaryProps) => { const absoluteDelta = Math.abs(newNumberOfMachines - currentNumberOfMachines); if (absoluteDelta === 0) { @@ -141,14 +149,23 @@ const ResizeSummary = ({ ) : null} {!isPreviewLoading ? ( <> +
Your {isMonthly ? "monthly" : "yearly"} payment will be{" "} - {isDecreasing ? "reduced" : "increased"} by{" "} - {currencyFormatter.format( - preview ? preview.amountDue / 100 : absoluteDelta * unitPrice - )} - . + {isDecreasing + ? currencyFormatter.format( + totalCost - absoluteDelta * unitPrice + ) + : currencyFormatter.format( + totalCost + absoluteDelta * unitPrice + )} + * .
+ + * Taxes and/or balance credits are not included in this price and + may apply at renewal time. + +
) : ( @@ -227,6 +244,29 @@ const SubscriptionEdit = ({ subscription?.current_number_of_machines ?? 0 ); + const { data: renewableSubscriptions } = useUserSubscriptions({ + select: selectAutoRenewableSubscriptionsByMarketplace( + subscription?.marketplace ?? UserSubscriptionMarketplace.CanonicalUA + ), + }); + + const totalCost: number = + renewableSubscriptions?.reduce( + (price: number, renewableSubscription: UserSubscription) => { + if (renewableSubscription?.period != subscription?.period) { + return price; + } + + return ( + price + + ((renewableSubscription.price ?? 0) * + renewableSubscription.current_number_of_machines) / + (100 * renewableSubscription.number_of_machines) + ); + }, + 0 + ) || 0; + useEffect(() => { if (isResized) { // Invalidate the data as it all may have changed. @@ -352,6 +392,7 @@ const SubscriptionEdit = ({ nextCycle={nextCycleStart} preview={preview} isPreviewLoading={isPreviewLoading} + totalCost={totalCost} />
diff --git a/static/js/src/advantage/react/utils/getSubscriptionCost.test.ts b/static/js/src/advantage/react/utils/getSubscriptionCost.test.ts deleted file mode 100644 index c7e2552b25b..00000000000 --- a/static/js/src/advantage/react/utils/getSubscriptionCost.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { UserSubscriptionPeriod } from "advantage/api/enum"; -import { - freeSubscriptionFactory, - userSubscriptionFactory, -} from "advantage/tests/factories/api"; -import { getSubscriptionCost } from "./getSubscriptionCost"; - -describe("getSubscriptionCost", () => { - it("handles free subscriptions", () => { - expect(getSubscriptionCost(freeSubscriptionFactory.build())).toBe("Free"); - }); - - it("handles yearly prices", () => { - expect( - getSubscriptionCost( - userSubscriptionFactory.build({ - currency: "USD", - price: 2000, - period: UserSubscriptionPeriod.Yearly, - }) - ) - ).toBe("$20 USD/yr"); - }); - - it("handles monthly prices", () => { - expect( - getSubscriptionCost( - userSubscriptionFactory.build({ - currency: "USD", - price: 2000, - period: UserSubscriptionPeriod.Monthly, - }) - ) - ).toBe("$240 USD/yr"); - }); -}); diff --git a/static/js/src/advantage/react/utils/getSubscriptionCost.ts b/static/js/src/advantage/react/utils/getSubscriptionCost.ts deleted file mode 100644 index 6d37b5a68e6..00000000000 --- a/static/js/src/advantage/react/utils/getSubscriptionCost.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UserSubscriptionPeriod } from "advantage/api/enum"; -import { UserSubscription } from "advantage/api/types"; -import { isFreeSubscription } from "./isFreeSubscription"; - -export const getSubscriptionCost = ( - subscription: UserSubscription -): string | null => { - if (isFreeSubscription(subscription)) { - return "Free"; - } - const formatter = new Intl.NumberFormat("en-US", { - currency: subscription.currency, - maximumFractionDigits: 0, - minimumFractionDigits: 0, - style: "currency", - }); - // The provided price is in cents, so this converts it to dollars: - let price = (subscription.price || 0) / 100; - if (subscription.period === UserSubscriptionPeriod.Monthly) { - price *= 12; - } - return price - ? `${formatter.format(price)} ${subscription.currency}/yr` - : null; -}; diff --git a/static/js/src/advantage/react/utils/index.ts b/static/js/src/advantage/react/utils/index.ts index f4e30842a73..d7cb0d713c1 100644 --- a/static/js/src/advantage/react/utils/index.ts +++ b/static/js/src/advantage/react/utils/index.ts @@ -4,7 +4,6 @@ export { getFeaturesDisplay } from "./getFeaturesDisplay"; export { filterAndFormatEntitlements } from "./filterAndFormatEntitlements"; export { getMachineTypeDisplay } from "./getMachineTypeDisplay"; export { getPeriodDisplay } from "./getPeriodDisplay"; -export { getSubscriptionCost } from "./getSubscriptionCost"; export { isFreeSubscription } from "./isFreeSubscription"; export { isBlenderSubscription } from "./isBlenderSubscription"; export { makeInteractiveProps } from "./makeInteractiveProps";