Spaces:
Paused
Paused
Download Controller/host.js from imkrish/campverse-backend: direct link, hf CLI and curl.
- Browser
- Download file 7.54 kB
-
https://huggingface.co/spaces/imkrish/campverse-backend/resolve/main/Controller/host.js
- Command line
-
hf download hf://spaces/imkrish/campverse-backend/Controller/host.js
-
curl -L -o host.js https://huggingface.co/spaces/imkrish/campverse-backend/resolve/main/Controller/host.js
7.54 kB
| const mongoose = require('mongoose'); | |
| const Event = require('../Models/Event'); | |
| const User = require('../Models/User'); | |
| const EventParticipationLog = require('../Models/EventParticipationLog'); | |
| const { asyncHandler } = require('../Middleware/errorHandler'); | |
| // Host dashboard: list events and detailed analytics | |
| const getHostDashboard = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| // Optimized: Use a single aggregation pipeline to fetch events and their analytics | |
| const eventsWithAnalytics = await Event.aggregate([ | |
| { $match: { hostUserId: new mongoose.Types.ObjectId(userId) } }, | |
| { | |
| $lookup: { | |
| from: 'eventparticipationlogs', | |
| localField: '_id', | |
| foreignField: 'eventId', | |
| as: 'logs' | |
| } | |
| }, | |
| { | |
| $project: { | |
| title: 1, | |
| date: 1, | |
| location: 1, | |
| status: 1, | |
| capacity: 1, | |
| type: 1, | |
| isPaid: 1, | |
| price: 1, | |
| bannerURL: 1, | |
| logoURL: 1, | |
| verificationStatus: 1, | |
| createdAt: 1, | |
| updatedAt: 1, | |
| analytics: { | |
| totalRegistered: { $size: '$logs' }, | |
| totalAttended: { | |
| $size: { | |
| $filter: { | |
| input: '$logs', | |
| as: 'log', | |
| cond: { $eq: ['$$log.status', 'attended'] } | |
| } | |
| } | |
| }, | |
| totalWaitlisted: { | |
| $size: { | |
| $filter: { | |
| input: '$logs', | |
| as: 'log', | |
| cond: { $eq: ['$$log.status', 'waitlisted'] } | |
| } | |
| } | |
| }, | |
| totalPaid: { | |
| $size: { | |
| $filter: { | |
| input: '$logs', | |
| as: 'log', | |
| cond: { $eq: ['$$log.paymentType', 'paid'] } | |
| } | |
| } | |
| }, | |
| totalFree: { | |
| $size: { | |
| $filter: { | |
| input: '$logs', | |
| as: 'log', | |
| cond: { $eq: ['$$log.paymentType', 'free'] } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| { | |
| $addFields: { | |
| 'analytics.attendanceRate': { | |
| $cond: [ | |
| { $gt: ['$analytics.totalRegistered', 0] }, | |
| { | |
| $multiply: [ | |
| { $divide: ['$analytics.totalAttended', '$analytics.totalRegistered'] }, | |
| 100 | |
| ] | |
| }, | |
| 0 | |
| ] | |
| } | |
| } | |
| } | |
| ]); | |
| const totalEvents = eventsWithAnalytics.length; | |
| const totalParticipants = eventsWithAnalytics.reduce( | |
| (sum, e) => sum + e.analytics.totalRegistered, | |
| 0, | |
| ); | |
| const totalAttendedCount = eventsWithAnalytics.reduce( | |
| (sum, e) => sum + e.analytics.totalAttended, | |
| 0, | |
| ); | |
| const upcomingEventsCount = eventsWithAnalytics.filter( | |
| (e) => e.date && new Date(e.date) > new Date() | |
| ).length; | |
| // Formatting attendanceRate to string as per original implementation | |
| eventsWithAnalytics.forEach(event => { | |
| event.analytics.attendanceRate = event.analytics.attendanceRate.toFixed(2); | |
| }); | |
| return res.json({ | |
| totalEvents, | |
| totalParticipants, | |
| totalAttended: totalAttendedCount, | |
| upcomingEvents: upcomingEventsCount, | |
| events: eventsWithAnalytics, | |
| }); | |
| }); | |
| // Create a new event (host only) | |
| const createEvent = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| const eventData = req.body; | |
| eventData.hostUserId = userId; | |
| const event = await Event.create(eventData); | |
| // Optionally add event to user's eventHistory.hosted | |
| await User.findByIdAndUpdate(userId, { | |
| $push: { 'eventHistory.hosted': event._id }, | |
| }); | |
| return res.status(201).json(event); | |
| }); | |
| // Update an event (host only) | |
| const updateEvent = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| const eventId = req.params.id; | |
| const event = await Event.findOne({ _id: eventId, hostUserId: userId }); | |
| if (!event) | |
| return res | |
| .status(404) | |
| .json({ error: 'Event not found or not owned by user.' }); | |
| // Whitelist allow-able fields | |
| const allowedUpdates = [ | |
| 'title', 'description', 'type', 'organizationName', | |
| 'location', 'capacity', 'date', 'isPaid', 'price', | |
| 'tags', 'requirements', 'audienceType', 'features', | |
| 'sessions', 'about', 'socialLinks' | |
| ]; | |
| allowedUpdates.forEach((field) => { | |
| if (req.body[field] !== undefined) { | |
| event[field] = req.body[field]; | |
| } | |
| }); | |
| // Handle special cases safely if needed (e.g. nested objects) | |
| // For now, the direct assignment works for top-level schema fields. | |
| await event.save(); | |
| return res.json(event); | |
| }); | |
| // Delete an event (host only) | |
| const deleteEvent = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| const eventId = req.params.id; | |
| const event = await Event.findOneAndDelete({ | |
| _id: eventId, | |
| hostUserId: userId, | |
| }); | |
| if (!event) | |
| return res | |
| .status(404) | |
| .json({ error: 'Event not found or not owned by user.' }); | |
| // Optionally remove from user's eventHistory.hosted | |
| await User.findByIdAndUpdate(userId, { | |
| $pull: { 'eventHistory.hosted': eventId }, | |
| }); | |
| return res.json({ message: 'Event deleted.' }); | |
| }); | |
| // List all events hosted by the current user | |
| const getMyEvents = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| const events = await Event.find({ | |
| $or: [ | |
| { hostUserId: userId }, | |
| { coHosts: userId } | |
| ] | |
| }).lean(); | |
| const eventIds = events.map(e => e._id); | |
| const logs = await EventParticipationLog.find({ eventId: { $in: eventIds } }).lean(); | |
| const users = await User.find({ _id: { $in: logs.map(l => l.userId) } }).lean(); | |
| const userMap = {}; | |
| users.forEach(u => { userMap[u._id.toString()] = u; }); | |
| const eventParticipantsMap = {}; | |
| logs.forEach(log => { | |
| if (!eventParticipantsMap[log.eventId]) eventParticipantsMap[log.eventId] = []; | |
| eventParticipantsMap[log.eventId].push({ | |
| userId: log.userId, | |
| name: userMap[log.userId.toString()]?.name, | |
| email: userMap[log.userId.toString()]?.email, | |
| phone: userMap[log.userId.toString()]?.phone, | |
| status: log.status, | |
| paymentType: log.paymentType, | |
| paymentStatus: log.paymentStatus, | |
| attendanceTimestamp: log.attendanceTimestamp, | |
| timestamp: log.timestamp, | |
| }); | |
| }); | |
| const eventsWithParticipants = events.map(event => ({ | |
| ...event, | |
| participants: eventParticipantsMap[event._id] || [] | |
| })); | |
| return res.json(eventsWithParticipants); | |
| }); | |
| // Get participants for a given event (host only) | |
| const getEventParticipants = asyncHandler(async (req, res) => { | |
| const userId = req.user.id; | |
| const eventId = req.params.id; | |
| const event = await Event.findOne({ _id: eventId, hostUserId: userId }); | |
| if (!event) | |
| return res | |
| .status(404) | |
| .json({ error: 'Event not found or not owned by user.' }); | |
| // Get detailed participant information from EventParticipationLog | |
| const logs = await EventParticipationLog.find({ eventId }).populate( | |
| 'userId', | |
| 'name email phone', | |
| ); | |
| const participants = logs.map((log) => ({ | |
| userId: log.userId._id, | |
| name: log.userId.name, | |
| email: log.userId.email, | |
| phone: log.userId.phone, | |
| status: log.status, | |
| paymentType: log.paymentType, | |
| paymentStatus: log.paymentStatus, | |
| attendanceTimestamp: log.attendanceTimestamp, | |
| timestamp: log.timestamp, | |
| })); | |
| return res.json({ participants }); | |
| }); | |
| module.exports = { | |
| getHostDashboard, | |
| createEvent, | |
| updateEvent, | |
| deleteEvent, | |
| getMyEvents, | |
| getEventParticipants, | |
| }; | |