diff --git a/package-lock.json b/package-lock.json index 8197e6f22..94217b93a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "react-hotel", "version": "0.1.0", "dependencies": { + "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1" @@ -11681,6 +11682,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", diff --git a/package.json b/package.json index e3e1562a7..f81c28013 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/src/AddBooking.js b/src/AddBooking.js new file mode 100644 index 000000000..1d4adbe20 --- /dev/null +++ b/src/AddBooking.js @@ -0,0 +1,14 @@ +import BookingForm from "./BookingForm"; + +const AddBooking = (props) => { + return ( +
+

Add New Booking

+
+ +
+
+ ); +}; + +export default AddBooking; diff --git a/src/App.js b/src/App.js index 953c98560..358aa0298 100644 --- a/src/App.js +++ b/src/App.js @@ -1,13 +1,26 @@ import React from "react"; - +import TouristInfoCards from "./TouristInfoCards"; +import Footer from "./Footer"; import Bookings from "./Bookings"; +import SearchResults from "./SearchResults"; import "./App.css"; +import Heading from "./Heading"; +import Restaurant from "./Restaurant"; const App = () => { return (
-
CYF Hotel
+ + + +
); }; diff --git a/src/BookingForm.css b/src/BookingForm.css new file mode 100644 index 000000000..a946789af --- /dev/null +++ b/src/BookingForm.css @@ -0,0 +1,7 @@ +.booking-form { + padding-bottom: 2rem; +} + +.booking-label { + width: 100%; +} \ No newline at end of file diff --git a/src/BookingForm.js b/src/BookingForm.js new file mode 100644 index 000000000..313e06441 --- /dev/null +++ b/src/BookingForm.js @@ -0,0 +1,49 @@ +import React, { useState, useEffect } from "react"; +import "./BookingForm.css"; +const BookingForm = (props) => { + const [title, setTitle] = useState(""); + const [firstName, setFirstName] = useState(""); + const [surname, setSurname] = useState(""); + const [email, setEmail] = useState(""); + const [roomId, setRoomId] = useState(""); + const [checkInDate, setCheckInDate] = useState(""); + const [checkOutDate, setCheckOutDate] = useState(""); + function handleSubmit(event) { + event.preventDefault(); + const createdBooking = { title, firstName, surname, email, roomId, checkInDate, checkOutDate }; + fetch("https://malkit-hotel-server.glitch.me/bookings/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(createdBooking) }) + .then((res) => { + console.log("res", res); + return res.json(); + }) + .then((data) => { + props.setBookings(data); + }); + } + + return ( +
+
+ + setTitle(e.target.value)} /> + + setFirstName(e.target.value)} /> + + setSurname(e.target.value)} /> + + setEmail(e.target.value)} /> + + setRoomId(e.target.value)} /> + + setCheckInDate(e.target.value)} /> + + setCheckOutDate(e.target.value)} /> +

+

