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 = (
{formData.rsvp_status === 'confirmed' && ( <> {showMealPref && (
)} {showCompanions && (
)} )}
) // ─── Early returns ───────────────────────────────────────────────────── if (eventId && eventLoading) { return (

טוען פרטי אירוע...

) } if (eventId && eventError) { return (

💒 אישור הגעה

{eventError}
) } // ─── Event header (shown when we have event details) ───────────────── const eventHeader = event ? ( <>

💒 {event.name}

{(event.partner1_name || event.partner2_name) && (

{[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 (
{/* Left panel — invitation image */} {hasImage && (
הזמנה
)} {/* Right panel — form */}
{eventHeader} {!guest ? ( /* ── Step 1: phone lookup ── */
setPhoneNumber(e.target.value)} placeholder="לדוגמה: 0501234567" required />
{error &&
{error}
}
) : ( /* ── Step 2: RSVP form ── */

שלום! 👋

אנא אשר את הגעתך והעדפותיך

{!success && ( )}
{success && (
✓ תודה! אישור ההגעה שלך נשמר בהצלחה 🎉
)} {error &&
{error}
} {!success && rsvpForm}
)}
) } export default GuestSelfService