- Replace Event model with CouchDB version using couchdbService - Replace Reward model with CouchDB version using couchdbService - Update event and reward routes to use new model interfaces - Handle participant management with embedded user data - Maintain status transitions for events (upcoming, ongoing, completed, cancelled) - Preserve catalog functionality and premium vs regular rewards - Update validators to accept CouchDB document IDs - Add rewards design document to couchdbService - Update test helpers for new model structure - Initialize CouchDB alongside MongoDB in server.js for backward compatibility - Fix linting issues in migrated routes 🤖 Generated with [AI Assistant] Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
311 lines
7.5 KiB
JavaScript
311 lines
7.5 KiB
JavaScript
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; |