diff --git a/package-lock.json b/package-lock.json index 8197e6f22..f5a670d51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "react-hotel", "version": "0.1.0", "dependencies": { + "axios": "^1.4.0", + "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1" @@ -4483,6 +4485,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -11681,6 +11706,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -13685,6 +13718,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index e3e1562a7..46a89f1c3 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { + "axios": "^1.4.0", + "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1" diff --git a/src/App.css b/src/App.css index 05fe2d52e..5c947b66b 100644 --- a/src/App.css +++ b/src/App.css @@ -1,40 +1,126 @@ +@import url('https://fonts.googleapis.com/css2?family=Anton&family=Monomaniac+One&family=Quicksand:wght@300&display=swap'); + .App { text-align: left; } +.rwo-btn { + height: 50px; + width: 88px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + background-color: blue; + color: aliceblue; + font-weight: bolder; +} + +.card-img-top { + width: 450px; + height: 301px; +} + +.tourist-cards { + margin-top: 10px; + margin-left: 80px; + margin-right: 40px; + display: grid; + grid-template-columns: repeat(3, 1fr); + /* margin-top: 30px; + display: flex; + flex-direction: row; + justify-content: space-between; + padding-left: 40px; + padding-right: 40px; */ +} + .App-logo { - animation: App-logo-spin infinite 20s linear; - height: 80px; + /* animation: App-logo-spin infinite 20s linear; */ + height: 100px; + margin-bottom: 20px; + border: 1px solid rgb(245, 163, 32) } .App-header { - background-color: #222; - height: 50px; + background-color: #272626; + height: 150px; + width: 100%; padding: 20px; - color: white; + color: rgb(245, 163, 32); text-align: left; - font-family: Arial, Helvetica, sans-serif; - font-size: 1em; + /* font-family: Arial, Helvetica, sans-serif; */ + font-size: 2.8em; font-weight: bold; + display: flex; + justify-content: center; + align-items: center; + gap: 30px; + padding-top: 51px; + font-family: 'Monomaniac One', sans-serif; } -.App-title { - font-size: 1.5em; + + +.App-header h1{ + font-size: 3.3rem; } +/* .App-title { + font-size: 1.5em; +} */ + .App-content { padding-top: 20px; font-size: large; } +.order-type { + display: grid; + grid-template-columns: repeat(4, 1fr); + margin: 0 100px; +} + +.card-body { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; +} + +.row-nonHighlight { + background-color: rgb(241, 239, 237); +} + +.row-highlight { + background-color: rgb(245, 163, 32); +} + +.order-head { + display: flex; + justify-content: center; +} + +.customer-profile { + display: flex; + flex-direction: column; + flex-wrap: wrap; + align-items: center; + background-color: #4c4949; + color: snow; +} + + @keyframes App-logo-spin { from { transform: rotate(0deg); } + to { transform: rotate(360deg); } } + .search { padding: 5px 0 20px 0; } @@ -53,5 +139,5 @@ tr { } .card { - width: 18rem; -} + width: 28.2rem; +} \ No newline at end of file diff --git a/src/App.js b/src/App.js index 953c98560..57bb30ba3 100644 --- a/src/App.js +++ b/src/App.js @@ -1,15 +1,30 @@ import React from "react"; - +import Heading from "./Heading"; import Bookings from "./Bookings"; +import Restaurant from "./Restaurant"; +import TouristInfoCards from "./TouristInfoCards"; +import FooterCompo from "./FooterCompo"; import "./App.css"; const App = () => { return (
-
CYF Hotel
- + + + + +
); }; export default App; + diff --git a/src/Bookings.js b/src/Bookings.js index e0d911b13..4bde8de5c 100644 --- a/src/Bookings.js +++ b/src/Bookings.js @@ -1,21 +1,47 @@ -import React from "react"; +import React, { useCallback, useEffect, useState } from "react"; +import Axios from "axios"; import Search from "./Search.js"; -// import SearchResults from "./SearchResults.js"; +import SearchResults from "./SearchResults.js"; // import FakeBookings from "./data/fakeBookings.json"; const Bookings = () => { - const search = searchVal => { + const [bookings, setBookings] = useState([]); + const [searchVal, setSearchVal] = useState(""); + const [loading, setLoading] = useState(false); + + const search = (searchVal) => { console.info("TO DO!", searchVal); + setSearchVal(searchVal); }; + useEffect(() => { + const fetchData = async () => { + try { + const res = await Axios.get("https://cyf-react.glitch.me/delayed"); + setBookings(res.data); + } catch (error) { + console.log(error); + } + setLoading(true); + } + fetchData(); + + }, []); + + const searchOutCome = bookings.filter( + (el) => el.firstName.includes(searchVal) || el.surname.includes(searchVal) + ); + return (
- - {/* */} + + {!loading ? (

Loading...

) : ( + ) + }
); }; -export default Bookings; +export default Bookings; \ No newline at end of file diff --git a/src/CustomerProfile.js b/src/CustomerProfile.js new file mode 100644 index 000000000..88ff7cf32 --- /dev/null +++ b/src/CustomerProfile.js @@ -0,0 +1,35 @@ +// import Axios from 'axios'; +import React, { useEffect, useState } from "react"; + +const CustomerProfile = (props) => { + const [showDataProfile, setShowDataProfile] = useState(""); + const idApi = `https://cyf-react.glitch.me/customers/${props.id}`; + + useEffect(() => { + if (props.id) { + fetch(idApi) + .then((response) => response.json()) + .then((data) => setShowDataProfile(data)); + } + }, [props.id]); + return ( +
+ {props.id !== "" ?

Customer Profile

: <>} + {props.id !== "" ? ( + + ) : ( + <> + )} +
+ ); +}; + +export default CustomerProfile; diff --git a/src/FooterCompo.js b/src/FooterCompo.js new file mode 100644 index 000000000..989a64262 --- /dev/null +++ b/src/FooterCompo.js @@ -0,0 +1,17 @@ +import React from "react"; + +const FooterCompo = ({ details }) => { + return ( +
+ +
+ ); +}; + +export default FooterCompo; diff --git a/src/Heading.js b/src/Heading.js new file mode 100644 index 000000000..d68bf258a --- /dev/null +++ b/src/Heading.js @@ -0,0 +1,16 @@ +import React from "react"; +import logoHotel from "./images/495.jpg"; + +const Heading = () => { + const name = "Beko CYF Luxury Hotel"; + return ( +
+
+

{name}

+ +
+
+ ); +}; + +export default Heading; diff --git a/src/Order.js b/src/Order.js new file mode 100644 index 000000000..fb0e93613 --- /dev/null +++ b/src/Order.js @@ -0,0 +1,23 @@ +import React, { useState } from "react"; +import RestaurantButton from "./RestaurantButton"; + + +const Order = ({orderType}) => { + const [order, setOder] = useState(0); + + const orderOne = () => { + setOder(order + 1); + }; + + return ( +
+ +
+ ); +} + +export default Order; \ No newline at end of file diff --git a/src/Restaurant.js b/src/Restaurant.js index ecb2b43a2..0660ad2f3 100644 --- a/src/Restaurant.js +++ b/src/Restaurant.js @@ -1,15 +1,17 @@ import React from "react"; +import Order from "./Order"; const Restaurant = () => { - const pizzas = 0; + return (
-

Restaurant Orders

- +

Restaurant Orders

+
+ + + + +
); }; diff --git a/src/RestaurantButton.js b/src/RestaurantButton.js new file mode 100644 index 000000000..f6cf3394b --- /dev/null +++ b/src/RestaurantButton.js @@ -0,0 +1,13 @@ +import React from "react"; + +const RestaurantButton = ({ handleClick }) => { + return ( +
+ +
+ ); +}; + +export default RestaurantButton; \ No newline at end of file diff --git a/src/Search.js b/src/Search.js index 7bd5871c0..32ecea6ea 100644 --- a/src/Search.js +++ b/src/Search.js @@ -1,6 +1,21 @@ -import React from "react"; +import React, { useState } from "react"; +import SearchButton from "./SearchButton"; + +const Search = ({ search }) => { + const [searchInput, setSearchInput] = useState(""); + + const handleSearchInput = (event) => { + setSearchInput(event.target.value); + // console.log(event.target.value); + }; + + + const handleSearch = (event) => { + search(searchInput); + event.preventDefault(); + } + -const Search = () => { return (
@@ -8,16 +23,18 @@ const Search = () => {
-
+
- +
diff --git a/src/SearchButton.js b/src/SearchButton.js new file mode 100644 index 000000000..04a59714b --- /dev/null +++ b/src/SearchButton.js @@ -0,0 +1,13 @@ +import React from "react"; + +const SearchButton = () => { + return ( +
+ +
+ ); +}; + +export default SearchButton; diff --git a/src/SearchResults.js b/src/SearchResults.js new file mode 100644 index 000000000..38ecbe566 --- /dev/null +++ b/src/SearchResults.js @@ -0,0 +1,113 @@ +import React, { useState } from "react"; +import moment from "moment"; +import CustomerProfile from "./CustomerProfile"; + +const getNumbersOfNights = (checkInDate, checkOutDate) => { + const date1 = moment(checkInDate); + const date2 = moment(checkOutDate); + return date2.diff(date1, "days"); +}; + +const Row = (props) => { + const { + id, + title, + firstName, + surname, + email, + roomId, + checkInDate, + checkOutDate, + setProfile, + } = props; + + const night = getNumbersOfNights(checkInDate, checkOutDate); + + const [rowSelect, setRowSelect] = useState(false); + // TODO: we don't need two states to represent showing the profile or not. + const [showProfile, setShowProfile] = useState(false); + + const handleClick = () => setRowSelect(!rowSelect); + + const handleProfile = () => { + showProfile ? setProfile("") : setProfile(id); + setShowProfile(!showProfile); + }; + + return ( + + {id} + {title} + {firstName} + {surname} + {email} + {roomId} + {checkInDate} + {checkOutDate} + {night} + + + + + ); +}; +const Table = (props) => { + const { data } = props; + const [profile, setProfile] = useState(""); + return ( +
+ + + + + + + + + + + + + + + + + + {data.map((column, index) => { + return ( + + ); + })} + +
idTitleFirst nameSurnameEmailRoom idCheck in dateCheck out dateNightShow profile
+
+ ); +}; + +const SearchResults = (props) => { + // const [myData, setMyData] = useState(props.results); + // console.log(myData, "here"); + return ( +
+ + + ); +}; + +export default SearchResults; diff --git a/src/TouristInfoCards.js b/src/TouristInfoCards.js new file mode 100644 index 000000000..669ba5d31 --- /dev/null +++ b/src/TouristInfoCards.js @@ -0,0 +1,54 @@ +import React from "react"; +import GlasgowImg from "./images/George Square Glasgow.jpeg"; +import LancasterCastleImg from "./images/Lancaster Castle.jpeg"; +import LondonEyeImg from "./images/London Eye.jpeg"; + +const TouristInfoCards = () => { + const glasgow = + "Where to start but right in the heart of it all! The city's civic square, George Square attracts everything from global events to people watchers. The square is lined with beautiful buildings, including the City Chambers. Join one of their free daily tours to see their Instagram-worthy interiors"; + const lancasterCastle = + "Steeped in almost 1000 years of history including the trials of the Pendle Witches and the Birmingham Six, Lancaster Castle is one of the most important historic monuments in the North West. Come and visit the old cells, Shire Hall and Crown Court."; + const londonEye = + "Enjoy amazing 360-degree views over London from the lastminute.com London Eye - the world’s tallest cantilevered observation wheel. The special engineering achievement has become a symbol of the modern capital and a world-famous icon of architecture."; + + return ( +
+
+ +
+

George Square

+ {glasgow} + + Click for info + +
+
+
+ +
+

Lancaster Castle

+ {lancasterCastle} + + Click for info + +
+
+
+ +
+

London Eye

+ {londonEye} +

+ + Click for info + +
+
+
+ ); +}; + +export default TouristInfoCards; diff --git a/src/images/495.jpg b/src/images/495.jpg new file mode 100644 index 000000000..779ff41d3 Binary files /dev/null and b/src/images/495.jpg differ diff --git a/src/images/George Square Glasgow.jpeg b/src/images/George Square Glasgow.jpeg new file mode 100644 index 000000000..4d9e73567 Binary files /dev/null and b/src/images/George Square Glasgow.jpeg differ diff --git a/src/images/Lancaster Castle.jpeg b/src/images/Lancaster Castle.jpeg new file mode 100644 index 000000000..2d65a1583 Binary files /dev/null and b/src/images/Lancaster Castle.jpeg differ diff --git a/src/images/London Eye.jpeg b/src/images/London Eye.jpeg new file mode 100644 index 000000000..8b3373dd0 Binary files /dev/null and b/src/images/London Eye.jpeg differ