Changeset f5b256e for my-react-app/src/components/RestaurantDetails.js
- Timestamp:
- 04/28/25 14:20:18 (3 weeks ago)
- Branches:
- main
- Children:
- deea3c4
- Parents:
- 8ca35dc
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
my-react-app/src/components/RestaurantDetails.js
r8ca35dc rf5b256e 6 6 import StarRating from "./StarRating"; 7 7 8 8 9 const RestaurantDetails = () => { 9 10 const navigate = useNavigate(); 11 const { id } = useParams(); 10 12 11 const { id } = useParams();12 13 const [restaurant, setRestaurant] = useState(null); 13 14 const [selectedTableId, setSelectedTableId] = useState(''); 14 const [selectedTimeSlot, setSelectedTimeSlot] = useState(''); 15 const [selectedDate, setSelectedDate] = useState(''); 16 const [selectedTime, setSelectedTime] = useState(''); 17 const [timeOptions, setTimeOptions] = useState([]); 15 18 const [selectedTable, setSelectedTable] = useState(null); 16 const [filteredTimeSlots, setFilteredTimeSlots] = useState([]);17 const [selectedCapacity, setSelectedCapacity] = useState(''); // Define selectedCapacity state18 19 19 20 useEffect(() => { … … 32 33 33 34 useEffect(() => { 34 if (!selectedTableId) return; // If no table is selected, return early35 if (!selectedTableId) return; 35 36 36 37 const fetchTableDetails = async () => { … … 46 47 }, [selectedTableId]); 47 48 48 useEffect(() => { 49 if (!selectedTable || !restaurant) return; // If table or restaurant is not loaded, return early 49 const today = new Date(); 50 const year = today.getFullYear(); 51 const month = String(today.getMonth() + 1).padStart(2, '0'); 52 const day = String(today.getDate()).padStart(2, '0'); 53 const formattedDate = `${year}-${month}-${day}`; 54 const parseOperatingHours = (operatingHours) => { 55 const [start, end] = operatingHours.split('-'); 56 const [startHour, startMinute] = start.split(':').map(Number); 57 const [endHour, endMinute] = end.split(':').map(Number); 50 58 51 // Filter time slots based on the selected table 52 const currentTime = new Date(); 53 const filteredSlots = selectedTable.timeSlots.filter(timeSlot => new Date(timeSlot) >= currentTime); 54 setFilteredTimeSlots(filteredSlots); 55 }, [selectedTable, restaurant]); 59 const startTime = new Date(); 60 startTime.setHours(startHour, startMinute, 0, 0); 56 61 62 const endTime = new Date(); 63 endTime.setHours(endHour < startHour ? endHour + 24 : endHour, endMinute, 0, 0); 57 64 58 const formatTimeSlot = (timeSlot) => { 59 const date = new Date(timeSlot); 60 const formattedDate = date.toLocaleDateString(); 61 const formattedTime = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); 62 return `${formattedDate} - ${formattedTime}`; 65 return { startTime, endTime }; 63 66 }; 64 67 65 const handleTableSelect = (event) => { 66 const selectedTableId = event.target.value; 67 setSelectedTableId(selectedTableId); 68 const generateTimeOptions = (operatingHours) => { 69 const { startTime, endTime } = parseOperatingHours(operatingHours); 70 const now = new Date(); 71 72 const selectedDateObj = new Date(selectedDate); 73 const isToday = selectedDateObj.toDateString() === now.toDateString(); 74 75 let currentTime = isToday ? roundToNext15Minutes(new Date()) : new Date(startTime); 76 77 const options = []; 78 while (currentTime <= endTime) { 79 options.push(currentTime.toTimeString().slice(0, 5)); 80 currentTime = new Date(currentTime.getTime() + 15 * 60 * 1000); 81 } 82 83 return options; 68 84 }; 69 85 70 const handleTimeSlotSelect = (event) => { 71 const selectedTimeSlot = event.target.value; 72 setSelectedTimeSlot(selectedTimeSlot); 86 useEffect(() => { 87 if (restaurant && selectedDate) { 88 const options = generateTimeOptions(restaurant.operatingHours); 89 setTimeOptions(options); 90 } 91 }, [restaurant, selectedDate]); 92 93 const handleTableSelect = (event) => { 94 setSelectedTableId(event.target.value); 73 95 }; 74 96 75 const handleReservationConfirmation = ( restaurant) => {76 const tableNumber = selectedTableId;77 const formattedTimeSlot = selectedTimeSlot;78 const restaurantId = restaurant.restaurantId;97 const handleReservationConfirmation = () => { 98 const encodedTableId = encodeURIComponent(selectedTableId); 99 const encodedDateTime = encodeURIComponent(`${selectedDate}T${selectedTime}`); 100 const encodedRestaurantId = encodeURIComponent(restaurant.restaurantId); 79 101 80 const encodedTableNumber = encodeURIComponent(tableNumber); 81 const encodedTimeSlot = encodeURIComponent(formattedTimeSlot); 82 const encodedRestaurantId = encodeURIComponent(restaurantId); 83 84 navigate(`/reservationConfirmation/${encodedTableNumber}/${encodedTimeSlot}/${encodedRestaurantId}`); 102 navigate(`/reservationConfirmation/${encodedTableId}/${encodedDateTime}/${encodedRestaurantId}`); 85 103 }; 86 104 105 const roundToNext15Minutes = (date) => { 106 const minutes = date.getMinutes(); 107 const remainder = minutes % 15; 108 if (remainder === 0) return date; 109 110 date.setMinutes(minutes + 15 - remainder); 111 date.setSeconds(0, 0); 112 return date; 113 }; 87 114 88 115 return ( … … 91 118 <> 92 119 <h2 className="card-title"> 93 {restaurant.name} <StarRating key={restaurant.id} rating={restaurant.rating} />120 {restaurant.name} <StarRating key={restaurant.id} rating={restaurant.rating} /> 94 121 </h2> 95 122 <div className="restaurant-details"> … … 98 125 <p>Address: {restaurant.address}</p> 99 126 <p>Phone: {restaurant.phone}</p> 100 <p>Website: <a href={restaurant.website}>{restaurant.website}</a></p> 127 <p> 128 Website: <a href={restaurant.website}>{restaurant.website}</a> 129 </p> 101 130 <p>Social Media Links: {restaurant.socialMediaLinks}</p> 102 131 103 132 <label>Select Table:</label> 104 <select className="form-select" aria-label="Select Table" onChange={handleTableSelect} 105 value={selectedTableId}> 133 <select 134 className="form-select" 135 aria-label="Select Table" 136 onChange={handleTableSelect} 137 value={selectedTableId} 138 > 106 139 <option value="">Select Table</option> 107 {restaurant.tablesList.map((table, index) => ( 108 <option key={index} 109 value={table.id}>{`Capacity: ${table.capacity} - ${table.location}`}</option> 140 {restaurant.tablesList.map((table) => ( 141 <option key={table.id} value={table.id}> 142 {`Capacity: ${table.capacity} - ${table.location}`} 143 </option> 110 144 ))} 111 145 </select> 146 112 147 {selectedTable && ( 113 148 <> 114 <label>Select Time Slot:</label> 115 <select className="form-select mt-2" aria-label="Select Time Slot" onChange={handleTimeSlotSelect}> 116 <option value="">Select Time Slot</option> 117 {filteredTimeSlots.map((timeSlot, index) => ( 118 <option key={index} value={timeSlot}>{formatTimeSlot(timeSlot)}</option> 149 <label>Select Date:</label> 150 <input 151 type="date" 152 className="form-control mt-2" 153 onChange={(event) => setSelectedDate(event.target.value)} 154 value={selectedDate} 155 min={formattedDate} 156 onKeyDown={(e) => e.preventDefault()} 157 /> 158 {!selectedDate && <p style={{ color: "red" }}>Please select a valid date.</p>} 159 160 <label>Select Time:</label> 161 <select 162 className="form-select mt-2" 163 onChange={(event) => setSelectedTime(event.target.value)} 164 value={selectedTime} 165 disabled={!selectedDate} 166 > 167 <option value="">Select Time</option> 168 {timeOptions.map((time, index) => ( 169 <option key={index} value={time}> 170 {time} 171 </option> 119 172 ))} 120 173 </select> 121 174 </> 122 175 )} 123 <br/> 124 {/* Add a button to trigger reservation confirmation */} 125 <button className="btn btn-primary" onClick={() => handleReservationConfirmation(restaurant)}> 176 177 <br /> 178 <button 179 className="btn btn-primary" 180 onClick={handleReservationConfirmation} 181 disabled={!selectedTableId || !selectedDate || !selectedTime} 182 > 126 183 Confirm Reservation 127 184 </button>
Note:
See TracChangeset
for help on using the changeset viewer.