-
-
Notifications
You must be signed in to change notification settings - Fork 767
BAKI TUNCER/LONDON-10/CFY HOTEL #618
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,27 @@ | ||
import React from "react"; | ||
|
||
import Bookings from "./Bookings"; | ||
import "./App.css"; | ||
import Heading from "./components/Heading"; | ||
import TouristInfoCards from "./components/TouristInfoCards"; | ||
import Footer from "./components/Footer"; | ||
import Restaurant from "./components/Restaurant"; | ||
|
||
const App = () => { | ||
const addresses = [ | ||
"123 Fake Street, London, E1 4UD", | ||
"[email protected]", | ||
"0123 456789", | ||
]; | ||
|
||
return ( | ||
<div className="App"> | ||
<header className="App-header">CYF Hotel</header> | ||
<Heading /> | ||
<TouristInfoCards /> | ||
<Bookings /> | ||
<Restaurant /> | ||
<Footer addresses={addresses} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default App; | ||
export default App; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,52 @@ | ||
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 "./components/SearchResults.js"; | ||
import fakeBookings from "./data/fakeBookings.json"; | ||
const Bookings = () => { | ||
const search = searchVal => { | ||
console.info("TO DO!", searchVal); | ||
const [bookings, setBookings] = useState([]); | ||
const [isLoading, setIsLoading] = useState(true); | ||
const [error, setError] = useState(null); | ||
|
||
useEffect(() => { | ||
console.log("Page loaded"); | ||
setIsLoading(true); | ||
setError(null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really nice use of error handling here on page load. However, you shouldnt need this since you already have the default set to null. |
||
fetch("https://cyf-react.glitch.me") | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error("Failed to fetch data"); | ||
} | ||
return response.json(); | ||
}) | ||
.then((data) => { | ||
setBookings(data); | ||
setIsLoading(false); | ||
}) | ||
.catch((error) => { | ||
setError(error.message); | ||
setIsLoading(false); | ||
}); | ||
}, []); | ||
|
||
const search = (searchVal) => { | ||
const filteredBookings = bookings.filter( | ||
(booking) => | ||
booking.firstName.toLowerCase().includes(searchVal.toLowerCase()) || | ||
booking.surname.toLowerCase().includes(searchVal.toLowerCase()) | ||
); | ||
setBookings(filteredBookings); | ||
}; | ||
|
||
return ( | ||
<div className="App-content"> | ||
<div className="container"> | ||
<Search search={search} /> | ||
{/* <SearchResults results={FakeBookings} /> */} | ||
</div> | ||
<div className="container"> | ||
<Search search={search} /> | ||
{isLoading ? ( | ||
<p>Loading...</p> | ||
) : error ? ( | ||
<p>Error: {error}</p> | ||
) : ( | ||
<SearchResults bookings={bookings} /> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React, { useEffect, useState } from "react"; | ||
|
||
const CustomerProfile = ({ customerId }) => { | ||
const [customerProfile, setCustomerProfile] = useState(null); | ||
|
||
useEffect(() => { | ||
if (customerId) { | ||
fetch(`https://cyf-react.glitch.me/customers/${customerId}`) | ||
.then((response) => response.json()) | ||
.then((data) => { | ||
setCustomerProfile(data); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to add a catch here aswell and some error handling similar to the other api requests. Then you can use that to display an error message. |
||
}); | ||
} | ||
}, [customerId]); | ||
|
||
if (!customerProfile) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div className="customer-profile"> | ||
<h2>Customer Profile</h2> | ||
<ul> | ||
<li>ID: {customerProfile.id}</li> | ||
<li>Email: {customerProfile.email}</li> | ||
<li>VIP: {customerProfile.vip ? "Yes" : "No"}</li> | ||
<li>Phone: {customerProfile.phoneNumber}</li> | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
export default CustomerProfile; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from "react"; | ||
|
||
const Footer = ({addresses})=> { | ||
return ( | ||
<footer> | ||
<ul> | ||
{addresses.map((address, index) => ( | ||
<li key={index}>{address}</li> | ||
))} | ||
</ul> | ||
</footer> | ||
); | ||
} | ||
|
||
export default Footer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from "react"; | ||
|
||
const Heading = () => { | ||
return ( | ||
<header className="App-header"> | ||
<img | ||
src="https://image.flaticon.com/icons/svg/139/139899.svg" | ||
alt="Hotel Logo" | ||
/> | ||
</header> | ||
); | ||
} | ||
|
||
export default Heading; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React, { useState } from "react"; | ||
|
||
const Order = ({ orderType }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is great separation making them all into smaller components however it still might be best to split them into separate files to keep them smaller and easier to read. |
||
const [orders, setOrders] = useState(0); | ||
|
||
const orderOne = () => { | ||
setOrders(orders + 1); | ||
}; | ||
|
||
return ( | ||
<li> | ||
{orderType}: {orders} <RestaurantButton onClick={orderOne} /> | ||
</li> | ||
); | ||
}; | ||
|
||
const RestaurantButton = ({ onClick }) => { | ||
return ( | ||
<button className="btn btn-primary" onClick={onClick}> | ||
Add | ||
</button> | ||
); | ||
}; | ||
|
||
const Restaurant = () => { | ||
return ( | ||
<div> | ||
<h3>Restaurant Orders</h3> | ||
<ul> | ||
<Order orderType="Pizzas" /> | ||
<Order orderType="Salads" /> | ||
<Order orderType="Chocolate cake" /> | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Restaurant; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const SearchButton = () => { | ||
return <button className="btn btn-primary">Search</button>; | ||
} | ||
|
||
export default SearchButton; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import React, { useEffect, useState } from "react"; | ||
|
||
const SearchResults = ({ bookings }) => { | ||
const [selectedCustomerId, setSelectedCustomerId] = useState(null); | ||
|
||
const handleShowProfile = (customerId) => { | ||
setSelectedCustomerId(customerId); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<table className="table table-striped"> | ||
<thead> | ||
<tr> | ||
<th>Title</th> | ||
<th>First Name</th> | ||
<th>Surname</th> | ||
<th>Email</th> | ||
<th>Room ID</th> | ||
<th>Check-in Date</th> | ||
<th>Check-out Date</th> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For task 6 to add the difference of nights You installed moment library which is great. The docs provide some guidance on calculating the difference here https://momentjs.com/docs/#/displaying/difference/ |
||
<th>Actions</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{bookings.map((booking) => ( | ||
<tr key={booking.id}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The map works perfectly here and it seems to function as expected. It just seems to be missing lesson 2 task 15. You can achieve it by adding a onClick here and a function to change its class |
||
<td>{booking.title}</td> | ||
<td>{booking.firstName}</td> | ||
<td>{booking.surname}</td> | ||
<td>{booking.email}</td> | ||
<td>{booking.roomId}</td> | ||
<td>{booking.checkInDate}</td> | ||
<td>{booking.checkOutDate}</td> | ||
<td> | ||
<button | ||
className="btn btn-primary" | ||
onClick={() => handleShowProfile(booking.id)} | ||
> | ||
Show profile | ||
</button> | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
{selectedCustomerId && ( | ||
<CustomerProfile customerId={selectedCustomerId} /> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
const CustomerProfile = ({ customerId }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You used the Id really well here to allow for searching. Only suggestion would be to move this into a separate file so it becomes its own reusable component if it needs to be used elsewhere. Similar to the other components in the app. |
||
const [customerData, setCustomerData] = useState(null); | ||
const [isLoading, setIsLoading] = useState(true); | ||
|
||
useEffect(() => { | ||
setIsLoading(true); | ||
fetch(`https://cyf-react.glitch.me/customers/${customerId}`) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error("Failed to fetch customer data"); | ||
} | ||
return response.json(); | ||
}) | ||
.then((data) => { | ||
setCustomerData(data); | ||
setIsLoading(false); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
setIsLoading(false); | ||
}); | ||
}, [customerId]); | ||
|
||
return ( | ||
<div> | ||
{isLoading ? ( | ||
<p>Loading customer profile...</p> | ||
) : ( | ||
<div> | ||
<h2>Customer Profile</h2> | ||
{customerData ? ( | ||
<ul> | ||
<li>ID: {customerData.id}</li> | ||
<li>Email: {customerData.email}</li> | ||
<li>VIP: {customerData.vip ? "Yes" : "No"}</li> | ||
<li>Phone: {customerData.phoneNumber}</li> | ||
</ul> | ||
) : ( | ||
<p>Unable to fetch customer profile.</p> | ||
)} | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchResults; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable makes it seem like the list contains only addresses. However it has an email and a phone number. It might be better to rename it to something like details.