source: my-react-app/src/components/Restaurants.js@ f5b256e

main
Last change on this file since f5b256e was f5b256e, checked in by Aleksandar Panovski <apano77@…>, 3 weeks ago

Big change done works with handle_reservation_update() trigger

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[cfc16a3]1import React, {useState, useEffect, useContext} from 'react';
[d24f17c]2import 'bootstrap/dist/css/bootstrap.min.css';
3import StarRating from './StarRating';
4import { useNavigate } from 'react-router-dom';
[cfc16a3]5import {RestaurantContext} from "./RestaurantContext";
[f5b256e]6import {Alert} from "bootstrap";
7
8const parseTime = (timeString) => {
9 const [hours, minutes] = timeString.trim().split(':').map(Number);
10 return new Date().setHours(hours, minutes, 0, 0);
11};
12
13const roundToNextQuarter = (date) => {
14 const minutes = date.getMinutes();
15 const roundedMinutes = Math.floor(minutes / 15) * 15;
16 date.setMinutes(roundedMinutes, 0, 0);
17 return date;
18};
19
20const shouldMoveToNextDay = (currentTime, endTime) => {
21 return (endTime - currentTime) <= 2 * 60 * 60 * 1000;
22};
[d24f17c]23
24const Restaurants = () => {
25 const [restaurants, setRestaurants] = useState([]);
26 const navigate = useNavigate();
[cfc16a3]27 const restaurantContext = useContext(RestaurantContext);
[d24f17c]28
29 useEffect(() => {
[cfc16a3]30 setRestaurants(restaurantContext.restaurants);
31 }, [restaurantContext]);
[d24f17c]32
[f5b256e]33
34 const generateTimeSlots = (operatingHours) => {
35 const timeSlots = [];
36 const [startTimeStr, endTimeStr] = operatingHours.split('-').map((time) => time.trim());
37
38 const startTime = parseTime(startTimeStr);
39 let endTime = parseTime(endTimeStr);
40
41 const currentTime = new Date().getTime();
42 if (shouldMoveToNextDay(currentTime, endTime)) {
43 endTime += 24 * 60 * 60 * 1000;
44 }
45
46 let currentTimeSlot = new Date(startTime);
47 currentTimeSlot = roundToNextQuarter(currentTimeSlot);
48
49 while (currentTimeSlot.getTime() < endTime) {
50 timeSlots.push(currentTimeSlot.toISOString());
51 currentTimeSlot.setMinutes(currentTimeSlot.getMinutes() + 15);
52 }
53
54 return timeSlots;
55 };
56
[d24f17c]57 const handleDetailClick = (restaurantId) => {
58 navigate(`/restaurants/${restaurantId}`);
[f5b256e]59 };
[d24f17c]60
61 const handleTimeSlotClick = (table, timeSlot, restaurant) => {
62 const tableNumber = table.id;
63 const formattedTimeSlot = timeSlot;
64 const restaurantId = restaurant.restaurantId;
65
[f5b256e]66 const encodedTableNumber = encodeURIComponent(tableNumber);
[d24f17c]67 const encodedTimeSlot = encodeURIComponent(formattedTimeSlot);
68 const encodedRestaurantId = encodeURIComponent(restaurantId);
69
70 navigate(`/reservationConfirmation/${encodedTableNumber}/${encodedTimeSlot}/${encodedRestaurantId}`);
[f5b256e]71 };
[d24f17c]72
73 const renderTimeSlots = (tablesList, restaurant) => {
74 const currentTime = new Date().getTime();
[f5b256e]75 let renderedTimeSlots = {};
76
77 if (tablesList.length === 0) {
78 return <p>No tables available for reservations at this restaurant.</p>;
79 }
80
81 return tablesList.flatMap((table) => {
82 const tableTimeSlots = generateTimeSlots(restaurant.operatingHours);
[d24f17c]83
84 if (!renderedTimeSlots[table.capacity]) {
85 renderedTimeSlots[table.capacity] = 0;
86 return (
87 <div key={table.capacity}>
[f5b256e]88 <h3>Table for {table.capacity} guests</h3>
89 {tableTimeSlots.map((timeSlot, index) => {
[d24f17c]90 const timeSlotTime = new Date(timeSlot).getTime();
91
[f5b256e]92 if (timeSlotTime > currentTime && renderedTimeSlots[table.capacity] < 3) {
93 renderedTimeSlots[table.capacity]++;
[d24f17c]94 const timeSlotDateTime = new Date(timeSlot);
[f5b256e]95 const formattedTime = timeSlotDateTime.toLocaleTimeString([], {
96 hour: '2-digit',
97 minute: '2-digit'
98 });
[d24f17c]99
100 return (
[f5b256e]101 <button
102 key={index}
103 className="btn btn-primary me-2 mb-2"
104 onClick={() => handleTimeSlotClick(table, timeSlot, restaurant)}
105 >
106 {formattedTime} {}
[d24f17c]107 </button>
108 );
109 } else {
[f5b256e]110 return null;
[d24f17c]111 }
112 })}
113 </div>
114 );
115 } else {
116 return null;
117 }
118 });
[f5b256e]119 };
[d24f17c]120
121 return (
122 <div className="container">
123 <h2>Restaurants</h2>
124 <div className="row">
125 {restaurants.map((restaurant) => (
[f5b256e]126 <div key={restaurant.restaurantId} className="col-md-4 mb-4">
[d24f17c]127 <div className="card">
128 <div className="card-body">
129 <h5 className="card-title">
[f5b256e]130 {restaurant.name}
[d24f17c]131 </h5>
132 <p className="card-text">{restaurant.cuisineType}</p>
133 <p className="card-text">{restaurant.operatingHours}</p>
134 <p className="card-text">Ul. {restaurant.address}</p>
[f5b256e]135
136 {restaurant.tablesList && restaurant.tablesList.length > 0 ? (
137 <div className="d-flex flex-wrap">
138 {renderTimeSlots(restaurant.tablesList, restaurant)}
139 </div>
140 ) : (
141 <p>No tables available for reservations at this restaurant.</p>
142 )}
[d24f17c]143 </div>
[f5b256e]144 <button onClick={() => handleDetailClick(restaurant.restaurantId)} className="btn btn-primary">
145 View Details
[cfc16a3]146 </button>
[d24f17c]147 </div>
148 </div>
149 ))}
150 </div>
151 </div>
152 );
153};
154
[f5b256e]155export default Restaurants;
Note: See TracBrowser for help on using the repository browser.