source: my-react-app/src/components/Reservations.js

main
Last change on this file was b67dfd3, checked in by Aleksandar Panovski <apano77@…>, 12 days ago

Normalization needed to continue, till here done

  • Property mode set to 100644
File size: 7.9 KB
Line 
1import React, {useState, useEffect, useContext} from 'react';
2import axios from 'axios';
3import 'bootstrap/dist/css/bootstrap.min.css';
4import {useNavigate} from "react-router-dom";
5import {jwtDecode} from "jwt-decode";
6import {RestaurantContext} from "./RestaurantContext";
7
8
9const Reservations = () => {
10 const navigate = useNavigate();
11 const { restaurants } = useContext(RestaurantContext);
12 const [reservations, setReservations] = useState([]);
13
14 useEffect(() => {
15 const fetchReservations = async () => {
16 try {
17 const token = localStorage.getItem("token");
18 if (!token) {
19 console.error("No token found");
20 return;
21 }
22 const decodedToken = jwtDecode(token);
23 const userId = decodedToken.iss;
24
25 const response = await axios.get(`http://localhost:8081/api/reservations/by/${userId}`);
26 setReservations(response.data);
27 } catch (error) {
28 console.error('Error fetching reservations:', error);
29 }
30 };
31
32 fetchReservations();
33 }, []);
34
35 const handleEditReservation = async (reservationId) => {
36 if(reservationId!=null) {
37 navigate(`/reservations/reservationEdit/${reservationId}`);
38 }
39 }
40
41 const handleCancelReservation = async (reservationID) => {
42 try {
43 await axios.delete(`http://localhost:8081/api/reservations/delete/${reservationID}`);
44 setReservations(reservations.filter(reservation => reservation.reservationID !== reservationID));
45 alert('Reservation canceled successfully!');
46 } catch (error) {
47 console.error('Error canceling reservation:', error);
48 alert('An error occurred while canceling the reservation. Please try again later.');
49 }
50 };
51 return (
52 <div className="container">
53 <div className="row">
54 {reservations.length === 0 ? (
55 <div className="text-center mt-5">
56 <h4>No active reservations</h4>
57 <p>Looking for a place to dine? Check out our <a href="/restaurants" className="text-primary">restaurants</a>.</p>
58 </div>
59 ) : (
60 reservations.map(reservation => (
61 <div key={reservation.reservationID} className="col-md-4 mb-4">
62 <div className="card h-100">
63 <div className="card-body">
64 <h5 className="card-title">Reservation ID: {reservation.reservationID}</h5>
65 <p className="card-text">
66 Restaurant: {
67 restaurants.find(r => r.restaurantId === reservation.restaurantId)?.name || "Not specified"
68 }
69 </p>
70
71 <p className="card-text">Table
72 Number: {reservation?.tableNumber || "Not specified"}</p>
73 <p className="card-text">
74 Reservation Date: {reservation.checkInTime ?
75 new Date(reservation.checkInTime).toLocaleDateString('en-US', {
76 weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
77 }) :
78 "Not specified"}
79 </p>
80 <p className="card-text">
81 Reservation Time: {reservation.checkInTime ?
82 new Date(reservation.checkInTime).toLocaleTimeString('en-US', {
83 hour: 'numeric', minute: 'numeric', hour12: true
84 }) :
85 "Not specified"}
86 </p>
87 <p className="card-text">Reservation made on: {reservation.reservationDateTime ?
88 new Date(reservation.reservationDateTime).toLocaleTimeString('en-US', {
89 hour: 'numeric', minute: 'numeric', hour12: true
90 }) :
91 "Not specified"} {reservation.reservationDateTime ?
92 new Date(reservation.reservationDateTime).toLocaleDateString('en-US', {
93 weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
94 }) :
95 "Not specified"} </p>
96 <p className="card-text">Party Size: {reservation.partySize || "Not specified"}</p>
97 {reservation.preOrderedItems && reservation.preOrderedItems.length > 0 ? (
98 <div className="mt-3">
99 <h5 className="text-primary">Pre-Ordered Items:</h5>
100 <ul className="list-group mb-3">
101 {reservation.preOrderedItems.map((item, index) => (
102 <li key={index} className="list-group-item d-flex justify-content-between align-items-center">
103 <span><strong>{item?.preorderedItemName}</strong> × {item.quantity}</span>
104 <span className="badge bg-success rounded-pill">${(item.price * item.quantity).toFixed(2)}</span>
105 </li>
106 ))}
107 </ul>
108
109 <div className="alert alert-info text-center" role="alert">
110 <h5>Grand Total: ${reservation.preOrderedItems.reduce((acc, item) => acc + (item.quantity * item.price), 0).toFixed(2)}</h5>
111 </div>
112 </div>
113 ) : (
114 <p>No pre-ordered items.</p>
115 )}
116 <p className="card-text text-danger">Special Requests: {reservation.specialRequests || "None"}</p>
117 <p className="card-text">Status: {reservation.status || "Pending"}</p>
118 <p className="card-text text-danger">Grace period of 15 minutes +-</p>
119 <div className="d-flex justify-content-between mt-3">
120 <button
121 className="btn btn-warning"
122 onClick={() => handleEditReservation(reservation.reservationID)}>
123 Edit Reservation
124 </button>
125 <button
126 className="btn btn-danger"
127 onClick={() => handleCancelReservation(reservation.reservationID)}>
128 Cancel Reservation
129 </button>
130 </div>
131 </div>
132 </div>
133 </div>
134 ))
135 )}
136 </div>
137 </div>
138 );
139};
140
141export default Reservations;
142
Note: See TracBrowser for help on using the repository browser.