import { useState, useEffect } from 'react' import { getPublicEvent, getGuestForEvent, submitEventRsvp } from '../api/api' import './GuestSelfService.css' /** * GuestSelfService * * Primary flow : guest opens /guest/:eventId (from WhatsApp button) * → page loads event details * → guest enters phone number * → backend looks up guest scoped to THAT event * → guest fills RSVP form * → POST /public/events/:eventId/rsvp (only updates this event's record) * * Fallback flow : /guest with no eventId → plain phone lookup (legacy) */ function GuestSelfService({ eventId }) { // ─── Event state ────────────────────────────────────────────────────── const [event, setEvent] = useState(null) const [eventLoading, setEventLoading] = useState(false) const [eventError, setEventError] = useState('') // ─── Phone lookup state ────────────────────────────────────────────── const [phoneNumber, setPhoneNumber] = useState('') const [guest, setGuest] = useState(null) // ─── RSVP form state ───────────────────────────────────────────────── const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [success, setSuccess] = useState(false) const [formData, setFormData] = useState({ first_name: '', last_name: '', rsvp_status: 'invited', meal_preference: '', has_plus_one: false, plus_one_name: '', }) // ─── Load event on mount ──────────────────────────────────────────── useEffect(() => { if (!eventId) return setEventLoading(true) getPublicEvent(eventId) .then(setEvent) .catch(() => setEventError('האירוע לא נמצא.')) .finally(() => setEventLoading(false)) }, [eventId]) // ─── Phone lookup ──────────────────────────────────────────────────── const handleLookup = async (e) => { e.preventDefault() setError('') setLoading(true) try { const guestData = await getGuestForEvent(eventId, phoneNumber) // Always present the form regardless of whether the guest was pre-imported. // Never pre-fill the name — the host may have saved a nickname in their // contacts that the guest should not see. setGuest(guestData) // found:true or found:false — both show the RSVP form setFormData({ first_name: '', // guest enters their own name last_name: '', rsvp_status: guestData.rsvp_status || 'invited', meal_preference: guestData.meal_preference || '', has_plus_one: guestData.has_plus_one || false, plus_one_name: guestData.plus_one_name || '', }) } catch { // Only real network / server errors reach here setError('אירעה שגיאה. אנא נסה שוב.') } finally { setLoading(false) } } // ─── Submit RSVP ───────────────────────────────────────────────────── const handleSubmit = async (e) => { e.preventDefault() setError('') setLoading(true) try { await submitEventRsvp(eventId, { phone: phoneNumber, ...formData }) setSuccess(true) } catch { setError('נכשל בשמירת הפרטים. אנא נסה שוב.') } finally { setLoading(false) } } const handleChange = (e) => { const { name, value, type, checked } = e.target setFormData((prev) => ({ ...prev, [name]: type === 'checkbox' ? checked : value })) } // ─── RSVP form (shared JSX) ────────────────────────────────────────── const rsvpForm = (
) // ─── Early returns ───────────────────────────────────────────────────── if (eventId && eventLoading) { return (טוען פרטי אירוע...
{[event.partner1_name, event.partner2_name].filter(Boolean).join(' ו')}
)} {event.date &&📅 {event.date}
} {event.venue &&📍 {event.venue}
} {event.event_time &&⏰ {event.event_time}
} > ) : ( <>עדכן את הגעתך והעדפותיך
> ) // ─── Main render ────────────────────────────────────────────────────── return (אנא אשר את הגעתך והעדפותיך
{!success && ( )}