Ignore:
Timestamp:
01/19/25 23:18:37 (4 months ago)
Author:
Aleksandar Panovski <apano77@…>
Branches:
main
Children:
f5b256e
Parents:
db39d9e
Message:

Done with stupid timeslots

Location:
my-react-app/src/components
Files:
2 added
16 edited

Legend:

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

    rdb39d9e r8ca35dc  
    1 import * as React from "react";
     1import React from "react";
     2import axios from "axios";
    23import WelcomeContent from "./WelcomeContent";
    34import AuthContent from "./AuthContent";
    45import LoginForm from "./LoginForm";
    5 import { request, setAuthToken } from "../axios_helper";
    6 import Buttons from './Buttons'
     6import AuthForm from "./AuthForm";
     7import Buttons from './Buttons';
     8import restaurants from "./Restaurants";
    79
    8 export default class AppContent extends React.Component {
     10class AppContent extends React.Component {
    911    constructor(props) {
    1012        super(props);
    1113        this.state = {
    12             componentToShow: "welcome"
     14            componentToShow: "welcome",
     15            isAuthenticated: false,
     16            user: null,
     17            loading: false // Add loading state
    1318        };
     19    }
     20
     21    componentDidMount() {
     22        const token = localStorage.getItem('token');
     23        console.log(token);
     24        if (token) {
     25            this.setAuthToken(token);
     26            this.setState({ componentToShow: "restaurants", isAuthenticated: true });
     27        }
     28    }
     29
     30    fetchUserDetails = (token) => {
     31        console.log("Fetch");
     32        axios.get("/api/user")
     33            .then((response) => {
     34                this.setState({ user: response.data, componentToShow: "restaurants", isAuthenticated: true });
     35            })
     36            .catch((error) => {
     37                console.error("Failed to fetch user details:", error);
     38                this.logout();
     39            });
    1440    };
    1541
    1642    login = () => {
    17         this.setState({componentToShow: "login"})
     43        this.setState({ componentToShow: "login" });
    1844    }
    1945
    2046    logout = () => {
    21         this.setState({componentToShow: "welcome"})
     47        localStorage.removeItem('token');
     48        this.setAuthToken(null);
     49        this.setState({ componentToShow: "welcome", isAuthenticated: false });
    2250    }
    2351
    2452    onLogin = (e, email, password) => {
    2553        e.preventDefault();
    26         request(
    27             "POST",
    28             "/api/login",
    29             {email: email, password: password}
    30         ).then((response) => {
    31             this.setState({componentToShow: "restaurants"})
    32             setAuthToken(response.data.token);
    33         }).catch((error) => {
    34             this.setState({componentToShow: "welcome"})
    35         });
     54        // After successful login, save the token
     55        axios.post("/api/login", { email, password })
     56            .then((response) => {
     57                const token = response.data.token;
     58                localStorage.setItem('token', token);  // Save the token
     59                console.log(token);
     60                this.setAuthToken(token);  // Set the token for future requests
     61                this.setState({ componentToShow: "restaurants", isAuthenticated: true });
     62            })
     63            .catch((error) => {
     64                console.error("Login failed:", error);
     65                this.setState({ componentToShow: "welcome" });
     66            });
     67
    3668    };
    3769
    3870    onRegister = (e, firstName, lastName, email, password) => {
    3971        e.preventDefault();
    40         request(
    41             "POST",
    42             "/api/register",
    43             {
    44                 firstName: firstName,
    45                 lastName: lastName,
    46                 email: email,
    47                 password: password
    48             }
    49         ).then((response) => {
    50             this.setState({componentToShow: "restaurants"})
    51             setAuthToken(response.data.token);
    52         }).catch((error) => {
    53             this.setState({componentToShow: "welcome"})
    54         });
     72        axios.post("/api/register", { firstName, lastName, email, password })
     73            .then((response) => {
     74                const token = response.data.token;
     75                localStorage.setItem('token', token);
     76                console.log(token);
     77                this.setAuthToken(token);
     78                this.fetchUserDetails(token);
     79            })
     80            .catch((error) => {
     81                this.setState({ componentToShow: "welcome" });
     82                console.error(error);
     83            });
     84    };
     85
     86    setAuthToken = (token) => {
     87        if (token) {
     88            axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
     89        } else {
     90            delete axios.defaults.headers.common["Authorization"];
     91        }
    5592    };
    5693
     
    5895        return (
    5996            <div>
    60                 <Buttons login={this.login} logout={this.logout}></Buttons>
    61                 {this.state.componentToShow === "welcome" && <WelcomeContent/>}
    62                 {this.state.componentToShow === "restaurants" && <AuthContent/>}
    63                 {this.state.componentToShow === "login" && <LoginForm onLogin={this.onLogin} onRegister={this.onRegister}/>}
     97                <Buttons login={this.login} logout={this.logout} />
     98                {this.state.componentToShow === "welcome" && <WelcomeContent />}
     99                {this.state.componentToShow === "restaurants" && <AuthContent />}
     100                {this.state.componentToShow === "login" && <LoginForm onLogin={this.onLogin} onRegister={this.onRegister} />}
     101                {this.state.loading && <div>Loading...</div>} {/* Show loading state */}
    64102            </div>
    65         )
     103        );
    66104    }
    67105}
     106
     107
     108export default AppContent;
  • my-react-app/src/components/AuthContent.js

    rdb39d9e r8ca35dc  
    2828                        <p>Cuisine Type: {restaurant.cuisineType}</p>
    2929                        <p>Address: {restaurant.address}</p>
    30 
     30                        <p>User: {}</p>
    3131                    </div>
    3232                ))}
  • my-react-app/src/components/CuisineContext.js

    rdb39d9e r8ca35dc  
    1010        const fetchCuisineTypes = async () => {
    1111            try {
    12                 const response = await axios.get('http://localhost:8080/api/cuisineTypes');
     12                const response = await axios.get('http://localhost:8081/api/cuisineTypes');
    1313                setCuisineTypes(response.data);
    1414            } catch (error) {
  • my-react-app/src/components/CustomerContext.js

    rdb39d9e r8ca35dc  
    1010        const fetchCustomers = async () => {
    1111            try {
    12                 const response = await axios.get("http://localhost:8080/api/customers");
     12                const response = await axios.get("http://localhost:8081/api/customers");
    1313                setCustomers(response.data)
    1414            } catch (error) {
  • my-react-app/src/components/CustomerDetails.js

    rdb39d9e r8ca35dc  
    1010        const fetchCustomer = async () => {
    1111            try {
    12                 const response = await axios.get(`http://localhost:8080/api/customers/${id}`);
     12                const response = await axios.get(`http://localhost:8081/api/customers/${id}`);
    1313                setCustomer(response.data);
    1414            } catch (error) {
  • my-react-app/src/components/CustomerFormContainer.js

    rdb39d9e r8ca35dc  
    2626            const fetchCustomer = async () => {
    2727                try {
    28                     const response = await axios.get(`http://localhost:8080/api/customers/${id}`);
     28                    const response = await axios.get(`http://localhost:8081/api/customers/${id}`);
    2929                    const customerData = response.data;
    3030                    setFormData({
     
    5454        try {
    5555            if (customer) {
    56                 await axios.put(`http://localhost:8080/api/customers/edit/${customer.id}`, formData);
     56                await axios.put(`http://localhost:8081/api/customers/edit/${customer.id}`, formData);
    5757            } else {
    58                 await axios.post("http://localhost:8080/api/customers", formData);
     58                await axios.post("http://localhost:8081/api/customers", formData);
    5959            }
    6060            navigate("/customers");
  • my-react-app/src/components/Customers.js

    rdb39d9e r8ca35dc  
    2626    const handleDeleteClick = async (customerId) => {
    2727        try {
    28             await axios.delete(`http://localhost:8080/api/customers/delete/${customerId}`);
     28            await axios.delete(`http://localhost:8081/api/customers/delete/${customerId}`);
    2929            setCustomers(customers.filter(customer => customer.customerID !== customerId));
    3030            window.location.reload();
     
    4848                                    <p className="card-text"><strong>Phone:</strong> {customer.phone}</p>
    4949                                    <p className="card-text"><strong>Address:</strong> {customer.address}</p>
    50                                     <p className="card-text"><strong>Membership
    51                                         Level:</strong> {customer.membershipLevel}</p>
     50                                    <p className="card-text"><strong>Membership Level:</strong> {customer.membershipLevel}</p>
    5251                                    {/*<p className="card-text"><strong>Registration*/}
    5352                                    {/*    Date:</strong> {new Date(customer.registrationDate).toLocaleString()}</p>*/}
  • my-react-app/src/components/Header.js

    rdb39d9e r8ca35dc  
    11import React from 'react';
    2 import { Link } from 'react-router-dom';
     2import { Link, useNavigate } from 'react-router-dom';
    33
    44const Header = () => {
     5    const navigate = useNavigate();
     6
     7    // Check if the user is logged in by looking for a token in localStorage
     8    const isLoggedIn = localStorage.getItem('token');
     9
     10    const handleLogout = () => {
     11        // Clear the token from localStorage
     12        localStorage.removeItem('token');
     13        // Redirect to the home page or login page after logging out
     14        navigate('/login');
     15    };
     16
    517    return (
    618        <header className="header navbar navbar-expand-lg navbar-light bg-light">
     
    1527                        </li>
    1628                        <li className="nav-item">
    17                             <Link className="nav-link" to="/customers">Customers</Link>
    18                         </li>
    19                         <li className="nav-item">
    20                             <Link className="nav-link" to="/customers/add">Add Customer</Link>
    21                         </li>
    22                         <li className="nav-item">
    2329                            <Link className="nav-link" to="/restaurants">Restaurants</Link>
    2430                        </li>
     
    2632                            <Link className="nav-link" to="/reservations">Reservations</Link>
    2733                        </li>
     34                        <li className="nav-item">
     35                            <Link className="nav-link" to="/reservations-past">Reservation history</Link>
     36                        </li>
    2837                        <form className="form-inline mt-2 mt-md-0 ml-3">
    29                             <Link className="btn btn-outline-info my-2 my-sm-0" to={"/login"}>Login</Link>
     38                            {isLoggedIn ? (
     39                                <button className="btn btn-outline-danger my-2 my-sm-0" onClick={handleLogout}>Logout</button>
     40                            ) : (
     41                                <Link className="btn btn-outline-info my-2 my-sm-0" to="/login">Login</Link>
     42                            )}
    3043                        </form>
    3144                    </ul>
  • my-react-app/src/components/Login.js

    rdb39d9e r8ca35dc  
    66    const navigate = useNavigate();
    77    const [credentials, setCredentials] = useState({ username: '', password: '' });
     8    const [error, setError] = useState('');
    89
    910    const handleChange = (e) => {
     
    1516        e.preventDefault();
    1617        try {
    17             const response = await axios.post('http://localhost:8080/api/login', {
     18            const response = await axios.post('http://localhost:8081/api/login', {
    1819                email: credentials.username,
    1920                password: credentials.password
    2021            });
    2122            const { token } = response.data;
    22             // Store token securely (e.g., using HTTP cookies)
     23
     24            // Store token securely (consider httpOnly cookies)
    2325            localStorage.setItem('token', token);
    2426
     
    2729            // Handle login failure
    2830            console.error('Login failed:', error);
     31            setError('Login failed. Please check your credentials and try again.');
    2932        }
    3033    };
    31 
    3234
    3335    return (
     
    5355                    />
    5456                </div>
     57                {error && <div style={{ color: 'red' }}>{error}</div>}
    5558                <button type="submit">Login</button>
    5659            </form>
  • my-react-app/src/components/LoginForm.js

    rdb39d9e r8ca35dc  
    5555                    <div className="tab-content">
    5656                        <div
    57                             className={classNames("tab-pane", "fade", this.state.active === "login" ? "show active" : "")} id="pills-login">
     57                            className={classNames("tab-pane", "fade", this.state.active === "login" ? "show active" : "")}
     58                            id="pills-login">
    5859                            <form onSubmit={this.onSubmitLogin}>
    5960                                <div className="form-outline mb-4">
    60                                     <input type="email" id="email" name="email" className="form-control" onChange={this.onChangeHandler}/>
     61                                    <input type="email" id="email" name="email" className="form-control"
     62                                           onChange={this.onChangeHandler}/>
    6163                                    <label className="form-label" htmlFor="email">Email</label>
    6264                                </div>
    6365                                <div className="form-outline mb-4">
    64                                     <input type="password" id="loginPassword" name="password" className="form-control" onChange={this.onChangeHandler}/>
     66                                    <input type="password" id="loginPassword" name="password" className="form-control"
     67                                           onChange={this.onChangeHandler}/>
    6568                                    <label className="form-label" htmlFor="loginPassword">Password</label>
    6669                                </div>
     
    7174
    7275                        <div
    73                             className={classNames("tab-pane", "fade", this.state.active === "register" ? "show active" : "")} id="pills-register">
     76                            className={classNames("tab-pane", "fade", this.state.active === "register" ? "show active" : "")}
     77                            id="pills-register">
    7478                            <form onSubmit={this.onSubmitRegister}>
    7579                                <div className="form-outline mb-4">
    76                                     <input type="text" id="firstName" name="firstName" className="form-control" onChange={this.onChangeHandler}/>
     80                                    <input type="text" id="firstName" name="firstName" className="form-control"
     81                                           onChange={this.onChangeHandler}/>
    7782                                    <label className="form-label" htmlFor="firstName">First Name</label>
    7883                                </div>
    7984                                <div className="form-outline mb-4">
    80                                     <input type="text" id="lastName" name="lastName" className="form-control" onChange={this.onChangeHandler}/>
     85                                    <input type="text" id="lastName" name="lastName" className="form-control"
     86                                           onChange={this.onChangeHandler}/>
    8187                                    <label className="form-label" htmlFor="lastName">Last Name</label>
    8288                                </div>
    8389                                <div className="form-outline mb-4">
    84                                     <input type="text" id="email" name="email" className="form-control" onChange={this.onChangeHandler}/>
     90                                    <input type="email" id="email" name="email" className="form-control"
     91                                           onChange={this.onChangeHandler}/>
    8592                                    <label className="form-label" htmlFor="email">Email</label>
    8693                                </div>
    8794                                <div className="form-outline mb-4">
    88                                     <input type="password" id="loginPassword" name="password" className="form-control" onChange={this.onChangeHandler}/>
     95                                    <input type="password" id="loginPassword" name="password" className="form-control"
     96                                           onChange={this.onChangeHandler}/>
    8997                                    <label className="form-label" htmlFor="loginPassword">Password</label>
    9098                                </div>
    9199
    92                                 <button type="submit" className="btn btn-primary btn-block mb-4">Sign In</button>
     100                                <button type="submit" className="btn btn-primary btn-block mb-4">Register</button>
    93101                            </form>
    94102                        </div>
     
    96104                </div>
    97105            </div>
    98         )
     106        );
     107
    99108    }
    100109}
  • my-react-app/src/components/MembershipsEnum.js

    rdb39d9e r8ca35dc  
    33
    44const MembershipsEnum = () => {
    5     const [memberships, setMemberships] = useState([]);
    6 
    7     useEffect(() => {
    8         const fetchMemberships = async () => {
    9             try {
    10                 const response = await axios.get('http://localhost:8080/api/memberships');
    11                 // Assuming the response.data is an array of enum values
    12                 setMemberships(response.data);
    13             } catch (error) {
    14                 console.error('Error fetching enum data:', error);
    15             }
    16         };
    17 
    18         fetchMemberships();
    19     }, []);
    20 
    21     return memberships;
     5    return ['GOLD', 'PLATINUM', 'STANDARD'];
    226};
    237
  • my-react-app/src/components/ReservationConfirmation.js

    rdb39d9e r8ca35dc  
    33import axios from 'axios';
    44import { useNavigate } from 'react-router-dom';
     5import {jwtDecode} from "jwt-decode";
    56
    67const ReservationConfirmation = () => {
     
    1718        const fetchTableDetails = async () => {
    1819            try {
    19                 const tableResponse = await axios.get(`http://localhost:8080/api/tables/${tableNumber}`);
     20                const tableResponse = await axios.get(`http://localhost:8081/api/tables/${tableNumber}`);
    2021                setTable(tableResponse.data);
    2122
    22                 const restaurantResponse = await axios.get(`http://localhost:8080/api/restaurants/${restaurantId}`);
     23                const restaurantResponse = await axios.get(`http://localhost:8081/api/restaurants/${restaurantId}`);
    2324                setRestaurant(restaurantResponse.data);
    2425            } catch (error) {
     
    3132    const handleSubmit = async (e) => {
    3233        e.preventDefault();
    33         // Handle form submission here
     34
     35        if (!restaurant || !table) {
     36            console.error("Restaurant or table is missing.");
     37            return;
     38        }
     39
    3440        try {
    35             // Check if restaurant and table are valid
    36             if (!restaurant || !table) {
    37                 console.error("Restaurant or table is missing.");
     41            const token = localStorage.getItem("token");
     42            if (!token) {
     43                console.error("No token found");
    3844                return;
    3945            }
    4046
    41             const response = await axios.post(`http://localhost:8080/api/reservations`, {
    42                 restaurant: restaurant, // Assuming restaurant has an 'id' property
    43                 table: table, // Assuming table has an 'id' property
    44                 checkInTime: timeSlot, // Fill in as needed
    45                 partySize: partySize,
    46                 specialRequests: specialRequests
    47             });
    48             // Handle successful reservation creation
    49             // console.log("Reservation created:", response.data);
    50             navigate("/reservations")
     47            // Decode the token to get the user email
     48            const decodedToken = jwtDecode(token);
     49            console.log(decodedToken)
     50            const userId = decodedToken.iss;// Assuming the email is part of the decoded JWT token
     51
     52            const response = await axios.post(
     53                `http://localhost:8081/api/reservations/${userId}`,
     54                {
     55                    restaurant: restaurant,
     56                    table: table,
     57                    checkInTime: timeSlot,
     58                    partySize: partySize,
     59                    specialRequests: specialRequests
     60                },
     61                {
     62                    headers: {
     63                        Authorization: `Bearer ${token}` // Include the token here
     64                    }
     65                }
     66            );
     67
     68            navigate("/reservations");
    5169        } catch (error) {
    5270            console.error("Error creating reservation:", error);
  • my-react-app/src/components/ReservationEdit.js

    rdb39d9e r8ca35dc  
    33import {useNavigate, useParams} from 'react-router-dom';
    44import StarRating from "./StarRating";
     5import {jwtDecode} from "jwt-decode";
    56
    67const ReservationEdit = () => {
     
    1415    const [timeSlots, setTimeSlots] = useState([]);
    1516    const [filteredTimeSlots, setFilteredTimeSlots] = useState([]);
     17    const [checkInTime, setCheckInTime] = useState([]);
    1618
    1719    useEffect(() => {
     
    1921            try {
    2022                setIsLoading(true);
    21                 const response = await axios.get(`http://localhost:8080/api/reservations/${reservationId}`);
    22                 setFormData(response.data); // Set form data with reservation data
     23                const response = await axios.get(`http://localhost:8081/api/reservations/${reservationId}`);
     24                setCheckInTime(response.data.checkInTime)
     25                setFormData(response.data);
    2326                setTable(response.data.table);
    2427                setRestaurant(response.data.restaurant);
     
    5659    const handleSubmit = async (e) => {
    5760        e.preventDefault();
     61
    5862        try {
    59             // Send updated reservation data to the server
    60             await axios.post(`http://localhost:8080/api/reservations/${reservationId}`, formData);
    61             // Redirect or show success message
     63            const token = localStorage.getItem("token");
     64            if (!token) {
     65                console.error("No token found");
     66                return;
     67            }
     68
     69            const decodedToken = jwtDecode(token);
     70            console.log(decodedToken)
     71            const userId = decodedToken.iss;
     72
     73            await axios.post(`http://localhost:8081/api/reservations/${reservationId}/${userId}`, formData);
     74
    6275            navigate(`/reservations`)
    6376        } catch (error) {
     
    7184        const formattedTime = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
    7285        return `${formattedDate} - ${formattedTime}`;
     86    };
     87
     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}`;
    7393    };
    7494
     
    100120                                ))}
    101121                            </select>
     122                            <label className=".text-danger">Current check in time: {formatTimeSlot(checkInTime)}</label>
    102123                        </div>
    103124                        <div className="mb-3">
  • my-react-app/src/components/Reservations.js

    rdb39d9e r8ca35dc  
    33import 'bootstrap/dist/css/bootstrap.min.css';
    44import {useNavigate} from "react-router-dom";
     5import {jwtDecode} from "jwt-decode";
    56
    67
     
    1314        const fetchReservations = async () => {
    1415            try {
    15                 const response = await axios.get('http://localhost:8080/api/reservations'); // Adjust URL as needed
     16                const token = localStorage.getItem("token");
     17                if (!token) {
     18                    console.error("No token found");
     19                    return;
     20                }
     21                const decodedToken = jwtDecode(token);
     22                console.log(decodedToken)
     23                const userId = decodedToken.iss;
     24
     25                const response = await axios.get(`http://localhost:8081/api/reservations/by/${userId}`);
    1626                setReservations(response.data);
    1727            } catch (error) {
     
    3141    const handleCancelReservation = async (reservationID) => {
    3242        try {
    33             await axios.delete(`http://localhost:8080/api/reservations/delete/${reservationID}`);
     43            await axios.delete(`http://localhost:8081/api/reservations/delete/${reservationID}`);
    3444            setReservations(reservations.filter(reservation => reservation.reservationID !== reservationID));
    3545            alert('Reservation canceled successfully!');
  • my-react-app/src/components/RestaurantContext.js

    rdb39d9e r8ca35dc  
    1010        const fetchRestaurants = async () => {
    1111            try {
    12                 const response = await axios.get('http://localhost:8080/api/restaurants');
     12                const response = await axios.get('http://localhost:8081/api/restaurants');
    1313                setRestaurants(response.data);
    1414            } catch (error) {
     
    1717        };
    1818
    19         fetchRestaurants();
     19        fetchRestaurants().then(r => console.log(fetchRestaurants()));
    2020    }, []);
    2121
  • my-react-app/src/components/RestaurantDetails.js

    rdb39d9e r8ca35dc  
    2121            try {
    2222                if (!id) return;
    23                 const response = await axios.get(`http://localhost:8080/api/restaurants/${id}`);
     23                const response = await axios.get(`http://localhost:8081/api/restaurants/${id}`);
    2424                setRestaurant(response.data);
    2525            } catch (error) {
     
    3636        const fetchTableDetails = async () => {
    3737            try {
    38                 const response = await axios.get(`http://localhost:8080/api/tables/${selectedTableId}`);
     38                const response = await axios.get(`http://localhost:8081/api/tables/${selectedTableId}`);
    3939                setSelectedTable(response.data);
    4040            } catch (error) {
Note: See TracChangeset for help on using the changeset viewer.