diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 370d9a7..9c88dec 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -16,5 +16,6 @@ module.exports = { "warn", { allowConstantExport: true }, ], + "react/prop-types": "off", }, }; diff --git a/src/components/Bookings/Bookings.jsx b/src/components/Bookings/Bookings.jsx index e1fc38c..e497bfa 100644 --- a/src/components/Bookings/Bookings.jsx +++ b/src/components/Bookings/Bookings.jsx @@ -1,11 +1,25 @@ import Search from "@/components/Search/Search"; import SearchResult from "../SearchResult/SearchResult"; -import FakeBookings from "@/data/fakeBookings.json"; -import { useState } from "react"; +import { useState, useEffect } from "react"; const Bookings = () => { - const [bookings, setBookings] = useState(FakeBookings); + const [bookings, setBookings] = useState([]); + useEffect(() => { + fetch("https://nw6-cyf-hotel.glitch.me/fakebookings") + .then((res) => { + if (!res.ok) { + throw new Error(`${res.status}: ${getReasonPhrase(res.status)}`); + } + return res.json(); + }) + .then((data) => setBookings(data)) + .catch((error) => { + setFetchError(error); + console.log(error); + }); + }), + []; const search = (searchVal) => { console.info("TO DO!", searchVal); const searchValueCase = searchVal.toLowerCase(); diff --git a/src/components/CustomerProfile/CustomerProfile.jsx b/src/components/CustomerProfile/CustomerProfile.jsx new file mode 100644 index 0000000..112512a --- /dev/null +++ b/src/components/CustomerProfile/CustomerProfile.jsx @@ -0,0 +1,33 @@ +import { useState, useEffect } from "react"; + +function CustomerProfile({ id }) { + const [customerProfileData, setCustomerProfileData] = useState(null); + + useEffect(() => { + fetch(`https://cyf-hotel-api.netlify.app/customers/${id}`) + .then((res) => res.json()) + .then((data) => setCustomerProfileData(data)) + .catch((error) => + console.error("Error fetching customer profile:", error) + ); + }, [id]); + + if (!customerProfileData) { + return ( + + Loading... + + ); + } + return ( + + {customerProfileData.phoneNumber} + + {customerProfileData.vip ? `VIP Customer`: `Regular Customer`} + + ID: {customerProfileData.id} + + ); +} + +export default CustomerProfile; diff --git a/src/components/CustomerProfile/CustomerProfile.scss b/src/components/CustomerProfile/CustomerProfile.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CustomerProfile/CustomerProfile.test.jsx b/src/components/CustomerProfile/CustomerProfile.test.jsx new file mode 100644 index 0000000..1012fd9 --- /dev/null +++ b/src/components/CustomerProfile/CustomerProfile.test.jsx @@ -0,0 +1,31 @@ +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import CustomerProfile from "./CustomerProfile"; + +describe("CustomerProfile", () => { + it("renders loading state initially", () => { + render(); + const loadingText = screen.getByText("Loading..."); + expect(loadingText).toBeInTheDocument(); + }); + + it("renders customer profile after data is fetched", async () => { + global.fetch = () => + Promise.resolve({ + json: async () => ({ + id: 1, + phoneNumber: "+44 1632 960185", + vip: true, + }), + }); + + render(); + + await screen.findByText("+44 1632 960185"); + + const phoneNumber = screen.getByText("+44 1632 960185"); + expect(phoneNumber).toBeInTheDocument(); + expect(screen.getByText("VIP Customer")).toBeInTheDocument(); + expect(screen.getByText("ID: 1")).toBeInTheDocument(); + }); +}); diff --git a/src/components/Footer/Footer.jsx b/src/components/Footer/Footer.jsx index 83a8357..c564bba 100644 --- a/src/components/Footer/Footer.jsx +++ b/src/components/Footer/Footer.jsx @@ -1,16 +1,14 @@ import React from "react"; -import "./Footer.scss" +import "./Footer.scss"; export default function Footer(props) { return ( <> -
-
    - {props.details.map((detail, id) => ( -
  • {detail}
  • - ))} -
-
+ ); } diff --git a/src/components/SearchResult/SearchResult.jsx b/src/components/SearchResult/SearchResult.jsx index bce4a47..3e4e5a6 100644 --- a/src/components/SearchResult/SearchResult.jsx +++ b/src/components/SearchResult/SearchResult.jsx @@ -1,39 +1,18 @@ import "./SearchResult.scss"; -import TableBody from "./TableBody"; -import TableHead from "./TableHead"; -import dayjs from "dayjs"; -function SearchResult(props) { - const Bookings = props.results; +import CustomerProfile from "../CustomerProfile/CustomerProfile"; +import Table from "./Table"; + + + +function SearchResult() { + + return ( - - - - - - {Bookings.map((book) => { - const stayNightsTotal = dayjs(book.checkOutDate).diff( - dayjs(book.checkInDate), - "day" - ); - return ( - - ); - })} - -
+ <> + + + ); } export default SearchResult; - diff --git a/src/components/SearchResult/Table.jsx b/src/components/SearchResult/Table.jsx new file mode 100644 index 0000000..c555e2e --- /dev/null +++ b/src/components/SearchResult/Table.jsx @@ -0,0 +1,41 @@ +import TableBody from "./TableBody"; +import TableHead from "./TableHead"; +import dayjs from "dayjs"; +import FakeBookings from "@/data/fakeBookings.json"; + +function Table() { + const Bookings = FakeBookings; + return ( + <> +
+ + + + + {Bookings.map((book) => { + const stayNightsTotal = dayjs(book.checkOutDate).diff( + dayjs(book.checkInDate), + "day" + ); + return ( + + ); + })} + +
+ + ); +} + +export default Table; diff --git a/src/components/SearchResult/TableBody.jsx b/src/components/SearchResult/TableBody.jsx index a441220..bb8569a 100644 --- a/src/components/SearchResult/TableBody.jsx +++ b/src/components/SearchResult/TableBody.jsx @@ -1,9 +1,16 @@ import React from "react"; import { useState } from "react"; +import CustomerProfile from "../CustomerProfile/CustomerProfile"; function TableBody(props) { const [selectedRow, setSelectedRow] = useState("unselect"); + const [showProfile, setShowProfile] = useState(false); function handleSelect() { setSelectedRow(selectedRow === "unselect" ? "selected" : "unselect"); + showProfileHandle(); + } + + function showProfileHandle() { + setShowProfile(!showProfile); } let { id, @@ -33,7 +40,9 @@ function TableBody(props) { {checkInDate} {checkOutDate} {stayNights} + + {showProfile ? : null} ); } diff --git a/src/components/SearchResult/TableHead.jsx b/src/components/SearchResult/TableHead.jsx index 9afda64..f544522 100644 --- a/src/components/SearchResult/TableHead.jsx +++ b/src/components/SearchResult/TableHead.jsx @@ -11,6 +11,7 @@ function TableHead() { Check in date Check out date Total Nights to Stay + Profile );