diff --git a/src/OnboardingSPA/components/App/index.js b/src/OnboardingSPA/components/App/index.js index 50e32d63a..3c681ed8a 100644 --- a/src/OnboardingSPA/components/App/index.js +++ b/src/OnboardingSPA/components/App/index.js @@ -4,8 +4,6 @@ import Drawer from '../Drawer'; import Sidebar from '../Sidebar'; import classNames from 'classnames'; import { useLocation } from 'react-router-dom'; -import { setFlow } from '../../utils/api/flow'; -import { getSettings, setSettings } from '../../utils/api/settings'; import { isEmpty, updateWPSettings } from '../../utils/api/ecommerce'; import { store as nfdOnboardingStore } from '../../store'; @@ -44,21 +42,8 @@ const App = () => { }; }, []); - const [isRequestPlaced, setIsRequestPlaced] = useState(false); - const [didVisitBasicInfo, setDidVisitBasicInfo] = useState(false); const [didVisitEcommerce, setDidVisitEcommerce] = useState(false); - const { setActiveStep, setActiveFlow, setCurrentOnboardingData } = useDispatch(nfdOnboardingStore); - - async function syncSocialSettings() { - const initialData = await getSettings(); - const result = await setSettings(currentData?.data?.socialData); - setDidVisitBasicInfo(false); - if (result?.error != null) { - console.error('Unable to Save Social Data!'); - return initialData?.body; - } - return result?.body; - } + const { setActiveStep, setActiveFlow } = useDispatch(nfdOnboardingStore); async function syncStoreDetails() { let { address, tax } = currentData.storeDetails; @@ -92,39 +77,12 @@ const App = () => { } async function syncStoreToDB() { - // The First Welcome Step doesn't have any Store changes - const isFirstStep = location?.pathname === firstStep?.path; - if (currentData && !isFirstStep){ - if(!isRequestPlaced){ - setIsRequestPlaced(true); - - if (didVisitEcommerce) { - await syncStoreDetails(); - } - - // If Social Data is changed then sync it - if (didVisitBasicInfo){ - const socialData = await syncSocialSettings(); - - // If Social Data is changed then Sync that also to the store - if (socialData && currentData?.data) - currentData.data.socialData = socialData; - } - - const result = await setFlow(currentData); - if (result?.error != null) { - setIsRequestPlaced(false); - console.error('Unable to Save data!'); - } else { - setCurrentOnboardingData(result?.body); - setIsRequestPlaced(false); - } - + if ( currentData ){ + if (didVisitEcommerce) { + await syncStoreDetails(); } } - // Check if the Basic Info page was visited - if (location?.pathname.includes('basic-info')) - setDidVisitBasicInfo(true); + if (location?.pathname.includes('ecommerce')) { setDidVisitEcommerce(true); } diff --git a/src/OnboardingSPA/pages/Steps/BasicInfo/index.js b/src/OnboardingSPA/pages/Steps/BasicInfo/index.js index 072a052c6..5c744ef30 100644 --- a/src/OnboardingSPA/pages/Steps/BasicInfo/index.js +++ b/src/OnboardingSPA/pages/Steps/BasicInfo/index.js @@ -6,22 +6,27 @@ import { store as nfdOnboardingStore } from '../../../store'; import { useSelect, useDispatch } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; +import { FLOW_SYNC, SETTINGS_SYNC } from '../../../utils/api-queuer/constants'; const StepBasicInfo = () => { const isLargeViewport = useViewportMatch( 'medium' ); - const { setIsDrawerOpened, setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed } = + const { enqueueRequest, flushQueue, setIsDrawerOpened, setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed } = useDispatch( nfdOnboardingStore ); - const { currentStep } = useSelect( + const { currentStep, currentData } = useSelect( (select) => { return { - currentStep: select(nfdOnboardingStore).getCurrentStep() + currentStep: select(nfdOnboardingStore).getCurrentStep(), + currentData: select(nfdOnboardingStore).getCurrentOnboardingData() }; }, [] ); useEffect( () => { + flushQueue(currentData); + enqueueRequest(FLOW_SYNC); + enqueueRequest(SETTINGS_SYNC); if ( isLargeViewport ) { setIsDrawerOpened( true ); } diff --git a/src/OnboardingSPA/pages/Steps/DesignThemes/index.js b/src/OnboardingSPA/pages/Steps/DesignThemes/index.js index ab6d8a9aa..edf258e9d 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemes/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemes/index.js @@ -2,14 +2,21 @@ import CommonLayout from '../../../components/Layouts/Common'; import StepOverview from '../../../components/StepOverview'; import { VIEW_DESIGN_THEMES } from '../../../../constants'; import { store as nfdOnboardingStore } from '../../../store'; -import { useDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; const StepDesignThemes = () => { - const { setDrawerActiveView, setIsDrawerOpened, setIsSidebarOpened } = + const { flushQueue, setDrawerActiveView, setIsDrawerOpened, setIsSidebarOpened } = useDispatch( nfdOnboardingStore ); + const { currentData } = useSelect((select) => { + return { + currentData: select(nfdOnboardingStore).getCurrentOnboardingData() + }; + }, []); + useEffect( () => { + flushQueue(currentData); setIsSidebarOpened( false ); setIsDrawerOpened( true ); setDrawerActiveView( VIEW_DESIGN_THEMES ); diff --git a/src/OnboardingSPA/pages/Steps/Ecommerce/StepAddress/index.js b/src/OnboardingSPA/pages/Steps/Ecommerce/StepAddress/index.js index 33c51908e..bcaded9ee 100644 --- a/src/OnboardingSPA/pages/Steps/Ecommerce/StepAddress/index.js +++ b/src/OnboardingSPA/pages/Steps/Ecommerce/StepAddress/index.js @@ -16,6 +16,7 @@ import { useWPSettings } from '../useWPSettings'; const StepAddress = () => { const isLargeViewport = useViewportMatch( 'medium' ); const { + flushQueue, setDrawerActiveView, setIsDrawerOpened, setIsDrawerSuppressed, @@ -24,6 +25,7 @@ const StepAddress = () => { } = useDispatch(nfdOnboardingStore); useEffect(() => { + flushQueue(currentData); if (isLargeViewport) { setIsDrawerOpened(true); } diff --git a/src/OnboardingSPA/pages/Steps/Ecommerce/StepProducts/index.js b/src/OnboardingSPA/pages/Steps/Ecommerce/StepProducts/index.js index 00732c448..24c98d6ff 100644 --- a/src/OnboardingSPA/pages/Steps/Ecommerce/StepProducts/index.js +++ b/src/OnboardingSPA/pages/Steps/Ecommerce/StepProducts/index.js @@ -15,6 +15,7 @@ import content from '../content.json'; const StepProducts = () => { const isLargeViewport = useViewportMatch( 'medium' ); const { + flushQueue, setDrawerActiveView, setIsDrawerOpened, setIsDrawerSuppressed, @@ -27,6 +28,7 @@ const StepProducts = () => { ); let productInfo = currentData.storeDetails.productInfo; useEffect(() => { + flushQueue(currentData); if (isLargeViewport) { setIsDrawerOpened(true); } diff --git a/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js b/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js index 8239a0a0e..5a92a8819 100644 --- a/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js +++ b/src/OnboardingSPA/pages/Steps/Ecommerce/StepTax/index.js @@ -21,6 +21,7 @@ function createReverseLookup(state) { const StepTax = () => { const isLargeViewport = useViewportMatch( 'medium' ); const { + flushQueue, setDrawerActiveView, setIsDrawerOpened, setIsDrawerSuppressed, @@ -34,6 +35,7 @@ const StepTax = () => { ); useEffect(() => { + flushQueue(currentData); if (isLargeViewport) { setIsDrawerOpened(true); } diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js index 7730415ec..68f568f86 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/GetStartedExperience/index.js @@ -6,6 +6,8 @@ import NeedHelpTag from '../../../../components/NeedHelpTag'; import { VIEW_NAV_GET_STARTED } from '../../../../../constants'; import { store as nfdOnboardingStore } from '../../../../store'; import content from './content.json'; +import { FLOW_SYNC } from '../../../../utils/api-queuer/constants'; + import { RadioControl } from '@wordpress/components'; import { useState, useEffect } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -21,7 +23,7 @@ const GetStartedExperience = () => { const [ isLoaded, setisLoaded ] = useState( false ); const [ wpComfortLevel, setWpComfortLevel ] = useState( '0' ); - const { setCurrentOnboardingData } = useDispatch( nfdOnboardingStore ); + const { enqueueRequest, flushQueue, setCurrentOnboardingData } = useDispatch( nfdOnboardingStore ); const { currentData, currentStep } = useSelect( ( select ) => { return { @@ -37,6 +39,8 @@ const GetStartedExperience = () => { } = useDispatch( nfdOnboardingStore ); useEffect( () => { + flushQueue(currentData); + enqueueRequest(FLOW_SYNC); setIsSidebarOpened( false ); setIsDrawerSuppressed( true ); setDrawerActiveView( VIEW_NAV_GET_STARTED ); diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js index 04ba89845..2e873134f 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/PrimarySite/index.js @@ -10,11 +10,12 @@ import NavCardButton from '../../../../../components/Button/NavCardButton'; import NeedHelpTag from '../../../../../components/NeedHelpTag'; import content from '../content.json'; import { translations } from '../../../../../utils/locales/translations'; +import { FLOW_SYNC } from '../../../../../utils/api-queuer/constants'; const StepPrimarySetup = () => { - const { setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed } = useDispatch( + const { enqueueRequest, flushQueue, setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed } = useDispatch( nfdOnboardingStore ); @@ -29,6 +30,8 @@ const StepPrimarySetup = () => { ); useEffect(() => { + flushQueue(currentData); + enqueueRequest(FLOW_SYNC); setIsSidebarOpened(false); setIsDrawerSuppressed(true); setDrawerActiveView(VIEW_NAV_GET_STARTED); diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js index b57d6fd9d..30ea91a31 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/SiteTypeSetup/SecondarySite/index.js @@ -10,14 +10,28 @@ import NavCardButton from '../../../../../components/Button/NavCardButton'; import NeedHelpTag from '../../../../../components/NeedHelpTag'; import content from '../content.json'; import { translations } from '../../../../../utils/locales/translations'; - +import { FLOW_SYNC } from '../../../../../utils/api-queuer/constants'; const StepPrimarySetup = () => { - const { setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed } = useDispatch( - nfdOnboardingStore - ); + const { enqueueRequest, + flushQueue, + setDrawerActiveView, + setIsSidebarOpened, + setIsDrawerSuppressed, + setCurrentOnboardingData + } + = useDispatch( nfdOnboardingStore ); + + const { currentStep, currentData } = useSelect((select) => { + return { + currentStep: select(nfdOnboardingStore).getCurrentStep(), + currentData: select(nfdOnboardingStore).getCurrentOnboardingData() + }; + }, []); useEffect(() => { + flushQueue(currentData); + enqueueRequest(FLOW_SYNC); setIsSidebarOpened(false); setIsDrawerSuppressed(true); setDrawerActiveView(VIEW_NAV_GET_STARTED); @@ -26,16 +40,6 @@ const StepPrimarySetup = () => { const [clickedIndex, changeCategory] = useState(-1); const [inputCategVal, changeInputCateg] = useState(''); - - const { setCurrentOnboardingData } = useDispatch(nfdOnboardingStore); - - const { currentStep, currentData } = useSelect((select) => { - return { - currentStep: select(nfdOnboardingStore).getCurrentStep(), - currentData: select(nfdOnboardingStore).getCurrentOnboardingData() - }; - }, []); - const selectedCategoryInStore = currentData?.data?.siteType?.secondary; const categoriesArray = content.categories; const subCategories = categoriesArray[0]?.subCategories; diff --git a/src/OnboardingSPA/pages/Steps/GetStarted/Welcome/index.js b/src/OnboardingSPA/pages/Steps/GetStarted/Welcome/index.js index 2e1fbea6d..4aaba4e1b 100644 --- a/src/OnboardingSPA/pages/Steps/GetStarted/Welcome/index.js +++ b/src/OnboardingSPA/pages/Steps/GetStarted/Welcome/index.js @@ -22,22 +22,25 @@ import { VIEW_NAV_GET_STARTED } from '../../../../../constants'; */ const StepWelcome = () => { const location = useLocation(); - const { currentStep, brandName } = useSelect( + const { currentStep, currentData, brandName } = useSelect( (select) => { return { currentStep: select(nfdOnboardingStore).getCurrentStep(), + currentData: select(nfdOnboardingStore).getCurrentOnboardingData(), brandName: select(nfdOnboardingStore).getNewfoldBrandName(), }; }, [location.pathname] ); const { + flushQueue, setDrawerActiveView, setIsSidebarOpened, setIsDrawerSuppressed, } = useDispatch( nfdOnboardingStore ); useEffect( () => { + flushQueue(currentData); setIsSidebarOpened( false ); setIsDrawerSuppressed( true ); setDrawerActiveView( VIEW_NAV_GET_STARTED ); diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js index ce88f95e6..f604b33d0 100644 --- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js +++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js @@ -10,6 +10,7 @@ import { store as nfdOnboardingStore } from '../../../store'; import CommonLayout from '../../../components/Layouts/Common'; import HeadingWithSubHeading from '../../../components/HeadingWithSubHeading'; import SelectableCardList from '../../../components/SelectableCardList/selectable-card-list'; +import { FLOW_SYNC } from '../../../utils/api-queuer/constants'; const StepTopPriority = ( props ) => { const priorityTypes = { @@ -42,6 +43,8 @@ const StepTopPriority = ( props ) => { const isLargeViewport = useViewportMatch( 'medium' ); const { + enqueueRequest, + flushQueue, setDrawerActiveView, setIsDrawerOpened, setIsSidebarOpened, @@ -63,6 +66,8 @@ const StepTopPriority = ( props ) => { }; useEffect( () => { + flushQueue(currentData); + enqueueRequest(FLOW_SYNC); if ( isLargeViewport ) { setIsDrawerOpened( true ); } diff --git a/src/OnboardingSPA/store/actions.js b/src/OnboardingSPA/store/actions.js index 9f80cb9ee..15b4150e4 100644 --- a/src/OnboardingSPA/store/actions.js +++ b/src/OnboardingSPA/store/actions.js @@ -138,3 +138,23 @@ export function updatePreviewSettings( previewSettings ) { previewSettings, }; } + +export function enqueueRequest( request ) { + return { + type: 'ENQUEUE_REQUEST', + request, + }; +} + +export function dequeueRequest() { + return { + type: 'DEQUEUE_REQUEST' + }; +} + +export function flushQueue( storeData ) { + return { + type: 'FLUSH_QUEUE', + storeData, + }; +} diff --git a/src/OnboardingSPA/store/reducer.js b/src/OnboardingSPA/store/reducer.js index cb2213f20..d5cf32837 100644 --- a/src/OnboardingSPA/store/reducer.js +++ b/src/OnboardingSPA/store/reducer.js @@ -1,6 +1,7 @@ import { combineReducers } from '@wordpress/data'; import { VIEW_NAV_PRIMARY } from '../../constants'; +import { apiExecuter } from '../utils/api-queuer/api-executer'; import { routes as initialRoutes, @@ -71,6 +72,7 @@ export function drawer( return state; } + export function currentData( state = {}, action ) { switch ( action.type ) { case 'SET_CURRENT_DATA': @@ -107,6 +109,25 @@ export function sidebar( return state; } +export function queue(state = [], action) { + switch (action.type) { + // Add a new API Request to the Queue + case 'ENQUEUE_REQUEST': + return [...state, action.request]; + + // Take out the topmost Queue Item + case 'DEQUEUE_REQUEST': + return [...state.slice(1)]; + + // Make all the Queue Requests and Empty the queue + case 'FLUSH_QUEUE': + apiExecuter(action.storeData, state); + return []; + } + + return state; +} + export function runtime( state = {}, action ) { switch ( action.type ) { case 'SET_RUNTIME': @@ -136,11 +157,12 @@ export function settings( state = {}, action ) { return state; } -export default combineReducers( { +export default combineReducers({ drawer, runtime, currentData, settings, flow, sidebar, -} ); + queue, +}); diff --git a/src/OnboardingSPA/store/selectors.js b/src/OnboardingSPA/store/selectors.js index ea6dd57eb..3bd9103b1 100644 --- a/src/OnboardingSPA/store/selectors.js +++ b/src/OnboardingSPA/store/selectors.js @@ -83,6 +83,16 @@ export function getOnboardingFlow( state ) { return state.runtime.currentFlow ?? 'wp-setup'; } +/** + * Gets the Queue Element on top + * + * @param {*} state + * @return string + */ +export function getQueuePeek(state) { + return state?.queue[0] ?? null; +} + /** * Gets steps to display in drawer. * diff --git a/src/OnboardingSPA/utils/api-queuer/api-executer.js b/src/OnboardingSPA/utils/api-queuer/api-executer.js new file mode 100644 index 000000000..224c728a0 --- /dev/null +++ b/src/OnboardingSPA/utils/api-queuer/api-executer.js @@ -0,0 +1,18 @@ +import { setFlow } from '../api/flow'; +import { setSettings } from '../api/settings'; +import { FLOW_SYNC, SETTINGS_SYNC } from './constants'; + +// This Function is responsible to execute requests in a sequence +export async function apiExecuter(data, requests) { + + requests.forEach(request => { + switch (request) { + case FLOW_SYNC: setFlow(data); + break; + case SETTINGS_SYNC: setSettings(data?.data?.socialData); + break; + default: + break; + } + }); +} diff --git a/src/OnboardingSPA/utils/api-queuer/constants.js b/src/OnboardingSPA/utils/api-queuer/constants.js new file mode 100644 index 000000000..9fe4bc7eb --- /dev/null +++ b/src/OnboardingSPA/utils/api-queuer/constants.js @@ -0,0 +1,2 @@ +export const FLOW_SYNC = 'FLOW_SYNC'; +export const SETTINGS_SYNC = 'SETTINGS_SYNC';