Skip to content

Commit 76c9a33

Browse files
committed
Add woo-hosted setup flow
1 parent 5de2bc8 commit 76c9a33

File tree

22 files changed

+309
-3
lines changed

22 files changed

+309
-3
lines changed

client/blocks/product-purchase-features-list/index.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {
2121
WPCOM_FEATURES_WORDADS,
2222
TYPE_WOOEXPRESS_MEDIUM,
2323
TYPE_WOOEXPRESS_SMALL,
24+
TYPE_WOO_HOSTED_BASIC,
25+
TYPE_WOO_HOSTED_PRO,
2426
TYPE_100_YEAR,
2527
TYPE_STARTER,
2628
} from '@automattic/calypso-products';
@@ -395,6 +397,8 @@ export class ProductPurchaseFeaturesList extends Component {
395397
[ TYPE_ECOMMERCE ]: () => this.getEcommerceFeatures(),
396398
[ TYPE_WOOEXPRESS_MEDIUM ]: () => this.getEcommerceFeatures(),
397399
[ TYPE_WOOEXPRESS_SMALL ]: () => this.getEcommerceFeatures(),
400+
[ TYPE_WOO_HOSTED_BASIC ]: () => this.getEcommerceFeatures(),
401+
[ TYPE_WOO_HOSTED_PRO ]: () => this.getEcommerceFeatures(),
398402
[ TYPE_BUSINESS ]: () => this.getBusinessFeatures(),
399403
[ TYPE_PREMIUM ]: () => this.getPremiumFeatures(),
400404
[ TYPE_PERSONAL ]: () => this.getPersonalFeatures(),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# woo-hosted flow
2+
3+
## Testing instructions
4+
5+
Please improve the instructions on how to test this flow.
6+
7+
1. Go to /setup/woo-hosted.
8+
9+
## Owned by
10+
11+
@michaeldcain
12+
13+
## Context
14+
15+
https://ciabp2.wordpress.com/2025/07/31/ciab-plans-and-pricing-where-we-are-and-next-steps/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.woo-hosted {
2+
// Set WooCommerce purple as the accent color
3+
--color-accent: var(--studio-woocommerce-purple-60);
4+
--color-accent-60: var(--studio-woocommerce-purple-70);
5+
--wp-components-color-accent-darker-10: var(--studio-woocommerce-purple-70);
6+
--wp-components-color-accent-darker-20: var(--studio-woocommerce-purple-80);
7+
--wp-components-color-accent: var(--studio-woocommerce-purple-60);
8+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { WooCommerceWooLogo } from '@automattic/components';
2+
import { WOO_HOSTED_FLOW } from '@automattic/onboarding';
3+
import { MinimalRequestCartProduct } from '@automattic/shopping-cart';
4+
import { useDispatch, useSelect, dispatch } from '@wordpress/data';
5+
import { addQueryArgs } from '@wordpress/url';
6+
import { persistSignupDestination } from 'calypso/signup/storageUtils';
7+
import { useQuery } from '../../../hooks/use-query';
8+
import { ONBOARD_STORE } from '../../../stores';
9+
import { stepsWithRequiredLogin } from '../../../utils/steps-with-required-login';
10+
import { STEPS } from '../../internals/steps';
11+
import { ProcessingResult } from '../../internals/steps-repository/processing-step/constants';
12+
import type { FlowV2, SubmitHandler } from '../../internals/types';
13+
import type { DomainSuggestion } from '@automattic/api-core';
14+
import type { OnboardActions, OnboardSelect } from '@automattic/data-stores';
15+
import './style.scss';
16+
17+
const WooHostedLogo = () => <WooCommerceWooLogo width={ 50 } />;
18+
19+
async function initialize() {
20+
const { resetOnboardStore } = dispatch( ONBOARD_STORE ) as OnboardActions;
21+
22+
await resetOnboardStore();
23+
24+
const steps = [ STEPS.UNIFIED_DOMAINS, STEPS.UNIFIED_PLANS, STEPS.PROCESSING ];
25+
26+
return stepsWithRequiredLogin( steps );
27+
}
28+
29+
const wooHosted: FlowV2< typeof initialize > = {
30+
name: WOO_HOSTED_FLOW,
31+
__experimentalUseBuiltinAuth: true,
32+
isSignupFlow: false,
33+
logo: WooHostedLogo,
34+
initialize,
35+
useStepsProps() {
36+
return {
37+
plans: {
38+
displayedIntervals: [ 'monthly', 'yearly' ],
39+
},
40+
};
41+
},
42+
useStepNavigation( _currentStepSlug, navigate ) {
43+
const {
44+
setDomain,
45+
setDomainCartItem,
46+
setDomainCartItems,
47+
setPlanCartItem,
48+
setProductCartItems,
49+
setSiteUrl,
50+
setSignupDomainOrigin,
51+
resetCouponCode,
52+
} = useDispatch( ONBOARD_STORE ) as OnboardActions;
53+
const couponCode = useSelect(
54+
( select ) => ( select( ONBOARD_STORE ) as OnboardSelect ).getCouponCode(),
55+
[]
56+
);
57+
58+
const query = useQuery();
59+
60+
const wooHostedSiteSlug = query.get( 'site' );
61+
const showDomainStep = query.has( 'showDomainStep' );
62+
63+
const getGoBack = () => {
64+
if ( _currentStepSlug === STEPS.UNIFIED_PLANS.slug && showDomainStep ) {
65+
return () => navigate( STEPS.UNIFIED_PLANS.slug );
66+
}
67+
};
68+
69+
const submit: SubmitHandler< typeof initialize > = ( submittedStep ) => {
70+
const { slug, providedDependencies } = submittedStep;
71+
72+
switch ( slug ) {
73+
case STEPS.UNIFIED_DOMAINS.slug: {
74+
if ( ! providedDependencies ) {
75+
throw new Error( 'No provided dependencies found' );
76+
}
77+
78+
if ( providedDependencies.navigateToUseMyDomain ) {
79+
throw new Error( 'Navigation to use my domain is not supported for this flow' );
80+
}
81+
82+
setSiteUrl( wooHostedSiteSlug as string );
83+
setDomain( providedDependencies.suggestion as DomainSuggestion );
84+
setDomainCartItem( providedDependencies.domainItem as MinimalRequestCartProduct );
85+
setDomainCartItems( providedDependencies.domainCart as MinimalRequestCartProduct[] );
86+
setSignupDomainOrigin( providedDependencies.signupDomainOrigin as string );
87+
88+
return navigate( STEPS.UNIFIED_PLANS.slug );
89+
}
90+
91+
case STEPS.UNIFIED_PLANS.slug: {
92+
const cartItems = providedDependencies.cartItems;
93+
const [ pickedPlan, ...extraProducts ] = cartItems ?? [];
94+
95+
if ( ! pickedPlan ) {
96+
throw new Error( 'No product slug found' );
97+
}
98+
99+
setPlanCartItem( {
100+
...pickedPlan,
101+
extra: {
102+
...pickedPlan.extra,
103+
},
104+
} );
105+
106+
setProductCartItems( extraProducts.filter( ( product ) => product !== null ) );
107+
return navigate( STEPS.PROCESSING.slug );
108+
}
109+
110+
case STEPS.PROCESSING.slug: {
111+
if ( providedDependencies.processingResult === ProcessingResult.SUCCESS ) {
112+
const destination = `https://${ wooHostedSiteSlug }/wp-admin/admin.php?page=wc-admin`;
113+
114+
if ( providedDependencies.goToCheckout ) {
115+
persistSignupDestination( destination );
116+
117+
couponCode && resetCouponCode();
118+
return window.location.assign(
119+
addQueryArgs(
120+
`/checkout/${ encodeURIComponent(
121+
( providedDependencies?.siteSlug as string ) ?? ''
122+
) }`,
123+
{ redirect_to: destination, coupon: couponCode }
124+
)
125+
);
126+
}
127+
128+
return navigate( STEPS.UNIFIED_PLANS.slug );
129+
}
130+
}
131+
}
132+
};
133+
134+
return {
135+
goBack: getGoBack(),
136+
submit,
137+
};
138+
},
139+
};
140+
141+
export default wooHosted;

client/landing/stepper/declarative-flow/helpers/should-use-step-container-v2.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
TRANSFERRING_HOSTED_SITE_FLOW,
77
ONBOARDING_UNIFIED_FLOW,
88
DOMAIN_FLOW,
9+
WOO_HOSTED_FLOW,
910
} from '@automattic/onboarding';
1011

