From 8031f811cc00129d6969f91559c8d7f8399c6707 Mon Sep 17 00:00:00 2001 From: Jeremy Yip Date: Fri, 22 Nov 2024 17:10:59 -0800 Subject: [PATCH] Logged-In Plans Page: Show discounted prices when coupon is applied (#95703) --- .../data-stores/src/plans/hooks/use-current-plan.ts | 2 +- .../data-stores/src/plans/hooks/use-intro-offers.ts | 2 +- .../plans/hooks/use-pricing-meta-for-grid-plans.ts | 6 +++++- .../src/plans/queries/lib/use-query-keys-factory.ts | 6 +++++- .../data-stores/src/plans/queries/use-site-plans.ts | 13 +++++++++++-- packages/data-stores/src/plans/types.ts | 2 ++ 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/data-stores/src/plans/hooks/use-current-plan.ts b/packages/data-stores/src/plans/hooks/use-current-plan.ts index 8da2763b509d3..0990c7d1e1af0 100644 --- a/packages/data-stores/src/plans/hooks/use-current-plan.ts +++ b/packages/data-stores/src/plans/hooks/use-current-plan.ts @@ -7,7 +7,7 @@ interface Props { } const useCurrentPlan = ( { siteId }: Props ): SitePlan | undefined => { - const sitePlans = useSitePlans( { siteId } ); + const sitePlans = useSitePlans( { coupon: undefined, siteId } ); return useMemo( () => diff --git a/packages/data-stores/src/plans/hooks/use-intro-offers.ts b/packages/data-stores/src/plans/hooks/use-intro-offers.ts index 8c0c3ee44a87d..7cccdf2732d2e 100644 --- a/packages/data-stores/src/plans/hooks/use-intro-offers.ts +++ b/packages/data-stores/src/plans/hooks/use-intro-offers.ts @@ -20,7 +20,7 @@ interface Props { * or `undefined` if we haven't observed any metadata yet */ const useIntroOffers = ( { siteId, coupon }: Props ): IntroOffersIndex | undefined => { - const sitePlans = useSitePlans( { siteId } ); + const sitePlans = useSitePlans( { coupon: undefined, siteId } ); const plans = usePlans( { coupon } ); return useMemo( () => { diff --git a/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts b/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts index 22f94d4034a95..a110a0f7c389e 100644 --- a/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts +++ b/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts @@ -83,7 +83,7 @@ const usePricingMetaForGridPlans = ( { // plans - should have a definition for all plans, being the main source of API data const plans = Plans.usePlans( { coupon } ); // sitePlans - unclear if all plans are included - const sitePlans = Plans.useSitePlans( { siteId } ); + const sitePlans = Plans.useSitePlans( { coupon, siteId } ); const currentPlan = Plans.useCurrentPlan( { siteId } ); const introOffers = Plans.useIntroOffers( { siteId, coupon } ); const purchasedPlan = Purchases.useSitePurchaseById( { @@ -227,7 +227,11 @@ const usePricingMetaForGridPlans = ( { }; // Do not return discounted prices if discount is due to plan proration + // If there is, however, a sale coupon, show the discounted price + // without proration. This isn't ideal, but is intentional. Because of + // this, the price will differ between the plans grid and checkout screen. if ( + ! sitePlan?.pricing?.hasSaleCoupon && ! withProratedDiscounts && sitePlan?.pricing?.costOverrides?.[ 0 ]?.overrideCode === COST_OVERRIDE_REASONS.RECENT_PLAN_PRORATION diff --git a/packages/data-stores/src/plans/queries/lib/use-query-keys-factory.ts b/packages/data-stores/src/plans/queries/lib/use-query-keys-factory.ts index 1cb54697b58ae..bdb5f3671fa6b 100644 --- a/packages/data-stores/src/plans/queries/lib/use-query-keys-factory.ts +++ b/packages/data-stores/src/plans/queries/lib/use-query-keys-factory.ts @@ -1,5 +1,9 @@ const useQueryKeysFactory = () => ( { - sitePlans: ( siteId?: string | number | null ) => [ 'site-plans', siteId ], + sitePlans: ( coupon?: string, siteId?: string | number | null ) => [ + 'site-plans', + siteId, + coupon, + ], plans: ( coupon?: string ) => [ 'plans', coupon ], } ); diff --git a/packages/data-stores/src/plans/queries/use-site-plans.ts b/packages/data-stores/src/plans/queries/use-site-plans.ts index 8a309bbc19a23..15a022a82d845 100644 --- a/packages/data-stores/src/plans/queries/use-site-plans.ts +++ b/packages/data-stores/src/plans/queries/use-site-plans.ts @@ -14,6 +14,11 @@ interface PricedAPISitePlansIndex { } interface Props { + /** + * To match the use-plans hook, `coupon` is required on purpose to mitigate risk of not passing + * something through when we should + */ + coupon: string | undefined; siteId: string | number | null | undefined; } @@ -22,15 +27,18 @@ interface Props { * - Plans from `/sites/[siteId]/plans`, unlike `/plans`, are returned indexed by product_id, and do not include that in the plan's payload. * - UI works with product/plan slugs everywhere, so returned index is transformed to be keyed by product_slug */ -function useSitePlans( { siteId }: Props ): UseQueryResult< SitePlansIndex > { +function useSitePlans( { coupon, siteId }: Props ): UseQueryResult< SitePlansIndex > { const queryKeys = useQueryKeysFactory(); + const params = new URLSearchParams(); + coupon && params.append( 'coupon_code', coupon ); return useQuery( { - queryKey: queryKeys.sitePlans( siteId ), + queryKey: queryKeys.sitePlans( coupon, siteId ), queryFn: async (): Promise< SitePlansIndex > => { const data: PricedAPISitePlansIndex = await wpcomRequest( { path: `/sites/${ encodeURIComponent( siteId as string ) }/plans`, apiVersion: '1.3', + query: params.toString(), } ); return Object.fromEntries( @@ -52,6 +60,7 @@ function useSitePlans( { siteId }: Props ): UseQueryResult< SitePlansIndex > { hasRedeemedDomainCredit: plan?.has_redeemed_domain_credit, purchaseId: plan.id ? Number( plan.id ) : undefined, pricing: { + hasSaleCoupon: plan.has_sale_coupon, currencyCode: plan.currency_code, introOffer: unpackIntroOffer( plan ), costOverrides: unpackCostOverrides( plan ), diff --git a/packages/data-stores/src/plans/types.ts b/packages/data-stores/src/plans/types.ts index 106722bf58c6f..d4d748d7e9098 100644 --- a/packages/data-stores/src/plans/types.ts +++ b/packages/data-stores/src/plans/types.ts @@ -120,6 +120,7 @@ export interface PlanPricing { } export interface SitePlanPricing extends Omit< PlanPricing, 'billPeriod' > { + hasSaleCoupon?: boolean; costOverrides?: CostOverride[]; } @@ -269,6 +270,7 @@ export interface PricedAPIPlan extends PricedAPIPlanPricing, PricedAPIPlanIntrod export interface PricedAPISitePlan extends PricedAPISitePlanPricing, PricedAPIPlanIntroductoryOffer { + has_sale_coupon?: boolean; /* product_id: number; // not included in the plan's payload */ product_slug: StorePlanSlug; current_plan?: boolean;