diff --git a/components/contact.js b/components/contact.js
index b64a2c9..1e2d95f 100644
--- a/components/contact.js
+++ b/components/contact.js
@@ -15,6 +15,10 @@ export default function Contact() {
Name
+
+ E-Mail
+
+
Straße
@@ -29,18 +33,6 @@ export default function Contact() {
-
- Verein
-
-
-
- Zweck der Fahrt
-
-
-
- Ziel der Fahrt
-
-
>
)
}
diff --git a/components/dateSelect.js b/components/dateSelect.js
index 40bde0f..a56edec 100644
--- a/components/dateSelect.js
+++ b/components/dateSelect.js
@@ -13,8 +13,8 @@ const fetcher = (path) => fetch(path).then((r) => r.json())
export default function DateSelect() {
const { state, dispatch } = useContext(WizardContext)
- const { data: bookedOn, error: fetchBookedOnError } = useSWR(
- '/api/booked',
+ const { data: daysBooked, error: fetchBookedOnError } = useSWR(
+ '/api/daysbooked',
fetcher
)
@@ -29,18 +29,15 @@ export default function DateSelect() {
function isDayBlocked(momentDay) {
return (
- bookedOn && bookedOn.some((rawDay) => momentDay.isSame(rawDay, 'day'))
+ daysBooked && daysBooked.some((rawDay) => momentDay.isSame(rawDay, 'day'))
)
}
- if (!bookedOn) {
- return Lade Buchungen...
- }
-
if (fetchBookedOnError) {
return (
- Entschuldige, aber die Buchungszeiten konnten nicht geladen werden
+ Entschuldige, aber die Buchungszeiten konnten nicht geladen werden.
+ Versuchen Sie es später nochmals.
)
}
diff --git a/components/reason.js b/components/reason.js
new file mode 100644
index 0000000..a9f8d2a
--- /dev/null
+++ b/components/reason.js
@@ -0,0 +1,28 @@
+import { useContext } from 'react'
+import { WizardContext, ACTIONS } from '../context/wizardStore'
+
+import Form from 'react-bootstrap/Form'
+import Col from 'react-bootstrap/Col'
+
+export default function Contact() {
+ const { state, dispatch } = useContext(WizardContext)
+
+ const { multipleDays, startDate, endDate } = state
+
+ return (
+ <>
+
+ Zweck der Fahrt
+
+
+
+ Verein
+
+
+
+ Ziel der Fahrt
+
+
+ >
+ )
+}
diff --git a/components/wizard.js b/components/wizard.js
index e4622e5..325927d 100644
--- a/components/wizard.js
+++ b/components/wizard.js
@@ -6,16 +6,18 @@ import Form from 'react-bootstrap/Form'
import WizardStore, { WizardContext, ACTIONS } from '../context/wizardStore'
import DateSelect from './dateSelect'
+import Reason from './reason'
import Contact from './contact'
-import Driver from './driver'
+//import Driver from './driver'
const STEPS = [
{ id: 'DATE_SELECT', component: DateSelect },
+ { id: 'REASON', component: Reason },
{ id: 'CONTACT', component: Contact },
]
function WizardInternal() {
- const { state, dispatch } = useContext(WizardContext)
+ const { state, dispatch, onSubmit } = useContext(WizardContext)
const { currentStep } = state
const isFirstStep = currentStep === 0
@@ -36,7 +38,7 @@ function WizardInternal() {
return
}
- dispatch({ type: ACTIONS.SUBMIT })
+ onSubmit()
}}
>
{STEPS.map(({ id, component: Component }, index) => (
diff --git a/context/wizardStore.js b/context/wizardStore.js
index eef6b5a..2da9b01 100644
--- a/context/wizardStore.js
+++ b/context/wizardStore.js
@@ -1,7 +1,5 @@
import React, { useReducer } from 'react'
-import { getDays } from '../lib/dateHelper'
-
export const WizardContext = React.createContext()
export const ACTIONS = {
@@ -12,7 +10,6 @@ export const ACTIONS = {
SET_FOCUSED_INPUT: 'setFocusedInput',
SET_PICKUP_TIME: 'setPickupTime',
SET_DROPOFF_TIME: 'setDropoffTime',
- SUBMIT: 'submit',
}
function reducer(state, action) {
@@ -41,11 +38,6 @@ function reducer(state, action) {
...state,
startDate: action.payload.startDate,
endDate: action.payload.endDate,
- days: getDays({
- startDate: action.payload.startDate || state.startDate,
- endDate: action.payload.endDate || state.endDate,
- multipleDays: state.multipleDays,
- }),
}
case ACTIONS.SET_FOCUSED_INPUT:
return { ...state, focusedInput: action.payload }
@@ -53,10 +45,6 @@ function reducer(state, action) {
return { ...state, pickupTime: action.payload }
case ACTIONS.SET_DROPOFF_TIME:
return { ...state, dropoffTime: action.payload }
- case ACTIONS.SUBMIT:
- // TODO: should probably not kick this off here, that sucks
- createBooking(state)
- return { ...state }
default:
throw new Error(`Unkown Action type ${action.type}`)
}
@@ -70,7 +58,7 @@ function debugReducer(state, action) {
}
async function createBooking(state) {
- const { name, email, days } = state
+ const { name, email, startDate, endDate } = state
const response = await fetch('/api/booking', {
method: 'POST',
mode: 'cors',
@@ -80,7 +68,7 @@ async function createBooking(state) {
'Content-Type': 'application/json',
},
referrerPolicy: 'no-referrer',
- body: JSON.stringify({ name, email, days }),
+ body: JSON.stringify({ name, email, startDate, endDate }),
})
return response.json()
@@ -103,8 +91,10 @@ const initialState = {
export default function WizardStore({ children }) {
const [state, dispatch] = useReducer(debugReducer, initialState)
+ const onSubmit = () => createBooking(state)
+
return (
-
+
{children}
)
diff --git a/db/index.js b/db/index.js
new file mode 100644
index 0000000..fe0b871
--- /dev/null
+++ b/db/index.js
@@ -0,0 +1,49 @@
+import mongoose from 'mongoose'
+import { BookingSchema, BookerSchema } from './schema'
+import { getDays } from '../lib/dateHelper'
+
+mongoose.connect(process.env.MONGO_URI, {
+ useNewUrlParser: true,
+ useUnifiedTopology: true,
+ connectTimeoutMS: 1000,
+ serverSelectionTimeoutMS: 5000,
+})
+
+if (process.env.NODE_ENV !== 'production') {
+ mongoose.modelNames().includes('Booker') && mongoose.deleteModel('Booker')
+ mongoose.modelNames().includes('Booking') && mongoose.deleteModel('Booking')
+}
+
+export const Booker = mongoose.model('Booker', BookerSchema)
+export const Booking = mongoose.model('Booking', BookingSchema)
+
+export async function getBookedDays() {
+ const bookings = await Booking.find({
+ status: { $ne: 'rejected' },
+ $or: [{ endDate: { $gt: new Date() } }, { startDate: { $gt: new Date() } }],
+ }).exec()
+
+ return bookings
+ .reduce((acc, booking) => {
+ acc.push(
+ getDays({ startDate: booking.startDate, endDate: booking.endDate })
+ )
+ return acc
+ }, [])
+ .flat()
+}
+
+export async function createBooking({ name, email, startDate, endDate }) {
+ const 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,
+ }
+}
diff --git a/db/schema.js b/db/schema.js
new file mode 100644
index 0000000..0a250da
--- /dev/null
+++ b/db/schema.js
@@ -0,0 +1,18 @@
+import { Schema } from 'mongoose'
+
+export const BookerSchema = new Schema({
+ name: { type: String, required: true },
+ email: { type: String, required: true },
+})
+
+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',
+ },
+})
diff --git a/lib/dateHelper.js b/lib/dateHelper.js
new file mode 100644
index 0000000..f4fcf2d
--- /dev/null
+++ b/lib/dateHelper.js
@@ -0,0 +1,18 @@
+import moment from 'moment'
+
+export function getDays({ startDate, endDate }) {
+ let currentDay = moment(startDate)
+ const days = [currentDay.format('YYYY-MM-DD')]
+
+ if (!endDate) {
+ return days
+ }
+
+ const end = moment(endDate)
+ while (currentDay < end) {
+ currentDay = currentDay.add(1, 'day')
+ days.push(currentDay.format('YYYY-MM-DD'))
+ }
+
+ return days
+}
diff --git a/pages/_app.js b/pages/_app.js
index 33f5150..6958b1a 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -1,8 +1,8 @@
import 'bootstrap/dist/css/bootstrap.min.css'
import 'react-dates/lib/css/_datepicker.css'
-import moment from 'moment'
-import deLocale from 'moment/locale/de'
+import 'moment'
+import 'moment/locale/de'
export default function MyApp({ Component, pageProps }) {
return
diff --git a/pages/api/booked.js b/pages/api/booked.js
deleted file mode 100644
index e9d374c..0000000
--- a/pages/api/booked.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-
-import { getAllBookings } from './db/index'
-
-export default async (req, res) => {
- const bookings = await getAllBookings()
-
- console.log(bookings)
-
- res.statusCode = 200
- res.json(['2020-07-23', '2020-07-24', '2020-07-25', '2020-08-01'])
-}
diff --git a/pages/api/booking.js b/pages/api/booking.js
new file mode 100644
index 0000000..81bd209
--- /dev/null
+++ b/pages/api/booking.js
@@ -0,0 +1,14 @@
+import { createBooking } from '../../db/index'
+export default async function userHandler(req, res) {
+ const { method } = req
+
+ switch (method) {
+ case 'POST':
+ const data = await createBooking(req.body)
+ res.status(200).json(data)
+ break
+ default:
+ res.setHeader('Allow', ['POST'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
diff --git a/pages/api/daysbooked.js b/pages/api/daysbooked.js
new file mode 100644
index 0000000..71e5e1e
--- /dev/null
+++ b/pages/api/daysbooked.js
@@ -0,0 +1,18 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+import { getBookedDays } from '../../db/index'
+
+export default async function useHandler(req, res) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ const days = await getBookedDays()
+ res.statusCode = 200
+ res.json(days)
+ break
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
diff --git a/pages/index.js b/pages/index.js
index 0cbb53a..633b83e 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,5 +1,3 @@
-import { useContext } from 'react'
-
import Head from 'next/head'
import Wizard from '../components/wizard'