ghostguild-org/server/api/events/[id]/register.post.js

149 lines
4 KiB
JavaScript

import Event from "../../../models/event.js";
import Member from "../../../models/member.js";
import { connectDB } from "../../../utils/mongoose.js";
import { sendEventRegistrationEmail } from "../../../utils/resend.js";
import mongoose from "mongoose";
export default defineEventHandler(async (event) => {
try {
// Ensure database connection
await connectDB();
const identifier = getRouterParam(event, "id");
const body = await readBody(event);
if (!identifier) {
throw createError({
statusCode: 400,
statusMessage: "Event identifier is required",
});
}
// Validate required fields
if (!body.name || !body.email) {
throw createError({
statusCode: 400,
statusMessage: "Name and email are required",
});
}
// Fetch the event - try by slug first, then by ID
let eventData;
// Check if identifier is a valid MongoDB ObjectId
if (mongoose.Types.ObjectId.isValid(identifier)) {
eventData = await Event.findById(identifier);
}
// If not found by ID or not a valid ObjectId, try by slug
if (!eventData) {
eventData = await Event.findOne({ slug: identifier });
}
if (!eventData) {
throw createError({
statusCode: 404,
statusMessage: "Event not found",
});
}
// Check if event is full
if (
eventData.maxAttendees &&
eventData.registrations.length >= eventData.maxAttendees
) {
throw createError({
statusCode: 400,
statusMessage: "Event is full",
});
}
// Check if already registered
const alreadyRegistered = eventData.registrations.some(
(reg) => reg.email.toLowerCase() === body.email.toLowerCase(),
);
if (alreadyRegistered) {
throw createError({
statusCode: 400,
statusMessage: "You are already registered for this event",
});
}
// Check member status and handle different registration scenarios
const member = await Member.findOne({ email: body.email.toLowerCase() });
if (eventData.membersOnly && !member) {
throw createError({
statusCode: 403,
statusMessage:
"This event is for members only. Please become a member to register.",
});
}
// If event requires payment and user is not a member, redirect to payment flow
if (
eventData.pricing.paymentRequired &&
!eventData.pricing.isFree &&
!member
) {
throw createError({
statusCode: 402, // Payment Required
statusMessage:
"This event requires payment. Please use the payment registration endpoint.",
});
}
// Set member status and membership level
let isMember = false;
let membershipLevel = "non-member";
if (member) {
isMember = true;
membershipLevel = `${member.circle}-${member.contributionTier}`;
}
// Add registration
const registration = {
memberId: member ? member._id : null,
name: body.name,
email: body.email.toLowerCase(),
membershipLevel,
isMember,
paymentStatus: "not_required", // Free events or member registrations
amountPaid: 0,
dietary: body.dietary || false,
registeredAt: new Date(),
};
eventData.registrations.push(registration);
// Save the updated event
await eventData.save();
// Send confirmation email using Resend
try {
await sendEventRegistrationEmail(registration, eventData);
} catch (emailError) {
// Log error but don't fail the registration
console.error("Failed to send confirmation email:", emailError);
}
return {
success: true,
message: "Successfully registered for the event",
registrationId:
eventData.registrations[eventData.registrations.length - 1]._id,
};
} catch (error) {
console.error("Error registering for event:", error);
if (error.statusCode) {
throw error;
}
throw createError({
statusCode: 500,
statusMessage: "Failed to register for event",
});
}
});