/** * 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'; import { isFontLibraryAvailable } from './guards'; 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 const hasFontInstallInUrl = () => { const { path = '' } = getQuery() as { path: string }; const pathFragments = path.split( '/' ); return ( pathFragments[ 2 ] === 'design' && pathFragments[ 3 ] === 'install-fonts' ); }; export const hasPatternInstallInUrl = () => { const { path = '' } = getQuery() as { path: string }; const pathFragments = path.split( '/' ); return ( pathFragments[ 2 ] === 'design' && pathFragments[ 3 ] === 'install-patterns' ); }; const installFontFamiliesState = { initial: 'checkFontLibrary', states: { checkFontLibrary: { always: [ { cond: { type: 'isFontLibraryAvailable', }, target: 'pending', }, { target: 'success' }, ], }, pending: { invoke: { src: 'installFontFamilies', onDone: { target: 'success', }, onError: { actions: 'redirectToIntroWithError', }, }, }, success: { type: 'final', }, }, }; export type DesignWithoutAIStateMachineEvents = | { type: 'EXTERNAL_URL_UPDATE' } | { type: 'INSTALL_FONTS' } | { type: 'INSTALL_PATTERNS' } | { 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', }, INSTALL_FONTS: { target: 'installFontFamilies', }, INSTALL_PATTERNS: { target: 'installPatterns', }, }, context: { startLoadingTime: null, flowType: FlowType.noAI, apiCallLoader: { hasErrors: false, }, isFontLibraryAvailable: false, isPTKPatternsAPIAvailable: false, isBlockTheme: false, }, initial: 'navigate', states: { navigate: { always: [ { cond: { type: 'hasFontInstallInUrl', step: 'design', }, target: 'installFontFamilies', }, { cond: { type: 'hasPatternInstallInUrl', step: 'design', }, target: 'installPatterns', }, { cond: { type: 'hasStepInUrl', step: 'design', }, target: 'preAssembleSite', }, ], }, installFontFamilies: { meta: { component: ApiCallLoader, }, initial: 'enableTracking', states: { enableTracking: { invoke: { src: 'enableTracking', onDone: { target: 'checkFontLibrary', }, }, }, checkFontLibrary: installFontFamiliesState.states.checkFontLibrary, pending: installFontFamiliesState.states.pending, success: { type: 'final', }, }, onDone: { target: '#designWithoutAI.showAssembleHubTypography', }, }, installPatterns: { meta: { component: ApiCallLoader, }, initial: 'enableTracking', states: { enableTracking: { invoke: { src: 'enableTracking', onDone: { target: 'fetchPatterns', }, }, }, fetchPatterns: { invoke: { src: 'installPatterns', onDone: { target: 'success', }, onError: { actions: 'redirectToIntroWithError', }, }, }, success: { type: 'final', }, }, onDone: { target: '#designWithoutAI.showAssembleHubHomepage', }, }, 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' }, }, }, createProducts: { initial: 'pending', states: { pending: { invoke: { src: 'createProducts', onDone: { target: 'success', }, onError: { actions: 'redirectToIntroWithError', }, }, }, success: { type: 'final', }, }, }, installFontFamilies: { initial: installFontFamiliesState.initial, states: { checkFontLibrary: installFontFamiliesState.states .checkFontLibrary, pending: installFontFamiliesState.states.pending, success: { type: 'final', }, }, }, installPatterns: { initial: 'pending', states: { pending: { invoke: { src: 'installPatterns', onDone: { target: 'success', }, onError: { target: 'success', }, }, }, success: { type: 'final', }, }, }, }, onDone: { target: 'assembleSite', }, }, assembleSite: { initial: 'pending', states: { pending: { invoke: { src: 'assembleSite', onDone: { target: 'success', }, onError: { actions: 'redirectToIntroWithError', }, }, }, success: { type: 'final', }, }, onDone: { target: '#designWithoutAI.showAssembleHub', }, }, }, }, showAssembleHub: { id: 'showAssembleHub', meta: { component: AssembleHubLoader, }, entry: [ 'redirectToAssemblerHub' ], }, showAssembleHubHomepage: { entry: [ { type: 'redirectToAssemblerHubSection', section: 'homepage', }, ], }, showAssembleHubTypography: { entry: [ { type: 'redirectToAssemblerHubSection', section: 'typography', }, ], }, }, }, { actions, services, guards: { hasStepInUrl, isFontLibraryAvailable, hasFontInstallInUrl, hasPatternInstallInUrl, }, } );