Add guest support for events and RSVP system
All checks were successful
Build And Push Image / docker (push) Successful in 3m52s
All checks were successful
Build And Push Image / docker (push) Successful in 3m52s
- Add guest settings to event creation with configurable max guests per person - Implement guest selection in RSVP form when guests are permitted - Update API endpoints to handle guest count in RSVP requests - Extend event and RSVP types to support guest-related fields
This commit is contained in:
@@ -106,13 +106,15 @@ export const useEvents = () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* RSVP to an event
|
||||
* RSVP to an event with support for guests and real-time updates
|
||||
*/
|
||||
const rsvpToEvent = async (eventId: string, rsvpData: Omit<EventRSVPRequest, 'event_id'>) => {
|
||||
const rsvpToEvent = async (eventId: string, rsvpData: Omit<EventRSVPRequest, 'event_id'> & { extra_guests?: string }) => {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
console.log('[useEvents] RSVP to event:', eventId, 'with data:', rsvpData);
|
||||
|
||||
const response = await $fetch<{ success: boolean; data: any; message: string }>(`/api/events/${eventId}/rsvp`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
@@ -123,28 +125,46 @@ export const useEvents = () => {
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
// Update local event data - match by database ID (stored in Id field or as fallback)
|
||||
const eventIndex = events.value.findIndex(e =>
|
||||
(e as any).Id === eventId || e.id === eventId
|
||||
);
|
||||
// Find event by event_id first, then fallback to database ID
|
||||
let eventIndex = events.value.findIndex(e => e.event_id === eventId);
|
||||
if (eventIndex === -1) {
|
||||
eventIndex = events.value.findIndex(e => (e as any).Id === eventId || e.id === eventId);
|
||||
}
|
||||
|
||||
console.log('[useEvents] Looking for event with database ID:', eventId, 'found at index:', eventIndex);
|
||||
console.log('[useEvents] Event found at index:', eventIndex, 'using event_id:', eventId);
|
||||
|
||||
if (eventIndex !== -1) {
|
||||
events.value[eventIndex].user_rsvp = response.data;
|
||||
const event = events.value[eventIndex];
|
||||
|
||||
// Update attendee count if confirmed
|
||||
// Update RSVP status
|
||||
event.user_rsvp = response.data;
|
||||
|
||||
// Calculate attendee count including guests
|
||||
if (rsvpData.rsvp_status === 'confirmed') {
|
||||
const currentCount = typeof events.value[eventIndex].current_attendees === 'string'
|
||||
? parseInt(events.value[eventIndex].current_attendees) || 0
|
||||
: events.value[eventIndex].current_attendees || 0;
|
||||
events.value[eventIndex].current_attendees = (currentCount + 1).toString();
|
||||
const currentCount = parseInt(event.current_attendees || '0');
|
||||
const guestCount = parseInt(rsvpData.extra_guests || '0');
|
||||
const totalAdded = 1 + guestCount; // Member + guests
|
||||
|
||||
event.current_attendees = (currentCount + totalAdded).toString();
|
||||
|
||||
console.log('[useEvents] Updated attendee count:', {
|
||||
previous: currentCount,
|
||||
added: totalAdded,
|
||||
new: event.current_attendees,
|
||||
guests: guestCount
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger reactivity
|
||||
events.value[eventIndex] = { ...event };
|
||||
}
|
||||
|
||||
// Clear cache
|
||||
// Clear cache for fresh data on next load
|
||||
cache.clear();
|
||||
|
||||
// Force refresh events data to ensure accuracy
|
||||
await fetchEvents({ force: true });
|
||||
|
||||
return response.data;
|
||||
} else {
|
||||
throw new Error(response.message || 'Failed to RSVP');
|
||||
@@ -158,6 +178,61 @@ export const useEvents = () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel RSVP to an event
|
||||
*/
|
||||
const cancelRSVP = async (eventId: string) => {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
// Find the event to get current RSVP info
|
||||
let event = events.value.find(e => e.event_id === eventId);
|
||||
if (!event) {
|
||||
event = events.value.find(e => (e as any).Id === eventId || e.id === eventId);
|
||||
}
|
||||
|
||||
if (!event?.user_rsvp) {
|
||||
throw new Error('No RSVP found to cancel');
|
||||
}
|
||||
|
||||
const response = await $fetch<{ success: boolean; data: any; message: string }>(`/api/events/${eventId}/rsvp`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
const eventIndex = events.value.findIndex(e => e === event);
|
||||
|
||||
if (eventIndex !== -1) {
|
||||
const currentCount = parseInt(events.value[eventIndex].current_attendees || '0');
|
||||
const guestCount = parseInt(events.value[eventIndex].user_rsvp?.extra_guests || '0');
|
||||
const totalRemoved = 1 + guestCount; // Member + guests
|
||||
|
||||
// Update attendee count and remove RSVP
|
||||
events.value[eventIndex].current_attendees = Math.max(0, currentCount - totalRemoved).toString();
|
||||
events.value[eventIndex].user_rsvp = undefined;
|
||||
|
||||
// Trigger reactivity
|
||||
events.value[eventIndex] = { ...events.value[eventIndex] };
|
||||
}
|
||||
|
||||
// Clear cache and refresh
|
||||
cache.clear();
|
||||
await fetchEvents({ force: true });
|
||||
|
||||
return response.data;
|
||||
} else {
|
||||
throw new Error(response.message || 'Failed to cancel RSVP');
|
||||
}
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Failed to cancel RSVP';
|
||||
console.error('Error canceling RSVP:', err);
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update attendance for an event (board/admin only)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user