import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import axios from 'axios'; import { Box, Paper, Typography, TextField, Button, FormControl, InputLabel, Select, MenuItem, SelectChangeEvent, Container, Checkbox, ListItemText, OutlinedInput, Chip, } from '@mui/material'; interface RSVPFormData { name: string; attending: string; bringing_guests: string; guest_count: number; guest_names: string; items_bringing: string[]; } const RSVPForm: React.FC = () => { const { slug } = useParams<{ slug: string }>(); const [formData, setFormData] = useState({ name: '', attending: '', bringing_guests: '', guest_count: 0, guest_names: '', 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); const navigate = useNavigate(); useEffect(() => { const fetchEventDetails = async () => { try { const [eventResponse, rsvpsResponse] = await Promise.all([ axios.get(`/api/events/${slug}`), axios.get(`/api/events/${slug}/rsvps`) ]); // Process needed items let items: string[] = []; if (eventResponse.data.needed_items) { try { 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 { let rsvpItems: string[] = []; if (typeof rsvp.items_bringing === 'string') { try { const parsed = JSON.parse(rsvp.items_bringing); rsvpItems = Array.isArray(parsed) ? parsed : []; } catch (e) { console.error('Error parsing items_bringing JSON:', e); rsvpItems = []; } } else if (Array.isArray(rsvp.items_bringing)) { rsvpItems = rsvp.items_bringing; } if (Array.isArray(rsvpItems)) { rsvpItems.forEach((item: string) => claimed.add(item)); } } catch (e) { console.error('Error processing RSVP items:', e); } }); // Filter out claimed items const availableItems = items.filter(item => !claimed.has(item)); setNeededItems(availableItems); setClaimedItems(Array.from(claimed)); } catch (error) { console.error('Error fetching event details:', error); setError('Failed to load event details'); setNeededItems([]); } }; fetchEventDetails(); }, [slug]); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleSelectChange = (e: SelectChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleItemsChange = (e: SelectChangeEvent) => { const { value } = e.target; const itemsArray = Array.isArray(value) ? value : []; setFormData(prev => ({ ...prev, items_bringing: itemsArray })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); setError(null); try { const submissionData = { ...formData, items_bringing: formData.items_bringing }; const response = await axios.post(`/api/events/${slug}/rsvp`, submissionData); // Update the needed and claimed items const [eventResponse, rsvpsResponse] = await Promise.all([ axios.get(`/api/events/${slug}`), axios.get(`/api/events/${slug}/rsvps`) ]); // Process needed items let items: string[] = []; if (eventResponse.data.needed_items) { try { if (typeof eventResponse.data.needed_items === 'string') { const parsed = JSON.parse(eventResponse.data.needed_items); items = Array.isArray(parsed) ? parsed : []; } else if (Array.isArray(eventResponse.data.needed_items)) { items = eventResponse.data.needed_items; } } catch (e) { console.error('Error parsing needed_items:', e); items = []; } } // Get all claimed items from existing RSVPs including the new submission const claimed = new Set(); // First add items from the new submission if (Array.isArray(response.data.items_bringing)) { response.data.items_bringing.forEach(item => claimed.add(item)); } // Then add items from existing RSVPs rsvpsResponse.data.forEach((rsvp: any) => { try { let rsvpItems: string[] = []; if (typeof rsvp.items_bringing === 'string') { try { const parsed = JSON.parse(rsvp.items_bringing); rsvpItems = Array.isArray(parsed) ? parsed : []; } catch (e) { console.error('Error parsing items_bringing JSON:', e); } } else if (Array.isArray(rsvp.items_bringing)) { rsvpItems = rsvp.items_bringing; } if (rsvpItems.length > 0) { rsvpItems.forEach(item => claimed.add(item)); } } catch (e) { console.error('Error processing RSVP items:', e); } }); // Filter out claimed items const availableItems = items.filter(item => !claimed.has(item)); setNeededItems(availableItems); setClaimedItems(Array.from(claimed)); setSuccess(true); } catch (err) { console.error('Error submitting RSVP:', err); setError('Failed to submit RSVP. Please try again.'); } finally { setIsSubmitting(false); } }; if (success) { return ( Thank You! Your RSVP has been submitted successfully. ); } return ( RSVP Form {error && ( {error} )} Are you attending? {formData.attending === 'yes' && ( <> Are you bringing any guests? {formData.bringing_guests === 'yes' && ( <> )} {neededItems.length > 0 && ( What items are you bringing? )} )} ); }; export default RSVPForm;