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

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

menu feature done

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[d24f17c]1import React, { useState, useEffect } from 'react';
2import axios from 'axios';
3import 'bootstrap/dist/css/bootstrap.min.css';
4import {useNavigate} from "react-router-dom";
[8ca35dc]5import {jwtDecode} from "jwt-decode";
[d24f17c]6
7
8const Reservations = () => {
9 const navigate = useNavigate();
10
11 const [reservations, setReservations] = useState([]);
12
13 useEffect(() => {
14 const fetchReservations = async () => {
15 try {
[8ca35dc]16 const token = localStorage.getItem("token");
17 if (!token) {
18 console.error("No token found");
19 return;
20 }
21 const decodedToken = jwtDecode(token);
22 const userId = decodedToken.iss;
23
24 const response = await axios.get(`http://localhost:8081/api/reservations/by/${userId}`);
[d24f17c]25 setReservations(response.data);
[e15e8d9]26 console.log(response.data)
[d24f17c]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 {
[8ca35dc]43 await axios.delete(`http://localhost:8081/api/reservations/delete/${reservationID}`);
[d24f17c]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">
[f5b256e]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">Restaurant: {reservation?.restaurant.name || "Not specified"}</p>
66 <p className="card-text">Table Number: {reservation?.tableNumber || "Not specified"}</p>
67 <p className="card-text">
68 Reservation Date: {reservation.checkInTime ?
69 new Date(reservation.checkInTime).toLocaleDateString('en-US', {
70 weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
71 }) :
72 "Not specified"}
73 </p>
74 <p className="card-text">
75 Reservation Time: {reservation.checkInTime ?
76 new Date(reservation.checkInTime).toLocaleTimeString('en-US', {
77 hour: 'numeric', minute: 'numeric', hour12: true
78 }) :
79 "Not specified"}
80 </p>
81 <p className="card-text">Reservation made on: {reservation.reservationDateTime ?
82 new Date(reservation.reservationDateTime).toLocaleTimeString('en-US', {
83 hour: 'numeric', minute: 'numeric', hour12: true
84 }) :
85 "Not specified"} {reservation.reservationDateTime ?
86 new Date(reservation.reservationDateTime).toLocaleDateString('en-US', {
87 weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
88 }) :
89 "Not specified"} </p>
90 <p className="card-text">Party Size: {reservation.partySize || "Not specified"}</p>
[e15e8d9]91 {reservation.preOrderedItems && reservation.preOrderedItems.length > 0 ? (
92 <div className="mt-3">
93 <h5 className="text-primary">Pre-Ordered Items:</h5>
94 <ul className="list-group mb-3">
95 {reservation.preOrderedItems.map((itemStr, index) => {
96 const parts = itemStr.split(':');
97 const name = parts[0];
98 const quantity = parseInt(parts[1], 10) || 0;
99 const price = parseFloat(parts[2]) || 0;
100
101 return (
102 <li key={index} className="list-group-item d-flex justify-content-between align-items-center">
103 <span><strong>{name}</strong> × {quantity}</span>
104 <span className="badge bg-success rounded-pill">${(price * quantity).toFixed(2)}</span>
105 </li>
106 );
107 })}
108 </ul>
109
110 <div className="alert alert-info text-center" role="alert">
111 <h5>Grand Total: ${reservation.preOrderedItems.reduce((acc, itemStr) => {
112 const parts = itemStr.split(':');
113 const quantity = parseInt(parts[1], 10) || 0;
114 const price = parseFloat(parts[2]) || 0;
115 return acc + (quantity * price);
116 }, 0).toFixed(2)}</h5>
117 </div>
118 </div>
119 ) : (
120 <p>No pre-ordered items.</p>
121 )}
[f5b256e]122 <p className="card-text text-danger">Special Requests: {reservation.specialRequests || "None"}</p>
123 <p className="card-text">Status: {reservation.status || "Pending"}</p>
124 <p className="card-text text-danger">Grace period of 15 minutes +-</p>
125 <div className="d-flex justify-content-between mt-3">
126 <button
127 className="btn btn-warning"
128 onClick={() => handleEditReservation(reservation.reservationID)}>
129 Edit Reservation
[d24f17c]130 </button>
[f5b256e]131 <button
132 className="btn btn-danger"
133 onClick={() => handleCancelReservation(reservation.reservationID)}>
134 Cancel Reservation
[d24f17c]135 </button>
136 </div>
137 </div>
138 </div>
139 </div>
[f5b256e]140 ))
141 )}
[d24f17c]142 </div>
143 </div>
144 );
145};
146
147export default Reservations;
[f5b256e]148
Note: See TracBrowser for help on using the repository browser.