woocommerce/plugins/woocommerce-admin/client/guided-tours/wc-addons-tour/index.tsx

123 lines
3.3 KiB
TypeScript
Raw Normal View History

/**
* External dependencies
*/
import { useEffect, useState } from '@wordpress/element';
import { TourKit, TourKitTypes } from '@woocommerce/components';
import { recordEvent } from '@woocommerce/tracks';
import { useDispatch } from '@wordpress/data';
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
import qs from 'qs';
/**
* Internal dependencies
*/
import { observePositionChange, waitUntilElementTopNotChange } from '../utils';
import { getTourConfig } from './get-config';
import { scrollPopperToVisibleAreaIfNeeded } from './utils';
import { getSteps } from './get-steps';
const WCAddonsTour = () => {
const [ showTour, setShowTour ] = useState( false );
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
const steps = getSteps();
const defaultAutoScrollBlock: ScrollLogicalPosition = 'center';
useEffect( () => {
const query = qs.parse( window.location.search.slice( 1 ) );
if ( query?.tutorial === 'true' ) {
const intervalId = waitUntilElementTopNotChange(
steps[ 0 ].referenceElements?.desktop || '',
() => {
const stepName = steps[ 0 ]?.meta?.name;
setShowTour( true );
recordEvent( 'in_app_marketplace_tour_started', {
step: stepName,
} );
},
500
);
return () => clearInterval( intervalId );
}
// only run once
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
useEffect( () => {
if ( showTour ) {
function showPopper() {
const tourKitElement = document.querySelector(
'.tour-kit-frame__container'
);
if ( tourKitElement ) {
scrollPopperToVisibleAreaIfNeeded(
tourKitElement.getBoundingClientRect()
);
}
}
// In a rare case, admin notices might load before observe is added below (moving `.wc-addons-wrap`).
// In such a case, if Tour is shown before this effect is called, it might not be position correctly.
// Updating popper's position here, ensures it's always visible.
const timeoutId = setTimeout( showPopper, 500 );
const intervalId = observePositionChange(
'.wc-addons-wrap',
showPopper,
150
);
return () => {
clearTimeout( timeoutId );
clearInterval( intervalId );
};
}
}, [ showTour ] );
if ( ! showTour ) {
return null;
}
const closeHandler: TourKitTypes.CloseHandler = (
tourSteps,
currentStepIndex
) => {
setShowTour( false );
// mark tour as completed
updateOptions( {
woocommerce_admin_dismissed_in_app_marketplace_tour: 'yes',
} );
// remove `tutorial` from search query, so it's not shown on page refresh
const url = new URL( window.location.href );
url.searchParams.delete( 'tutorial' );
window.history.replaceState( null, '', url );
if ( steps.length - 1 === currentStepIndex ) {
recordEvent( 'in_app_marketplace_tour_completed' );
} else {
const stepName = tourSteps[ currentStepIndex ]?.meta?.name;
recordEvent( 'in_app_marketplace_tour_dismissed', {
step: stepName,
} );
}
};
const onNextStepHandler = ( previousStepIndex: number ) => {
const stepName = steps[ previousStepIndex + 1 ]?.meta?.name || '';
recordEvent( 'in_app_marketplace_tour_step_viewed', {
step: stepName,
} );
};
const tourConfig = getTourConfig( {
closeHandler,
onNextStepHandler,
autoScrollBlock: defaultAutoScrollBlock,
steps,
} );
return <TourKit config={ tourConfig } />;
};
export default WCAddonsTour;