diff --git a/frontend/src/components/rsvp/rsvp-form.tsx b/frontend/src/components/rsvp/rsvp-form.tsx index eeedf94..1a1ce28 100644 --- a/frontend/src/components/rsvp/rsvp-form.tsx +++ b/frontend/src/components/rsvp/rsvp-form.tsx @@ -1,6 +1,5 @@ "use client"; import React, { useState, useEffect } from "react"; -import { useRSVPs } from "@/context/rsvp-context"; import { useGuests } from "@/context/guest-context"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; @@ -23,8 +22,12 @@ interface RSVPProps { } export const RSVP: React.FC = ({ eventId, onRSVPSuccess }) => { - const { createRsvp } = useRSVPs(); - const { guests, isLoadingGuests } = useGuests(); + const { + guests, + isLoadingGuests, + findGuestByInvitationCode, + submitGuestRsvp, + } = useGuests(); const searchParams = useSearchParams(); const [status, setStatus] = useState(RsvpStatus.ATTENDING); @@ -46,19 +49,18 @@ export const RSVP: React.FC = ({ eventId, onRSVPSuccess }) => { } // Find the guest with matching invitation code - if (guests && guests.length > 0) { - const matchingGuest = guests.find( - (guest) => guest.invitation_code === invitationCode, - ); - console.debug("matchingGuest", matchingGuest); + if (guests) { + const matchingGuest = findGuestByInvitationCode(invitationCode); + if (matchingGuest) { + console.log("matchingGuest ", matchingGuest); setGuestId(matchingGuest.id); setError(null); } else { setError("Invalid invitation code. Please check your invitation link."); } } - }, [searchParams, guests]); + }, [searchParams, guests, findGuestByInvitationCode]); const submitRsvp = async (e: React.FormEvent) => { e.preventDefault(); @@ -74,7 +76,8 @@ export const RSVP: React.FC = ({ eventId, onRSVPSuccess }) => { setError(null); try { - await createRsvp({ + // Use the combined endpoint to update both RSVP and Guest status + await submitGuestRsvp(guestId, { event_id: eventId, guest_id: guestId, status, diff --git a/frontend/src/context/guest-context.tsx b/frontend/src/context/guest-context.tsx index d34b39b..928b065 100644 --- a/frontend/src/context/guest-context.tsx +++ b/frontend/src/context/guest-context.tsx @@ -14,20 +14,22 @@ import { RefetchOptions, } from "@tanstack/react-query"; import { - GetGuestsResponse, GuestRead, GuestCreate, GuestUpdate, + RsvpSchemaCreate, + GuestWithRsvpResponse, } from "@/client/types.gen"; import { getGuestsOptions, getGuestOptions, + createGuestRsvpMutation, } from "@/client/@tanstack/react-query.gen"; import { createGuest, updateGuest, deleteGuest } from "@/client"; // Guest context state interface GuestsContextState { - guests: GetGuestsResponse | undefined; + guests: GuestRead[] | undefined; guest: GuestRead | undefined; isLoadingGuests: boolean; isLoadingGuest: boolean; @@ -43,6 +45,15 @@ interface GuestsContextState { deleteGuest: (id: string) => Promise; fetchGuestById: (id: string) => void; + // New method for submitting RSVPs + submitGuestRsvp: ( + guestId: string, + rsvpData: RsvpSchemaCreate, + ) => Promise; + + // Find guest by invitation code + findGuestByInvitationCode: (code: string) => GuestRead | undefined; + currentGuestId: string | null; setCurrentGuestId: (id: string | null) => void; } @@ -68,6 +79,10 @@ const defaultGuestsContextState: GuestsContextState = { throw new Error("GuestsProvider is not initialized"); }, fetchGuestById: () => {}, + submitGuestRsvp: async () => { + throw new Error("GuestsProvider is not initialized"); + }, + findGuestByInvitationCode: () => undefined, currentGuestId: null, setCurrentGuestId: () => {}, }; @@ -114,7 +129,16 @@ export const GuestsProvider: React.FC = ({ children }) => { enabled: !!currentGuestId, }); - // explicitly fetch guest by id + // Find guest by invitation code + const findGuestByInvitationCode = useCallback( + (code: string): GuestRead | undefined => { + if (!guests || !Array.isArray(guests)) return undefined; + return guests.find((guest) => guest.invitation_code === code); + }, + [guests], + ); + + // Explicitly fetch guest by id const fetchGuestById = useCallback((id: string) => { setCurrentGuestId(id); }, []); @@ -160,6 +184,27 @@ export const GuestsProvider: React.FC = ({ children }) => { }, }); + // RSVP mutation + const rsvpMutation = useMutation(createGuestRsvpMutation()); + + // Submit RSVP function + const submitGuestRsvp = async ( + guestId: string, + rsvpData: RsvpSchemaCreate, + ): Promise => { + const result = await rsvpMutation.mutateAsync({ + path: { guest_id: guestId }, + body: rsvpData, + }); + + // Invalidate queries to ensure fresh data + queryClient.invalidateQueries({ + queryKey: getGuestsOptions().queryKey, + }); + + return result; + }; + // Context state value const value: GuestsContextState = { guests, @@ -173,6 +218,8 @@ export const GuestsProvider: React.FC = ({ children }) => { createGuest: createMutation.mutateAsync, updateGuest: (id, data) => updateMutation.mutateAsync({ id, data }), deleteGuest: deleteMutation.mutateAsync, + submitGuestRsvp, + findGuestByInvitationCode, fetchGuestById, currentGuestId,