woocommerce/plugins/woocommerce-admin/client/customize-store/design-without-ai/state-machine.tsx

166 lines
3.4 KiB
TypeScript

/**
* External dependencies
*/
import { createMachine } from 'xstate';
import { getQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { ApiCallLoader, AssembleHubLoader } from './pages/ApiCallLoader';
import { FlowType } from '../types';
import { DesignWithoutAIStateMachineContext } from './types';
import { services } from './services';
import { actions } from './actions';
export const hasStepInUrl = (
_ctx: unknown,
_evt: unknown,
{ cond }: { cond: unknown }
) => {
const { path = '' } = getQuery() as { path: string };
const pathFragments = path.split( '/' );
return (
pathFragments[ 2 ] === // [0] '', [1] 'customize-store', [2] design step slug
( cond as { step: string | undefined } ).step
);
};
export type DesignWithoutAIStateMachineEvents =
| { type: 'EXTERNAL_URL_UPDATE' }
| { type: 'NO_AI_FLOW_ERROR'; payload: { hasError: boolean } };
export const designWithNoAiStateMachineDefinition = createMachine(
{
id: 'designWithoutAI',
predictableActionArguments: true,
preserveActionOrder: true,
schema: {
context: {} as DesignWithoutAIStateMachineContext,
events: {} as DesignWithoutAIStateMachineEvents,
},
invoke: {
src: 'browserPopstateHandler',
},
on: {
EXTERNAL_URL_UPDATE: {
target: 'navigate',
},
},
context: {
startLoadingTime: null,
flowType: FlowType.noAI,
apiCallLoader: {
hasErrors: false,
},
},
initial: 'navigate',
states: {
navigate: {
always: [
{
cond: {
type: 'hasStepInUrl',
step: 'design',
},
target: 'preAssembleSite',
},
],
},
preAssembleSite: {
initial: 'preApiCallLoader',
id: 'preAssembleSite',
states: {
preApiCallLoader: {
meta: {
// @todo: Move the current component in a common folder or create a new one dedicated to this flow.
component: ApiCallLoader,
},
type: 'parallel',
states: {
installAndActivateTheme: {
initial: 'pending',
states: {
pending: {
invoke: {
src: 'installAndActivateTheme',
onDone: {
target: 'success',
},
onError: {
actions:
'redirectToIntroWithError',
},
},
},
success: { type: 'final' },
},
},
assembleSite: {
initial: 'pending',
states: {
pending: {
invoke: {
src: 'assembleSite',
onDone: {
target: 'success',
},
onError: {
actions:
'redirectToIntroWithError',
},
},
},
success: {
type: 'final',
},
},
},
createProducts: {
initial: 'pending',
states: {
pending: {
invoke: {
src: 'createProducts',
onDone: {
target: 'success',
},
onError: {
actions:
'redirectToIntroWithError',
},
},
},
success: {
type: 'final',
},
},
},
},
onDone: {
target: '#designWithoutAI.showAssembleHub',
},
},
},
},
showAssembleHub: {
id: 'showAssembleHub',
meta: {
component: AssembleHubLoader,
},
entry: [ 'redirectToAssemblerHub' ],
type: 'final',
},
},
},
{
actions,
services,
guards: {
hasStepInUrl,
},
}
);