Skip to content
This repository was archived by the owner on Feb 9, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 0 additions & 133 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,136 +1,3 @@
A hotel booking application in React. Homework for the [CodeYourFuture React module](https://codeyourfuture.github.io/syllabus-master/react/)

![Bookings Search page](Bookings.png)

# Installation

1. Follow [the instructions](https://codeyourfuture.github.io/syllabus-master/others/making-a-pull-request.html#how-to-fork-a-github-repo) to fork & clone the GitHub repo
2. Install the dependencies by running `npm install`
3. Launch the server using `npm start`
4. It should automatically open `http://localhost:3000/` in your browser

# Exercises

## Lesson 1

#### 1. Extract the search button in its own component

**Instructions:** Extract the search `<button>` from the `src/Search.js` file to be its own separate component. You can name it `SearchButton`. Import and use this new component in `src/Search.js`.

**Test:** The search button should still render on the page.

#### 2. Extract the header in its own component

**Instructions:** Extract the `<header>` from the `src/App.js` file to be its own separate component called `Heading`. Make sure that you import and render the `<Heading />` component within `src/App.js`. In the `Heading` component, render the hotel's logo in an `<img>` (you can use `https://image.flaticon.com/icons/svg/139/139899.svg` or find your own image URL). You can adjust the CSS by editing `src/App.css` to make your Heading looks better if necessary.

**Test:** The header should be displayed with a logo on the page.

#### 3. Create and use a new component to show info cards

**Instructions:** In `src/App.js`, above the `<Bookings />` component add a new component called `TouristInfoCards` which shows 3 _cards_. A card is a common user interface pattern with an image at the top and some related text underneath. The cards must link to `peoplemakeglasgow.com`, `visitmanchester.com` and `visitlondon.com`. The cards should contain the name of the city and an image of the city. Here is an example of what an info card should look like:

![Info Card](InfoCard.png)

**Hint:** Use the same className as the example below to benefit from [Bootstrap](https://getbootstrap.com/docs/4.2/components/card) library which is already imported for you in the project. Use the JSX code below as an example of one card (note that in JSX, you'll need to use `className` instead of `class`):

```
<div className="card">
<img src="..." className="card-img-top" />
<div className="card-body">
<a href="#" className="btn btn-primary">Go somewhere</a>
</div>
</div>
```

**Test:** 3 info cards should be displayed on the page for each city (Glasgow, Manchester, London). Each card should link to the correct website.

#### 4. Create a Footer component

**Instructions:** Create a `<Footer />` component which should be rendered at the bottom of the page. Pass the following array as a prop to this component: `["123 Fake Street, London, E1 4UD", "hello@fakehotel.com", "0123 456789"]`. Inside the component, use the data you passed as a prop to render a `<ul>` list with each item of the array displayed as a `<li>`.

**Hint:** The `.map()` method will by useful.

**Test:** The footer should render at the bottom of the page with each address property displayed as a list item.

#### 5. Create a table to show hotel bookings

**Instructions:** Create a `<SearchResults />` component that shows hotel bookings in a `<table>` element. Each booking will have an `id`, `title`, `first name`, `surname`, `email`, `room id`, `check in date` and `check out date`. You can make up data in the `<SearchResults />` component to show in the table. Then show `<SearchResults />` component within the `<Bookings />` component that is provided. Be sure to split out your components into small well-named components, similar to the method used in exercise 1.

**Hint:** You will find some useful `<table>` examples in the [Bootstrap documentation for tables](https://getbootstrap.com/docs/4.2/content/tables/#examples).

**Test:** A table should render with a column for each booking attribute. The table can show more than one booking. The bookings that are displayed can be made up and hardcoded for now.

#### 6. Show more bookings in the table

**Instructions:** Instead of using your hard-coded data in the `<SearchResults />` component, load data from the `src/data/fakeBookings.json` file in the `<Bookings />` component and pass it as a prop to `<SearchResults />`. All the bookings in `src/data/fakeBookings.json` should now be displayed in your table.

**Hint:** Look in the `<Bookings />` component for how to import data from a JSON file.

**Test:** All the bookings in the file `src/data/fakeBookings.json` should be displayed in your table.

#### 7. Calculate and show the number of nights for each booking

**Instructions:** Add another column to your `<SearchResults />` table which shows the number of nights a guest is staying.

**Hint:** Try installing the [moment.js library](http://momentjs.com/) (you'll need to install it with `npm install moment --save`) and using the [`.diff()` method](http://momentjs.com/docs/#/displaying/difference/) to compare dates.

**Test:** Each booking in your table should show the number of nights in a separate column. For example, Mr John Doe has a booking for **2** nights.

## Lesson 2

#### 8. Render the Restaurant component

**Instructions:** Within the `src/App.js` file, render the `<Restaurant />` component (that is provided for you in `src/Restaurant.js`) underneath the `<Bookings />` component.

**Test:** The restaurant orders should render on the page.

#### 9. Preparing to add more pizzas

**Instructions:** At the moment, the number of pizzas a guest can order is static and set to 0, even if they click on the 'Add' button. We will change that in the following to let a guest add more pizzas to their order. First, declare a new state variable `orders` along with the function to set the orders state `setOrders`. The initial value of the `orders` state should be **0**. Use the new `orders` variable instead of the `pizzas` variable (that you can now delete).

**Hint:** You need to use the React function `useState` to create a state variable. Remember to import the function at the top with `import React, {useState} from "react";`.

**Test:** Verify the number of ordered pizzas it still **0** on the screen.

#### 10. Add more pizzas

**Instructions:** In the `<Restaurant />` component, create a new function named `orderOne`. The `orderOne` function doesn't take any parameters and should use the `setOrders` function to increment the `orders` state variable by 1. Then, add a `onClick` handler to the Add `<button>` that calls the `orderOne` function when it's being clicked.

**Test:** Try to click on the Add button a few times and verify that the number of pizzas increases accordingly.

#### 11. Extract the Add button to its own component

**Instructions:** Extract the `<button>` currently in the `<Restaurant />` component to a new component named `RestaurantButton`. Pass the `orderOne` function as a prop to the `<RestaurantButton />` component and use this prop in the `onClick` handler.

**Test:** Clicking the button should still increment the number of pizzas.

#### 12. Extract pizza order to its own Order component

**Instructions:** Extract the `<li>` containing "Pizzas" from the `<Restaurant />` component to a new component named `Order`. Also, move the declaration of the `orders` state and the `orderOne` function from the `<Restaurant />` component to the new `<Order />` component. Use the `<Order />` component in the `<ul>` list of the `<Restaurant />` component.

**Test:** Make sure the pizza order is still rendered on the page and that clicking on the "Add" button still increments the number of orders.

#### 13. Render more orders

**Instructions:** Pass a new prop named `orderType` to the `<Order />` component with the value "Pizzas". Then render the `orderType` prop instead of "Pizzas" in the `<Order />` component. Make sure that "Pizzas" is still displayed on the screen. In the `<ul>` list of the `<Restaurant />` component, render 2 others `<Order />` components but this time pass different values for the `orderType` prop: "Salads" and "Chocolate cake".

**Test:** For each order, the number of items can be incremented independently. Verify that you are able to explain what is happening.

#### 14. Passing bookings from a state variable

**Instructions:** In the `<Bookings />` component, declare a new state `bookings` with the corresponding setter function `setBookings` to hold the `FakeBookings` data. Instead of passing `FakeBookings` directly to the `<SearchResults />` component, pass the new `bookings` state variable.

**Hint:** The new `bookings` state should be initialised with the `FakeBookings` variable.

**Test:** Check that the bookings are still rendered correctly in the page.

#### 15. Highlight booking row when clicked

**Instructions:** Within the `<SearchResults />` component or its child components, add an `onClick` handler to each row in the table (hint: on the `<tr>` element). When clicked, the row is "selected" and highlighted with a different colour. When clicked again, the row is unselected and the coloured highlighting is removed.

**Hint:** Use a new state variable for each row to record if the row is selected or not, and use this value to set a class to the `className` prop of the row.

**Test:** Verify that each row of your table can be highlighted (on and off) independently when being clicked.

## Lesson 3

Expand Down
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "^5.0.1"
Expand Down
26 changes: 17 additions & 9 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
height: 80px;
}

.App-header {
background-color: #222;
height: 50px;
padding: 20px;
color: white;
text-align: left;
font-family: Arial, Helvetica, sans-serif;
font-size: 1em;
font-weight: bold;
.touristInfoCard {
display: flex;
justify-content: space-around;
flex-direction: row;
align-items: center;
}

.App-header {
/* background-color: black; */
height: 150px;
padding: 50px;
color: black;
display: flex;
justify-content: space-around;
flex-direction: row;
align-items: center;
}
.App-title {
font-size: 1.5em;
}
Expand Down Expand Up @@ -55,3 +61,5 @@ tr {
.card {
width: 18rem;
}


15 changes: 0 additions & 15 deletions src/App.js

This file was deleted.

29 changes: 29 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import TouristInfoCards from "./component/TouristInfoCards";
import Bookings from "./component/Bookings";
import Footer from "./component/Footer"
import "./App.css";
import Header from "./component/Header";
import Restaurant from "./component/Restaurant";
const App = () => {



return (
<>
<div className="App">
<Header/>
<div className="touristInfoCard">
<TouristInfoCards descriptions="Glasgow is one of Europe's most vibrant and cosmopolitan cities. It boasts world famous art collections, the best shopping in the UK outside of London, first-class sports and leisure facilities, a vast array of restaurants and bars, and the most vibrant and exciting nightlife in Scotland." name="Glasgow" img="https://encrypted-tbn3.gstatic.com/licensed-image?q=tbn:ANd9GcS-MTkd_tz-3PjogOAt9GSX-d0URIvsjNkN7d32_UOVQsPVZIX3mFYbvH7RfvWc3nAyq9ZDrCx1nwBldO7SiIRtIXzL3w" />
<TouristInfoCards descriptions="What is London? London is the capital city of the United Kingdom. It is the U.K.'s largest metropolis and its economic, transportation, and cultural centre. " name="London" img="https://lh5.googleusercontent.com/p/AF1QipPNCWInlw7BoFL1uPM16LNueMYCyx6TruCivY5i=w548-h318-n-k-no" />
<TouristInfoCards descriptions="Manchester is the nucleus of the largest metropolitan area in the north of England, and it remains an important regional city, but it has lost the extraordinary vitality and unique influence that put it at the forefront of the Industrial Revolution." name="Manchester" img="https://dynamic-media-cdn.tripadvisor.com/media/photo-o/06/3d/31/60/manchester-town-hall.jpg?w=700&h=-1&s=1"/>
</div>
<Bookings />
<Restaurant />
<Footer/>
</div>
</>
);
};

export default App;
21 changes: 0 additions & 21 deletions src/Bookings.js

This file was deleted.

17 changes: 0 additions & 17 deletions src/Restaurant.js

This file was deleted.

26 changes: 26 additions & 0 deletions src/component/Bookings.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { useState } from "react";
import Search from "./search/Search";
import SearchResults from "../component/SearchResults";
import FakeBookings from "../data/fakeBookings.json";

const Bookings = () => {
// Declare a state variable for bookings and its setter function
const [bookings, setBookings] = useState(FakeBookings);

const search = searchVal => {
console.info("TO DO!", searchVal);
};

return (
<div className="App-content">
<div className="container">
<Search search={search} />
{/* Pass the bookings state variable to SearchResults */}
<SearchResults bookings={bookings} />
</div>
</div>
);
};

export default Bookings;

22 changes: 22 additions & 0 deletions src/component/Footer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useState } from "react";
import React from "react";
import footerData from "./data/footerData.json"
import "../index.css"

const Footer = () => {

return (
<>
<div className="Footer">
{footerData.map((element, index) => (
<ul>
<li key={index}> {element} </li>
</ul>
)
)}
</div>
</>
)
}

export default Footer;
15 changes: 15 additions & 0 deletions src/component/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";

const Header = () =>
{
return (
<>
<nav className="App-header">
<header>CYF Hotel</header>
<img src="https://media2.giphy.com/avatars/SuraHotels/jiNVeTTR8MgP.png" width="80" height="80"/>
</nav>
</>
)
}

export default Header;
36 changes: 36 additions & 0 deletions src/component/Restaurant.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from "react";
import Order from "./orders"; // Import the Order component
import "./restaurant.css"
const Restaurant = () => {
// Declare state variables for different orders
const [pizzaCount, setPizzaCount] = useState(0);
const [saladCount, setSaladCount] = useState(0);
const [cakeCount, setCakeCount] = useState(0);

return (
<div className="restaurant-container">
<h3>Restaurant Orders</h3>
<ul className="order-list">
<Order
orderType="Pizzas"
count={pizzaCount}
onIncrement={() => setPizzaCount(pizzaCount + 1)}
/>
<Order
orderType="Salads"
count={saladCount}
onIncrement={() => setSaladCount(saladCount + 1)}
/>
<Order
orderType="Chocolate cake"
count={cakeCount}
onIncrement={() => setCakeCount(cakeCount + 1)}
/>
</ul>
</div>
);
};

export default Restaurant;


Loading