const express = require("express"); const Event = require("../models/Event"); const User = require("../models/User"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createEventValidation, eventIdValidation, } = require("../middleware/validators/eventValidator"); const { paginate, buildPaginatedResponse } = require("../middleware/pagination"); const couchdbService = require("../services/couchdbService"); const router = express.Router(); // Get all events (with pagination) router.get( "/", paginate, asyncHandler(async (req, res) => { const { page, limit } = req.pagination; const result = await Event.getAllPaginated(page, limit); // Transform participants data to match expected format const events = result.events.map(event => ({ ...event, participants: event.participants.map(p => ({ _id: p.userId, name: p.name, profilePicture: p.profilePicture })) })); res.json(buildPaginatedResponse(events, result.pagination.totalCount, page, limit)); }), ); // Create an event router.post( "/", auth, createEventValidation, asyncHandler(async (req, res) => { const { title, description, date, location } = req.body; const event = await Event.create({ title, description, date, location, }); res.json(event); }), ); // RSVP to an event router.put( "/rsvp/:id", auth, eventIdValidation, asyncHandler(async (req, res) => { const eventId = req.params.id; const userId = req.user.id; // Check if event exists const event = await Event.findById(eventId); if (!event) { return res.status(404).json({ msg: "Event not found" }); } // Check if user has already RSVPed const alreadyParticipating = event.participants.some(p => p.userId === userId); if (alreadyParticipating) { return res.status(400).json({ msg: "Already RSVPed" }); } // Get user data for embedding const user = await User.findById(userId); if (!user) { return res.status(404).json({ msg: "User not found" }); } // Add participant to event const updatedEvent = await Event.addParticipant( eventId, userId, user.name, user.profilePicture ); // Update user's events array if (!user.events.includes(eventId)) { user.events.push(eventId); user.stats.eventsParticipated = user.events.length; await User.update(userId, user); } // Award points for event participation using couchdbService const updatedUser = await couchdbService.updateUserPoints( userId, 15, `Joined event: ${event.title}`, { entityType: 'Event', entityId: eventId, entityName: event.title } ); // Check and award badges await couchdbService.checkAndAwardBadges(userId, updatedUser.points); res.json({ participants: updatedEvent.participants, pointsAwarded: 15, newBalance: updatedUser.points, }); }), ); // Get event by ID router.get( "/:id", eventIdValidation, asyncHandler(async (req, res) => { const event = await Event.findById(req.params.id); if (!event) { return res.status(404).json({ msg: "Event not found" }); } // Transform participants data to match expected format const transformedEvent = { ...event, participants: event.participants.map(p => ({ _id: p.userId, name: p.name, profilePicture: p.profilePicture })) }; res.json(transformedEvent); }) ); // Update event router.put( "/:id", auth, eventIdValidation, createEventValidation, asyncHandler(async (req, res) => { const { title, description, date, location, status } = req.body; const event = await Event.findById(req.params.id); if (!event) { return res.status(404).json({ msg: "Event not found" }); } const updateData = { title, description, date, location }; if (status) { updateData.status = status; } const updatedEvent = await Event.update(req.params.id, updateData); res.json(updatedEvent); }) ); // Update event status router.patch( "/:id/status", auth, eventIdValidation, asyncHandler(async (req, res) => { const { status } = req.body; if (!["upcoming", "ongoing", "completed", "cancelled"].includes(status)) { return res.status(400).json({ msg: "Invalid status" }); } const updatedEvent = await Event.updateStatus(req.params.id, status); res.json(updatedEvent); }) ); // Cancel RSVP router.delete( "/rsvp/:id", auth, eventIdValidation, asyncHandler(async (req, res) => { const eventId = req.params.id; const userId = req.user.id; // Check if event exists const event = await Event.findById(eventId); if (!event) { return res.status(404).json({ msg: "Event not found" }); } // Check if user is participating const isParticipating = event.participants.some(p => p.userId === userId); if (!isParticipating) { return res.status(400).json({ msg: "Not participating in this event" }); } // Remove participant from event const updatedEvent = await Event.removeParticipant(eventId, userId); // Update user's events array const user = await User.findById(userId); if (user) { user.events = user.events.filter(id => id !== eventId); user.stats.eventsParticipated = user.events.length; await User.update(userId, user); } res.json({ participants: updatedEvent.participants, msg: "RSVP cancelled successfully" }); }) ); // Delete event router.delete( "/:id", auth, eventIdValidation, asyncHandler(async (req, res) => { const event = await Event.findById(req.params.id); if (!event) { return res.status(404).json({ msg: "Event not found" }); } await Event.delete(req.params.id); res.json({ msg: "Event deleted successfully" }); }) ); // Get upcoming events router.get( "/upcoming/list", asyncHandler(async (req, res) => { const { limit = 10 } = req.query; const events = await Event.getUpcomingEvents(parseInt(limit)); // Transform participants data const transformedEvents = events.map(event => ({ ...event, participants: event.participants.map(p => ({ _id: p.userId, name: p.name, profilePicture: p.profilePicture })) })); res.json(transformedEvents); }) ); // Get events by status router.get( "/status/:status", asyncHandler(async (req, res) => { const { status } = req.params; if (!["upcoming", "ongoing", "completed", "cancelled"].includes(status)) { return res.status(400).json({ msg: "Invalid status" }); } const events = await Event.findByStatus(status); // Transform participants data const transformedEvents = events.map(event => ({ ...event, participants: event.participants.map(p => ({ _id: p.userId, name: p.name, profilePicture: p.profilePicture })) })); res.json(transformedEvents); }) ); // Get user's events router.get( "/user/:userId", auth, asyncHandler(async (req, res) => { const { userId } = req.params; const events = await Event.getEventsByUser(userId); // Transform participants data const transformedEvents = events.map(event => ({ ...event, participants: event.participants.map(p => ({ _id: p.userId, name: p.name, profilePicture: p.profilePicture })) })); res.json(transformedEvents); }) ); module.exports = router;