Skip to content

Commit 288500f

Browse files
committed
A4A > Marketplace: Implement Term pricing for Hosting, Products & Cart
1 parent 5a89741 commit 288500f

File tree

14 files changed

+269
-78
lines changed

14 files changed

+269
-78
lines changed

client/a8c-for-agencies/sections/marketplace/commissions-info/index.tsx

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1+
import { isEnabled } from '@automattic/calypso-config';
12
import { formatCurrency } from '@automattic/number-formatters';
23
import { useTranslate } from 'i18n-calypso';
34
import { getProductCommissionPercentage } from '../../referrals/lib/commissions';
4-
import type { ShoppingCartItem } from '../types';
5+
import type { ShoppingCartItem, TermPricingType } from '../types';
56

67
import './style.scss';
78

8-
export default function CommissionsInfo( { items }: { items: ShoppingCartItem[] } ) {
9+
export default function CommissionsInfo( {
10+
items,
11+
termPricing,
12+
}: {
13+
items: ShoppingCartItem[];
14+
termPricing?: TermPricingType;
15+
} ) {
916
const translate = useTranslate();
1017

18+
const isTermPricingEnabled = isEnabled( 'a4a-bd-term-pricing' ) && isEnabled( 'a4a-bd-checkout' );
19+
1120
const totalCommissions = items.reduce( ( acc, item ) => {
1221
const product = item;
1322
const commissionPercentage = getProductCommissionPercentage( product.family_slug );
@@ -22,15 +31,30 @@ export default function CommissionsInfo( { items }: { items: ShoppingCartItem[]
2231
return null;
2332
}
2433

34+
const totalPricePerTerm =
35+
termPricing === 'yearly'
36+
? translate( '%(total)s/yr', {
37+
args: {
38+
total: 'YEARLY PRICE',
39+
},
40+
} )
41+
: translate( '%(total)s/mo', {
42+
args: {
43+
total: 'MONTHLY PRICE',
44+
},
45+
} );
46+
2547
return (
2648
<div className="commissions-info">
2749
<span>{ translate( 'Your estimated commission:' ) }</span>
2850
<span>
29-
{ translate( '%(total)s/mo', {
30-
args: {
31-
total: formatCurrency( totalCommissions, 'USD' ),
32-
},
33-
} ) }
51+
{ isTermPricingEnabled
52+
? totalPricePerTerm
53+
: translate( '%(total)s/mo', {
54+
args: {
55+
total: formatCurrency( totalCommissions, 'USD' ),
56+
},
57+
} ) }
3458
</span>
3559
</div>
3660
);

client/a8c-for-agencies/sections/marketplace/hosting-overview/hosting-content/premier-agency-hosting/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { recordTracksEvent } from 'calypso/state/analytics/actions';
2020
import { APIProductFamilyProduct } from 'calypso/state/partner-portal/types';
2121
import HostingAdditionalFeaturesSection from '../../../common/hosting-additional-features-section';
2222
import HostingTestimonialsSection from '../../../common/hosting-testimonials-section';
23-
import { MarketplaceTypeContext } from '../../../context';
23+
import { MarketplaceTypeContext, TermPricingContext } from '../../../context';
2424
import useGetPressablePlanByProductId from '../../../pressable-overview/hooks/use-get-pressable-plan-by-product-id';
2525
import getPressablePlan from '../../../pressable-overview/lib/get-pressable-plan';
2626
import usePressableOwnershipType from '../../hooks/use-pressable-ownership-type';
@@ -44,6 +44,8 @@ export default function PremierAgencyHosting( { onAddToCart }: Props ) {
4444
};
4545

4646
const { marketplaceType } = useContext( MarketplaceTypeContext );
47+
const { termPricing } = useContext( TermPricingContext );
48+
4749
const pressableOwnership = usePressableOwnershipType();
4850

4951
const isReferralMode = marketplaceType === 'referral';
@@ -97,6 +99,7 @@ export default function PremierAgencyHosting( { onAddToCart }: Props ) {
9799
existingPlan={ agencyPressablePlan }
98100
existingPlanInfo={ existingPlanInfo }
99101
isFetching={ isExistingPlanFetched }
102+
termPricing={ termPricing }
100103
/>
101104

102105
<HostingFeatures

client/a8c-for-agencies/sections/marketplace/hosting-overview/hosting-content/premier-agency-hosting/pressable-plan-section/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import HostingPlanSection from '../../common/hosting-plan-section';
2222
import CustomPlanCardContent from './custom-plan-card-content';
2323
import PremiumPlanSection from './premium-plan-section';
2424
import RegularPlanCardContent from './regular-plan-card-content';
25+
import type { TermPricingType } from 'calypso/a8c-for-agencies/sections/marketplace/types';
2526

2627
import './style.scss';
2728

@@ -32,6 +33,7 @@ type Props = {
3233
existingPlan: APIProductFamilyProduct | null;
3334
existingPlanInfo: PressablePlan | null;
3435
isFetching?: boolean;
36+
termPricing: TermPricingType;
3537
};
3638

3739
const getSelectedTab = (
@@ -67,6 +69,7 @@ export default function PressablePlanSection( {
6769
existingPlan,
6870
existingPlanInfo,
6971
isFetching,
72+
termPricing,
7073
}: Props ) {
7174
const translate = useTranslate();
7275

@@ -210,6 +213,7 @@ export default function PressablePlanSection( {
210213
onSelect={ onPlanAddToCart }
211214
isReferralMode={ isReferralMode }
212215
pressableOwnership={ pressableOwnership }
216+
termPricing={ termPricing }
213217
/>
214218
) }
215219
</HostingPlanSection.Card>

client/a8c-for-agencies/sections/marketplace/hosting-overview/hosting-content/premier-agency-hosting/pressable-plan-section/regular-plan-card-content.tsx

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isEnabled } from '@automattic/calypso-config';
12
import { formatCurrency } from '@automattic/number-formatters';
23
import { Button } from '@wordpress/components';
34
import { useTranslate } from 'i18n-calypso';
@@ -7,19 +8,22 @@ import PressableLogo from 'calypso/assets/images/a8c-for-agencies/pressable-logo
78
import { useSelector } from 'calypso/state';
89
import { APIProductFamilyProduct } from 'calypso/state/partner-portal/types';
910
import { getProductsList } from 'calypso/state/products-list/selectors';
11+
import type { TermPricingType } from 'calypso/a8c-for-agencies/sections/marketplace/types';
1012

1113
type Props = {
1214
plan: APIProductFamilyProduct;
1315
onSelect: ( plan: APIProductFamilyProduct ) => void;
1416
isReferralMode?: boolean;
1517
pressableOwnership?: 'agency' | 'regular' | 'none';
18+
termPricing: TermPricingType;
1619
};
1720

18-
export default function PressablePlanSelectorCard( {
21+
export default function RegularPlanCardContent( {
1922
plan,
2023
onSelect,
2124
isReferralMode,
2225
pressableOwnership,
26+
termPricing,
2327
}: Props ) {
2428
const translate = useTranslate();
2529
const userProducts = useSelector( getProductsList );
@@ -48,6 +52,36 @@ export default function PressablePlanSelectorCard( {
4852
} );
4953
}, [ isReferralMode, plan.name, translate ] );
5054

55+
const isTermPricingEnabled = isEnabled( 'a4a-bd-term-pricing' ) && isEnabled( 'a4a-bd-checkout' );
56+
57+
const renderPrice = () => {
58+
if ( isTermPricingEnabled ) {
59+
return (
60+
<div className="pressable-plan-card-content__price">
61+
<b className="pressable-plan-card-content__price-actual-value">
62+
{ termPricing === 'yearly' ? 'YEARLY PRICE' : 'MONTHLY PRICE' }
63+
</b>
64+
<div className="pressable-plan-card-content__price-interval">
65+
{ termPricing === 'yearly' ? translate( 'per year' ) : translate( 'per month' ) }
66+
</div>
67+
</div>
68+
);
69+
}
70+
71+
return (
72+
<div className="pressable-plan-card-content__price">
73+
<b className="pressable-plan-card-content__price-actual-value">
74+
{ formatCurrency( discountedCost, plan.currency ) }
75+
</b>
76+
77+
<div className="pressable-plan-card-content__price-interval">
78+
{ plan.price_interval === 'day' && translate( 'per day, billed monthly' ) }
79+
{ plan.price_interval === 'month' && translate( 'per month, billed monthly' ) }
80+
</div>
81+
</div>
82+
);
83+
};
84+
5185
return (
5286
<div className="pressable-plan-card-content">
5387
<div className="pressable-plan-card-content__top">
@@ -63,16 +97,7 @@ export default function PressablePlanSelectorCard( {
6397
) }
6498
</div>
6599
) : (
66-
<div className="pressable-plan-card-content__price">
67-
<b className="pressable-plan-card-content__price-actual-value">
68-
{ formatCurrency( discountedCost, plan.currency ) }
69-
</b>
70-
71-
<div className="pressable-plan-card-content__price-interval">
72-
{ plan.price_interval === 'day' && translate( 'per day, billed monthly' ) }
73-
{ plan.price_interval === 'month' && translate( 'per month, billed monthly' ) }
74-
</div>
75-
</div>
100+
renderPrice()
76101
) }
77102
</div>
78103
{ pressableOwnership === 'regular' ? (

client/a8c-for-agencies/sections/marketplace/hosting-overview/hosting-content/standard-agency-hosting/wpcom-plan-section/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import { useRandomSiteName } from 'calypso/a8c-for-agencies/components/site-conf
88
import useFetchDevLicenses from 'calypso/a8c-for-agencies/data/purchases/use-fetch-dev-licenses';
99
import useSiteCreatedCallback from 'calypso/a8c-for-agencies/hooks/use-site-created-callback';
1010
import useWPCOMOwnedSites from 'calypso/a8c-for-agencies/hooks/use-wpcom-owned-sites';
11-
import { MarketplaceTypeContext } from 'calypso/a8c-for-agencies/sections/marketplace/context';
11+
import {
12+
MarketplaceTypeContext,
13+
TermPricingContext,
14+
} from 'calypso/a8c-for-agencies/sections/marketplace/context';
1215
import useProductAndPlans from 'calypso/a8c-for-agencies/sections/marketplace/hooks/use-product-and-plans';
1316
import { getWPCOMCreatorPlan } from 'calypso/a8c-for-agencies/sections/marketplace/lib/hosting';
1417
import { useDispatch } from 'calypso/state';
@@ -59,6 +62,8 @@ export default function WPCOMPlanSection( { onSelect }: Props ) {
5962
const { marketplaceType } = useContext( MarketplaceTypeContext );
6063
const isReferralMode = marketplaceType === 'referral';
6164

65+
const { termPricing } = useContext( TermPricingContext );
66+
6267
const ownedPlans = useMemo( () => {
6368
if ( isReferralMode ) {
6469
return 0;
@@ -107,6 +112,7 @@ export default function WPCOMPlanSection( { onSelect }: Props ) {
107112
isReferralMode={ isReferralMode }
108113
quantity={ displayQuantity }
109114
setQuantity={ setQuantity }
115+
termPricing={ termPricing }
110116
/>
111117
) : (
112118
<WPCOMPlanSelector.Placeholder />

client/a8c-for-agencies/sections/marketplace/hosting-overview/hosting-content/standard-agency-hosting/wpcom-plan-section/wpcom-plan-selector.tsx

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isEnabled } from '@automattic/calypso-config';
12
import { formatCurrency } from '@automattic/number-formatters';
23
import { Button } from '@wordpress/components';
34
import clsx from 'clsx';
@@ -9,6 +10,7 @@ import { calculateTier } from 'calypso/a8c-for-agencies/sections/marketplace/lib
910
import WPCOMLogo from 'calypso/assets/images/a8c-for-agencies/wpcom-logo.svg';
1011
import { APIProductFamilyProduct } from 'calypso/state/partner-portal/types';
1112
import useWPCOMDiscountTiers from '../../../hooks/use-wpcom-discount-tiers';
13+
import type { TermPricingType } from 'calypso/a8c-for-agencies/sections/marketplace/types';
1214

1315
type Props = {
1416
plan: APIProductFamilyProduct;
@@ -17,6 +19,7 @@ type Props = {
1719
isReferralMode?: boolean;
1820
quantity: number;
1921
setQuantity: ( quantity: number ) => void;
22+
termPricing: TermPricingType;
2023
};
2124

2225
function Placeholder() {
@@ -40,9 +43,12 @@ export default function WPCOMPlanSelector( {
4043
isReferralMode,
4144
quantity,
4245
setQuantity,
46+
termPricing,
4347
}: Props ) {
4448
const translate = useTranslate();
4549

50+
const isTermPricingEnabled = isEnabled( 'a4a-bd-term-pricing' ) && isEnabled( 'a4a-bd-checkout' );
51+
4652
const discountTiers = useWPCOMDiscountTiers();
4753

4854
const [ isCompact, setIsCompact ] = useState( false );
@@ -93,36 +99,17 @@ export default function WPCOMPlanSelector( {
9399
};
94100
}, [ containerRef ] );
95101

96-
return (
97-
<div
98-
className={ clsx( 'wpcom-plan-selector__details', { 'is-compact': isCompact } ) }
99-
ref={ containerRef }
100-
>
101-
<div className="wpcom-plan-selector__top">
102-
{ ownedPlans > 0 && (
103-
<div className="wpcom-plan-selector__owned-plan">
104-
{ translate( 'You own %(count)s site', 'You own %(count)s sites', {
105-
args: {
106-
count: ownedPlans,
107-
},
108-
count: ownedPlans,
109-
comment: '%(count)s is the number of WordPress.com sites owned by the user',
110-
} ) }
111-
</div>
112-
) }
113-
114-
<div className="wpcom-plan-selector__plan-name">
115-
<img src={ WPCOMLogo } alt="WPCOM" />
116-
</div>
117-
102+
const renderPrice = () => {
103+
if ( isTermPricingEnabled ) {
104+
return (
118105
<div className="wpcom-plan-selector__price">
119106
<b className="wpcom-plan-selector__price-actual-value">
120-
{ formatCurrency( actualPrice, plan.currency ) }
107+
{ termPricing === 'yearly' ? 'YEARLY PRICE' : 'MONTHLY PRICE' }
121108
</b>
122109
{ !! discount && (
123110
<>
124111
<b className="wpcom-plan-selector__price-original-value">
125-
{ formatCurrency( originalPrice, plan.currency ) }
112+
{ termPricing === 'yearly' ? 'YEARLY PRICE' : 'MONTHLY PRICE' }
126113
</b>
127114

128115
<span className="wpcom-plan-selector__price-discount">
@@ -136,10 +123,63 @@ export default function WPCOMPlanSelector( {
136123
</>
137124
) }
138125
<div className="wpcom-plan-selector__price-interval">
139-
{ plan.price_interval === 'day' && translate( 'per day, billed monthly' ) }
140-
{ plan.price_interval === 'month' && translate( 'per month, billed monthly' ) }
126+
{ termPricing === 'yearly' ? translate( 'per year' ) : translate( 'per month' ) }
127+
</div>
128+
</div>
129+
);
130+
}
131+
132+
return (
133+
<div className="wpcom-plan-selector__price">
134+
<b className="wpcom-plan-selector__price-actual-value">
135+
{ formatCurrency( actualPrice, plan.currency ) }
136+
</b>
137+
{ !! discount && (
138+
<>
139+
<b className="wpcom-plan-selector__price-original-value">
140+
{ formatCurrency( originalPrice, plan.currency ) }
141+
</b>
142+
143+
<span className="wpcom-plan-selector__price-discount">
144+
{ translate( 'You save %(discount)s%', {
145+
args: {
146+
discount: Math.floor( discount * 100 ),
147+
},
148+
comment: '%(discount)s is the discount percentage.',
149+
} ) }
150+
</span>
151+
</>
152+
) }
153+
<div className="wpcom-plan-selector__price-interval">
154+
{ plan.price_interval === 'day' && translate( 'per day, billed monthly' ) }
155+
{ plan.price_interval === 'month' && translate( 'per month, billed monthly' ) }
156+
</div>
157+
</div>
158+
);
159+
};
160+
161+
return (
162+
<div
163+
className={ clsx( 'wpcom-plan-selector__details', { 'is-compact': isCompact } ) }
164+
ref={ containerRef }
165+
>
166+
<div className="wpcom-plan-selector__top">
167+
{ ownedPlans > 0 && (
168+
<div className="wpcom-plan-selector__owned-plan">
169+
{ translate( 'You own %(count)s site', 'You own %(count)s sites', {
170+
args: {
171+
count: ownedPlans,
172+
},
173+
count: ownedPlans,
174+
comment: '%(count)s is the number of WordPress.com sites owned by the user',
175+
} ) }
141176
</div>
177+
) }
178+
179+
<div className="wpcom-plan-selector__plan-name">
180+
<img src={ WPCOMLogo } alt="WPCOM" />
142181
</div>
182+
{ renderPrice() }
143183
</div>
144184
<div className="wpcom-plan-selector__cta">
145185
<div className="wpcom-plan-selector__cta-component">

client/a8c-for-agencies/sections/marketplace/hosting-overview/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ function HostingOverview( { section }: SectionProps ) {
101101
}, 300 );
102102
}, [ sidebarRef ] );
103103

104+
const isTermPricingEnabled = isEnabled( 'a4a-bd-term-pricing' ) && isEnabled( 'a4a-bd-checkout' );
105+
104106
return (
105107
<Layout
106108
className="hosting-overview"
@@ -127,7 +129,7 @@ function HostingOverview( { section }: SectionProps ) {
127129
hideOnMobile
128130
/>
129131
<Actions>
130-
{ isEnabled( 'a4a-bd-term-pricing' ) && (
132+
{ isTermPricingEnabled && (
131133
<div className="a4a-marketplace__header-actions">
132134
<TermPricingToggle />
133135
</div>

0 commit comments

Comments
 (0)