UNPKG

@shopgate/engage

Version:
177 lines (172 loc) 5.53 kB
import React, { useState, useMemo, useCallback, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useCookies } from 'react-cookie'; import { useRoute, i18n, LoadingProvider, EUNAUTHORIZED, EAUTHENTICATION, ENOTFOUND } from '@shopgate/engage/core'; import { useFormState } from '@shopgate/engage/core/hooks/useFormState'; import { authenticateConstraints } from "./OrderDetailsProvider.constraints"; import connect from "./OrderDetailsProvider.connector"; import Context from "./OrderDetailsProvider.context"; import { jsx as _jsx } from "react/jsx-runtime"; const defaultFormState = { email: '', phone: '' }; /** * Converts validation errors into errors for form builder. * @param {Object} validationErrors The validation errors. * @returns {Array} */ const convertValidationErrors = validationErrors => Object.keys(validationErrors).map(key => ({ path: key, message: i18n.text(validationErrors[key]) })); /** * @param {Object} props The component props. * @returns {JSX} */ const OrderDetailsProvider = ({ isUserLoggedIn, order, orderId, shopSettings, userLocation, fetchOrderDetails, cancelOrder, children }) => { const { pathname } = useRoute(); const [showForm, setShowForm] = useState(!isUserLoggedIn); const [isLoading, setIsLoading] = useState(false); const [errorMessage, setErrorMessage] = useState(''); const orderTokenCookie = useMemo(() => [`shopgate_order_token_${orderId}`], [orderId]); const [cookies, setCookie] = useCookies([orderTokenCookie]); const orderToken = cookies[orderTokenCookie]; // Form visibility useEffect(() => { if (isUserLoggedIn) { setShowForm(errorMessage); } else { setShowForm(!order && !orderToken || errorMessage); } }, [errorMessage, isUserLoggedIn, order, orderToken]); const handleRequest = useCallback(async (email, phone, token) => { setIsLoading(true); let message; try { const response = await fetchOrderDetails(orderId, { email, phone, token }); if (response.token && response.tokenExpires) { setCookie(orderTokenCookie, response.token, { expires: new Date(response.tokenExpires) }); } setErrorMessage(''); } catch (error) { const { code } = error; if (code === EUNAUTHORIZED) { message = 'order_details.errors.authorize'; } else if (code === EAUTHENTICATION) { message = 'order_details.errors.authenticate'; } else if (code === ENOTFOUND) { message = 'order_details.errors.not_found'; } } if (message) { setErrorMessage(i18n.text(message)); } setIsLoading(false); }, [fetchOrderDetails, orderTokenCookie, orderId, setCookie]); const handleCancel = useCallback(async () => { setIsLoading(true); let message; try { await cancelOrder(orderId, orderToken); setErrorMessage(''); } catch (error) { const { code } = error; if (code === EAUTHENTICATION) { message = 'order_details.errors.expired'; } else if (code === ENOTFOUND) { message = 'order_details.errors.not_found'; } } if (message) { setErrorMessage(i18n.text(message)); } setIsLoading(false); }, [cancelOrder, orderId, orderToken]); // Loading state useEffect(() => { if (isLoading) { LoadingProvider.setLoading(pathname); return; } LoadingProvider.unsetLoading(pathname); }, [isLoading, pathname]); useEffect(() => { if (!isUserLoggedIn && !orderToken) { return; } (async () => { await handleRequest(undefined, undefined, !isUserLoggedIn ? orderToken : undefined); })(); /* eslint-disable react-hooks/exhaustive-deps */ }, []); /* eslint-enable react-hooks/exhaustive-deps */ let authenticateFormState = { valid: false, values: [] }; // Authentication form const handleAuthenticateFormSubmit = useCallback(async () => { if (!authenticateFormState.valid) { return; } const { email, phone } = authenticateFormState.values; await handleRequest(email, phone); }, [authenticateFormState.valid, authenticateFormState.values, handleRequest]); authenticateFormState = useFormState(defaultFormState, handleAuthenticateFormSubmit, authenticateConstraints); const handleSubmit = useCallback(() => { authenticateFormState.handleSubmit(new Event('submit')); }, [authenticateFormState]); const value = useMemo(() => ({ isUserLoggedIn, order, handleSubmit, isLoading, showForm, supportedCountries: shopSettings.supportedCountries, countrySortOrder: shopSettings.countrySortOrder, validationErrors: convertValidationErrors(authenticateFormState.validationErrors || {}), updateForm: authenticateFormState.setValues, defaultFormState, userLocation, fetchOrderDetails, cancelOrder: handleCancel, errorMessage }), [authenticateFormState.setValues, authenticateFormState.validationErrors, fetchOrderDetails, handleCancel, handleSubmit, isUserLoggedIn, showForm, isLoading, order, shopSettings.supportedCountries, shopSettings.countrySortOrder, userLocation, errorMessage]); return /*#__PURE__*/_jsx(Context.Provider, { value: value, children: children }); }; OrderDetailsProvider.defaultProps = { children: null, shopSettings: null, userLocation: null, order: null, orderId: null }; export default connect(OrderDetailsProvider);