added app context with reducer

This commit is contained in:
Thomas Ruoff
2020-07-01 00:25:36 +02:00
parent 96c62e3e9f
commit 563d57a8ba
6 changed files with 207 additions and 124 deletions

View File

@@ -17,18 +17,6 @@ export default function Contact({}) {
<label htmlFor="destination">Fahrtziel</label>
<input id="destination" name="destination" type="text" />
</div>
<div>
<label htmlFor="driver1">Fahrer 1</label>
<input id="driver1" name="driver1" type="text" />
<label htmlFor="driver">Alter</label>
<input id="ageDriver1" name="ageDriver1" type="number" min="20" />
</div>
<div>
<label htmlFor="driver">Fahrer 2</label>
<input id="driver2" name="driver2" type="text" />
<label htmlFor="driver">Alter</label>
<input id="ageDriver2" name="ageDriver2" type="number" min="20" />
</div>
</>
)
}

View File

@@ -1,80 +1,102 @@
import { useContext } from 'react'
import { AppContext, ACTIONS } from '../context/appStore'
import TimeSelect from './timeSelect'
import moment from 'moment'
import 'react-dates/initialize'
import { DateRangePicker, SingleDatePicker } from 'react-dates'
import TimeSelect from './timeSelect'
export default function DateSelect() {
const { state, dispatch } = useContext(AppContext)
export default function DateSelect({
multipleDays,
startDate,
setStartDate,
endDate,
setEndDate,
focusedInput,
setFocusedInput,
pickupTime,
setPickupTime,
dropoffTime,
setDropoffTime,
}) {
const timeSelect = (
const {
multipleDays,
startDate,
endDate,
focusedInput,
pickupTime,
dropoffTime,
bookedOn,
} = state
function isDayBlocked(momentDay) {
return bookedOn.some((rawDay) => momentDay.isSame(rawDay))
}
if (multipleDays === null || multipleDays === undefined) {
return null
}
return (
<>
<div>
{state.multipleDays === false && (
<SingleDatePicker
date={startDate && moment(startDate)}
onDateChange={(date) =>
dispatch({
type: ACTIONS.SET_DATE,
payload: { startDate: date.toISOString() },
})
}
focused={typeof focusedInput === 'boolean' && focusedInput}
onFocusChange={({ focused }) =>
dispatch({
type: ACTIONS.SET_FOCUSED_INPUT,
payload: focused,
})
}
isDayBlocked={isDayBlocked}
id="your_unique_id"
/>
)}
{state.multipleDays === true && (
<DateRangePicker
startDate={startDate && moment(startDate)}
startDateId="bussle_start_date_id"
endDate={endDate && moment(endDate)}
endDateId="bussle_end_date_id"
onDatesChange={({ startDate, endDate }) => {
dispatch({
type: ACTIONS.SET_DATE,
payload: {
startDate: startDate && startDate.toISOString(),
endDate: endDate && endDate.toISOString(),
},
})
}}
focusedInput={focusedInput}
onFocusChange={(focusedInput) =>
dispatch({
type: ACTIONS.SET_FOCUSED_INPUT,
payload: focusedInput,
})
}
isDayBlocked={isDayBlocked}
minDate={moment()}
/>
)}
</div>
<TimeSelect
id="pickup"
name="pickupTime"
label="Abholung Uhrzeit"
value={pickupTime}
setValue={setPickupTime}
setValue={(payload) =>
dispatch({ type: ACTIONS.SET_PICKUP_TIME, payload })
}
/>
<TimeSelect
id="dropoff"
name="dropoffTime"
label="Rückgabe Uhrzeit"
value={dropoffTime}
setValue={setDropoffTime}
setValue={(payload) =>
dispatch({ type: ACTIONS.SET_DROPOFF_TIME, payload })
}
/>
</>
)
if (multipleDays === false) {
return (
<>
<div>
<SingleDatePicker
date={startDate}
onDateChange={(date) => setStartDate(date)}
focused={typeof focusedInput === 'boolean' && focusedInput}
onFocusChange={({ focused }) => setFocusedInput(focused)}
id="your_unique_id"
/>
</div>
{timeSelect}
</>
)
}
if (multipleDays === true) {
return (
<>
<div>
<DateRangePicker
startDate={startDate}
startDateId="bussle_start_date_id"
endDate={endDate}
endDateId="bussle_end_date_id"
onDatesChange={({ startDate, endDate }) => {
setStartDate(startDate)
setEndDate(endDate)
}}
focusedInput={focusedInput}
onFocusChange={(focusedInput) => setFocusedInput(focusedInput)}
minDate={moment()}
/>
</div>
{timeSelect}
</>
)
}
return null
}

18
components/driver.js Normal file
View File

@@ -0,0 +1,18 @@
export default function Driver({}) {
return (
<>
<div>
<label htmlFor="driver1">Fahrer 1</label>
<input id="driver1" name="driver1" type="text" />
<label htmlFor="driver">Alter</label>
<input id="ageDriver1" name="ageDriver1" type="number" min="20" />
</div>
<div>
<label htmlFor="driver">Fahrer 2</label>
<input id="driver2" name="driver2" type="text" />
<label htmlFor="driver">Alter</label>
<input id="ageDriver2" name="ageDriver2" type="number" min="20" />
</div>
</>
)
}

View File

@@ -1,23 +1,31 @@
export default function RangeSelect({ multipleDays, setMultipleDays }) {
return (
<div>
Ich will das Bussle für
<input
type="radio"
id="single"
name="days"
value="singleDay"
onChange={() => setMultipleDays(false)}
/>
<label htmlFor="single">einen Tag</label>
<input
type="radio"
id="multiple"
name="days"
value="multipleDays"
onChange={() => setMultipleDays(true)}
/>
<label htmlFor="multiple">mehrere Tage</label> mieten
</div>
)
import { useContext } from 'react'
import { AppContext, ACTIONS } from '../context/appStore'
export default function RangeSelect() {
const { state, dispatch } = useContext(AppContext)
return (
<div>
Ich will das Bussle für
<input
type="radio"
id="single"
name="days"
checked={state.multipleDays === false}
onChange={() =>
dispatch({ type: ACTIONS.SET_MULTIPLE_DAYS, payload: false })
}
/>
<label htmlFor="single">einen Tag</label>
<input
type="radio"
id="multiple"
name="days"
checked={state.multipleDays === true}
onChange={() =>
dispatch({ type: ACTIONS.SET_MULTIPLE_DAYS, payload: true })
}
/>
<label htmlFor="multiple">mehrere Tage</label> mieten
</div>
)
}

66
context/appStore.js Normal file
View File

@@ -0,0 +1,66 @@
import React, { useReducer } from 'react'
export const AppContext = React.createContext()
export const ACTIONS = {
SET_MULTIPLE_DAYS: 'setMultipleDays',
SET_DATE: 'setDate',
SET_FOCUSED_INPUT: 'setFocusedInput',
SET_PICKUP_TIME: 'setPickupTime',
SET_DROPOFF_TIME: 'setDropoffTime',
}
function reducer(state, action) {
switch (action.type) {
case ACTIONS.SET_MULTIPLE_DAYS:
return {
...state,
multipleDays: action.payload,
focusedInput: undefined,
startDate: undefined,
endDate: undefined,
}
case ACTIONS.SET_DATE:
return {
...state,
startDate: action.payload.startDate,
endDate: action.payload.endDate,
}
case ACTIONS.SET_FOCUSED_INPUT:
return { ...state, focusedInput: action.payload }
case ACTIONS.SET_PICKUP_TIME:
return { ...state, pickupTime: action.payload }
case ACTIONS.SET_DROPOFF_TIME:
return { ...state, dropoffTime: 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 = {
multipleDays: null,
bookedOn: [
'2020-07-10',
'2020-07-11',
'2020-07-12',
'2020-07-23',
'2020-08-01',
],
}
export default function AppStore({ children }) {
const [state, dispatch] = useReducer(debugReducer, initialState)
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
)
}

View File

@@ -1,20 +1,15 @@
import { useState } from 'react'
import { useContext } from 'react'
import Head from 'next/head'
import AppStore from '../context/appStore'
import RangeSelect from '../components/rangeSelect'
import DateSelect from '../components/dateSelect'
import Contact from '../components/contact'
import Driver from '../components/driver'
export default function Home() {
const [multipleDays, setMultipleDays] = useState(null)
const [startDate, setStartDate] = useState(null)
const [endDate, setEndDate] = useState(null)
const [focusedInput, setFocusedInput] = useState(null)
const [pickupTime, setPickupTime] = useState('')
const [dropoffTime, setDropoffTime] = useState('')
return (
<div className="container">
<Head>
@@ -29,29 +24,15 @@ export default function Home() {
Du willst das Pfadi Bussle buchen? Hier bist du richtig!
</p>
<form className="bookingForm">
<RangeSelect
multipleDay={multipleDays}
setMultipleDays={setMultipleDays}
/>
<DateSelect
multipleDays={multipleDays}
startDate={startDate}
setStartDate={setStartDate}
endDate={endDate}
setEndDate={setEndDate}
focusedInput={focusedInput}
setFocusedInput={setFocusedInput}
pickupTime={pickupTime}
setPickupTime={setPickupTime}
dropoffTime={dropoffTime}
setDropoffTime={setDropoffTime}
/>
<AppStore>
<form className="bookingForm">
<RangeSelect />
<DateSelect />
<Contact />
<Contact />
<input type="submit" />
</form>
<input type="submit" />
</form>
</AppStore>
</main>
<footer>