monacousa-portal/server/api/events/[id]/rsvp.post.ts

200 lines
5.5 KiB
TypeScript
Raw Normal View History

// server/api/events/[id]/rsvp.post.ts
import { createNocoDBEventsClient } from '~/server/utils/nocodb-events';
import { createNocoDBClient } from '~/server/utils/nocodb';
import type { EventRSVPRequest } from '~/utils/types';
export default defineEventHandler(async (event) => {
try {
const eventId = getRouterParam(event, 'id');
const body = await readBody(event) as EventRSVPRequest;
if (!eventId) {
throw createError({
statusCode: 400,
statusMessage: 'Event ID is required'
});
}
// Get user session
const session = await getUserSession(event);
if (!session || !session.user) {
throw createError({
statusCode: 401,
statusMessage: 'Authentication required'
});
}
const eventsClient = createNocoDBEventsClient();
const membersClient = createNocoDBClient();
// Get the event details
const eventDetails = await eventsClient.findOne(eventId);
if (!eventDetails) {
throw createError({
statusCode: 404,
statusMessage: 'Event not found'
});
}
// Check if event is active
if (eventDetails.status !== 'active') {
throw createError({
statusCode: 400,
statusMessage: 'Cannot RSVP to inactive events'
});
}
// Check if event is in the past
const eventDate = new Date(eventDetails.start_datetime);
const now = new Date();
if (eventDate < now) {
throw createError({
statusCode: 400,
statusMessage: 'Cannot RSVP to past events'
});
}
// Get member details for pricing logic
const member = await membersClient.findByKeycloakId(session.user.id);
if (!member) {
throw createError({
statusCode: 404,
statusMessage: 'Member record not found'
});
}
// Check if user already has an RSVP
const existingRSVP = await eventsClient.findUserRSVP(eventId, member.member_id || member.Id);
if (existingRSVP && body.rsvp_status === 'confirmed') {
// Update existing RSVP instead of creating new one
const updatedRSVP = await eventsClient.updateRSVP(existingRSVP.id, {
rsvp_status: body.rsvp_status,
rsvp_notes: body.rsvp_notes || '',
updated_at: new Date().toISOString()
});
return {
success: true,
data: updatedRSVP,
message: 'RSVP updated successfully'
};
}
// Check event capacity if confirming
if (body.rsvp_status === 'confirmed') {
const isFull = await eventsClient.isEventFull(eventId);
if (isFull) {
// Add to waitlist instead
body.rsvp_status = 'waitlist';
}
}
// Determine pricing and payment status
let paymentStatus = 'not_required';
let isMemberPricing = 'false';
if (eventDetails.is_paid === 'true' && body.rsvp_status === 'confirmed') {
paymentStatus = 'pending';
// Check if member qualifies for member pricing
const isDuesCurrent = member.current_year_dues_paid === 'true';
const memberPricingEnabled = eventDetails.member_pricing_enabled === 'true';
if (isDuesCurrent && memberPricingEnabled) {
isMemberPricing = 'true';
}
}
// Generate payment reference
const paymentReference = eventsClient.generatePaymentReference(
member.member_id || member.Id
);
// Create RSVP record
const rsvpData = {
event_id: eventId,
member_id: member.member_id || member.Id,
rsvp_status: body.rsvp_status,
payment_status: paymentStatus,
payment_reference: paymentReference,
attended: 'false',
rsvp_notes: body.rsvp_notes || '',
is_member_pricing: isMemberPricing
};
const newRSVP = await eventsClient.createRSVP(rsvpData);
// Update event attendee count if confirmed
if (body.rsvp_status === 'confirmed') {
const currentCount = parseInt(eventDetails.current_attendees) || 0;
await eventsClient.updateAttendeeCount(eventId, currentCount + 1);
}
// Include payment information in response for paid events
let responseData: any = newRSVP;
if (eventDetails.is_paid === 'true' && paymentStatus === 'pending') {
const registrationConfig = await getRegistrationConfig();
responseData = {
...newRSVP,
payment_info: {
cost: isMemberPricing === 'true' ?
eventDetails.cost_members :
eventDetails.cost_non_members,
iban: registrationConfig.iban,
recipient: registrationConfig.accountHolder,
reference: paymentReference,
member_pricing: isMemberPricing === 'true'
}
};
}
return {
success: true,
data: responseData,
message: body.rsvp_status === 'waitlist' ?
'Added to waitlist - event is full' :
'RSVP submitted successfully'
};
} catch (error) {
console.error('Error processing RSVP:', error);
if (error.statusCode) {
throw error;
}
throw createError({
statusCode: 500,
statusMessage: 'Failed to process RSVP'
});
}
});
// Helper functions
async function getUserSession(event: any) {
try {
const sessionCookie = getCookie(event, 'session') || getHeader(event, 'authorization');
if (!sessionCookie) return null;
return {
user: {
id: 'user-id',
tier: 'user'
}
};
} catch {
return null;
}
}
async function getRegistrationConfig() {
// This should fetch from your admin config system
return {
iban: 'FR76 1234 5678 9012 3456 7890 123',
accountHolder: 'MonacoUSA Association'
};
}