Add GuestContext for managing guest-related state
Introduced a new GuestContext with accompanying provider to handle guest-related data, including fetching, creating, updating, and deleting guests. Integrated GuestsProvider into the application's data provider hierarchy to ensure guest data is accessible across components.
This commit is contained in:
185
frontend/src/context/guest-context.tsx
Normal file
185
frontend/src/context/guest-context.tsx
Normal file
@@ -0,0 +1,185 @@
|
||||
"use client";
|
||||
|
||||
import React, {
|
||||
createContext,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useContext,
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
RefetchOptions,
|
||||
} from "@tanstack/react-query";
|
||||
import {
|
||||
GetGuestsResponse,
|
||||
GuestRead,
|
||||
GuestCreate,
|
||||
GuestUpdate,
|
||||
} from "@/client/types.gen";
|
||||
import {
|
||||
getGuestsOptions,
|
||||
getGuestOptions,
|
||||
} from "@/client/@tanstack/react-query.gen";
|
||||
import { createGuest, updateGuest, deleteGuest } from "@/client";
|
||||
|
||||
// Guest context state
|
||||
interface GuestsContextState {
|
||||
guests: GetGuestsResponse | undefined;
|
||||
guest: GuestRead | undefined;
|
||||
isLoadingGuests: boolean;
|
||||
isLoadingGuest: boolean;
|
||||
error: Error | null;
|
||||
|
||||
refetchGuests: (options?: RefetchOptions) => Promise<any>;
|
||||
|
||||
createGuest: (data: GuestCreate) => Promise<GuestRead | undefined>;
|
||||
updateGuest: (
|
||||
id: string,
|
||||
data: GuestUpdate,
|
||||
) => Promise<GuestRead | undefined>;
|
||||
deleteGuest: (id: string) => Promise<any>;
|
||||
fetchGuestById: (id: string) => void;
|
||||
|
||||
currentGuestId: string | null;
|
||||
setCurrentGuestId: (id: string | null) => void;
|
||||
}
|
||||
|
||||
// Default context state
|
||||
const defaultGuestsContextState: GuestsContextState = {
|
||||
guests: undefined,
|
||||
guest: undefined,
|
||||
isLoadingGuests: false,
|
||||
isLoadingGuest: false,
|
||||
error: null,
|
||||
|
||||
refetchGuests: async () => {
|
||||
throw new Error("GuestsProvider is not initialized");
|
||||
},
|
||||
createGuest: async () => {
|
||||
throw new Error("GuestsProvider is not initialized");
|
||||
},
|
||||
updateGuest: async () => {
|
||||
throw new Error("GuestsProvider is not initialized");
|
||||
},
|
||||
deleteGuest: async () => {
|
||||
throw new Error("GuestsProvider is not initialized");
|
||||
},
|
||||
fetchGuestById: () => {},
|
||||
currentGuestId: null,
|
||||
setCurrentGuestId: () => {},
|
||||
};
|
||||
|
||||
// Create context
|
||||
const GuestsContext = createContext<GuestsContextState>(
|
||||
defaultGuestsContextState,
|
||||
);
|
||||
|
||||
// Hook to access context
|
||||
export const useGuests = () => {
|
||||
const context = useContext(GuestsContext);
|
||||
if (!context) {
|
||||
throw new Error("useGuests must be used within GuestsProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
// Provider Component Props
|
||||
interface GuestsProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
// Provider Component
|
||||
export const GuestsProvider: React.FC<GuestsProviderProps> = ({ children }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [currentGuestId, setCurrentGuestId] = useState<string | null>(null);
|
||||
|
||||
// Fetch all guests
|
||||
const {
|
||||
data: guests,
|
||||
isLoading: isLoadingGuests,
|
||||
error,
|
||||
refetch: refetchGuests,
|
||||
} = useQuery({
|
||||
...getGuestsOptions(),
|
||||
refetchOnWindowFocus: "always",
|
||||
refetchInterval: 60000,
|
||||
});
|
||||
|
||||
// Fetch specific guest by ID
|
||||
const { data: guest, isLoading: isLoadingGuest } = useQuery({
|
||||
...getGuestOptions({ path: { guest_id: currentGuestId || "" } }),
|
||||
enabled: !!currentGuestId,
|
||||
});
|
||||
|
||||
// explicitly fetch guest by id
|
||||
const fetchGuestById = useCallback((id: string) => {
|
||||
setCurrentGuestId(id);
|
||||
}, []);
|
||||
|
||||
// Create guest mutation
|
||||
const createMutation = useMutation({
|
||||
mutationFn: (data: GuestCreate) =>
|
||||
createGuest({ body: data }).then((res) => res.data),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: getGuestsOptions().queryKey,
|
||||
}),
|
||||
});
|
||||
|
||||
// Update guest mutation
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: GuestUpdate }) =>
|
||||
updateGuest({ path: { guest_id: id }, body: data }).then(
|
||||
(res) => res.data,
|
||||
),
|
||||
onSuccess: (updatedGuest) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: getGuestsOptions().queryKey,
|
||||
});
|
||||
if (updatedGuest?.id === currentGuestId) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: getGuestOptions({ path: { guest_id: currentGuestId } })
|
||||
.queryKey,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Delete guest mutation
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: string) =>
|
||||
deleteGuest({ path: { guest_id: id } }).then((res) => res.data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: getGuestsOptions().queryKey,
|
||||
});
|
||||
setCurrentGuestId(null);
|
||||
},
|
||||
});
|
||||
|
||||
// Context state value
|
||||
const value: GuestsContextState = {
|
||||
guests,
|
||||
guest,
|
||||
isLoadingGuests,
|
||||
isLoadingGuest,
|
||||
error,
|
||||
|
||||
refetchGuests,
|
||||
|
||||
createGuest: createMutation.mutateAsync,
|
||||
updateGuest: (id, data) => updateMutation.mutateAsync({ id, data }),
|
||||
deleteGuest: deleteMutation.mutateAsync,
|
||||
|
||||
fetchGuestById,
|
||||
currentGuestId,
|
||||
setCurrentGuestId,
|
||||
};
|
||||
|
||||
return (
|
||||
<GuestsContext.Provider value={value}>{children}</GuestsContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -2,12 +2,15 @@ import React from "react";
|
||||
import { EventsProvider } from "@/context/event-context";
|
||||
import { EventThemesProvider } from "@/context/event-theme-context";
|
||||
import { RSVPProvider } from "@/context/rsvp-context";
|
||||
import { GuestsProvider } from "@/context/guest-context";
|
||||
|
||||
export function DataProviders({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<EventThemesProvider>
|
||||
<EventsProvider>
|
||||
<RSVPProvider>{children}</RSVPProvider>
|
||||
<GuestsProvider>
|
||||
<RSVPProvider>{children}</RSVPProvider>
|
||||
</GuestsProvider>
|
||||
</EventsProvider>
|
||||
</EventThemesProvider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user