Files
pfadi-bussle/context/book.tsx
Thomas Ruoff 9f3b6bb2e1 remover booker, that's overdosed
It also brings the problem of consolidating bookers over multiple
bookings. The amount of data is not justifying having it in an own
entity
2021-06-21 23:21:23 +02:00

187 lines
4.1 KiB
TypeScript

import React, { useEffect, useReducer } from 'react'
import { useRouter } from 'next/router'
import { clearBookingData, loadBookingData } from '../helpers/storage'
import { createBooking } from '../helpers/booking'
import { Booking } from '../db/booking'
export type BookFormData = Omit<Booking, 'uuid'> & {
storeData?: boolean
}
type BookingProviderState = {
postData?: boolean
postDataError?: string
postDataSuccess?: boolean
formData: BookFormData
formDataChanged: string[]
booking?: Booking
dataStored: boolean
dataStoredLoaded: boolean
}
type BookProvider = {
state: BookingProviderState
dispatch: React.Dispatch<BookAction>
onChange: (data: object) => void
onChangeEvent: (event: React.ChangeEvent<React.ElementRef<'input'>>) => void
onSubmit: () => void
forgetData: () => void
}
type BookAction = {
type: string
payload?: any
}
export const BookContext: React.Context<BookProvider> = React.createContext<
BookProvider
>(null)
export const ACTIONS = {
SET_FORM_DATA: 'setFormData',
POST_DATA: 'postData',
POST_DATA_ERROR: 'postDataError',
DATA_STORED: 'dataStored',
DATA_STORED_LOADED: 'dataStoredLoaded',
DATA_STORED_FORGOTTEN: 'dataStoredForgotten',
}
function reducer(state: BookingProviderState, action: BookAction) {
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.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}`)
}
}
const initialState: BookingProviderState = {
postData: false,
postDataError: null,
postDataSuccess: null,
formData: {
startDate: '',
endDate: '',
purpose: '',
org: '',
destination: '',
name: '',
email: '',
phone: '',
street: '',
zip: '',
city: '',
},
formDataChanged: [],
dataStored: undefined,
dataStoredLoaded: undefined,
}
export default function BookProvider({ children }) {
const router = useRouter()
const [state, dispatch] = useReducer(reducer, initialState)
useEffect(() => {
const data = loadBookingData()
if (data !== null) {
dispatch({ type: ACTIONS.DATA_STORED_LOADED, payload: data })
}
}, [])
const onChangeEvent = (
event: React.ChangeEvent<React.ElementRef<'input'>>
) => {
const { name, value } = event.target
dispatch({
type: ACTIONS.SET_FORM_DATA,
payload: { [name]: value },
})
}
const onChange = (data: object) => {
dispatch({
type: ACTIONS.SET_FORM_DATA,
payload: data,
})
}
const onSubmit = async () => {
dispatch({ type: ACTIONS.POST_DATA })
try {
const booking = await createBooking(state.formData)
router.push(`/booking/${booking.uuid}/stored`)
} catch (error) {
console.error(error)
dispatch({ type: ACTIONS.POST_DATA_ERROR, payload: error.message })
}
}
const forgetData = () => {
clearBookingData()
dispatch({ type: ACTIONS.DATA_STORED_FORGOTTEN })
}
return (
<BookContext.Provider
value={{
state,
dispatch,
onChangeEvent,
onChange,
onSubmit,
forgetData,
}}
>
{children}
</BookContext.Provider>
)
}