diff --git a/components/contact.js b/components/contact.js index 85ac856..22b78f4 100644 --- a/components/contact.js +++ b/components/contact.js @@ -5,7 +5,7 @@ import Form from 'react-bootstrap/Form' import Col from 'react-bootstrap/Col' export default function Contact() { - const { state } = useContext(WizardContext) + const { state, onChangeEvent } = useContext(WizardContext) const { name, email, street, zip, city } = state.formData @@ -13,38 +13,53 @@ export default function Contact() { <> Name - + E-Mail Straße PLZ - + Stadt diff --git a/components/dateSelect.js b/components/dateSelect.js index 34dfbb5..19678cd 100644 --- a/components/dateSelect.js +++ b/components/dateSelect.js @@ -9,11 +9,13 @@ import moment from 'moment' import 'react-dates/initialize' import { DateRangePicker, SingleDatePicker } from 'react-dates' +import { dateFormat } from '../lib/dateHelper' + const fetcher = (path) => fetch(path).then((r) => r.json()) export default function DateSelect() { const [focusedInput, setFocusedInput] = useState(null) - const { state, dispatch } = useContext(WizardContext) + const { state, onChange, onChangeEvent } = useContext(WizardContext) const { data: daysBooked, error: fetchBookedOnError } = useSWR( '/api/daysbooked', fetcher @@ -49,13 +51,10 @@ export default function DateSelect() { checked={multipleDays === false} onChange={() => { setFocusedInput(null) - dispatch({ - type: ACTIONS.SET_FORM_DATA, - payload: { - multipleDays: false, - startDate: null, - endDate: null, - }, + onChange({ + multipleDays: false, + startDate: null, + endDate: null, }) }} /> @@ -68,13 +67,10 @@ export default function DateSelect() { checked={multipleDays === true} onChange={() => { setFocusedInput(null) - dispatch({ - type: ACTIONS.SET_FORM_DATA, - payload: { - multipleDays: true, - startDate: null, - endDate: null, - }, + onChange({ + multipleDays: true, + startDate: null, + endDate: null, }) }} /> @@ -91,11 +87,8 @@ export default function DateSelect() { placeholder="Datum" numberOfMonths={1} onDateChange={(date) => - dispatch({ - type: ACTIONS.SET_FORM_DATA, - payload: { - startDate: date && date.toISOString(), - }, + onChange({ + startDate: date && dateFormat(date), }) } focused={typeof focusedInput === 'boolean' && focusedInput} @@ -115,12 +108,9 @@ export default function DateSelect() { endDate={endDate && moment(endDate)} endDateId="endDate" onDatesChange={({ startDate, endDate }) => { - dispatch({ - type: ACTIONS.SET_FORM_DATA, - payload: { - startDate: startDate && startDate.toISOString(), - endDate: endDate && endDate.toISOString(), - }, + onChange({ + startDate: startDate && dateFormat(startDate), + endDate: endDate && dateFormat(endDate), }) }} focusedInput={focusedInput} diff --git a/components/reason.js b/components/reason.js index 7dad69f..e8c82b7 100644 --- a/components/reason.js +++ b/components/reason.js @@ -4,7 +4,7 @@ import { WizardContext, ACTIONS } from '../context/wizardStore' import Form from 'react-bootstrap/Form' export default function Contact() { - const { state } = useContext(WizardContext) + const { state, onChangeEvent } = useContext(WizardContext) const { purpose, destination, org } = state.formData @@ -14,22 +14,30 @@ export default function Contact() { Zweck der Fahrt Verein - + Ziel der Fahrt diff --git a/components/wizard.js b/components/wizard.js index c6b9fef..1f3ed94 100644 --- a/components/wizard.js +++ b/components/wizard.js @@ -1,4 +1,4 @@ -import { useContext } from 'react' +import { useContext, useRef } from 'react' import Button from 'react-bootstrap/Button' import Form from 'react-bootstrap/Form' @@ -10,50 +10,23 @@ import Reason from './reason' import Contact from './contact' //import Driver from './driver' -const STEPS = [ - { id: 'DATE_SELECT', component: DateSelect }, - { id: 'REASON', component: Reason }, - { id: 'CONTACT', component: Contact }, -] - function WizardInternal() { - const { state, dispatch, onSubmit } = useContext(WizardContext) - const { currentStep } = state - - const isFirstStep = currentStep === 0 - const isLastStep = currentStep === STEPS.length - 1 - - const CurrentStepComponent = STEPS[currentStep].component + const { state, storeBooking } = useContext(WizardContext) + const onChange = (payload) => + dispatch({ action: ACTIONS.SET_FORM_DATA, payload }) return (
{ event.preventDefault() - const fd = new FormData(event.currentTarget) - for (const [key, value] of fd.entries()) { - console.log(key, value) - } - - if (!isLastStep) { - dispatch({ type: ACTIONS.NEXT_STEP }) - return - } - - onSubmit() + storeBooking() }} > - - {!isFirstStep && ( - - )} - {!isLastStep && } - {isLastStep && } + + + + ) } diff --git a/context/wizardStore.js b/context/wizardStore.js index 3a4009c..5fb7297 100644 --- a/context/wizardStore.js +++ b/context/wizardStore.js @@ -3,23 +3,11 @@ import React, { useReducer } from 'react' export const WizardContext = React.createContext() export const ACTIONS = { - NEXT_STEP: 'nextStep', - PREV_STEP: 'prevStep', SET_FORM_DATA: 'setFormData', } function reducer(state, action) { switch (action.type) { - case ACTIONS.NEXT_STEP: - return { - ...state, - currentStep: state.currentStep + 1, // wizards steps unkown here - } - case ACTIONS.PREV_STEP: - return { - ...state, - currentStep: Math.max(0, state.currentStep - 1), - } case ACTIONS.SET_FORM_DATA: return { ...state, @@ -59,27 +47,35 @@ async function createBooking(state) { const initialState = { formData: { - name: 'Thomas Ruoff', - email: 'thomasruoff@gmail.com', multipleDays: null, }, - currentStep: 0, - bookedOn: [ - '2020-07-10', - '2020-07-11', - '2020-07-12', - '2020-07-23', - '2020-08-01', - ], } export default function WizardStore({ children }) { const [state, dispatch] = useReducer(debugReducer, initialState) - const onSubmit = () => createBooking(state) + const storeBooking = () => createBooking(state) + + 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, + }) + } return ( - + {children} ) diff --git a/db/index.js b/db/index.js index fe0b871..cddc493 100644 --- a/db/index.js +++ b/db/index.js @@ -34,16 +34,15 @@ export async function getBookedDays() { } export async function createBooking({ name, email, startDate, endDate }) { - const booker = new Booker({ name, email }) - await booker.save() + const ignoreCaseEmailMatcher = new RegExp(email, 'i') + let booker = await Booker.findOne({ email: ignoreCaseEmailMatcher }).exec() + if (!booker) { + booker = new Booker({ name, email }) + await booker.save() + } + const booking = new Booking({ startDate, endDate, booker: booker._id }) await booking.save() - return { - booker: booking.booker._id, - startDate: booking.startDate, - endDate: booking.endDate, - bookedDate: booking.bookedDate, - confirmed: booking.confirmed, - confirmedDate: booking.confimredDate, - } + await booking.populate('booker').execPopulate() + return booking.toJSON({ getters: true, virtuals: true }) } diff --git a/db/schema.js b/db/schema.js index 0a250da..c248582 100644 --- a/db/schema.js +++ b/db/schema.js @@ -1,18 +1,34 @@ import { Schema } from 'mongoose' -export const BookerSchema = new Schema({ - name: { type: String, required: true }, - email: { type: String, required: true }, -}) +import { getDays, dateFormat } from '../lib/dateHelper' -export const BookingSchema = new Schema({ - booker: { type: Schema.Types.ObjectId, ref: 'Booker', required: true }, - startDate: { type: Date, required: true }, - endDate: { type: Date, required: false }, - status: { - type: String, - enum: ['requested', 'confirmed', 'rejected'], - required: true, - default: 'requested', +export const BookerSchema = new Schema( + { + name: { type: String, required: true }, + email: { type: String, required: true, unique: true }, }, + { timestamps: true } +) + +export const BookingSchema = new Schema( + { + booker: { type: Schema.Types.ObjectId, ref: 'Booker', required: true }, + startDate: { + type: Date, + required: true, + get: dateFormat, + }, + endDate: { type: Date, required: false, get: dateFormat }, + status: { + type: String, + enum: ['requested', 'confirmed', 'rejected'], + required: true, + default: 'requested', + }, + }, + { timestamps: true } +) + +BookingSchema.virtual('days').get(function () { + return getDays({ startDate: this.startDate, endDate: this.endDate }) })