ocd-website/backend/src/controllers/eventController.ts
TheMaddax 8e986796e0 feat(admin): Implement comprehensive admin dashboard system
Create central dashboard with statistics and quick actions
Build events management with filtering and CRUD UI
Implement members management with bulk actions
Develop video management with accessibility indicators
Add document repository with visibility controls
Create content management with WYSIWYG editor
Add settings interface for site configuration
Additional improvements:

Implement full Events Management System with CRUD
Enhance frontend architecture with TypeScript
Improve accessibility in navigation menu
Add comprehensive test suite for Events API
2025-03-26 10:13:53 -05:00

410 lines
8.8 KiB
TypeScript

import { Request, Response } from 'express';
import Event, { IEvent } from '../models/Event';
import mongoose from 'mongoose';
/**
* Get all events with optional filtering
*/
export const getEvents = async (req: Request, res: Response) => {
try {
const {
status,
category,
search,
startDate,
endDate,
page = 1,
limit = 10
} = req.query;
// Build query
const query: any = {};
// Filter by status if provided
if (status && status !== 'all') {
query.status = status;
}
// Filter by category if provided
if (category && category !== 'all') {
query.category = category;
}
// Filter by date range if provided
if (startDate || endDate) {
query.date = {};
if (startDate) {
query.date.$gte = new Date(startDate as string);
}
if (endDate) {
query.date.$lte = new Date(endDate as string);
}
}
// Text search if provided
if (search) {
query.$text = { $search: search as string };
}
// Calculate pagination
const skip = ((Number(page) || 1) - 1) * (Number(limit) || 10);
// Execute query with pagination
const events = await Event.find(query)
.sort({ date: 1 }) // Sort by date ascending
.skip(skip)
.limit(Number(limit));
// Get total count for pagination
const total = await Event.countDocuments(query);
return res.status(200).json({
events,
pagination: {
total,
page: Number(page),
limit: Number(limit),
pages: Math.ceil(total / Number(limit))
}
});
} catch (error) {
console.error('Error fetching events:', error);
return res.status(500).json({
error: {
message: 'Failed to fetch events'
}
});
}
};
/**
* Get a single event by ID
*/
export const getEventById = async (req: Request, res: Response) => {
try {
const { id } = req.params;
// Validate ID format
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({
error: {
message: 'Invalid event ID format'
}
});
}
// Find event
const event = await Event.findById(id);
// Check if event exists
if (!event) {
return res.status(404).json({
error: {
message: 'Event not found'
}
});
}
return res.status(200).json({ event });
} catch (error) {
console.error('Error fetching event:', error);
return res.status(500).json({
error: {
message: 'Failed to fetch event'
}
});
}
};
/**
* Create a new event
*/
export const createEvent = async (req: Request, res: Response) => {
try {
const {
title,
description,
date,
time,
location,
category,
status,
registrationRequired,
maxAttendees,
recurring,
recurrencePattern,
tags
} = req.body;
// Create new event
const event = new Event({
title,
description,
date,
time,
location,
category,
status: status || 'draft',
registrationRequired: registrationRequired || false,
registeredCount: 0,
maxAttendees,
recurring: recurring || false,
recurrencePattern,
tags
});
// Save event to database
await event.save();
return res.status(201).json({
message: 'Event created successfully',
event
});
} catch (error) {
console.error('Error creating event:', error);
// Handle validation errors
if (error instanceof mongoose.Error.ValidationError) {
return res.status(400).json({
error: {
message: 'Validation error',
details: error.errors
}
});
}
return res.status(500).json({
error: {
message: 'Failed to create event'
}
});
}
};
/**
* Update an existing event
*/
export const updateEvent = async (req: Request, res: Response) => {
try {
const { id } = req.params;
const updateData = req.body;
// Validate ID format
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({
error: {
message: 'Invalid event ID format'
}
});
}
// Find and update event
const event = await Event.findByIdAndUpdate(
id,
updateData,
{ new: true, runValidators: true }
);
// Check if event exists
if (!event) {
return res.status(404).json({
error: {
message: 'Event not found'
}
});
}
return res.status(200).json({
message: 'Event updated successfully',
event
});
} catch (error) {
console.error('Error updating event:', error);
// Handle validation errors
if (error instanceof mongoose.Error.ValidationError) {
return res.status(400).json({
error: {
message: 'Validation error',
details: error.errors
}
});
}
return res.status(500).json({
error: {
message: 'Failed to update event'
}
});
}
};
/**
* Delete an event
*/
export const deleteEvent = async (req: Request, res: Response) => {
try {
const { id } = req.params;
// Validate ID format
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({
error: {
message: 'Invalid event ID format'
}
});
}
// Find and delete event
const event = await Event.findByIdAndDelete(id);
// Check if event exists
if (!event) {
return res.status(404).json({
error: {
message: 'Event not found'
}
});
}
return res.status(200).json({
message: 'Event deleted successfully'
});
} catch (error) {
console.error('Error deleting event:', error);
return res.status(500).json({
error: {
message: 'Failed to delete event'
}
});
}
};
/**
* Register for an event
*/
export const registerForEvent = async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { userId } = req.body;
// Validate ID format
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({
error: {
message: 'Invalid event ID format'
}
});
}
// Find event
const event = await Event.findById(id);
// Check if event exists
if (!event) {
return res.status(404).json({
error: {
message: 'Event not found'
}
});
}
// Check if registration is required
if (!event.registrationRequired) {
return res.status(400).json({
error: {
message: 'Registration is not required for this event'
}
});
}
// Check if event is at capacity
if (event.maxAttendees && event.registeredCount >= event.maxAttendees) {
return res.status(400).json({
error: {
message: 'Event is at full capacity'
}
});
}
// Increment registered count
event.registeredCount += 1;
await event.save();
// TODO: In a real implementation, we would also save the user's registration
// in a separate EventRegistration collection
return res.status(200).json({
message: 'Successfully registered for event',
event
});
} catch (error) {
console.error('Error registering for event:', error);
return res.status(500).json({
error: {
message: 'Failed to register for event'
}
});
}
};
/**
* Cancel registration for an event
*/
export const cancelRegistration = async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { userId } = req.body;
// Validate ID format
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({
error: {
message: 'Invalid event ID format'
}
});
}
// Find event
const event = await Event.findById(id);
// Check if event exists
if (!event) {
return res.status(404).json({
error: {
message: 'Event not found'
}
});
}
// Check if registration is required
if (!event.registrationRequired) {
return res.status(400).json({
error: {
message: 'Registration is not required for this event'
}
});
}
// Decrement registered count (ensure it doesn't go below 0)
if (event.registeredCount > 0) {
event.registeredCount -= 1;
await event.save();
}
// TODO: In a real implementation, we would also remove the user's registration
// from a separate EventRegistration collection
return res.status(200).json({
message: 'Successfully cancelled registration',
event
});
} catch (error) {
console.error('Error cancelling registration:', error);
return res.status(500).json({
error: {
message: 'Failed to cancel registration'
}
});
}
};