diff --git a/backend/controller/customer.controller.js b/backend/controller/customer.controller.js index a821f0d..8922b9f 100644 --- a/backend/controller/customer.controller.js +++ b/backend/controller/customer.controller.js @@ -188,6 +188,28 @@ async function resetPassword(req, res) { } } +async function getCustomerDetail (req, res) { + const { id } = req.user; + + try { + // Find user by ID and populate related fields if needed + const user = await Customer.findById(id) + .populate('bookedEvents') // Populate booked events if needed + .populate('orders') // Populate orders if needed + .populate('reservations') // Populate reservations if needed + .select('-password -verificationCode -otp'); // Exclude sensitive fields + + if (!user) { + return res.status(404).json({ message: 'User not found' }); + } + + res.status(200).json(user); + } catch (error) { + console.error("Error fetching user profile:", error); + res.status(500).json({ message: 'Server error while fetching user profile' }); + } +} + async function logout(req, res){ req.session.destroy((err) => { if (err) { @@ -202,5 +224,6 @@ module.exports = { loginCustomer, resetPassword, logout, - verifyOtp + verifyOtp, + getCustomerDetail, }; diff --git a/backend/controller/event.controller.js b/backend/controller/event.controller.js index 6b29ca6..3d135be 100644 --- a/backend/controller/event.controller.js +++ b/backend/controller/event.controller.js @@ -1,4 +1,5 @@ const logger = require("../config/logger"); +const Customer = require("../models/customer.model"); const Event = require("../models/events.model"); // Create a new event @@ -67,4 +68,68 @@ const getEvents = async (req, res) => { } }; -module.exports = { createEvent, getEvents, deleteEvent }; +const bookEvent = async (req, res) => { + const { eventId } = req.body; + const userId = req.user; + + try { + // Check if eventId is provided + if (!eventId) { + return res.status(400).json({ message: "Event ID is required" }); + } + + // Check if the event exists + const event = await Event.findById(eventId); + if (!event) { + return res.status(404).json({ message: "Event not found" }); + } + + // Find the user and check if they have already booked this event + const customer = await Customer.findById(userId); + if (!customer) { + return res.status(404).json({ message: "User not found" }); + } + + // Check if the event is already booked + const isAlreadyBooked = customer.bookedEvents.some( + (bookedEvent) => bookedEvent.toString() === eventId + ); + + if (isAlreadyBooked) { + return res.status(400).json({ message: "Event already booked" }); + } + + // Add the event to the user's bookedEvents array + customer.bookedEvents.push(eventId); + await customer.save(); + + res.status(200).json({ + message: "Event successfully booked", + bookedEvent: event, + }); + } catch (error) { + console.error("Error booking event:", error); + res.status(500).json({ message: "Internal server error while booking event" }); + } +}; + +const getBookedEvents = async (req, res) => { + const { id } = req.user; + + try { + // Find the customer by ID and populate the bookedEvents field with event details + const customer = await Customer.findById(id).populate('bookedEvents'); + + if (!customer) { + return res.status(404).json({ message: 'Customer not found' }); + } + + res.status(200).json({ + bookedEvents: customer.bookedEvents, + }); + } catch (error) { + console.error("Error fetching booked events:", error); + res.status(500).json({ message: 'Server error while fetching booked events' }); + } +} +module.exports = { createEvent, getEvents, deleteEvent , getBookedEvents , bookEvent}; diff --git a/backend/routes/customerRouter.js b/backend/routes/customerRouter.js index d06c51b..c4164bb 100644 --- a/backend/routes/customerRouter.js +++ b/backend/routes/customerRouter.js @@ -5,6 +5,7 @@ const { resetPassword, logout, verifyOtp, + getCustomerDetail, } = require("../controller/customer.controller"); const authenticateCustomer = require("../middlewares/authCustomer"); const passport = require("../config/passport.config"); @@ -38,5 +39,6 @@ router.get( router.post("/login", loginCustomer); router.post("/reset-password", resetPassword); +router.get('/profile',authenticateCustomer, getCustomerDetail ); module.exports = router; diff --git a/backend/routes/eventRouter.js b/backend/routes/eventRouter.js index a6e7c1d..166eeee 100644 --- a/backend/routes/eventRouter.js +++ b/backend/routes/eventRouter.js @@ -4,6 +4,9 @@ const { createEvent, getEvents, deleteEvent, + getBookedEvents, + + bookEvent, } = require("../controller/event.controller"); const authenticateCustomer = require("../middlewares/authCustomer"); @@ -30,6 +33,8 @@ router.get("/", async (req, res) => { router.post("/create",authenticateCustomer, createEvent); router.get("/all",authenticateCustomer, getEvents); router.get("/delete",authenticateCustomer, deleteEvent); +router.get('/booked-events',authenticateCustomer, getBookedEvents); +router.post('/book',authenticateCustomer, bookEvent); module.exports = router; diff --git a/frontend/src/components/Pages/Dashboard.tsx b/frontend/src/components/Pages/Dashboard.tsx index 2e81c6b..a0a8925 100644 --- a/frontend/src/components/Pages/Dashboard.tsx +++ b/frontend/src/components/Pages/Dashboard.tsx @@ -1,32 +1,32 @@ import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import Cookies from 'js-cookie'; -import { jwtDecode } from 'jwt-decode'; +import {jwtDecode} from 'jwt-decode'; // Import correction -function Profile() { +const Dashboard = () => { + const [profile, setProfile] = useState(null); const [reservations, setReservations] = useState([]); + const [events, setEvents] = useState([]); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const navigate = useNavigate(); - const API_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3000'; + const API_URL = 'http://localhost:3000'; - // Fetch reservation data from API useEffect(() => { - const fetchReservations = async () => { - const authToken = Cookies.get('authToken'); // Retrieve the authToken from cookies + const fetchUserData = async () => { + setLoading(true); + const authToken = Cookies.get('authToken'); if (!authToken) { - alert("Please sign in to view your reservations."); + alert("Please sign in to view your profile, reservations, and events."); navigate('/login'); return; } - // Decode the token to get the user ID let userId; try { const decodedToken = jwtDecode(authToken); - userId = decodedToken.sub; // Use `sub` based on the backend token payload - console.log("Decoded userId:", userId); // Debugging line + userId = decodedToken.sub; } catch (decodeError) { console.error("Error decoding token:", decodeError); alert("Invalid token. Please log in again."); @@ -35,40 +35,82 @@ function Profile() { } try { - const response = await fetch( - `${API_URL}/api/reservation/get/${userId}`, - { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${authToken}`, // Pass the token in headers - }, - credentials: 'include', - } - ); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to fetch reservations'); + // Fetch Profile Data + const profileResponse = await fetch(`${API_URL}/api/user/profile`, { + headers: { 'Authorization': `Bearer ${authToken}` }, + credentials: 'include', + }); + + if (!profileResponse.ok) { + const profileError = await profileResponse.json(); + console.error("Profile fetch error:", profileError); + throw new Error(profileError.message || 'Failed to fetch profile data'); } + const profileData = await profileResponse.json(); + setProfile(profileData); + + // Fetch Reservations Data + const reservationsResponse = await fetch(`${API_URL}/api/reservation/get/${userId}`, { + headers: { 'Authorization': `Bearer ${authToken}` }, + credentials: 'include', + }); - const data = await response.json(); - setReservations(data.data); + if (!reservationsResponse.ok) { + const reservationsError = await reservationsResponse.json(); + console.error("Reservations fetch error:", reservationsError); + throw new Error(reservationsError.message || 'Failed to fetch reservations'); + } + const reservationData = await reservationsResponse.json(); + setReservations(reservationData.data || []); + } catch (error) { + console.error("Error fetching user data:", error); setError(error.message); - console.error('Error fetching reservations:', error); + } finally { - setLoading(false); // Set loading to false after the fetch operation + setLoading(false); } }; - fetchReservations(); + fetchUserData(); }, [navigate]); + useEffect(() => { + const fetchEvents = async () => { + const authToken = Cookies.get('authToken'); + console.log("Testing events fetch with token:", authToken); + + if (!authToken) { + console.error("No auth token found"); + return; + } + + try { + const eventsResponse = await fetch(`${API_URL}/api/event/booked-events`, { + headers: { + 'Authorization': `Bearer ${authToken}`, + }, + credentials: 'include', + }); + + if (!eventsResponse.ok) throw new Error('Failed to fetch events'); + + const eventData = await eventsResponse.json(); + console.log("Fetched events successfully:", eventData); + setEvents(eventData.bookedEvents || []); + } catch (error) { + console.error("Error fetching events:", error.message); + } + }; + + fetchEvents(); + }, [API_URL]); + + return ( -
+
-

Your Reservations

+

Your Profile

{error && (

@@ -77,24 +119,51 @@ function Profile() { )} {loading ? ( -

Loading your reservations...

+

Loading your profile, reservations, and events...

) : ( -
- {reservations.length > 0 ? ( - reservations.map((reservation, index) => ( - - )) - ) : ( -

No reservations found.

- )} -
+ <> + {profile && } + +

Your Reservations

+
+ {reservations && reservations.length > 0 ? ( + reservations.map((reservation, index) => ( + + )) + ) : ( +

No reservations found.

+ )} +
+ +

Your Events

+
+ {events.length > 0 ? ( + events.map((event, index) => ( + + )) + ) : ( +

No events found.

+ )} +
+ )}
); } -// Separate ReservationCard component for better readability +// ProfileCard component for displaying user profile information +const ProfileCard = ({ profile }) => ( +
+

Profile Information

+

Name: {profile.name}

+

Email: {profile.email}

+

Role: {profile.role}

+ {profile.bio &&

Bio: {profile.bio}

} +
+); + +// ReservationCard component for displaying each reservation const ReservationCard = ({ reservation }) => (

Reservation Details

@@ -109,4 +178,20 @@ const ReservationCard = ({ reservation }) => (
); -export default Profile; +// EventCard component for displaying each event +const EventCard = ({ event }) => ( +
+

Event Details

+

Title: {event.title}

+

Date: {new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }).format(new Date(event.date))}

+

Location: {event.location}

+

Description: {event.description}

+
+); + + +export default Dashboard;