Changeset f5b256e for my-react-app/src/components/ReservationEdit.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/ReservationEdit.js
r8ca35dc rf5b256e 7 7 const ReservationEdit = () => { 8 8 const navigate = useNavigate(); 9 9 const { reservationId } = useParams(); 10 10 const [isLoading, setIsLoading] = useState(true); 11 const { reservationId } = useParams(); // Extract reservationId from URL params12 11 const [formData, setFormData] = useState({}); 12 const [tableNumber, setTableNumber] = useState({}); 13 13 const [table, setTable] = useState({}); 14 14 const [restaurant, setRestaurant] = useState({}); 15 const [restaurantId, setRestaurantId] = useState({}); 15 16 const [timeSlots, setTimeSlots] = useState([]); 16 17 const [filteredTimeSlots, setFilteredTimeSlots] = useState([]); 17 18 const [checkInTime, setCheckInTime] = useState([]); 19 const [tableReservations, setTableReservations] = useState([]); 20 21 const timeSlotInterval = 15; 22 23 const [selectedDate, setSelectedDate] = useState(''); 24 const [selectedTime, setSelectedTime] = useState(''); 25 const [timeOptions, setTimeOptions] = useState([]); 18 26 19 27 useEffect(() => { … … 22 30 setIsLoading(true); 23 31 const response = await axios.get(`http://localhost:8081/api/reservations/${reservationId}`); 24 setCheckInTime(response.data.checkInTime) 32 console.log(response) 33 setCheckInTime(response.data.reservationDateTime); 25 34 setFormData(response.data); 26 setTable(response.data.table); 27 setRestaurant(response.data.restaurant); 28 setTimeSlots(response.data.table.timeSlots); 35 setRestaurant(response.data.restaurantName); 36 setRestaurantId(response.data.restaurantId); 37 38 setTableNumber(response.data.tableNumber); 39 const tableResponse = await axios.get(`http://localhost:8081/api/tables/${response.data.tableNumber}`); 40 setTable(tableResponse.data) 41 29 42 setIsLoading(false); 30 43 } catch (error) { … … 32 45 } 33 46 }; 47 34 48 fetchReservation(); 35 49 }, [reservationId]); 36 50 37 51 useEffect(() => { 38 if (!table || !restaurant) return; // If table or restaurant is not loaded, return early 39 40 const currentTime = new Date(); 41 42 const filteredSlots = timeSlots.filter(timeSlot => new Date(timeSlot) >= currentTime); 43 setFilteredTimeSlots(filteredSlots); 44 }, [table, restaurant]); 52 const fetchTableReservations = async () => { 53 try { 54 const response = await axios.get(`http://localhost:8081/api/table-reservations/${table.tableId}`); 55 setTableReservations(response.data); 56 setIsLoading(false); 57 } catch (error) { 58 console.error('Error fetching table reservations:', error); 59 } 60 }; 61 62 if (table?.tableId) { 63 fetchTableReservations(); 64 } 65 }, [table]); 66 67 const generateTimeSlots = (operatingHours, interval) => { 68 const slots = []; 69 const [startTimeStr, endTimeStr] = operatingHours.split('-'); 70 const [startHours, startMinutes] = startTimeStr.split(':').map(Number); 71 const [endHours, endMinutes] = endTimeStr.split(':').map(Number); 72 73 const startTime = new Date(); 74 startTime.setHours(startHours, startMinutes, 0, 0); 75 76 const endTime = new Date(); 77 endTime.setHours(endHours, endMinutes, 0, 0); 78 79 let currentTime = startTime; 80 while (currentTime <= endTime) { 81 slots.push(new Date(currentTime).toISOString()); 82 currentTime = new Date(currentTime.getTime() + interval * 60000); 83 } 84 85 return slots; 86 }; 87 88 const generateTimeOptions = (operatingHours) => { 89 const { startTime, endTime } = parseOperatingHours(operatingHours); 90 const now = new Date(); 91 92 const selectedDateObj = new Date(selectedDate); 93 const isToday = selectedDateObj.toDateString() === now.toDateString(); 94 const isTomorrow = selectedDateObj > now && selectedDateObj.getDate() === now.getDate() + 1; 95 96 let currentTime; 97 98 if (isToday) { 99 currentTime = roundToNext15Minutes(new Date()); 100 } else { 101 currentTime = new Date(startTime); 102 } 103 104 const options = []; 105 while (currentTime <= endTime) { 106 options.push(currentTime.toTimeString().slice(0, 5)); 107 currentTime = new Date(currentTime.getTime() + 15 * 60 * 1000); 108 } 109 110 return options; 111 }; 112 113 useEffect(() => { 114 const operatingHours = table?.restaurant?.operatingHours || "09:00-00:00"; 115 const allTimeSlots = generateTimeSlots(operatingHours, timeSlotInterval); 116 117 const availableSlots = allTimeSlots.filter((slot) => 118 !tableReservations.includes(slot) 119 ); 120 121 setFilteredTimeSlots(availableSlots); 122 }, [tableReservations, table]); 45 123 46 124 const handleInputChange = (e) => { 47 125 const { name, value } = e.target; 48 126 49 // Check if the changed input is the time slot select element 50 if (name === 'selectedTimeSlot') { 51 // Update the formData with the selected time slot value 52 setFormData({ ...formData, checkInTime: value }); 127 if (name === 'partySize') { 128 const valueAsNumber = Math.min(value, table?.capacity); 129 setFormData(prevState => ({ 130 ...prevState, 131 [name]: valueAsNumber 132 })); 53 133 } else { 54 // For other input fields, update formData as usual 55 setFormData({ ...formData, [name]: value }); 56 } 57 }; 134 setFormData(prevState => ({ 135 ...prevState, 136 [name]: value 137 })); 138 } 139 }; 140 58 141 59 142 const handleSubmit = async (e) => { … … 68 151 69 152 const decodedToken = jwtDecode(token); 70 console.log(decodedToken)71 153 const userId = decodedToken.iss; 72 154 73 await axios.post(`http://localhost:8081/api/reservations/${reservationId}/${userId}`, formData); 74 75 navigate(`/reservations`) 155 const updatedReservationData = { 156 ...formData, 157 reservationDateTime: `${selectedDate}T${selectedTime}`, 158 checkInTime: checkInTime, 159 reservationID: reservationId, 160 }; 161 await axios.post( 162 `http://localhost:8081/api/reservations/${reservationId}/${userId}`, 163 updatedReservationData, 164 { 165 headers: { 166 'Content-Type': 'application/json', 167 } 168 } 169 ); 170 console.log(updatedReservationData) 171 172 navigate(`/reservations`); 76 173 } catch (error) { 77 174 console.error('Error updating reservation:', error); … … 86 183 }; 87 184 88 const formatCurrentTimeSlot = (timeSlot) => { 89 const date = new Date(timeSlot); 90 const formattedDate = date.toLocaleDateString('en-GB'); // Format date as YYYY-MM-DD 91 const formattedTime = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); // Format time as HH:MM 92 return `${formattedDate} ${formattedTime}`; 93 }; 185 const today = new Date(); 186 const year = today.getFullYear(); 187 const month = String(today.getMonth() + 1).padStart(2, '0'); 188 const day = String(today.getDate()).padStart(2, '0'); 189 const formattedDate = `${year}-${month}-${day}`; 190 191 const parseOperatingHours = (operatingHours) => { 192 const [start, end] = operatingHours.split('-'); 193 return { 194 startTime: new Date(`1970-01-01T${start}:00`), 195 endTime: new Date(`1970-01-01T${end}:00`) 196 }; 197 }; 198 199 useEffect(() => { 200 if (formData?.restaurant?.operatingHours && selectedDate) { 201 const options = generateTimeOptions(formData.restaurant.operatingHours); 202 setTimeOptions(options); 203 } 204 }, [restaurant, selectedDate]); 205 206 // useEffect(() => { 207 // if (checkInTime) { 208 // const checkInDateObj = new Date(checkInTime); 209 // setSelectedDate(checkInDateObj.toISOString().split("T")[0]); 210 // setSelectedTime(checkInDateObj.toTimeString().slice(0, 5)); 211 // } 212 // }, [checkInTime]); 94 213 95 214 return ( 96 215 <div className="container"> 97 {isLoading ? ( // Conditional rendering based on loading state216 {isLoading ? ( 98 217 <p>Loading...</p> 99 218 ) : ( … … 101 220 <h1>Edit Reservation</h1> 102 221 <div className="card-body"> 103 <h2 >104 { restaurant.name} <StarRating key={restaurant.id} rating={restaurant.rating}/>222 <h2 className="card-title"> 223 {formData.restaurant.name} <StarRating key={formData.restaurant.id} rating={formData.restaurant.rating} /> 105 224 </h2> 106 <p className="card-text">{ restaurant.cuisineType}</p>107 <p className="card-text">{ restaurant.operatingHours}</p>108 <p className="card-text">Ul. { restaurant.address}</p>109 <br />225 <p className="card-text">{formData.restaurant.name}</p> 226 <p className="card-text">{formData.restaurant.operatingHours}</p> 227 <p className="card-text">Ul. {formData.restaurant.address}</p> 228 <br /> 110 229 </div> 111 230 <form onSubmit={handleSubmit}> 112 231 <div className="mb-3"> 113 <label htmlFor="checkInTime" className="form-label">Check-in Time</label> 114 <select className="form-select mt-2" aria-label="Select Time Slot" 115 name="selectedTimeSlot" // Add name attribute 116 onChange={handleInputChange}> 117 <option value="">Select Time Slot</option> 118 {filteredTimeSlots.map((timeSlot, index) => ( 119 <option key={index} value={timeSlot}>{formatTimeSlot(timeSlot)}</option> 232 <label>Select Date:</label> 233 <input 234 type="date" 235 className="form-control mt-2" 236 onChange={(event) => setSelectedDate(event.target.value)} 237 value={selectedDate} 238 min={formattedDate} 239 /> 240 241 <label>Select Time:</label> 242 <select 243 className="form-select mt-2" 244 onChange={(event) => setSelectedTime(event.target.value)} 245 value={selectedTime} 246 disabled={!selectedDate} 247 > 248 <option value="">Select Time</option> 249 {timeOptions.map((time, index) => ( 250 <option key={index} value={time}> 251 {time} 252 </option> 120 253 ))} 121 254 </select> 122 <label className=".text-danger">Current check in time: {formatTimeSlot(checkInTime)}</label> 255 <label className="text-danger"> 256 Current check-in time: {formatTimeSlot(checkInTime)} 257 </label> 123 258 </div> 124 259 <div className="mb-3"> 125 260 <label htmlFor="partySize" className="form-label">Party Size</label> 126 <input type="number" className="form-control" id="partySize" name="partySize" 127 max={table.capacity} 128 value={formData.partySize || ''} onChange={handleInputChange}/> 261 <input 262 type="number" 263 className="form-control" 264 id="partySize" 265 name="partySize" 266 max={table?.capacity} 267 min={1} 268 value={formData.partySize || ''} 269 onChange={handleInputChange} 270 /> 271 <label className="text-danger"> 272 Table capacity: {table?.capacity} 273 </label> 129 274 </div> 130 275 <div className="mb-3"> 131 <label htmlFor="specialRequests" className="form-label">Special Requests</label> 132 <input type="text" className="form-control" id="specialRequests" name="specialRequests" 133 value={formData.specialRequests || ''} onChange={handleInputChange}/> 276 <label htmlFor="specialRequests" className="form-label">Special Requests</label> 277 <input 278 type="text" 279 className="form-control" 280 id="specialRequests" 281 name="specialRequests" 282 value={formData.specialRequests || ''} 283 onChange={handleInputChange} 284 /> 134 285 </div> 135 286 <button type="submit" className="btn btn-primary">Submit</button> … … 139 290 </div> 140 291 ); 141 142 292 }; 143 293
Note:
See TracChangeset
for help on using the changeset viewer.