Add RSVP context and provider for managing RSVP state
Some checks failed
Build and Push Docker Images / changes (push) Successful in 5s
Build and Push Docker Images / build-backend (push) Has been skipped
Build and Push Docker Images / build-frontend (push) Failing after 51s

Introduce a context and provider for handling RSVP data, including fetching, updating, creating, and deleting RSVPs. The implementation utilizes React Query for data management and exposes methods for managing RSVP operations throughout the application.
This commit is contained in:
2025-03-15 19:44:20 +01:00
parent c0516c1086
commit 58ac33990f
2 changed files with 192 additions and 1 deletions

View File

@@ -0,0 +1,188 @@
"use client";
import React, { createContext, ReactNode, useContext } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
getRsvps,
getRsvp,
createRsvp,
updateRsvp,
deleteRsvp,
updateRsvpStatus,
} from "@/client/sdk.gen";
import {
RsvpSchema,
RsvpSchemaCreate,
RsvpSchemaUpdate,
RsvpStatus,
} from "@/client/types.gen";
// RSVP context state
interface RSVPContextState {
rsvps: RsvpSchema[] | undefined;
rsvp: RsvpSchema | undefined;
isLoadingRsvps: boolean;
isLoadingRsvp: boolean;
refetchRsvps: () => Promise<any>;
fetchRsvpById: (id: string) => void;
createRsvp: (data: RsvpSchemaCreate) => Promise<RsvpSchema | undefined>;
updateRsvp: (
id: string,
data: RsvpSchemaUpdate,
) => Promise<RsvpSchema | undefined>;
updateRsvpStatus: (
id: string,
status: RsvpStatus,
additionalData?: Partial<RsvpSchemaUpdate>,
) => Promise<RsvpSchema | undefined>;
deleteRsvp: (id: string) => Promise<RsvpSchema | undefined>;
currentRsvpId: string | null;
setCurrentRsvpId: (id: string | null) => void;
error: Error | null;
}
// Default context state
const defaultRSVPContextState: RSVPContextState = {
rsvps: undefined,
rsvp: undefined,
isLoadingRsvps: false,
isLoadingRsvp: false,
refetchRsvps: async () => {
throw new Error("RSVPContext not initialized");
},
fetchRsvpById: () => {},
createRsvp: async () => {
throw new Error("RSVPContext not initialized");
},
updateRsvp: async () => {
throw new Error("RSVPContext not initialized");
},
updateRsvpStatus: async () => {
throw new Error("RSVPContext not initialized");
},
deleteRsvp: async () => {
throw new Error("RSVPContext not initialized");
},
currentRsvpId: null,
setCurrentRsvpId: () => {},
error: null,
};
// Create context
const RSVPContext = createContext<RSVPContextState>(defaultRSVPContextState);
// Hook to use context
export const useRSVPs = () => {
const context = useContext(RSVPContext);
if (!context) {
throw new Error("useRSVPs must be used within an RSVPProvider");
}
return context;
};
// RSVP Provider Props
interface RSVPProviderProps {
children: ReactNode;
}
// RSVP Provider Component
export const RSVPProvider: React.FC<RSVPProviderProps> = ({ children }) => {
const queryClient = useQueryClient();
const [currentRsvpId, setCurrentRsvpId] = React.useState<string | null>(null);
// Fetch all RSVPs
const {
data: rsvps,
isLoading: isLoadingRsvps,
error,
refetch: refetchRsvps,
} = useQuery({
queryKey: ["rsvps"],
queryFn: () => getRsvps().then((res) => res.data),
refetchInterval: 60000,
refetchOnWindowFocus: "always",
});
// Fetch specific RSVP
const { data: rsvp, isLoading: isLoadingRsvp } = useQuery({
queryKey: ["rsvp", currentRsvpId],
queryFn: () =>
getRsvp({ path: { rsvp_id: currentRsvpId ?? "" } }).then(
(res) => res.data,
),
enabled: !!currentRsvpId,
});
const fetchRsvpById = (id: string) => {
setCurrentRsvpId(id);
};
// Create RSVP Mutation
const createMutation = useMutation({
mutationFn: (data: RsvpSchemaCreate) =>
createRsvp({ body: data }).then((res) => res.data),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["rsvps"] }),
});
// Update RSVP Mutation
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: string; data: RsvpSchemaUpdate }) =>
updateRsvp({ path: { rsvp_id: id }, body: data }).then((res) => res.data),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["rsvps"] }),
});
// Update RSVP Status Mutation specifically
const updateStatusMutation = useMutation({
mutationFn: ({
id,
status,
additionalData = {},
}: {
id: string;
status: RsvpStatus;
additionalData?: Partial<RsvpSchemaUpdate>;
}) =>
updateRsvpStatus({
path: { rsvp_id: id },
body: { status, ...additionalData },
}).then((res) => res.data),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["rsvps"] }),
});
// Delete RSVP Mutation
const deleteMutation = useMutation({
mutationFn: (id: string) =>
deleteRsvp({ path: { rsvp_id: id } }).then((res) => res.data),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["rsvps"] }),
});
const contextValue: RSVPContextState = {
rsvps,
rsvp,
isLoadingRsvps,
isLoadingRsvp,
refetchRsvps,
fetchRsvpById,
createRsvp: createMutation.mutateAsync,
updateRsvp: (id, data) => updateMutation.mutateAsync({ id, data }),
updateRsvpStatus: (id, status, additionalData) =>
updateStatusMutation.mutateAsync({ id, status, additionalData }),
deleteRsvp: deleteMutation.mutateAsync,
currentRsvpId,
setCurrentRsvpId,
error: error as Error | null,
};
return (
<RSVPContext.Provider value={contextValue}>{children}</RSVPContext.Provider>
);
};

View File

@@ -1,11 +1,14 @@
import React from "react"; import React from "react";
import { EventsProvider } from "@/context/event-context"; import { EventsProvider } from "@/context/event-context";
import { EventThemesProvider } from "@/context/event-theme-context"; import { EventThemesProvider } from "@/context/event-theme-context";
import { RSVPProvider } from "@/context/rsvp-context";
export function DataProviders({ children }: { children: React.ReactNode }) { export function DataProviders({ children }: { children: React.ReactNode }) {
return ( return (
<EventThemesProvider> <EventThemesProvider>
<EventsProvider>{children}</EventsProvider> <EventsProvider>
<RSVPProvider>{children}</RSVPProvider>
</EventsProvider>
</EventThemesProvider> </EventThemesProvider>
); );
} }