1112
const FLOWS_USING_STEP_CONTAINER_V2 = [
@@ -16,6 +17,7 @@ const FLOWS_USING_STEP_CONTAINER_V2 = [
1617
SITE_MIGRATION_FLOW,
1718
ONBOARDING_UNIFIED_FLOW,
1819
DOMAIN_FLOW,
20+
WOO_HOSTED_FLOW,
1921
];
2022

2123
export const shouldUseStepContainerV2 = ( flow: string ) => {

client/landing/stepper/declarative-flow/internals/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export const FlowRenderer: React.FC< {
215215
variantSlug={ flow.variantSlug }
216216
stepName={ step.slug }
217217
data={ stepData }
218+
logo={ flow.logo }
218219
{ ...stepsProps?.[ step.slug ] }
219220
/>
220221
);

client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ const DomainsStep: Step< { submits: DomainStepSubmittedTypes } > = ( { navigatio
131131
step={ stepState }
132132
flowName={ props.flow }
133133
useStepperWrapper
134+
wrapperProps={ {
135+
logo: props.logo,
136+
} }
134137
/>
135138
</CalypsoShoppingCartProvider>
136139
);

client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ONBOARDING_FLOW,
99
ONBOARDING_UNIFIED_FLOW,
1010
START_WRITING_FLOW,
11+
WOO_HOSTED_FLOW,
1112
Step,
1213
useStepPersistedState,
1314
} from '@automattic/onboarding';
@@ -70,6 +71,8 @@ function getPlansIntent( flowName: string | null ): PlansIntent | null {
7071
break;
7172
case ONBOARDING_UNIFIED_FLOW:
7273
return 'plans-affiliate';
74+
case WOO_HOSTED_FLOW:
75+
return 'plans-woo-hosted';
7376
default:
7477
return null;
7578
}
@@ -220,11 +223,13 @@ const PlansStepAdaptor: StepType< {
220223
onIntentChange={ handleIntentChange }
221224
onPlanIntervalUpdate={ onPlanIntervalUpdate }
222225
intervalType={ planInterval }
226+
displayedIntervals={ props.displayedIntervals }
223227
wrapperProps={ {
224228
hideBack: false,
225229
goBack: props.navigation.goBack,
226230
isFullLayout: true,
227231
isExtraWideLayout: false,
232+
logo: props.logo,
228233
} }
229234
useStepperWrapper
230235
useStepContainerV2={ isUsingStepContainerV2 }

client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/unified-plans-step.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export interface UnifiedPlansStepProps {
120120
goBack: NavigationControls[ 'goBack' ];
121121
isFullLayout: boolean;
122122
isExtraWideLayout: boolean;
123+
logo?: React.ComponentType< any >;
123124
};
124125

125126
shouldHideNavButtons?: boolean;
@@ -581,6 +582,7 @@ function UnifiedPlansStep( {
581582
<Step.BackButton onClick={ goBack }>{ backLabelText }</Step.BackButton>
582583
) : undefined
583584
}
585+
logo={ wrapperProps.logo && <wrapperProps.logo /> }
584586
/>
585587
}
586588
heading={

client/landing/stepper/declarative-flow/internals/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ export interface FlowV2< FlowStepsInitialize extends DefaultFlowStepsConfig > {
267267
*/
268268
variantSlug?: string;
269269
title?: string;
270+
logo?: React.ComponentType< any >;
270271
classnames?: string | [ string ];
271272
/**
272273
* Required flag to indicate if the flow is a signup flow.
@@ -335,6 +336,7 @@ export type StepProps< StepDataShape extends StepPropTypes = object > = Conditio
335336
*/
336337
redirectTo?: string;
337338
signupUrl?: string;
339+
logo: React.ComponentType< any >;
338340
},
339341
StepDataShape[ 'accepts' ]
340342
>;

0 commit comments

Comments
 (0)