[8ca35dc] | 1 | import React, { useEffect, useState } from "react";
|
---|
| 2 | import {jwtDecode} from "jwt-decode";
|
---|
| 3 | import axios from "axios";
|
---|
| 4 |
|
---|
| 5 | const ReservationHistory = () => {
|
---|
| 6 | const [reservations, setReservations] = useState([]);
|
---|
| 7 | const [loading, setLoading] = useState(true);
|
---|
| 8 | const [error, setError] = useState(null);
|
---|
| 9 |
|
---|
| 10 | useEffect(() => {
|
---|
| 11 | const fetchReservations = async () => {
|
---|
| 12 | try {
|
---|
| 13 | const token = localStorage.getItem("token");
|
---|
| 14 | if (!token) {
|
---|
| 15 | setError("User not authenticated.");
|
---|
| 16 | setLoading(false);
|
---|
| 17 | return;
|
---|
| 18 | }
|
---|
| 19 |
|
---|
| 20 | const decodedToken = jwtDecode(token);
|
---|
| 21 | const userId = decodedToken.iss;
|
---|
| 22 |
|
---|
| 23 | const response = await axios.get(
|
---|
| 24 | `http://localhost:8081/api/past-reservations/${userId}`,
|
---|
| 25 | {
|
---|
| 26 | headers: { Authorization: `Bearer ${token}` },
|
---|
| 27 | }
|
---|
| 28 | );
|
---|
| 29 |
|
---|
| 30 | setReservations(response.data);
|
---|
| 31 | } catch (err) {
|
---|
| 32 | setError("Failed to fetch reservations.");
|
---|
| 33 | } finally {
|
---|
| 34 | setLoading(false);
|
---|
| 35 | }
|
---|
| 36 | };
|
---|
| 37 |
|
---|
| 38 | fetchReservations();
|
---|
| 39 | }, []);
|
---|
| 40 |
|
---|
| 41 | if (loading) return <div>Loading...</div>;
|
---|
| 42 | if (error) return <div className="alert alert-danger">{error}</div>;
|
---|
| 43 |
|
---|
| 44 | return (
|
---|
| 45 | <div className="container mt-5">
|
---|
| 46 | <h3>Past Reservations</h3>
|
---|
| 47 | <table className="table table-bordered">
|
---|
| 48 | <thead className="thead-dark">
|
---|
| 49 | <tr>
|
---|
| 50 | <th>#</th>
|
---|
| 51 | <th>Restaurant</th>
|
---|
| 52 | <th>Table</th>
|
---|
| 53 | <th>Date & Time</th>
|
---|
| 54 | <th>Party Size</th>
|
---|
| 55 | <th>Special Requests</th>
|
---|
| 56 | <th>Status</th>
|
---|
| 57 | <th>Cancellation Reason</th>
|
---|
| 58 | </tr>
|
---|
| 59 | </thead>
|
---|
| 60 | <tbody>
|
---|
| 61 | {reservations.map((res, index) => (
|
---|
| 62 | <tr key={res.id}>
|
---|
| 63 | <td>{index + 1}</td>
|
---|
| 64 | <td>{res.restaurant?.name || "N/A"}</td>
|
---|
| 65 | <td>{res.table?.id || "N/A"}</td>
|
---|
| 66 | <td>{new Date(res.reservationDateTime).toLocaleString()}</td>
|
---|
| 67 | <td>{res.partySize}</td>
|
---|
| 68 | <td>{res.specialRequests || "None"}</td>
|
---|
| 69 | <td>{res.status}</td>
|
---|
| 70 | <td>{res.cancellationReason || "None"}</td>
|
---|
| 71 | </tr>
|
---|
| 72 | ))}
|
---|
| 73 | </tbody>
|
---|
| 74 | </table>
|
---|
| 75 | </div>
|
---|
| 76 | );
|
---|
| 77 | };
|
---|
| 78 |
|
---|
| 79 | export default ReservationHistory;
|
---|