Changeset c44c5ed for my-react-app


Ignore:
Timestamp:
05/02/25 15:06:42 (2 weeks ago)
Author:
Aleksandar Panovski <apano77@…>
Branches:
main
Children:
142c0f8
Parents:
2518b3a
Message:

Fixed bugs and fully developed menu now. Readonly added.

Location:
my-react-app/src
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • my-react-app/src/App.js

    r2518b3a rc44c5ed  
    1919import ReservationHistory from "./components/ReservationHistory";
    2020import AuthContent from "./components/AuthContent";
     21import MenuList from "./components/MenuList";
     22import ReadOnlyMenuList from "./components/ReadOnlyMenuList";
    2123
    2224const ProtectedRoute = ({ element, isAuthenticated }) => {
     
    326328                        <div key={restaurant.id} className="card mb-3">
    327329                            <div className="card-body">
    328                                 <RestaurantInfo key={restaurant.id} restaurant={restaurant}/>
    329                                 {/*<p>Available time slots</p>*/}
    330                                 <div className="d-flex flex-wrap">
    331                                     {restaurant.tablesList && restaurant.tablesList.length > 0 ? (
     330                                <div className="row">
     331                                    {/* Narrow left column: info and actions */}
     332                                    <div className="col-md-4">
     333                                        <RestaurantInfo key={restaurant.id} restaurant={restaurant}/>
    332334                                        <div className="d-flex flex-wrap">
    333                                             {renderTimeSlots(restaurant.tablesList, restaurant)}
     335                                            {restaurant.tablesList && restaurant.tablesList.length > 0 ? (
     336                                                renderTimeSlots(restaurant.tablesList, restaurant)
     337                                            ) : (
     338                                                <p>No tables available for reservations at this restaurant</p>
     339                                            )}
    334340                                        </div>
    335                                     ) : (
    336                                         <p>No tables available for reservations at this restaurant</p>
    337                                     )}
     341                                        <button
     342                                            className="btn btn-secondary mt-3"
     343                                            onClick={() => handleGoToRestaurant(restaurant.restaurantId)}
     344                                        >
     345                                            Go to Restaurant
     346                                        </button>
     347                                    </div>
     348
     349                                    {/* Wide right column: menu */}
     350                                    <div className="col-md-8">
     351                                        <ReadOnlyMenuList restaurantId={restaurant.restaurantId}/>
     352                                    </div>
    338353                                </div>
    339                                 <button
    340                                     className="btn btn-secondary"
    341                                     onClick={() => handleGoToRestaurant(restaurant.restaurantId)}
    342                                 >
    343                                     Go to Restaurant
    344                                 </button>
    345354                            </div>
    346355                        </div>
    347356                    ))}
    348357                </div>
     358
    349359
    350360                {showCuisineSearch && (
  • my-react-app/src/components/MenuList.js

    r2518b3a rc44c5ed  
    5858    return (
    5959        <div className="container mt-4">
    60             <h3 className="text-center">Menu</h3>
     60            {menuItems.length > 0 && <h3 className="text-center">Menu</h3>}
    6161            <div className="row">
    6262                {menuItems.map((item) => (
  • my-react-app/src/components/ReservationHistory.js

    r2518b3a rc44c5ed  
    11import React, { useEffect, useState } from "react";
    2 import {jwtDecode} from "jwt-decode";
     2import { jwtDecode } from "jwt-decode";
    33import axios from "axios";
     4import 'bootstrap/dist/css/bootstrap.min.css';
     5import 'bootstrap/dist/js/bootstrap.bundle.min';
    46
    57const ReservationHistory = () => {
    68    const [reservations, setReservations] = useState([]);
    79    const [filteredReservations, setFilteredReservations] = useState([]);
     10    const [selectedReservation, setSelectedReservation] = useState(null);
    811    const [loading, setLoading] = useState(true);
    912    const [error, setError] = useState(null);
     
    1417    const [statusFilter, setStatusFilter] = useState("");
    1518    const [cancellationReasonFilter, setCancellationReasonFilter] = useState("");
    16 
    1719    const [startDate, setStartDate] = useState("");
    1820    const [endDate, setEndDate] = useState("");
     
    113115    if (error) return <div className="alert alert-danger">{error}</div>;
    114116
     117    const formatDateTime = (dateString) => {
     118        if (!dateString) return "N/A";
     119        const date = new Date(dateString);
     120        return date.toLocaleString("en-GB", {
     121            day: "2-digit",
     122            month: "short",
     123            year: "numeric",
     124            hour: "2-digit",
     125            minute: "2-digit",
     126        });
     127    };
     128
    115129    return (
    116130        <div className="container mt-5">
     
    140154                        type="date"
    141155                        className="form-control"
    142                         placeholder="Start date"
    143156                        value={startDate}
    144157                        onChange={(e) => setStartDate(e.target.value)}
     
    147160                        type="date"
    148161                        className="form-control"
    149                         placeholder="End date"
    150162                        value={endDate}
    151163                        onChange={(e) => setEndDate(e.target.value)}
     
    156168                        type="number"
    157169                        className="form-control"
    158                         placeholder="Filter by Party Size"
     170                        placeholder="Party Size"
    159171                        value={partySizeFilter}
    160172                        onChange={(e) => setPartySizeFilter(e.target.value)}
     
    167179                        className="form-control"
    168180                    >
    169                         <option value="">Filter by status</option>
     181                        <option value="">Filter by Status</option>
    170182                        <option value="successful">Successful</option>
    171183                        <option value="canceled">Canceled</option>
     
    176188                        type="text"
    177189                        className="form-control"
    178                         placeholder="Filter by Cancellation Reason"
     190                        placeholder="Cancellation Reason"
    179191                        value={cancellationReasonFilter}
    180192                        onChange={(e) => setCancellationReasonFilter(e.target.value)}
     
    198210                        <th>Restaurant</th>
    199211                        <th>Table</th>
    200                         <th>Date & Time</th>
     212                        <th>Check In Date</th>
     213                        <th>Reserved on</th>
    201214                        <th>Party Size</th>
    202215                        <th>Special Requests</th>
     
    208221                    {filteredReservations.length > 0 ? (
    209222                        filteredReservations.map((res, index) => (
    210                             <tr key={res.id}>
     223                            <tr key={res.id} onClick={() => setSelectedReservation(res)} style={{ cursor: "pointer" }}>
    211224                                <td>{index + 1}</td>
    212225                                <td>{res.restaurant?.name || "N/A"}</td>
    213226                                <td>{res.table?.id || "N/A"}</td>
     227                                <td>{formatDateTime(res.checkInDate)}</td>
    214228                                <td>{new Date(res.reservationDateTime).toLocaleString()}</td>
    215229                                <td>{res.partySize}</td>
     
    221235                    ) : (
    222236                        <tr>
    223                             <td colSpan="8" className="text-center">No reservations found.</td>
     237                            <td colSpan="9" className="text-center">No reservations found.</td>
    224238                        </tr>
    225239                    )}
     
    227241                </table>
    228242            </div>
     243
     244            {/* Modal for reservation details */}
     245            {selectedReservation && (
     246                <div className="modal fade show d-block" tabIndex="-1" style={{ backgroundColor: "rgba(0,0,0,0.5)" }} onClick={() => setSelectedReservation(null)}>
     247                    <div className="modal-dialog modal-lg" onClick={(e) => e.stopPropagation()}>
     248                        <div className="modal-content">
     249                            <div className="modal-header">
     250                                <h5 className="modal-title">Reservation Details</h5>
     251                                <button type="button" className="btn-close" onClick={() => setSelectedReservation(null)}></button>
     252                            </div>
     253                            <div className="modal-body">
     254                                <h6>🍽️ Restaurant Info</h6>
     255                                <p><strong>Name:</strong> {selectedReservation.restaurant?.name}</p>
     256                                <p><strong>Address:</strong> {selectedReservation.restaurant?.address}</p>
     257                                <p><strong>Phone:</strong> {selectedReservation.restaurant?.phone}</p>
     258                                <p><strong>Rating:</strong> {selectedReservation.restaurant?.rating} ⭐</p>
     259                                <p><strong>Cuisine:</strong> {selectedReservation.restaurant?.cuisineType}</p>
     260                                <p><strong>Hours:</strong> {selectedReservation.restaurant?.operatingHours}</p>
     261                                {selectedReservation.restaurant?.website && (
     262                                    <p><strong>Website:</strong> <a href={`https://${selectedReservation.restaurant.website}`} target="_blank" rel="noopener noreferrer">{selectedReservation.restaurant.website}</a></p>
     263                                )}
     264
     265                                <hr />
     266
     267                                <h6>🪑 Table Info</h6>
     268                                <p><strong>Location:</strong> {selectedReservation.table?.location}</p>
     269                                <p><strong>Capacity:</strong> {selectedReservation.table?.capacity}</p>
     270                                <p><strong>Smoking Area:</strong> {selectedReservation.table?.smokingArea ? "Yes" : "No"}</p>
     271                                <p><strong>Description:</strong> {selectedReservation.table?.description}</p>
     272                                <p><strong>Reservation Duration:</strong> {selectedReservation.table?.reservationDurationHours} hours</p>
     273
     274                                <hr />
     275
     276                                <h6>📋 Reservation Info</h6>
     277                                <p><strong>Check-In Date:</strong> {formatDateTime(selectedReservation.checkInDate)}</p>
     278                                <p><strong>Reserved on:</strong> {new Date(selectedReservation.reservationDateTime).toLocaleString()}</p>
     279                                <p><strong>Party Size:</strong> {selectedReservation.partySize}</p>
     280                                <p><strong>Special Requests:</strong> {selectedReservation.specialRequests || "None"}</p>
     281                                <p><strong>Status:</strong> {selectedReservation.status}</p>
     282                                <p><strong>Cancellation Reason:</strong> {selectedReservation.cancellationReason || "None"}</p>
     283                            </div>
     284                            <div className="modal-footer">
     285                                <button className="btn btn-secondary" onClick={() => setSelectedReservation(null)}>Close</button>
     286                            </div>
     287                        </div>
     288                    </div>
     289                </div>
     290            )}
    229291        </div>
    230292    );
  • my-react-app/src/components/RestaurantContext.js

    r2518b3a rc44c5ed  
    1212            try {
    1313                const response = await axios.get('http://localhost:8081/api/restaurants');
    14                 console.log("Fetched once", response.data);
    1514                setRestaurants(response.data);
    1615            } catch (error) {
  • my-react-app/src/components/Restaurants.js

    r2518b3a rc44c5ed  
    2626    const navigate = useNavigate();
    2727    const restaurantContext = useContext(RestaurantContext);
    28     console.log(restaurantContext)
    2928
    3029    useEffect(() => {
Note: See TracChangeset for help on using the changeset viewer.