diff --git a/src/controllers/eventController.js b/src/controllers/eventController.js index add130a81..69954ff77 100644 --- a/src/controllers/eventController.js +++ b/src/controllers/eventController.js @@ -10,51 +10,105 @@ const updateEventStatus = (event) => { return event.status; }; -const getEvents = async (req, res) => { - const { page = 1, limit = 9, type = '', location = '', sortBy = 'date' } = req.query; +const VALID_TYPES = new Set(['Workshop', 'Meeting', 'Webinar', 'Social Gathering']); +const VALID_LOCATIONS = new Set(['Virtual', 'In person', 'TBD']); +const VALID_SORT_FIELDS = new Set(['date', 'title', 'type', 'location', 'currentAttendees']); - try { - const validSortFields = ['date', 'title', 'type', 'location', 'currentAttendees']; - const sortField = validSortFields.includes(sortBy) ? sortBy : 'date'; +function validateQuery({ type, location, sortBy }) { + if (type && !VALID_TYPES.has(type)) { + throw new Error('Invalid Type of Event.'); + } - const query = { isActive: true }; - if (type) query.type = type; - if (location) query.location = location; + if (location && !VALID_LOCATIONS.has(location)) { + throw new Error('Invalid Location for the Event.'); + } - const pageNumber = Math.max(1, Number(page)); - const limitNumber = Math.max(1, Number(limit)); + if (sortBy && !VALID_SORT_FIELDS.has(sortBy)) { + throw new Error('Invalid Sort Field.'); + } +} - const totalEvents = await Event.countDocuments(query); - let events = await Event.find(query) - .populate('resources.userID') - .sort({ [sortField]: 1 }) - .skip((pageNumber - 1) * limitNumber) - .limit(limitNumber); +function buildSafeQuery(location, type) { + const query = { isActive: true }; - events = events.map((event) => { - event.status = updateEventStatus(event); + if (location === 'Virtual') { + query.location = 'Virtual'; + } else if (location === 'In person') { + query.location = 'In person'; + } else if (location === 'TBD') { + query.location = 'TBD'; + } - const eventObj = event.toObject(); + if (type === 'Workshop') { + query.type = 'Workshop'; + } else if (type === 'Meeting') { + query.type = 'Meeting'; + } else if (type === 'Webinar') { + query.type = 'Webinar'; + } else if (type === 'Social Gathering') { + query.type = 'Social Gathering'; + } - eventObj.waitlistCount = event.waitlist?.length || 0; + return query; +} - eventObj.waitlistEnabled = event.currentAttendees >= event.maxAttendees; +function getPagination(page, limit, total) { + if (!page || !limit) { + return { + pageNumber: 1, + limitNumber: total, + skip: 0, + }; + } - const { userId } = req.query; + const pageNumber = Math.max(1, Number(page)); + const limitNumber = Math.max(1, Number(limit)); - if (userId && mongoose.Types.ObjectId.isValid(userId)) { - const index = event.waitlist.findIndex( - (entry) => entry.userId?.toString() === userId.toString(), - ); + return { + pageNumber, + limitNumber, + skip: (pageNumber - 1) * limitNumber, + }; +} - eventObj.userWaitlistPosition = index !== -1 ? index + 1 : null; - } +function formatEvent(event, userId) { + event.status = updateEventStatus(event); - return eventObj; - }); + const eventObj = event.toObject(); + const waitlist = Array.isArray(event.waitlist) ? event.waitlist : []; + + eventObj.waitlistCount = waitlist.length; + eventObj.waitlistEnabled = event.currentAttendees >= event.maxAttendees; + + if (userId) { + const index = waitlist.findIndex((entry) => entry.userId?.toString() === userId.toString()); + + eventObj.userWaitlistPosition = index !== -1 ? index + 1 : null; + } + + return eventObj; +} + +const getEvents = async function (req, res) { + try { + const { page, limit, type, location, sortBy } = req.query; + + validateQuery({ type, location, sortBy }); + + const safeQuery = buildSafeQuery(location, type); + const totalEvents = await Event.countDocuments(safeQuery); + const { pageNumber, limitNumber, skip } = getPagination(page, limit, totalEvents); + + const events = await Event.find(safeQuery) + .populate('resources.userID') + .sort(sortBy ? { [sortBy]: 1 } : {}) + .skip(skip) + .limit(limitNumber); + + const formattedEvents = events.map((event) => formatEvent(event, safeQuery.userId)); res.json({ - events, + events: formattedEvents, pagination: { total: totalEvents, totalPages: Math.ceil(totalEvents / limitNumber), @@ -63,7 +117,14 @@ const getEvents = async (req, res) => { }, }); } catch (error) { - res.status(500).json({ error: 'Failed to fetch events', details: error.message }); + if (error.message.startsWith('Invalid')) { + return res.status(400).send(error.message); + } + + res.status(500).json({ + error: 'Failed to fetch events', + details: error.message, + }); } };