From 518b437d14792db3076c4e6295240c5a7ba730ae Mon Sep 17 00:00:00 2001 From: Thomas Ruoff Date: Sun, 26 Jul 2020 00:12:51 +0200 Subject: [PATCH] more hacking --- components/contact.js | 16 ++++--------- components/dateSelect.js | 13 ++++------- components/reason.js | 28 +++++++++++++++++++++++ components/wizard.js | 8 ++++--- context/wizardStore.js | 20 ++++------------ db/index.js | 49 ++++++++++++++++++++++++++++++++++++++++ db/schema.js | 18 +++++++++++++++ lib/dateHelper.js | 18 +++++++++++++++ pages/_app.js | 4 ++-- pages/api/booked.js | 12 ---------- pages/api/booking.js | 14 ++++++++++++ pages/api/daysbooked.js | 18 +++++++++++++++ pages/index.js | 2 -- 13 files changed, 166 insertions(+), 54 deletions(-) create mode 100644 components/reason.js create mode 100644 db/index.js create mode 100644 db/schema.js create mode 100644 lib/dateHelper.js delete mode 100644 pages/api/booked.js create mode 100644 pages/api/booking.js create mode 100644 pages/api/daysbooked.js 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'