import React, { useReducer, useEffect } from 'react' import { storeFormData, loadFormData, clearFormData } from '../helpers/storage' export const WizardContext = React.createContext() export const ACTIONS = { SET_FORM_DATA: 'setFormData', POST_DATA: 'postData', POST_DATA_ERROR: 'postDataError', POST_DATA_SUCCESS: 'postDataSuccess', DATA_STORED: 'dataStored', DATA_STORED_LOADED: 'dataStoredLoaded', DATA_STORED_FORGOTTEN: 'dataStoredForgotten', } function reducer(state, action) { switch (action.type) { case ACTIONS.SET_FORM_DATA: return { ...state, formData: { ...state.formData, ...action.payload, }, formDataChanged: [ ...state.formDataChanged, ...Object.keys(action.payload), ], } case ACTIONS.POST_DATA: return { ...state, postData: true, postDataError: null, postDataSuccess: null, } case ACTIONS.POST_DATA_ERROR: return { ...state, postData: false, postDataError: action.payload, postDataSuccess: null, } case ACTIONS.POST_DATA_SUCCESS: return { ...state, formData: { ...state.formData, ...action.payload, }, postData: false, postDataError: null, postDataSuccess: true, } case ACTIONS.DATA_STORED_LOADED: return { ...state, dataStoredLoaded: true, formData: { ...state.formData, ...action.payload, }, } case ACTIONS.DATA_STORED_FORGOTTEN: return { ...state, dataStored: undefined, dataStoredLoaded: undefined, formData: { ...initialState.formData }, } case ACTIONS.DATA_STORED: return { ...state, dataStored: action.payload, } default: throw new Error(`Unkown Action type ${action.type}`) } } function debugReducer(state, action) { console.debug('applying action', action) const newState = reducer(state, action) console.debug(newState) return newState } const initialState = { postData: false, postDataError: null, postDataSuccess: null, formData: { startDate: '', endDate: '', purpose: '', org: '', destination: '', name: '', email: '', street: '', zip: '', city: '', }, formDataChanged: [], } async function createBooking(formData) { const response = await fetch('/api/booking', { method: 'POST', mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', }, referrerPolicy: 'no-referrer', body: JSON.stringify(formData), }) return response.json() } export default function WizardStore({ children }) { const [state, dispatch] = useReducer(debugReducer, initialState) useEffect(() => { const data = loadFormData() if (data !== null) { dispatch({ type: ACTIONS.DATA_STORED_LOADED, payload: data }) } }, []) const onChangeEvent = (event) => { const { name, value } = event.target dispatch({ type: ACTIONS.SET_FORM_DATA, payload: { [name]: value }, }) } const onChange = (data) => { dispatch({ type: ACTIONS.SET_FORM_DATA, payload: data, }) } const onSubmit = async () => { dispatch({ type: ACTIONS.POST_DATA }) try { const bookingData = await createBooking(state.formData) dispatch({ type: ACTIONS.POST_DATA_SUCCESS, payload: bookingData }) } catch (error) { console.error(error) dispatch({ type: ACTIONS.POST_DATA_ERROR, payload: error.message }) } } const storeData = (value) => { if (value) { storeFormData(state.formData) } dispatch({ type: ACTIONS.DATA_STORED, payload: value }) } const forgetData = () => { clearFormData() dispatch({ type: ACTIONS.DATA_STORED_FORGOTTEN }) } return ( {children} ) }