diff --git a/modules/ppcp-settings/resources/js/data/constants.js b/modules/ppcp-settings/resources/js/data/constants.js new file mode 100644 index 000000000..61ebf948e --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/constants.js @@ -0,0 +1,2 @@ +export const NAMESPACE = '/wc/v3/wc_paypal'; +export const STORE_NAME = 'wc/paypal'; diff --git a/modules/ppcp-settings/resources/js/data/index.js b/modules/ppcp-settings/resources/js/data/index.js new file mode 100644 index 000000000..d305bc479 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/index.js @@ -0,0 +1,6 @@ +import { STORE_NAME } from './constants'; +import { initStore } from './store'; + +initStore(); + +export const WC_PAYPAL_STORE_NAME = STORE_NAME; diff --git a/modules/ppcp-settings/resources/js/data/onboarding/action-types.js b/modules/ppcp-settings/resources/js/data/onboarding/action-types.js new file mode 100644 index 000000000..bc215b491 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/action-types.js @@ -0,0 +1,4 @@ +export default { + SET_ONBOARDING_DETAILS: 'SET_ONBOARDING_DETAILS', + SET_IS_SAVING_ONBOARDING_DETAILS: 'SET_IS_SAVING_ONBOARDING_DETAILS', +}; diff --git a/modules/ppcp-settings/resources/js/data/onboarding/actions.js b/modules/ppcp-settings/resources/js/data/onboarding/actions.js new file mode 100644 index 000000000..060e39811 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/actions.js @@ -0,0 +1,64 @@ +import { dispatch, select } from '@wordpress/data'; +import { apiFetch } from '@wordpress/data-controls'; +import ACTION_TYPES from './action-types'; +import { NAMESPACE, STORE_NAME } from '../constants'; + +/** + * Persistent. Set the full onboarding details, usually during app initialization. + * + * @param {Object} payload + * @return {{payload, type: string}} The action. + */ +export const updateOnboardingDetails = ( payload ) => { + return { + type: ACTION_TYPES.SET_ONBOARDING_DETAILS, + payload, + }; +}; + +/** + * Non-persistent. Changes the "saving" flag. + * + * @param {boolean} isSaving + * @return {{type: string, isSaving}} The action. + */ +export function updateIsSavingOnboardingDetails( isSaving ) { + return { + type: ACTION_TYPES.SET_IS_SAVING_ONBOARDING_DETAILS, + isSaving, + }; +} + +/** + * Saves the persistent details to the WP database. + * + * @return {Generator} A generator function that handles the saving process. + */ +export function* saveOnboardingDetails() { + let error = null; + + try { + const settings = select( STORE_NAME ).getOnboardingDetails(); + + yield updateIsSavingOnboardingDetails( true ); + + yield apiFetch( { + path: `${ NAMESPACE }/onboarding`, + method: 'POST', + data: settings, + } ); + + yield dispatch( 'core/notices' ).createSuccessNotice( + __( 'Progress saved.', 'woocommerce-paypal-payments' ) + ); + } catch ( e ) { + error = e; + yield dispatch( 'core/notices' ).createErrorNotice( + __( 'Error saving progress.', 'woocommerce-paypal-payments' ) + ); + } finally { + yield updateIsSavingOnboardingDetails( false ); + } + + return error === null; +} diff --git a/modules/ppcp-settings/resources/js/data/onboarding/index.js b/modules/ppcp-settings/resources/js/data/onboarding/index.js new file mode 100644 index 000000000..0b07abf46 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/index.js @@ -0,0 +1,6 @@ +import reducer from './reducer'; +import * as selectors from './selectors'; +import * as actions from './actions'; +import * as resolvers from './resolvers'; + +export { reducer, selectors, actions, resolvers }; diff --git a/modules/ppcp-settings/resources/js/data/onboarding/reducer.js b/modules/ppcp-settings/resources/js/data/onboarding/reducer.js new file mode 100644 index 000000000..08002f192 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/reducer.js @@ -0,0 +1,31 @@ +import ACTION_TYPES from './action-types'; + +const defaultState = { + isSaving: false, + data: { + step: 0, + }, +}; + +export const onboardingReducer = ( + state = defaultState, + { type, ...action } +) => { + switch ( type ) { + case ACTION_TYPES.SET_ONBOARDING_DETAILS: + return { + ...state, + data: action.payload, + }; + + case ACTION_TYPES.SET_IS_SAVING_ONBOARDING_DETAILS: + return { + ...state, + isSaving: action.isSaving, + }; + } + + return state; +}; + +export default onboardingReducer; diff --git a/modules/ppcp-settings/resources/js/data/onboarding/resolvers.js b/modules/ppcp-settings/resources/js/data/onboarding/resolvers.js new file mode 100644 index 000000000..497d855a3 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/resolvers.js @@ -0,0 +1,24 @@ +import { dispatch } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { apiFetch } from '@wordpress/data-controls'; +import { NAMESPACE } from '../constants'; +import { updateOnboardingDetails } from './actions'; + +/** + * Retrieve settings from the site's REST API. + */ +export function* getOnboardingDetails() { + const path = `${ NAMESPACE }/onboarding`; + + try { + const result = yield apiFetch( { path } ); + yield updateOnboardingDetails( result ); + } catch ( e ) { + yield dispatch( 'core/notices' ).createErrorNotice( + __( + 'Error retrieving onboarding details.', + 'woocommerce-paypal-payments' + ) + ); + } +} diff --git a/modules/ppcp-settings/resources/js/data/onboarding/selectors.js b/modules/ppcp-settings/resources/js/data/onboarding/selectors.js new file mode 100644 index 000000000..522b9a93e --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/onboarding/selectors.js @@ -0,0 +1,17 @@ +const EMPTY_OBJ = {}; + +const getOnboardingState = ( state ) => { + if ( ! state ) { + return EMPTY_OBJ; + } + + return state.onboarding || EMPTY_OBJ; +}; + +export const getOnboardingDetails = ( state ) => { + return getOnboardingState( state ).data || EMPTY_OBJ; +}; + +export const getOnboardingStep = ( state ) => { + return getOnboardingDetails( state ).step || 0; +}; diff --git a/modules/ppcp-settings/resources/js/data/store.js b/modules/ppcp-settings/resources/js/data/store.js new file mode 100644 index 000000000..f5a1a4b13 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/store.js @@ -0,0 +1,30 @@ +import { createReduxStore, register, combineReducers } from '@wordpress/data'; +import { controls } from '@wordpress/data-controls'; +import { STORE_NAME } from './constants'; +import * as onboarding from './onboarding'; + +const actions = {}; +const selectors = {}; +const resolvers = {}; + +[ onboarding ].forEach( ( item ) => { + Object.assign( actions, { ...item.actions } ); + Object.assign( selectors, { ...item.selectors } ); + Object.assign( resolvers, { ...item.resolvers } ); +} ); + +const reducer = combineReducers( { + onboarding: onboarding.reducer, +} ); + +export const initStore = () => { + const store = createReduxStore( STORE_NAME, { + reducer, + controls, + actions, + selectors, + resolvers, + } ); + + register( store ); +};