diff --git a/src/App.test.jsx b/src/App.test.jsx
index 76119ee..1fca331 100644
--- a/src/App.test.jsx
+++ b/src/App.test.jsx
@@ -1,10 +1,21 @@
import { render, screen } from "@testing-library/react"
-import { describe, expect } from "vitest"
-import { BookingForm } from "./components/BookingForm.jsx"
+import { BookingForm } from "./components/BookingForm"
+import "@testing-library/jest-dom"
+import { initializeTimes, updateTimes } from "./components/Main"
-describe("Renders the BookingForm heading", () => {
+test("Renders the BookingForm heading", () => {
const availableTimes = ["17:00"]
render()
const headingElement = screen.getByText("Choose date")
expect(headingElement).toBeInTheDocument()
})
+
+test("Returns a correct array of times", () => {
+ expect(initializeTimes()).toHaveLength(6)
+ expect(initializeTimes()[0]).toMatch(/\d{2}:\d{2}/)
+})
+
+test("Returns the same value provided in the state", () => {
+ const times = initializeTimes()
+ expect(updateTimes(times, "2022-02-04")).toBe(times)
+})
diff --git a/src/components/BookingForm.jsx b/src/components/BookingForm.jsx
index 60eddf3..c6c12d6 100644
--- a/src/components/BookingForm.jsx
+++ b/src/components/BookingForm.jsx
@@ -1,43 +1,84 @@
import { useState } from "react"
import "../styles/BookingForm.css"
-export const BookingForm = ({ availableTimes, dispatch }) => {
+export const BookingForm = ({
+ availableTimes,
+ dispatch,
+ submitForm,
+ reservationError
+}) => {
const [date, setDate] = useState(new Date().toISOString().slice(0, 10))
const [time, setTime] = useState(availableTimes[0])
const [guests, setGuests] = useState(1)
- const [occasion, setOccasion] = useState("None")
+ const [occasion, setOccasion] = useState("Other")
+
+ const [dateError, setDateError] = useState("")
+ const [timeError, setTimeError] = useState("")
+ const [guestsError, setGuestsError] = useState("")
+ const [occasionError, setOccasionError] = useState("")
+
+ const isFormInvalid = () =>
+ guestsError !== "" ||
+ dateError !== "" ||
+ timeError !== "" ||
+ occasionError !== ""
+
+ const onDateChange = ({ target }) => {
+ let error = ""
+ if (target.value === "") error = "Field is required"
+ setDateError(error)
+ setDate(target.value)
+ if (!error) dispatch(target.valueAsDate)
+ }
+
+ const onTimeChange = ({ target }) => {
+ let error = ""
+ if (target.value === "") error = "Field is required"
+ setTimeError(error)
+ setTime(target.value)
+ }
+
+ const onGuestChange = ({ target }) => {
+ let error = ""
+ if (target.value === "") error = "Field is required"
+ else if (target.value < 1 || target.value > 10)
+ error = "Guests must be between 1 and 10."
+ setGuestsError(error)
+ setGuests(target.value)
+ }
+
+ const onOccasionChange = ({ target }) => {
+ let error = ""
+ if (target.value === "") error = "Field is required"
+ else if (
+ target.value !== "Other" &&
+ target.value !== "Birthday" &&
+ target.value !== "Anniversary"
+ )
+ error = "Invalid occasion."
+ setOccasionError(error)
+ setOccasion(target.value)
+ }
return (
-
)
}
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
index d58ddbf..4df41ba 100644
--- a/src/components/Footer.jsx
+++ b/src/components/Footer.jsx
@@ -6,24 +6,24 @@ export const Footer = () => (
)
diff --git a/src/components/Main.jsx b/src/components/Main.jsx
index 3277d72..0c0d0d3 100644
--- a/src/components/Main.jsx
+++ b/src/components/Main.jsx
@@ -2,39 +2,65 @@ import { Route } from "react-router-dom"
import { Routes } from "react-router-dom"
import { HomePage } from "../routes/HomePage"
import { BookingPage } from "../routes/BookingPage"
-import { useReducer } from "react"
+import { useReducer, useState } from "react"
+import { ConfirmedBookingPage } from "../routes/ConfirmedBookingPage"
+import { useNavigate } from "react-router-dom"
+
+export const initializeTimes = () => [
+ "17:00",
+ "18:00",
+ "19:00",
+ "20:00",
+ "21:00",
+ "22:00"
+]
+
+export const updateTimes = (_, date) => {
+ // API provided returns 404, so unable to post data. Mocking return instead.
+ const day = date.getDay()
+ const initialTimes = initializeTimes()
+ if (day === 0) return initialTimes.slice(0, 3)
+ if (day === 1) return initialTimes.slice(2, 5)
+ if (day === 2) return initialTimes.slice(4, 5)
+ if (day === 3) return initialTimes.slice(3, 5)
+ if (day === 4) return initialTimes.slice(1, 5)
+ if (day === 5) return initialTimes.slice(3, 3)
+ if (day === 6) return initialTimes.slice(1, 5)
+}
export const Main = () => {
- const initializeTimes = () => [
- "17:00",
- "18:00",
- "19:00",
- "20:00",
- "21:00",
- "22:00"
- ]
-
- const updateTimes = (times, date) => {
- console.log(times, date)
- return times
- }
-
+ const navigate = useNavigate()
const [availableTimes, dispatch] = useReducer(
updateTimes,
initializeTimes()
)
+ const [reservationError, setReservationError] = useState("")
+
+ const submitForm = (event) => {
+ event.preventDefault()
+ // API provided returns 404, so unable to post data. Mocking return instead.
+ if (Math.random() > 0.8)
+ setReservationError("Unable to book reservation. Please try again.")
+ else navigate("/confirmed")
+ }
return (
<>
} />
+ }
+ />
}
/>
diff --git a/src/components/Special.jsx b/src/components/Special.jsx
index a87fb4f..700b801 100644
--- a/src/components/Special.jsx
+++ b/src/components/Special.jsx
@@ -3,7 +3,7 @@ import "../styles/Special.css"
export const Special = ({ image, title, price, children }) => (
-
+
{title}
diff --git a/src/routes/BookingPage.jsx b/src/routes/BookingPage.jsx
index 2f95efc..515e37f 100644
--- a/src/routes/BookingPage.jsx
+++ b/src/routes/BookingPage.jsx
@@ -1,10 +1,20 @@
import { BookingForm } from "../components/BookingForm"
import "../styles/BookingPage.css"
-export const BookingPage = ({ availableTimes, dispatch }) => (
+export const BookingPage = ({
+ availableTimes,
+ dispatch,
+ submitForm,
+ reservationError
+}) => (
)
diff --git a/src/routes/ConfirmedBookingPage.jsx b/src/routes/ConfirmedBookingPage.jsx
new file mode 100644
index 0000000..5096a06
--- /dev/null
+++ b/src/routes/ConfirmedBookingPage.jsx
@@ -0,0 +1,10 @@
+import { Link } from "react-router-dom"
+import "../styles/ConfirmedBookingPage.css"
+
+export const ConfirmedBookingPage = () => (
+
+ Booking Confirmed
+ Your booking has been confirmed.
+ Back to home
+
+)
diff --git a/src/styles/BookingForm.css b/src/styles/BookingForm.css
index 8f194bb..82580f7 100644
--- a/src/styles/BookingForm.css
+++ b/src/styles/BookingForm.css
@@ -2,6 +2,7 @@
display: flex;
flex-direction: column;
gap: 0.2rem;
+ min-width: 20rem;
}
.booking-form :is(label, .submit) {
@@ -19,3 +20,9 @@
.booking-form .submit {
background-color: #fbdabb;
}
+
+.booking-form .error {
+ color: rgb(255, 152, 152);
+ font-weight: bold;
+ margin: 0.5rem 0;
+}
diff --git a/src/styles/ConfirmedBookingPage.css b/src/styles/ConfirmedBookingPage.css
new file mode 100644
index 0000000..eb1e3d7
--- /dev/null
+++ b/src/styles/ConfirmedBookingPage.css
@@ -0,0 +1,7 @@
+.confirmed {
+ background-color: var(--primary-1);
+ border-radius: 2rem;
+ margin: auto;
+ padding: 2rem 3rem;
+ text-align: center;
+}