"use client"; import React, { useState, useEffect } from "react"; import { useGuests } from "@/context/guest-context"; import { useEventThemes } from "@/context/event-theme-context"; import { useEvents } from "@/context/event-context"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { RsvpStatus } from "@/client/types.gen"; import { useSearchParams, useParams } from "next/navigation"; import { Loader2, Plus, Minus } from "lucide-react"; import { motion } from "framer-motion"; import { useTheme } from "next-themes"; import { useRSVPs } from "@/context/rsvp-context"; interface RSVPProps { eventId: string; onRSVPSuccess?: () => void; } export const RSVP: React.FC = ({ eventId, onRSVPSuccess }) => { const { guests, isLoadingGuests, findGuestByInvitationCode, submitGuestRsvp, } = useGuests(); const { rsvps } = useRSVPs(); const searchParams = useSearchParams(); const { slug } = useParams<{ slug: string }>(); const { event, fetchEventBySlug, isLoadingEvent } = useEvents(); const { themes, isLoadingThemes } = useEventThemes(); const [status, setStatus] = useState(RsvpStatus.ATTENDING); const [number_of_guests, setNumberOfGuests] = useState(1); const [response_message, setResponseMessage] = useState(""); const [dietary_requirements, setDietaryRequirements] = useState(""); const [guestId, setGuestId] = useState(null); const [isProcessing, setIsProcessing] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const [currentGuest, setCurrentGuest] = useState(null); const [currentRSVP, setCurrentRSVP] = useState(null); const { setTheme } = useTheme(); useEffect(() => { setTheme("light"); }, [setTheme]); // Load event data based on slug or event ID useEffect(() => { if (slug) { fetchEventBySlug(slug); } }, [slug, fetchEventBySlug]); useEffect(() => { if (rsvps && currentGuest) { setCurrentRSVP(rsvps.find((rsvp) => rsvp.guest_id === currentGuest?.id)); } }, [rsvps, currentGuest]); useEffect(() => { if (currentRSVP) { setStatus(currentRSVP.status); setNumberOfGuests(currentRSVP.number_of_guests); setResponseMessage(currentRSVP.response_message); setDietaryRequirements(currentRSVP.dietary_requirements); } }, [currentRSVP]); // Find the theme for this event const eventTheme = event && themes?.find((theme) => theme.id === event.theme_id); // Enhanced color palette that works well with safari animals const colors = eventTheme?.color_palette || { primary: "#90B77D", // Soft jungle green secondary: "#D2AB67", // Warm giraffe yellow accent: "#B5A9EA", // Soft hippo purple accent2: "#8FBDD3", // Elephant blue accent3: "#E8B87D", // Lion tan background: "#F9F5F0", // Cream paper texture backgroundDark: "#F0E9D6", // Slightly darker cream for panels text: "#5B4B49", // Warm dark brown textLight: "#7D6D6B", // Lighter text variant gold: "#D4AF37", // Gold accent for special elements }; // Font selections const fonts = eventTheme?.fonts || { heading: "Georgia, serif", body: "Arial, sans-serif", }; // Animation variants const formVariants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.4 }, }, }; const itemVariants = { hidden: { opacity: 0, y: 10 }, visible: { opacity: 1, y: 0, transition: { duration: 0.3 }, }, }; // Extract invitation code from URL parameters useEffect(() => { const invitationCode = searchParams.get("code"); if (!invitationCode) { setError( "Codice invito mancante. Si prega di utilizzare il link fornito nell'invito.", ); return; } // Find the guest with matching invitation code if (guests) { const matchingGuest = findGuestByInvitationCode(invitationCode); setCurrentGuest(matchingGuest); if (matchingGuest) { console.log("matchingGuest ", matchingGuest); setGuestId(matchingGuest.id); setError(null); } else { setError("Codice invito non valido. Controlla il link dell'invito."); } } }, [searchParams, guests, findGuestByInvitationCode]); // Handler for incrementing the number of guests const incrementGuests = () => { setNumberOfGuests((prev) => prev + 1); }; // Handler for decrementing the number of guests const decrementGuests = () => { setNumberOfGuests((prev) => Math.max(1, prev - 1)); }; // Handler for direct number input const handleGuestsInputChange = (e: React.ChangeEvent) => { const value = e.target.value === "" ? 1 : parseInt(e.target.value, 10); if (!isNaN(value)) { setNumberOfGuests(Math.max(1, value)); } }; const submitRsvp = async (e: React.FormEvent) => { e.preventDefault(); if (!guestId) { setError( "Impossibile identificare il tuo invito. Controlla il link o contatta l'organizzatore.", ); return; } setIsProcessing(true); setError(null); try { // Use the combined endpoint to update both RSVP and Guest status await submitGuestRsvp(guestId, { event_id: eventId, guest_id: guestId, status, number_of_guests, response_message, dietary_requirements, }); setSuccess(true); if (onRSVPSuccess) { setTimeout(() => { onRSVPSuccess(); }, 2000); } } catch (err) { console.error("Error submitting RSVP:", err); setError( "Impossibile inviare la tua risposta. Riprova o contatta l'organizzatore.", ); } finally { setIsProcessing(false); } }; // Show loading state while checking invitation code if (isLoadingGuests || isLoadingEvent || isLoadingThemes) { return (
); } // Show error if no valid invitation code if (error) { return (

Errore Invito

{error}

); } // Show success message if (success) { return (

Grazie per la tua risposta!

La tua presenza è stata registrata con successo.

); } return (

Conferma la tua presenza

Ti preghiamo di farci sapere se potrai partecipare

{/* Custom number input with buttons for better mobile experience */}

Quante persone (incluso te) parteciperanno?