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: '', companion_count: 1, }) // ─── 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 || '', companion_count: guestData.companion_count ?? 1, }) } 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 : type === 'number' ? parseInt(value, 10) || 1 : value, })) } // ─── Guest form field visibility (controlled by admin column settings) ── const guestFormFields = (() => { try { if (event?.guest_form_fields) return new Set(JSON.parse(event.guest_form_fields)) } catch {} // Default: show all fields when no setting saved yet return new Set(['mealPref', 'companions']) })() const showMealPref = guestFormFields.has('mealPref') // support both old key ('plusOne') and new key ('companions') const showCompanions = guestFormFields.has('companions') || guestFormFields.has('plusOne') // ─── 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 ────────────────────────────────────────────────────── const hasImage = !!event?.invitation_image_url return (אנא אשר את הגעתך והעדפותיך
{!success && ( )}