const express = require("express"); const mongoose = require("mongoose"); 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 { awardEventParticipationPoints, checkAndAwardBadges, } = require("../services/gamificationService"); const router = express.Router(); // Get all events (with pagination) router.get( "/", paginate, asyncHandler(async (req, res) => { const { skip, limit, page } = req.pagination; const events = await Event.find() .sort({ date: -1 }) .skip(skip) .limit(limit) .populate("participants", ["name", "profilePicture"]); const totalCount = await Event.countDocuments(); res.json(buildPaginatedResponse(events, totalCount, page, limit)); }), ); // Create an event router.post( "/", auth, createEventValidation, asyncHandler(async (req, res) => { const { title, description, date, location } = req.body; const newEvent = new Event({ title, description, date, location, }); const event = await newEvent.save(); res.json(event); }), ); // RSVP to an event router.put( "/rsvp/:id", auth, eventIdValidation, asyncHandler(async (req, res) => { const session = await mongoose.startSession(); session.startTransaction(); try { const event = await Event.findById(req.params.id).session(session); if (!event) { await session.abortTransaction(); session.endSession(); return res.status(404).json({ msg: "Event not found" }); } // Check if the user has already RSVPed if ( event.participants.filter( (participant) => participant.toString() === req.user.id, ).length > 0 ) { await session.abortTransaction(); session.endSession(); return res.status(400).json({ msg: "Already RSVPed" }); } event.participants.unshift(req.user.id); await event.save({ session }); // Update user's events array const user = await User.findById(req.user.id).session(session); if (!user.events.includes(event._id)) { user.events.push(event._id); await user.save({ session }); } // Award points for event participation const { transaction } = await awardEventParticipationPoints( req.user.id, event._id, session ); // Check and award badges const newBadges = await checkAndAwardBadges(req.user.id, session); await session.commitTransaction(); session.endSession(); res.json({ participants: event.participants, pointsAwarded: transaction.amount, newBalance: transaction.balanceAfter, badgesEarned: newBadges, }); } catch (err) { await session.abortTransaction(); session.endSession(); throw err; } }), ); module.exports = router;