import React from 'react'; import { useRef } from 'react'; import { useOutletContext } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { Button, FormControl, FormControlLabel, FormLabel, Grid, Paper, Radio, RadioGroup, TextField, } from '@mui/material'; import MailIcon from '@mui/icons-material/Mail'; import { useForm, Controller, useFieldArray } from 'react-hook-form'; import { useUpdateGuestMutation } from '../slices/api/guestSlice'; import { isFetchBaseQueryError } from '../error'; import { showSnackbar } from '../slices/snackbarSlice'; import type { Data } from '../error'; import type { Guest } from '../models'; function RsvpForm() { const dispatch = useDispatch(); const [updateGuest] = useUpdateGuestMutation(); const guest: Guest = useOutletContext(); const previousPartySize = useRef((guest.partySize ?? 1) - 1); const { register, handleSubmit, control, watch, formState: { errors }, } = useForm({ defaultValues: { id: guest.id, firstName: guest.firstName, lastName: guest.lastName, attendance: guest.attendance, email: guest.email, message: guest.message, partySize: guest.partySize, partyList: guest.partyList, }, }); const onSubmit = async (data: Guest) => { try { await updateGuest({ ...data }).unwrap(); dispatch( showSnackbar({ message: 'RSVP updated', severity: 'success', }) ); } catch (error) { if (isFetchBaseQueryError(error)) { dispatch( showSnackbar({ message: (error.data as Data).message, severity: 'error', }) ); } else { dispatch( showSnackbar({ message: 'RSVP failed', severity: 'error', }) ); } } }; const { fields, append, remove } = useFieldArray({ control, name: 'partyList', }); const handleParty = () => { const partySize = Number(watch('partySize')) - 1; if ( partySize > previousPartySize.current && partySize > 0 && partySize < 10 ) { append( new Array(partySize - previousPartySize.current).fill({ firstName: '', lastName: '', }) ); previousPartySize.current = partySize; } else if (partySize < previousPartySize.current && partySize >= 0) { remove( [...Array(previousPartySize.current - partySize).keys()].map( (_, i) => partySize - 1 + i ) ); previousPartySize.current = partySize; } }; return (

Please RSVP for the wedding by March 10, 2025. The ceremony will commence at 4:30 pm on April 26 in Divine Shepherd. The reception will follow at 6 pm in A Venue on the Ridge.

Attendance ( } label="Accept" /> } label="Decline" /> )} />
value.trim(), required: 'This field is required', pattern: { value: /\S+@\S+\.\S+/, message: 'Please enter a valid email address', }, })} /> { event.currentTarget.blur(); }} error={!!errors.partySize} helperText={errors.partySize?.message} required {...register('partySize', { valueAsNumber: true, onChange: handleParty, required: 'This field is required', min: { value: 1, message: 'Please enter a positive integer' }, max: { value: 9, message: 'Please enter an integer less than 10', }, })} /> {fields.map((field, index) => { return ( value.trim(), required: 'This field is required', })} /> value.trim(), required: 'This field is required', })} /> ); })}
); } export default RsvpForm;