Skip to content
Merged
125 changes: 93 additions & 32 deletions src/controllers/eventController.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Comment thread
ChiragBellara marked this conversation as resolved.
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);
Comment thread
ChiragBellara marked this conversation as resolved.

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));
Comment thread
ChiragBellara marked this conversation as resolved.

res.json({
events,
events: formattedEvents,
pagination: {
total: totalEvents,
totalPages: Math.ceil(totalEvents / limitNumber),
Expand All @@ -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,
});
}
};

Expand Down
Loading