2023-09-12 02:30:54 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import { Loader } from '@woocommerce/onboarding';
|
|
|
|
import { __ } from '@wordpress/i18n';
|
2024-03-04 19:09:36 +00:00
|
|
|
import { useEffect, useRef, useState } from '@wordpress/element';
|
2024-04-23 10:27:32 +00:00
|
|
|
import { getNewPath, getPersistedQuery } from '@woocommerce/navigation';
|
2023-09-12 02:30:54 +00:00
|
|
|
|
2023-08-29 06:00:54 +00:00
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2023-09-12 02:30:54 +00:00
|
|
|
import analyzingYourResponses from '../../assets/images/loader-analyzing-your-responses.svg';
|
|
|
|
import designingTheBestLook from '../../assets/images/loader-designing-the-best-look.svg';
|
|
|
|
import comparingTheTopPerformingStores from '../../assets/images/loader-comparing-top-performing-stores.svg';
|
|
|
|
import assemblingAiOptimizedStore from '../../assets/images/loader-assembling-ai-optimized-store.svg';
|
|
|
|
import applyingFinishingTouches from '../../assets/images/loader-applying-the-finishing-touches.svg';
|
2023-11-01 07:42:36 +00:00
|
|
|
import generatingContent from '../../assets/images/loader-generating-content.svg';
|
|
|
|
import openingTheDoors from '../../assets/images/loader-opening-the-doors.svg';
|
2024-03-04 19:09:36 +00:00
|
|
|
import {
|
|
|
|
attachIframeListeners,
|
|
|
|
createAugmentedSteps,
|
|
|
|
onIframeLoad,
|
|
|
|
} from '~/customize-store/utils';
|
2023-09-12 02:30:54 +00:00
|
|
|
|
|
|
|
const loaderSteps = [
|
|
|
|
{
|
|
|
|
title: __( 'Analyzing your responses', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ analyzingYourResponses }
|
|
|
|
alt={ __( 'Analyzing your responses', 'woocommerce' ) }
|
|
|
|
/>
|
|
|
|
),
|
2023-11-01 07:42:36 +00:00
|
|
|
progress: 14,
|
2023-09-12 02:30:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Comparing the top performing stores', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ comparingTheTopPerformingStores }
|
|
|
|
alt={ __(
|
|
|
|
'Comparing the top performing stores',
|
|
|
|
'woocommerce'
|
|
|
|
) }
|
|
|
|
/>
|
|
|
|
),
|
2023-11-01 07:42:36 +00:00
|
|
|
progress: 28,
|
2023-09-12 02:30:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Designing the best look for your business', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ designingTheBestLook }
|
|
|
|
alt={ __(
|
|
|
|
'Designing the best look for your business',
|
|
|
|
'woocommerce'
|
|
|
|
) }
|
|
|
|
/>
|
|
|
|
),
|
2023-11-01 07:42:36 +00:00
|
|
|
progress: 42,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Generating content', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ generatingContent }
|
|
|
|
alt={ __( 'Generating content', 'woocommerce' ) }
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
progress: 56,
|
2023-09-12 02:30:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Assembling your AI-optimized store', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ assemblingAiOptimizedStore }
|
|
|
|
alt={ __(
|
|
|
|
'Assembling your AI-optimized store',
|
|
|
|
'woocommerce'
|
|
|
|
) }
|
|
|
|
/>
|
|
|
|
),
|
2023-11-01 07:42:36 +00:00
|
|
|
progress: 70,
|
2023-09-12 02:30:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Applying the finishing touches', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ applyingFinishingTouches }
|
|
|
|
alt={ __( 'Applying the finishing touches', 'woocommerce' ) }
|
|
|
|
/>
|
|
|
|
),
|
2023-11-01 07:42:36 +00:00
|
|
|
progress: 84,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: __( 'Opening the doors', 'woocommerce' ),
|
|
|
|
image: (
|
|
|
|
<img
|
|
|
|
src={ openingTheDoors }
|
|
|
|
alt={ __( 'Opening the doors', 'woocommerce' ) }
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
progress: 100,
|
2023-09-12 02:30:54 +00:00
|
|
|
},
|
|
|
|
];
|
2023-08-29 06:00:54 +00:00
|
|
|
|
2023-10-31 13:09:21 +00:00
|
|
|
// Loader for the API call without the last frame.
|
2023-09-12 02:30:54 +00:00
|
|
|
export const ApiCallLoader = () => {
|
2023-11-08 08:50:15 +00:00
|
|
|
const [ progress, setProgress ] = useState( 5 );
|
|
|
|
|
2023-10-12 06:12:24 +00:00
|
|
|
useEffect( () => {
|
|
|
|
const preload = ( src: string ) => {
|
|
|
|
const img = new Image();
|
|
|
|
|
|
|
|
img.src = src;
|
|
|
|
img.onload = () => {};
|
|
|
|
};
|
|
|
|
|
2023-11-01 07:42:36 +00:00
|
|
|
// We preload the these images to avoid flickering. We only need to preload them because the others are small enough to be inlined in base64.
|
2023-10-12 06:12:24 +00:00
|
|
|
preload( assemblingAiOptimizedStore );
|
2023-11-01 07:42:36 +00:00
|
|
|
preload( openingTheDoors );
|
2023-10-12 06:12:24 +00:00
|
|
|
}, [] );
|
|
|
|
|
2023-12-07 04:14:57 +00:00
|
|
|
const augmentedSteps = createAugmentedSteps(
|
|
|
|
loaderSteps.slice( 0, -1 ),
|
|
|
|
10
|
|
|
|
);
|
2023-11-08 08:50:15 +00:00
|
|
|
|
2023-08-29 06:00:54 +00:00
|
|
|
return (
|
2023-09-12 02:30:54 +00:00
|
|
|
<Loader>
|
2023-10-31 13:09:21 +00:00
|
|
|
<Loader.Sequence
|
2023-11-08 08:50:15 +00:00
|
|
|
interval={ ( 40 * 1000 ) / ( augmentedSteps.length - 1 ) }
|
2023-10-31 13:09:21 +00:00
|
|
|
shouldLoop={ false }
|
2023-11-08 08:50:15 +00:00
|
|
|
onChange={ ( index ) => {
|
|
|
|
// to get around bad set state timing issue
|
|
|
|
setTimeout( () => {
|
|
|
|
setProgress( augmentedSteps[ index ].progress );
|
|
|
|
}, 0 );
|
|
|
|
} }
|
2023-10-31 13:09:21 +00:00
|
|
|
>
|
2023-11-08 08:50:15 +00:00
|
|
|
{ augmentedSteps.map( ( step, index ) => (
|
2023-10-31 13:09:21 +00:00
|
|
|
<Loader.Layout key={ index }>
|
|
|
|
<Loader.Illustration>
|
|
|
|
{ step.image }
|
|
|
|
</Loader.Illustration>
|
|
|
|
<Loader.Title>{ step.title }</Loader.Title>
|
|
|
|
</Loader.Layout>
|
|
|
|
) ) }
|
|
|
|
</Loader.Sequence>
|
2023-11-08 08:50:15 +00:00
|
|
|
<Loader.ProgressBar
|
|
|
|
className="smooth-transition"
|
|
|
|
progress={ progress || 0 }
|
|
|
|
/>
|
2023-10-31 13:09:21 +00:00
|
|
|
</Loader>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2024-03-04 19:09:36 +00:00
|
|
|
const AssemblerHub = () => {
|
2024-04-23 10:27:32 +00:00
|
|
|
const persistedQuery = getPersistedQuery();
|
|
|
|
const assemblerUrl = getNewPath(
|
|
|
|
persistedQuery,
|
|
|
|
'/customize-store/assembler-hub',
|
|
|
|
{}
|
|
|
|
);
|
2024-03-04 19:09:36 +00:00
|
|
|
const iframe = useRef< HTMLIFrameElement | null >( null );
|
|
|
|
const [ isVisible, setIsVisible ] = useState( false );
|
|
|
|
|
|
|
|
useEffect( () => {
|
|
|
|
const currentIframe = iframe.current;
|
|
|
|
if ( currentIframe === null ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
window.addEventListener(
|
|
|
|
'popstate',
|
|
|
|
() => {
|
|
|
|
const apiLoaderUrl = getNewPath(
|
2024-04-23 10:27:32 +00:00
|
|
|
persistedQuery,
|
2024-03-04 19:09:36 +00:00
|
|
|
'/customize-store/design-with-ai/api-call-loader',
|
|
|
|
{}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Only catch the back button click when the user is on the main assember hub page
|
|
|
|
// and trying to go back to the api loader page
|
|
|
|
if ( 'admin.php' + window.location.search === apiLoaderUrl ) {
|
|
|
|
currentIframe.contentWindow?.postMessage(
|
|
|
|
{
|
|
|
|
type: 'assemberBackButtonClicked',
|
|
|
|
},
|
|
|
|
'*'
|
|
|
|
);
|
|
|
|
// When the user clicks the back button, push state changes to the previous step
|
|
|
|
// Set it back to the assembler hub
|
|
|
|
window.history?.pushState( {}, '', assemblerUrl );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
false
|
|
|
|
);
|
2024-04-23 10:27:32 +00:00
|
|
|
}, [ assemblerUrl, iframe, persistedQuery ] );
|
2024-03-04 19:09:36 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<iframe
|
|
|
|
ref={ iframe }
|
|
|
|
onLoad={ ( frame ) => {
|
|
|
|
const showIframe = () => setIsVisible( true );
|
|
|
|
attachIframeListeners( frame.currentTarget );
|
|
|
|
onIframeLoad( showIframe );
|
|
|
|
// Ceiling wait time set to 60 seconds
|
|
|
|
setTimeout( showIframe, 60 * 1000 );
|
|
|
|
window.parent.history?.pushState( {}, '', assemblerUrl );
|
|
|
|
} }
|
|
|
|
style={ { opacity: isVisible ? 1 : 0 } }
|
|
|
|
src={ assemblerUrl }
|
|
|
|
title="assembler-hub"
|
|
|
|
className="cys-fullscreen-iframe"
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-10-31 13:09:21 +00:00
|
|
|
export const AssembleHubLoader = () => {
|
|
|
|
// Show the last two steps of the loader so that the last frame is the shortest time possible
|
2023-12-07 04:14:57 +00:00
|
|
|
const augmentedSteps = createAugmentedSteps( loaderSteps.slice( -2 ), 10 );
|
2023-11-08 08:50:15 +00:00
|
|
|
|
|
|
|
const [ progress, setProgress ] = useState( augmentedSteps[ 0 ].progress );
|
2023-10-31 13:09:21 +00:00
|
|
|
|
|
|
|
return (
|
2024-03-04 19:09:36 +00:00
|
|
|
<>
|
|
|
|
<Loader>
|
|
|
|
<Loader.Sequence
|
|
|
|
interval={ ( 10 * 1000 ) / ( augmentedSteps.length - 1 ) }
|
|
|
|
shouldLoop={ false }
|
|
|
|
onChange={ ( index ) => {
|
|
|
|
// to get around bad set state timing issue
|
|
|
|
setTimeout( () => {
|
|
|
|
setProgress( augmentedSteps[ index ].progress );
|
|
|
|
}, 0 );
|
|
|
|
} }
|
|
|
|
>
|
|
|
|
{ augmentedSteps.map( ( step, index ) => (
|
|
|
|
<Loader.Layout key={ index }>
|
|
|
|
<Loader.Illustration>
|
|
|
|
{ step.image }
|
|
|
|
</Loader.Illustration>
|
|
|
|
<Loader.Title>{ step.title }</Loader.Title>
|
|
|
|
</Loader.Layout>
|
|
|
|
) ) }
|
|
|
|
</Loader.Sequence>
|
|
|
|
<Loader.ProgressBar
|
|
|
|
className="smooth-transition"
|
|
|
|
progress={ progress || 0 }
|
|
|
|
/>
|
|
|
|
</Loader>
|
|
|
|
<AssemblerHub />
|
|
|
|
</>
|
2023-08-29 06:00:54 +00:00
|
|
|
);
|
|
|
|
};
|