diff --git a/frontend/src/components/EventAdmin.tsx b/frontend/src/components/EventAdmin.tsx index 9525e5a..7c392d7 100644 --- a/frontend/src/components/EventAdmin.tsx +++ b/frontend/src/components/EventAdmin.tsx @@ -28,6 +28,7 @@ import { OutlinedInput, ListItemText, Checkbox, + Chip, } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; import EditIcon from '@mui/icons-material/Edit'; @@ -59,6 +60,7 @@ const EventAdmin: React.FC = () => { const [event, setEvent] = useState(null); const [rsvps, setRsvps] = useState([]); const [neededItems, setNeededItems] = useState([]); + const [claimedItems, setClaimedItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); @@ -100,9 +102,9 @@ const EventAdmin: React.FC = () => { items = []; } } - setNeededItems(items); - // Parse items_bringing for each RSVP + // Get all claimed items from existing RSVPs + const claimed = new Set(); const processedRsvps = rsvpsResponse.data.map((rsvp: RSVP) => { let itemsBringing: string[] = []; try { @@ -111,6 +113,7 @@ const EventAdmin: React.FC = () => { : Array.isArray(rsvp.items_bringing) ? rsvp.items_bringing : []; + itemsBringing.forEach(item => claimed.add(item)); } catch (e) { console.error('Error parsing items_bringing:', e); itemsBringing = []; @@ -122,6 +125,11 @@ const EventAdmin: React.FC = () => { }; }); + // Filter out claimed items from needed items + const availableItems = items.filter(item => !claimed.has(item)); + + setNeededItems(availableItems); + setClaimedItems(Array.from(claimed)); setRsvps(processedRsvps); setLoading(false); } catch (error) { @@ -229,6 +237,54 @@ const EventAdmin: React.FC = () => { + {/* Add items status section */} + + + Items Status + + + + + Still Needed: + + + {neededItems.map((item, index) => ( + + ))} + {neededItems.length === 0 && ( + + All items have been claimed + + )} + + + + + Claimed Items: + + + {claimedItems.map((item, index) => ( + + ))} + {claimedItems.length === 0 && ( + + No items have been claimed yet + + )} + + + + + RSVPs ({rsvps.length}) diff --git a/frontend/src/components/RSVPForm.tsx b/frontend/src/components/RSVPForm.tsx index 187af7b..43de5fc 100644 --- a/frontend/src/components/RSVPForm.tsx +++ b/frontend/src/components/RSVPForm.tsx @@ -38,6 +38,7 @@ const RSVPForm: React.FC = () => { items_bringing: [] }); const [neededItems, setNeededItems] = useState([]); + const [claimedItems, setClaimedItems] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); @@ -46,26 +47,48 @@ const RSVPForm: React.FC = () => { useEffect(() => { const fetchEventDetails = async () => { try { - const response = await axios.get(`/api/events/${slug}`); - console.log('API Response:', response.data); + const [eventResponse, rsvpsResponse] = await Promise.all([ + axios.get(`/api/events/${slug}`), + axios.get(`/api/events/${slug}/rsvps`) + ]); + console.log('API Response:', eventResponse.data); - // Ensure needed_items is an array + // Process needed items let items: string[] = []; - if (response.data.needed_items) { + if (eventResponse.data.needed_items) { try { - items = typeof response.data.needed_items === 'string' - ? JSON.parse(response.data.needed_items) - : Array.isArray(response.data.needed_items) - ? response.data.needed_items + items = typeof eventResponse.data.needed_items === 'string' + ? JSON.parse(eventResponse.data.needed_items) + : Array.isArray(eventResponse.data.needed_items) + ? eventResponse.data.needed_items : []; } catch (e) { console.error('Error parsing needed_items:', e); items = []; } } + + // Get all claimed items from existing RSVPs + const claimed = new Set(); + rsvpsResponse.data.forEach((rsvp: any) => { + try { + const rsvpItems = typeof rsvp.items_bringing === 'string' + ? JSON.parse(rsvp.items_bringing) + : Array.isArray(rsvp.items_bringing) + ? rsvp.items_bringing + : []; + rsvpItems.forEach((item: string) => claimed.add(item)); + } catch (e) { + console.error('Error parsing RSVP items:', e); + } + }); - console.log('Processed needed items:', items); - setNeededItems(items); + // Filter out claimed items + const availableItems = items.filter(item => !claimed.has(item)); + + console.log('Available items:', availableItems); + setNeededItems(availableItems); + setClaimedItems(Array.from(claimed)); } catch (error) { console.error('Error fetching event details:', error); setError('Failed to load event details');