More progress
This commit is contained in:
parent
3d8c60ee00
commit
de88224b30
19 changed files with 1249 additions and 61 deletions
|
@ -16,6 +16,7 @@ module.exports = {
|
||||||
"warn",
|
"warn",
|
||||||
{ allowConstantExport: true }
|
{ allowConstantExport: true }
|
||||||
],
|
],
|
||||||
"react/prop-types": ["off"]
|
"react/prop-types": ["off"],
|
||||||
|
"no-unused-vars": ["warn"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
package.json
11
package.json
|
@ -7,15 +7,18 @@
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"test": "jest",
|
"test": "vitest",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "^6.14.2"
|
"react-router-dom": "6.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@vitejs/plugin-react": "^4.0.3",
|
"@vitejs/plugin-react": "^4.0.3",
|
||||||
|
@ -23,6 +26,8 @@
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.3",
|
"eslint-plugin-react-refresh": "^0.4.3",
|
||||||
"vite": "^4.4.5"
|
"jsdom": "^22.1.0",
|
||||||
|
"vite": "^4.4.5",
|
||||||
|
"vitest": "^0.33.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1094
pnpm-lock.yaml
generated
1094
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
BIN
public/images/Chef2.jpg
Normal file
BIN
public/images/Chef2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
11
src/App.jsx
Normal file
11
src/App.jsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { Footer } from "./components/Footer"
|
||||||
|
import { Header } from "./components/Header"
|
||||||
|
import { Main } from "./components/Main"
|
||||||
|
|
||||||
|
export const App = () => (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<Main />
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
)
|
10
src/App.test.jsx
Normal file
10
src/App.test.jsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { render, screen } from "@testing-library/react"
|
||||||
|
import { describe, expect } from "vitest"
|
||||||
|
import { BookingForm } from "./components/BookingForm.jsx"
|
||||||
|
|
||||||
|
describe("Renders the BookingForm heading", () => {
|
||||||
|
const availableTimes = ["17:00"]
|
||||||
|
render(<BookingForm availableTimes={availableTimes} />)
|
||||||
|
const headingElement = screen.getByText("Choose date")
|
||||||
|
expect(headingElement).toBeInTheDocument()
|
||||||
|
})
|
21
src/components/About.jsx
Normal file
21
src/components/About.jsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import "../styles/About.css"
|
||||||
|
|
||||||
|
export const About = () => (
|
||||||
|
<section className="about row">
|
||||||
|
<article>
|
||||||
|
<h2>Little Lemon</h2>
|
||||||
|
<p>
|
||||||
|
Little Lemon was opened in 1995 by two Italian brothers, Adrian
|
||||||
|
and Mario. The brothers saw the opportunity for a great
|
||||||
|
Mediterranean restaurant, and were inspired to bring the flavors
|
||||||
|
of their hometown in Italy to the people of Chicago. The two
|
||||||
|
brothers continue to oversee the Little Lemon restaurant even
|
||||||
|
now, nearly thirty years later.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
<section>
|
||||||
|
<img src="/images/Chef.jpg" alt="Mario" />{" "}
|
||||||
|
<img src="/images/Chef2.jpg" alt="Adrian" />
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
)
|
|
@ -1,16 +1,8 @@
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import "../styles/BookingForm.css"
|
import "../styles/BookingForm.css"
|
||||||
|
|
||||||
export const BookingForm = () => {
|
export const BookingForm = ({ availableTimes, dispatch }) => {
|
||||||
const [date, setDate] = useState(new Date().toISOString().slice(0, 10))
|
const [date, setDate] = useState(new Date().toISOString().slice(0, 10))
|
||||||
const [availableTimes] = useState([
|
|
||||||
"17:00",
|
|
||||||
"18:00",
|
|
||||||
"19:00",
|
|
||||||
"20:00",
|
|
||||||
"21:00",
|
|
||||||
"22:00"
|
|
||||||
])
|
|
||||||
const [time, setTime] = useState(availableTimes[0])
|
const [time, setTime] = useState(availableTimes[0])
|
||||||
const [guests, setGuests] = useState(1)
|
const [guests, setGuests] = useState(1)
|
||||||
const [occasion, setOccasion] = useState("None")
|
const [occasion, setOccasion] = useState("None")
|
||||||
|
@ -26,16 +18,21 @@ export const BookingForm = () => {
|
||||||
<label htmlFor="res-date">Choose date</label>
|
<label htmlFor="res-date">Choose date</label>
|
||||||
<input
|
<input
|
||||||
value={date}
|
value={date}
|
||||||
onChange={(event) => setDate(event.target.value)}
|
required
|
||||||
|
onChange={(event) => {
|
||||||
|
setDate(event.target.value)
|
||||||
|
dispatch(event.target.value)
|
||||||
|
}}
|
||||||
type="date"
|
type="date"
|
||||||
id="res-date"
|
id="res-date"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<label htmlFor="res-time">Choose time</label>
|
<label htmlFor="time">Choose time</label>
|
||||||
<select
|
<select
|
||||||
value={time}
|
value={time}
|
||||||
|
required
|
||||||
onChange={(event) => setTime(event.target.value)}
|
onChange={(event) => setTime(event.target.value)}
|
||||||
id="res-time"
|
id="time"
|
||||||
>
|
>
|
||||||
{availableTimes.map((time) => (
|
{availableTimes.map((time) => (
|
||||||
<option key={time}>{time}</option>
|
<option key={time}>{time}</option>
|
||||||
|
@ -45,6 +42,7 @@ export const BookingForm = () => {
|
||||||
<label htmlFor="guests">Number of guests</label>
|
<label htmlFor="guests">Number of guests</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
|
required
|
||||||
min="1"
|
min="1"
|
||||||
max="10"
|
max="10"
|
||||||
id="guests"
|
id="guests"
|
||||||
|
@ -66,7 +64,7 @@ export const BookingForm = () => {
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className="submit"
|
className="submit"
|
||||||
value="Make Your reservation"
|
value="Confirm reservation"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const Footer = () => (
|
||||||
<a href="#">Home</a>
|
<a href="#">Home</a>
|
||||||
<a href="#">About</a>
|
<a href="#">About</a>
|
||||||
<a href="#">Menu</a>
|
<a href="#">Menu</a>
|
||||||
<Link to="/book">Reservations</Link>
|
<Link to="/book">Reserve a table</Link>
|
||||||
<a href="#">Order Online</a>
|
<a href="#">Order Online</a>
|
||||||
<a href="#">Login</a>
|
<a href="#">Login</a>
|
||||||
</section>
|
</section>
|
||||||
|
|
45
src/components/Main.jsx
Normal file
45
src/components/Main.jsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
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"
|
||||||
|
|
||||||
|
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 [availableTimes, dispatch] = useReducer(
|
||||||
|
updateTimes,
|
||||||
|
initializeTimes()
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<main>
|
||||||
|
<Routes>
|
||||||
|
<Route index element={<HomePage />} />
|
||||||
|
<Route
|
||||||
|
path="/book"
|
||||||
|
element={
|
||||||
|
<BookingPage
|
||||||
|
availableTimes={availableTimes}
|
||||||
|
dispatch={dispatch}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ const Star = () => (
|
||||||
height="24"
|
height="24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
|
aria-label="Star"
|
||||||
>
|
>
|
||||||
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z" />
|
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
@ -27,10 +27,10 @@ a {
|
||||||
|
|
||||||
main {
|
main {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: auto;
|
|
||||||
color: white;
|
color: white;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
|
24
src/main.jsx
24
src/main.jsx
|
@ -1,27 +1,13 @@
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import ReactDOM from "react-dom/client"
|
import ReactDOM from "react-dom/client"
|
||||||
import { Root } from "./routes/Root.jsx"
|
import { BrowserRouter } from "react-router-dom"
|
||||||
import {
|
import { App } from "./App"
|
||||||
createBrowserRouter,
|
|
||||||
RouterProvider,
|
|
||||||
Route,
|
|
||||||
createRoutesFromElements
|
|
||||||
} from "react-router-dom"
|
|
||||||
import { HomePage } from "./routes/HomePage"
|
|
||||||
import { BookingPage } from "./routes/BookingPage"
|
|
||||||
|
|
||||||
const router = createBrowserRouter(
|
|
||||||
createRoutesFromElements(
|
|
||||||
<Route path="/" element={<Root />}>
|
|
||||||
<Route path="/" element={<HomePage />} />
|
|
||||||
<Route path="/book" element={<BookingPage />} />
|
|
||||||
</Route>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<RouterProvider router={router} />
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { BookingForm } from "../components/BookingForm"
|
import { BookingForm } from "../components/BookingForm"
|
||||||
import "../styles/BookingPage.css"
|
import "../styles/BookingPage.css"
|
||||||
|
|
||||||
export const BookingPage = () => (
|
export const BookingPage = ({ availableTimes, dispatch }) => (
|
||||||
<section className="booking">
|
<section className="booking">
|
||||||
<h1>Book a Table</h1>
|
<h1>Book a Table</h1>
|
||||||
<hr />
|
<hr />
|
||||||
<BookingForm />
|
<BookingForm availableTimes={availableTimes} dispatch={dispatch} />
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { About } from "../components/About"
|
||||||
import { Jumbo } from "../components/Jumbo"
|
import { Jumbo } from "../components/Jumbo"
|
||||||
import { Specials } from "../components/Specials"
|
import { Specials } from "../components/Specials"
|
||||||
import { Testimonials } from "../components/Testimonials"
|
import { Testimonials } from "../components/Testimonials"
|
||||||
|
@ -7,5 +8,6 @@ export const HomePage = () => (
|
||||||
<Jumbo />
|
<Jumbo />
|
||||||
<Specials />
|
<Specials />
|
||||||
<Testimonials />
|
<Testimonials />
|
||||||
|
<About />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
34
src/styles/About.css
Normal file
34
src/styles/About.css
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
.about {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
color: black;
|
||||||
|
position: relative;
|
||||||
|
height: 18rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about h2 {
|
||||||
|
font-size: 3rem;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--primary-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.about article {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about img {
|
||||||
|
height: 15rem;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about img:first-child {
|
||||||
|
top: 0;
|
||||||
|
right: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about img {
|
||||||
|
top: 2rem;
|
||||||
|
right: 10rem;
|
||||||
|
}
|
|
@ -5,8 +5,9 @@
|
||||||
background-color: #495e57;
|
background-color: #495e57;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
height: 100%;
|
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
width: 70%;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.booking h1 {
|
.booking h1 {
|
||||||
|
|
8
tests/setup.js
Normal file
8
tests/setup.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { expect, afterEach } from "vitest"
|
||||||
|
import { cleanup } from "@testing-library/react"
|
||||||
|
import matchers from "@testing-library/jest-dom/matchers"
|
||||||
|
|
||||||
|
expect.extend(matchers)
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup()
|
||||||
|
})
|
|
@ -1,7 +1,12 @@
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from "vite"
|
||||||
import react from '@vitejs/plugin-react'
|
import react from "@vitejs/plugin-react"
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: "jsdom",
|
||||||
|
setupFiles: "./tests/setup.js"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
Reference in a new issue