diff --git a/frontend/src/components/EventAdmin.tsx b/frontend/src/components/EventAdmin.tsx index d4fe464..6d21820 100644 --- a/frontend/src/components/EventAdmin.tsx +++ b/frontend/src/components/EventAdmin.tsx @@ -803,3 +803,604 @@ const EventAdmin: React.FC = () => { sx={{ minWidth: 'fit-content', whiteSpace: 'nowrap' + }} + > + Manage Items + + + + + + + + Info: {event.description || 'None'} + + + Location: {event.location} + + + Date: {new Date(event.date).toLocaleString()} + + {event.rsvp_cutoff_date && ( + + RSVP cut-off date: {new Date(event.rsvp_cutoff_date).toLocaleString()} + + )} + + + {/* Add items status section */} + + + Items Status + + + + + Still Needed: + + + {neededItems.map((item: string, index: number) => ( + + ))} + {neededItems.length === 0 && ( + + All items have been claimed + + )} + + + + + Claimed Items: + + + {claimedItems.map((item: string, index: number) => ( + + ))} + {claimedItems.length === 0 && ( + + No items have been claimed yet + + )} + + + {/* Other Items Section */} + + + Other Items: + + + {otherItems.length > 0 + ? otherItems.join(', ') + : 'No other items have been brought'} + + + + + + + RSVPs: {rsvps.length} | Total Guests: {rsvps.reduce((total, rsvp) => { + // Count the RSVP person as 1 if they're attending + const rsvpCount = rsvp.attending === 'yes' ? 1 : 0; + // Add their guests if they're bringing any + const guestCount = (rsvp.attending === 'yes' && rsvp.bringing_guests === 'yes') ? rsvp.guest_count : 0; + return total + rsvpCount + guestCount; + }, 0)} + + + + + + + Name + Email + Attending + Guests + Needed Items + Other Items + Actions + + + + {rsvps.map((rsvp: RSVP) => ( + + {rsvp.name || 'No name provided'} + {rsvp.attendee_email || 'No email provided'} + + {rsvp.attending ? + rsvp.attending.charAt(0).toUpperCase() + rsvp.attending.slice(1) : + 'Unknown' + } + + + {rsvp.bringing_guests === 'yes' ? + `${rsvp.guest_count || 0} (${Array.isArray(rsvp.guest_names) ? + rsvp.guest_names.join(', ') : + typeof rsvp.guest_names === 'string' ? + rsvp.guest_names.replace(/\s+/g, ', ') : + 'No names provided'})` : + 'No' + } + + + {Array.isArray(rsvp.items_bringing) ? + rsvp.items_bringing.map((item, index) => ( + + )) : + typeof rsvp.items_bringing === 'string' ? + JSON.parse(rsvp.items_bringing).map((item: string, index: number) => ( + + )) : + 'None' + } + + + {rsvp.other_items || 'None'} + + + handleEditRsvp(rsvp)} + sx={{ mr: 1 }} + > + + + handleDeleteRsvp(rsvp)} + sx={{ mr: 1 }} + > + + + handleSendEmail(rsvp)} + sx={{ mr: 1 }} + disabled={!rsvp.attendee_email} + > + + + handleCopyLink(rsvp)} + disabled={!rsvp.edit_id} + > + + + + + ))} + +
+
+ + + setDeleteDialogOpen(false)} + > + Delete RSVP + + + Are you sure you want to delete {rsvpToDelete?.name}'s RSVP? + + + + + + + + + setEditDialogOpen(false)} + maxWidth="sm" + fullWidth + > + Edit RSVP + + + + + + Attending + + + + Bringing Guests + + + {editForm.bringing_guests === 'yes' && ( + <> + + {/* Individual guest name fields */} + {Array.from({ length: editForm.guest_count }, (_, index) => ( + + ))} + + )} + + What items are you bringing? + + multiple + name="items_bringing" + value={editForm.items_bringing} + onChange={handleItemsChange} + input={} + renderValue={(selected) => ( + + {selected.map((value: string) => ( + + ))} + + )} + > + {Array.from(new Set([...neededItems, ...editForm.items_bringing])).map((item: string) => ( + + + + + ))} + + + setEditForm(prev => ({ ...prev, other_items: e.target.value }))} + fullWidth + multiline + rows={3} + /> + + + + + + + + + setDeleteEventDialogOpen(false)} + maxWidth="sm" + fullWidth + > + Delete Event + + + Are you sure you want to delete "{event.title}"? This action cannot be undone. + + + All RSVPs associated with this event will also be deleted. + + + + + + + + + setManageItemsDialogOpen(false)} + maxWidth="sm" + fullWidth + > + Manage Needed Items + + + + setNewItem(e.target.value)} + fullWidth + /> + + + + Current Items: + + + {event?.needed_items && Array.isArray(event.needed_items) && event.needed_items.map((item, index) => ( + handleRemoveItem(item)} + color={claimedItems.includes(item) ? "success" : "primary"} + /> + ))} + + + + + + + + + setUpdateInfoDialogOpen(false)} + maxWidth="sm" + fullWidth + > + Update Event Information + + + {/* Event Title Field */} + setUpdateForm(prev => ({ ...prev, title: e.target.value }))} + fullWidth + /> + setUpdateForm(prev => ({ ...prev, description: e.target.value }))} + fullWidth + multiline + rows={3} + /> + setUpdateForm(prev => ({ ...prev, location: e.target.value }))} + fullWidth + /> + setUpdateForm(prev => ({ ...prev, date: e.target.value }))} + fullWidth + InputLabelProps={{ + shrink: true, + }} + /> + setUpdateForm(prev => ({ ...prev, rsvp_cutoff_date: e.target.value }))} + fullWidth + InputLabelProps={{ + shrink: true, + }} + /> + + + Email Notifications + + setUpdateForm(prev => ({ + ...prev, + email_notifications_enabled: e.target.checked + }))} + /> + } + label="Enable Email Notifications" + /> + + {updateForm.email_notifications_enabled && ( + setUpdateForm(prev => ({ + ...prev, + email_recipients: e.target.value + }))} + variant="outlined" + placeholder="email1@example.com, email2@example.com" + helperText="Enter email addresses separated by commas" + sx={{ mt: 2 }} + /> + )} + + + {/* Event Conclusion Email Settings */} + + + Event Conclusion Email + + setUpdateForm(prev => ({ + ...prev, + event_conclusion_email_enabled: e.target.checked + }))} + /> + } + label="Enable Event Conclusion Email" + /> + + {updateForm.event_conclusion_email_enabled && ( + setUpdateForm(prev => ({ + ...prev, + event_conclusion_message: e.target.value + }))} + variant="outlined" + multiline + rows={4} + helperText="This message will be sent to attendees who opted for email notifications the day after the event." + sx={{ mt: 2 }} + /> + )} + + + + + Wallpaper + + {event.wallpaper && ( + + + Current wallpaper: + + + + )} + + {updateForm.wallpaper && ( + + Selected file: {updateForm.wallpaper.name} + + )} + + + + + + + + + + + + {snackbarMessage} + + + + + + ); +}; + +export default EventAdmin;