+ +
+
+ ); +}; + +export default BookingForm; diff --git a/src/Bookings.js b/src/Bookings.js index e0d911b13..6a6472534 100644 --- a/src/Bookings.js +++ b/src/Bookings.js @@ -1,18 +1,66 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import Search from "./Search.js"; -// import SearchResults from "./SearchResults.js"; -// import FakeBookings from "./data/fakeBookings.json"; +import SearchResults from "./SearchResults.js"; +import LoadingWait from "./LoadingWait.js"; +import AddBooking from "./AddBooking.js"; const Bookings = () => { - const search = searchVal => { - console.info("TO DO!", searchVal); + const [deleteRow, setDeleteRow] = useState(null); + let [dataAvailable, setDataAvailable] = useState(false); + + useEffect(() => { + fetch("https://malkit-hotel-server.glitch.me/bookings") + .then((res) => res.json()) + .then((data) => { + console.log(data); + setBookings(data); + setMasterBookings(data); + setDataAvailable(true); + }); + }, []); + + useEffect(() => { + if (deleteRow) + fetch("https://malkit-hotel-server.glitch.me/bookings/" + deleteRow, { method: "DELETE" }) + .then((res) => res.json()) + .then((data) => { + console.log(data); + setBookings(data); + setMasterBookings(data); + setDataAvailable(true); + }); + }, [deleteRow]); + + let [bookings, setBookings] = useState([]); + let [masterBookings, setMasterBookings] = useState([]); + + const search = (searchVal) => { + if (!searchVal) { + console.log("no search Val"); + fetch("https://malkit-hotel-server.glitch.me/bookings/") + .then((res) => res.json()) + .then((data) => { + console.log(data); + let filteredBookings = data; + setBookings(filteredBookings); + }); + } else { + fetch("https://malkit-hotel-server.glitch.me/bookings/search?term=" + searchVal) + .then((res) => res.json()) + .then((data) => { + console.log(data); + let filteredBookings = data; + setBookings(filteredBookings); + }); + } }; return (
+ - {/* */} + {dataAvailable ? : }
); diff --git a/src/CustomerProfile.js b/src/CustomerProfile.js new file mode 100644 index 000000000..697e2254d --- /dev/null +++ b/src/CustomerProfile.js @@ -0,0 +1,30 @@ +import React, { useState, useEffect } from "react"; + +const CustomerProfile = (props) => { + let [emailAddress, setEmailAddress] = useState(""); + let [vipStatus, setVipStatus] = useState(null); + let [phoneNumber, setPhoneNumber] = useState(""); + + useEffect(() => { + if (props.customerProfileId) { + fetch(`https://cyf-react.glitch.me/customers/${props.customerProfileId}`) + .then((res) => res.json()) + .then((data) => { + setEmailAddress(data.email); + setVipStatus(data.vip ? "Vip Status" : "Not VIP"); + setPhoneNumber(data.phoneNumber); + }); + } + }, [props.customerProfileId]); + + return props.customerProfileId ? ( + + ) : null; +}; + +export default CustomerProfile; diff --git a/src/Footer.js b/src/Footer.js new file mode 100644 index 000000000..8475c9d61 --- /dev/null +++ b/src/Footer.js @@ -0,0 +1,13 @@ +import React from "react"; + +const Footer = (props) => ( + +); + +export default Footer; \ No newline at end of file diff --git a/src/Heading.css b/src/Heading.css new file mode 100644 index 000000000..de946ce81 --- /dev/null +++ b/src/Heading.css @@ -0,0 +1,9 @@ +img { + height: 80px; + display: flex; + margin-left: auto; + margin-right: auto; + + + +} \ No newline at end of file diff --git a/src/Heading.js b/src/Heading.js new file mode 100644 index 000000000..a4e829842 --- /dev/null +++ b/src/Heading.js @@ -0,0 +1,11 @@ +import React from "react"; +import "./Heading.css"; + +const Heading = () => { + return (
+ +
+ ) +} + +export default Heading; \ No newline at end of file diff --git a/src/LoadingWait.css b/src/LoadingWait.css new file mode 100644 index 000000000..617c4b8c0 --- /dev/null +++ b/src/LoadingWait.css @@ -0,0 +1,5 @@ +.wait-text { + font-size: x-large; + color: red; + +} \ No newline at end of file diff --git a/src/LoadingWait.js b/src/LoadingWait.js new file mode 100644 index 000000000..4bafae305 --- /dev/null +++ b/src/LoadingWait.js @@ -0,0 +1,12 @@ +import React, { useState } from "react"; +import "./LoadingWait.css"; + +const LoadingWait = () => { + return ( +
+

Please Wait...Loading Bookings

+
+ ); +}; + +export default LoadingWait; diff --git a/src/NightsCount.js b/src/NightsCount.js new file mode 100644 index 000000000..af43c252d --- /dev/null +++ b/src/NightsCount.js @@ -0,0 +1,16 @@ +import React from "react"; +import moment from "moment"; + +const NightsCount = ({ checkInDate, checkOutDate }) => { + const calculateNumberOfNights = (checkInDate, checkOutDate) => { + const checkIn = moment(checkInDate); //convert the checkInDate string into a moment object + const checkOut = moment(checkOutDate); + return checkOut.diff(checkIn, "days"); //calculates the number of days between checkIn and checkOut. + }; + + const numberOfNights = calculateNumberOfNights(checkInDate, checkOutDate); + + return {numberOfNights} nights; +}; + +export default NightsCount; diff --git a/src/Order.js b/src/Order.js new file mode 100644 index 000000000..d9ad87ea0 --- /dev/null +++ b/src/Order.js @@ -0,0 +1,17 @@ +import React,{useState}from "react"; +import RestaurantButton from "./RestaurantButton"; + +const Order = (props) => { + const [orders, setOrders] = useState(0); + function orderOne() { + setOrders(orders + 1); + } + return ( +
  • + {props.orderType}: {orders} + +
  • + ); +}; + +export default Order; \ No newline at end of file diff --git a/src/Restaurant.js b/src/Restaurant.js index ecb2b43a2..bfea210a3 100644 --- a/src/Restaurant.js +++ b/src/Restaurant.js @@ -1,14 +1,14 @@ import React from "react"; +import Order from "./Order"; const Restaurant = () => { - const pizzas = 0; return (

    Restaurant Orders

    ); diff --git a/src/RestaurantButton.js b/src/RestaurantButton.js new file mode 100644 index 000000000..51d34575c --- /dev/null +++ b/src/RestaurantButton.js @@ -0,0 +1,11 @@ +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..f42138ff3 100644 --- a/src/Search.js +++ b/src/Search.js @@ -1,6 +1,13 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; +import SearchButton from "./SearchButton"; + +const Search = (props) => { + const [searchInput, setSearchInput] = useState(""); + function handleSearchInput(event) { + setSearchInput(event.target.value); + console.log(event.target.value); + } -const Search = () => { return (
    @@ -8,16 +15,24 @@ const Search = () => {
    -
    + { + e.preventDefault(); + props.search(searchInput); + }} + >
    - +
    diff --git a/src/SearchButton.js b/src/SearchButton.js new file mode 100644 index 000000000..b004dad88 --- /dev/null +++ b/src/SearchButton.js @@ -0,0 +1,9 @@ +import React from "react"; + +const SearchButton = () => { + return ( + + ); +}; + +export default SearchButton; \ No newline at end of file diff --git a/src/SearchResults.js b/src/SearchResults.js new file mode 100644 index 000000000..0e967a63c --- /dev/null +++ b/src/SearchResults.js @@ -0,0 +1,21 @@ +import React, { useState, useEffect } from "react"; +import TableHeading from "./TableHeading"; +import TableBody from "./TableBody"; +import CustomerProfile from "./CustomerProfile"; + +const SearchResults = (props) => { + const [customerProfileId, setCustomerProfileId] = useState(""); + + console.log("props value", props); + return ( +
    + + + +
    + +
    + ); +}; + +export default SearchResults; diff --git a/src/TableBody.js b/src/TableBody.js new file mode 100644 index 000000000..bac801b51 --- /dev/null +++ b/src/TableBody.js @@ -0,0 +1,14 @@ +import React from "react"; +import TableRow from "./TableRow"; + +const TableBody = (props) => { + return ( + + {props.bodyData.map((aBooking, index) => { + return ; + })} + + ); +}; + +export default TableBody; diff --git a/src/TableHeading.js b/src/TableHeading.js new file mode 100644 index 000000000..5ebe35145 --- /dev/null +++ b/src/TableHeading.js @@ -0,0 +1,21 @@ +import React from "react"; + +const TableHeading = () => { + return ( + + + ID + Title + First name + Surname + Email + Room id + Check in date + Check out date + Number of Nights + + + ); +}; + +export default TableHeading; diff --git a/src/TableRow.css b/src/TableRow.css new file mode 100644 index 000000000..98bcc46c8 --- /dev/null +++ b/src/TableRow.css @@ -0,0 +1,3 @@ +.red { + background-color: lightpink; +} \ No newline at end of file diff --git a/src/TableRow.js b/src/TableRow.js new file mode 100644 index 000000000..5d615c6eb --- /dev/null +++ b/src/TableRow.js @@ -0,0 +1,67 @@ +import React, { useState } from "react"; +import NightsCount from "./NightsCount"; +import "./TableRow.css"; + +function handleClick(highlightColor, setHighlightColor) { + if (highlightColor === "red") { + setHighlightColor(""); + } else { + setHighlightColor("red"); + } +} + +const TableRow = (props) => { + const [highlightColor, setHighlightColor] = useState(""); + + function handleProfileClick(id) { + props.setCustomerProfileId(id); + } + + function handleDeleteClick(id) { + props.setDeleteRow(id); + } + + return ( + { + handleClick(highlightColor, setHighlightColor); + }} + > + {props.aBooking.id} + {props.aBooking.title} + {props.aBooking.firstName} + {props.aBooking.surname} + {props.aBooking.email} + {props.aBooking.roomId} + {props.aBooking.checkInDate} + {props.aBooking.checkOutDate} + + + + + + + + + + + ); +}; + +export default TableRow; diff --git a/src/TouristInfoCards.css b/src/TouristInfoCards.css new file mode 100644 index 000000000..a4e66e5c3 --- /dev/null +++ b/src/TouristInfoCards.css @@ -0,0 +1,20 @@ +.card-container { + display: flex; + justify-content: center; + align-items: stretch; + gap: 20px; + height: 100%; + margin: 3rem; +} + +.card { + flex: 1; + display: grid; + grid-template-rows: auto 1fr auto; + border: 3px green solid; + text-align: center; +} +.card-img-top { + object-fit: cover; + height: 100%; +} diff --git a/src/TouristInfoCards.js b/src/TouristInfoCards.js new file mode 100644 index 000000000..34022fdf7 --- /dev/null +++ b/src/TouristInfoCards.js @@ -0,0 +1,62 @@ +import React from "react"; +import "./TouristInfoCards.css"; + +const Card = ({ image, title, description, link }) => { + return ( +
    + {title} +
    +
    {title}
    +

    {description}

    + + More Information + +
    +
    + ); +}; + +function TouristInfoCards() { + const cardsData = [ + { + image: + "https://images.unsplash.com/photo-1632724442187-6f189af4d4d3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", + title: "Glasgow", + description: + "Glasgow is a vibrant city known for its rich history, cultural attractions, and lively music scene. Explore the stunning architecture, visit world-class museums, and enjoy the friendly atmosphere.", + link: "https://www.peoplemakeglasgow.com/", + }, + { + image: + "https://images.unsplash.com/photo-1605021149343-bb75d2a2fa44?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", + title: "Manchester", + description: + "Manchester is a vibrant city known for its thriving music and art scene, world-class football, and rich industrial heritage. Explore its diverse neighborhoods, visit iconic landmarks, and indulge in its renowned shopping and dining experiences.", + link: "https://www.visitmanchester.com/", + }, + { + image: + "https://images.unsplash.com/photo-1520986606214-8b456906c813?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", + title: "London", + description: + "London, the capital city of England, is a global hub of culture, history, and entertainment. Explore its iconic landmarks, including the Tower of London and Buckingham Palace. Immerse yourself in the diverse culinary scene, vibrant theater shows, and world-class museums.", + link: "https://www.visitlondon.com/", + }, + ]; + + return ( +
    + {cardsData.map((card, index) => ( + + ))} +
    + ); +} + +export default TouristInfoCards;