Add RSVP context and provider for managing RSVP state
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:
188
frontend/src/context/rsvp-context.tsx
Normal file
188
frontend/src/context/rsvp-context.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,14 @@
|
||||
import React from "react";
|
||||
import { EventsProvider } from "@/context/event-context";
|
||||
import { EventThemesProvider } from "@/context/event-theme-context";
|
||||
import { RSVPProvider } from "@/context/rsvp-context";
|
||||
|
||||
export function DataProviders({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<EventThemesProvider>
|
||||
<EventsProvider>{children}</EventsProvider>
|
||||
<EventsProvider>
|
||||
<RSVPProvider>{children}</RSVPProvider>
|
||||
</EventsProvider>
|
||||
</EventThemesProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user