Add email field to RSVP edit form with automatic confirmation

- Added email_address field to RSVPEditForm interface and form
- Email field is required and positioned after name field
- Added helper text explaining new confirmation will be sent if email changes
- Updated form validation to include email as required field
- Backend now detects email changes and sends new confirmation emails
- Email field follows same editing rules as other fields (disabled when event closed)
- Updated backend to use email_address parameter instead of attendee_email for consistency
This commit is contained in:
Ryderjj89
2025-05-26 16:45:37 -04:00
parent f96a4d161f
commit c13957073d
2 changed files with 46 additions and 5 deletions

View File

@@ -547,10 +547,10 @@ app.delete('/api/events/:slug/rsvps/:id', async (req: Request, res: Response) =>
app.put('/api/rsvps/edit/:editId', async (req: Request, res: Response) => {
try {
const { editId } = req.params;
const { name, attending, bringing_guests, guest_count, guest_names, items_bringing, other_items, send_event_conclusion_email, attendee_email } = req.body; // Receive new fields
const { name, email_address, attending, bringing_guests, guest_count, guest_names, items_bringing, other_items, send_event_conclusion_email } = req.body; // Updated to use email_address
// Find the RSVP by edit_id
const rsvp = await db.get('SELECT id, event_id FROM rsvps WHERE edit_id = ?', [editId]);
// Find the RSVP by edit_id and get current email
const rsvp = await db.get('SELECT id, event_id, attendee_email, name FROM rsvps WHERE edit_id = ?', [editId]);
if (!rsvp) {
return res.status(404).json({ error: 'RSVP not found' });
@@ -558,6 +558,8 @@ app.put('/api/rsvps/edit/:editId', async (req: Request, res: Response) => {
const rsvpId = rsvp.id;
const eventId = rsvp.event_id;
const currentEmail = rsvp.attendee_email;
const newEmail = email_address?.trim() || null;
// Parse items_bringing if it's a string
let parsedItemsBringing: string[] = [];
@@ -594,8 +596,30 @@ app.put('/api/rsvps/edit/:editId', async (req: Request, res: Response) => {
(send_event_conclusion_email === 'true' || send_event_conclusion_email === true) :
Boolean(rsvp.send_event_conclusion_email); // Use existing value if not provided
const attendeeEmailToSave = attendee_email !== undefined ? attendee_email?.trim() || null : rsvp.attendee_email;
const attendeeEmailToSave = newEmail;
// Check if email address changed and send new confirmation if needed
const emailChanged = currentEmail !== newEmail && newEmail && process.env.EMAIL_USER;
if (emailChanged) {
try {
// Get event details for the email
const event = await db.get('SELECT title, slug FROM events WHERE id = ?', [eventId]);
if (event) {
const editLink = `${process.env.FRONTEND_BASE_URL}/events/${event.slug}/rsvp/edit/${editId}`;
await sendRSVPEditLinkEmail({
eventTitle: event.title,
eventSlug: event.slug,
name: name ?? rsvp.name,
to: newEmail,
editLink,
});
console.log(`Sent new RSVP edit link email to updated address: ${newEmail}`);
}
} catch (emailErr) {
console.error('Error sending RSVP edit link email to new address:', emailErr);
}
}
// Update the RSVP
await db.run(

View File

@@ -23,6 +23,7 @@ import { Event } from '../types';
interface RSVPFormData {
name: string;
email_address: string;
attending: string;
bringing_guests: string;
guest_count: number;
@@ -35,6 +36,7 @@ const RSVPEditForm: React.FC = () => {
const { slug, editId } = useParams<{ slug: string; editId: string }>();
const [formData, setFormData] = useState<RSVPFormData>({
name: '',
email_address: '',
attending: '',
bringing_guests: '',
guest_count: 1,
@@ -80,6 +82,7 @@ const RSVPEditForm: React.FC = () => {
// Pre-fill the form with existing RSVP data
setFormData({
name: rsvpResponse.data.name,
email_address: rsvpResponse.data.email_address || '',
attending: rsvpResponse.data.attending,
bringing_guests: rsvpResponse.data.bringing_guests,
guest_count: rsvpResponse.data.guest_count,
@@ -272,7 +275,7 @@ const RSVPEditForm: React.FC = () => {
setIsSubmitting(true);
setError(null);
if (!formData.name.trim() || !formData.attending) {
if (!formData.name.trim() || !formData.email_address.trim() || !formData.attending) {
setError('Please fill in all required fields');
setIsSubmitting(false);
return;
@@ -431,6 +434,19 @@ const RSVPEditForm: React.FC = () => {
disabled={isEventClosed} // Disable if event is closed
/>
<TextField
label="Email Address"
name="email_address"
type="email"
value={formData.email_address}
onChange={handleChange}
required
fullWidth
variant="outlined"
disabled={isEventClosed} // Disable if event is closed
helperText="If you change your email, a new confirmation will be sent to the new address"
/>
<FormControl fullWidth required disabled={isEventClosed}> {/* Disable if event is closed */}
<InputLabel>Are you attending?</InputLabel>
<Select
@@ -574,6 +590,7 @@ const RSVPEditForm: React.FC = () => {
size="large"
disabled={isSubmitting ||
!formData.name.trim() ||
!formData.email_address.trim() ||
!formData.attending ||
(formData.attending === 'yes' && !formData.bringing_guests) ||
(formData.bringing_guests === 'yes' && (formData.guest_count < 1 || formData.guest_names.some(name => !name.trim())))}