Add initial implementation of gift context in frontend
This commit is contained in:
780
frontend/src/context/gift-context.tsx
Normal file
780
frontend/src/context/gift-context.tsx
Normal file
@@ -0,0 +1,780 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { createContext, ReactNode, useContext } from "react";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import {
|
||||||
|
createGiftCategory,
|
||||||
|
readGiftCategories,
|
||||||
|
deleteGiftCategory,
|
||||||
|
readGiftCategory,
|
||||||
|
updateGiftCategory,
|
||||||
|
associateCategoryWithEvent,
|
||||||
|
updateCategoryEventSettings,
|
||||||
|
getEventsForCategory,
|
||||||
|
reorderGiftsInCategory,
|
||||||
|
createGiftItem,
|
||||||
|
readGiftItems,
|
||||||
|
deleteGiftItem,
|
||||||
|
readGiftItem,
|
||||||
|
updateGiftItem,
|
||||||
|
updateGiftItemStatus,
|
||||||
|
reserveGiftItem,
|
||||||
|
cancelGiftReservation,
|
||||||
|
createGiftPurchase,
|
||||||
|
readGiftPurchase,
|
||||||
|
readGiftPurchasesByGift,
|
||||||
|
readGiftPurchasesByGuest,
|
||||||
|
} from "@/client/sdk.gen";
|
||||||
|
import {
|
||||||
|
GiftCategory,
|
||||||
|
GiftCategoryCreate,
|
||||||
|
GiftCategoryUpdate,
|
||||||
|
GiftItem,
|
||||||
|
GiftItemCreate,
|
||||||
|
GiftItemUpdate,
|
||||||
|
GiftStatus,
|
||||||
|
GiftPriority,
|
||||||
|
GiftPurchase,
|
||||||
|
GiftPurchaseCreate,
|
||||||
|
} from "@/client/types.gen";
|
||||||
|
|
||||||
|
// Gift context state
|
||||||
|
interface GiftContextState {
|
||||||
|
// Gift Categories
|
||||||
|
categories: GiftCategory[] | undefined;
|
||||||
|
category: GiftCategory | undefined;
|
||||||
|
isLoadingCategories: boolean;
|
||||||
|
isLoadingCategory: boolean;
|
||||||
|
refetchCategories: (eventId: string) => Promise<any>;
|
||||||
|
|
||||||
|
fetchCategoryById: (id: string, eventId?: string) => void;
|
||||||
|
createCategory: (data: GiftCategoryCreate) => Promise<GiftCategory | undefined>;
|
||||||
|
updateCategory: (
|
||||||
|
id: string,
|
||||||
|
data: GiftCategoryUpdate,
|
||||||
|
eventId?: string
|
||||||
|
) => Promise<GiftCategory | undefined>;
|
||||||
|
deleteCategory: (id: string, eventId?: string) => Promise<GiftCategory | undefined>;
|
||||||
|
associateCategoryWithEvent: (
|
||||||
|
categoryId: string,
|
||||||
|
eventId: string,
|
||||||
|
displayOrder?: number,
|
||||||
|
isVisible?: boolean
|
||||||
|
) => Promise<GiftCategory | undefined>;
|
||||||
|
updateCategoryEventSettings: (
|
||||||
|
categoryId: string,
|
||||||
|
eventId: string,
|
||||||
|
displayOrder?: number,
|
||||||
|
isVisible?: boolean
|
||||||
|
) => Promise<GiftCategory | undefined>;
|
||||||
|
getEventsForCategory: (categoryId: string) => Promise<any>;
|
||||||
|
reorderGiftsInCategory: (
|
||||||
|
categoryId: string,
|
||||||
|
giftIds: string[]
|
||||||
|
) => Promise<GiftCategory | undefined>;
|
||||||
|
|
||||||
|
// Gift Items
|
||||||
|
items: GiftItem[] | undefined;
|
||||||
|
item: GiftItem | undefined;
|
||||||
|
isLoadingItems: boolean;
|
||||||
|
isLoadingItem: boolean;
|
||||||
|
refetchItems: (categoryId?: string, eventId?: string) => Promise<any>;
|
||||||
|
|
||||||
|
fetchItemById: (id: string) => void;
|
||||||
|
createItem: (data: GiftItemCreate) => Promise<GiftItem | undefined>;
|
||||||
|
updateItem: (
|
||||||
|
id: string,
|
||||||
|
data: GiftItemUpdate
|
||||||
|
) => Promise<GiftItem | undefined>;
|
||||||
|
deleteItem: (id: string) => Promise<GiftItem | undefined>;
|
||||||
|
updateItemStatus: (
|
||||||
|
id: string,
|
||||||
|
status: GiftStatus
|
||||||
|
) => Promise<GiftItem | undefined>;
|
||||||
|
reserveItem: (
|
||||||
|
id: string,
|
||||||
|
guestId: string,
|
||||||
|
quantity?: number
|
||||||
|
) => Promise<GiftItem | undefined>;
|
||||||
|
cancelReservation: (
|
||||||
|
id: string,
|
||||||
|
guestId: string
|
||||||
|
) => Promise<GiftItem | undefined>;
|
||||||
|
|
||||||
|
// Gift Purchases
|
||||||
|
purchases: GiftPurchase[] | undefined;
|
||||||
|
purchase: GiftPurchase | undefined;
|
||||||
|
isLoadingPurchases: boolean;
|
||||||
|
isLoadingPurchase: boolean;
|
||||||
|
refetchPurchases: (giftId?: string, guestId?: string) => Promise<any>;
|
||||||
|
|
||||||
|
fetchPurchaseById: (id: string) => void;
|
||||||
|
createPurchase: (data: GiftPurchaseCreate) => Promise<GiftPurchase | undefined>;
|
||||||
|
fetchPurchasesByGift: (giftId: string) => Promise<GiftPurchase[] | undefined>;
|
||||||
|
fetchPurchasesByGuest: (guestId: string) => Promise<GiftPurchase[] | undefined>;
|
||||||
|
|
||||||
|
// Current selections
|
||||||
|
currentCategoryId: string | null;
|
||||||
|
setCurrentCategoryId: (id: string | null) => void;
|
||||||
|
currentItemId: string | null;
|
||||||
|
setCurrentItemId: (id: string | null) => void;
|
||||||
|
currentPurchaseId: string | null;
|
||||||
|
setCurrentPurchaseId: (id: string | null) => void;
|
||||||
|
currentEventId: string | null;
|
||||||
|
setCurrentEventId: (id: string | null) => void;
|
||||||
|
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default context state
|
||||||
|
const defaultGiftContextState: GiftContextState = {
|
||||||
|
// Gift Categories
|
||||||
|
categories: undefined,
|
||||||
|
category: undefined,
|
||||||
|
isLoadingCategories: false,
|
||||||
|
isLoadingCategory: false,
|
||||||
|
refetchCategories: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchCategoryById: () => {},
|
||||||
|
createCategory: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
updateCategory: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
deleteCategory: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
associateCategoryWithEvent: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
updateCategoryEventSettings: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
getEventsForCategory: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
reorderGiftsInCategory: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gift Items
|
||||||
|
items: undefined,
|
||||||
|
item: undefined,
|
||||||
|
isLoadingItems: false,
|
||||||
|
isLoadingItem: false,
|
||||||
|
refetchItems: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchItemById: () => {},
|
||||||
|
createItem: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
updateItem: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
deleteItem: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
updateItemStatus: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
reserveItem: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
cancelReservation: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gift Purchases
|
||||||
|
purchases: undefined,
|
||||||
|
purchase: undefined,
|
||||||
|
isLoadingPurchases: false,
|
||||||
|
isLoadingPurchase: false,
|
||||||
|
refetchPurchases: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchPurchaseById: () => {},
|
||||||
|
createPurchase: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
fetchPurchasesByGift: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
fetchPurchasesByGuest: async () => {
|
||||||
|
throw new Error("GiftContext not initialized");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Current selections
|
||||||
|
currentCategoryId: null,
|
||||||
|
setCurrentCategoryId: () => {},
|
||||||
|
currentItemId: null,
|
||||||
|
setCurrentItemId: () => {},
|
||||||
|
currentPurchaseId: null,
|
||||||
|
setCurrentPurchaseId: () => {},
|
||||||
|
currentEventId: null,
|
||||||
|
setCurrentEventId: () => {},
|
||||||
|
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create context
|
||||||
|
const GiftContext = createContext<GiftContextState>(defaultGiftContextState);
|
||||||
|
|
||||||
|
// Hook to use context
|
||||||
|
export const useGifts = () => {
|
||||||
|
const context = useContext(GiftContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useGifts must be used within a GiftProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gift Provider Props
|
||||||
|
interface GiftProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gift Provider Component
|
||||||
|
export const GiftProvider: React.FC<GiftProviderProps> = ({ children }) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const [currentCategoryId, setCurrentCategoryId] = React.useState<string | null>(null);
|
||||||
|
const [currentItemId, setCurrentItemId] = React.useState<string | null>(null);
|
||||||
|
const [currentPurchaseId, setCurrentPurchaseId] = React.useState<string | null>(null);
|
||||||
|
const [currentEventId, setCurrentEventId] = React.useState<string | null>(null);
|
||||||
|
|
||||||
|
// Fetch all categories for an event
|
||||||
|
const {
|
||||||
|
data: categories,
|
||||||
|
isLoading: isLoadingCategories,
|
||||||
|
error: categoriesError,
|
||||||
|
refetch: refetchCategoriesInternal,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftCategories", currentEventId],
|
||||||
|
queryFn: () =>
|
||||||
|
currentEventId
|
||||||
|
? readGiftCategories({
|
||||||
|
path: { event_id: currentEventId }
|
||||||
|
}).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined),
|
||||||
|
enabled: !!currentEventId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const refetchCategories = async (eventId: string) => {
|
||||||
|
setCurrentEventId(eventId);
|
||||||
|
return refetchCategoriesInternal();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch specific category
|
||||||
|
const {
|
||||||
|
data: category,
|
||||||
|
isLoading: isLoadingCategory,
|
||||||
|
error: categoryError,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftCategory", currentCategoryId, currentEventId],
|
||||||
|
queryFn: () =>
|
||||||
|
currentCategoryId
|
||||||
|
? readGiftCategory({
|
||||||
|
path: {
|
||||||
|
category_id: currentCategoryId
|
||||||
|
},
|
||||||
|
query: currentEventId ? { event_id: currentEventId } : undefined
|
||||||
|
}).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined),
|
||||||
|
enabled: !!currentCategoryId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchCategoryById = (id: string, eventId?: string) => {
|
||||||
|
setCurrentCategoryId(id);
|
||||||
|
if (eventId) {
|
||||||
|
setCurrentEventId(eventId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create Category Mutation
|
||||||
|
const createCategoryMutation = useMutation({
|
||||||
|
mutationFn: (data: GiftCategoryCreate) =>
|
||||||
|
createGiftCategory({ body: data }).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Category Mutation
|
||||||
|
const updateCategoryMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
eventId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: GiftCategoryUpdate;
|
||||||
|
eventId?: string;
|
||||||
|
}) =>
|
||||||
|
updateGiftCategory({
|
||||||
|
path: { category_id: id },
|
||||||
|
body: data,
|
||||||
|
query: eventId ? { event_id: eventId } : undefined
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategory", currentCategoryId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete Category Mutation
|
||||||
|
const deleteCategoryMutation = useMutation({
|
||||||
|
mutationFn: ({ id, eventId }: { id: string; eventId?: string }) =>
|
||||||
|
deleteGiftCategory({
|
||||||
|
path: { category_id: id },
|
||||||
|
query: eventId ? { event_id: eventId } : undefined
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch all items for a category or event
|
||||||
|
const {
|
||||||
|
data: items,
|
||||||
|
isLoading: isLoadingItems,
|
||||||
|
error: itemsError,
|
||||||
|
refetch: refetchItemsInternal,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftItems", currentCategoryId, currentEventId],
|
||||||
|
queryFn: () => {
|
||||||
|
const query: Record<string, string> = {};
|
||||||
|
if (currentCategoryId) {
|
||||||
|
query.category_id = currentCategoryId;
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
query.event_id = currentEventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(query).length > 0
|
||||||
|
? readGiftItems({ query }).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined);
|
||||||
|
},
|
||||||
|
enabled: !!(currentCategoryId || currentEventId),
|
||||||
|
});
|
||||||
|
|
||||||
|
const refetchItems = async (categoryId?: string, eventId?: string) => {
|
||||||
|
if (categoryId) {
|
||||||
|
setCurrentCategoryId(categoryId);
|
||||||
|
}
|
||||||
|
if (eventId) {
|
||||||
|
setCurrentEventId(eventId);
|
||||||
|
}
|
||||||
|
return refetchItemsInternal();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch specific item
|
||||||
|
const {
|
||||||
|
data: item,
|
||||||
|
isLoading: isLoadingItem,
|
||||||
|
error: itemError,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftItem", currentItemId],
|
||||||
|
queryFn: () =>
|
||||||
|
currentItemId
|
||||||
|
? readGiftItem({
|
||||||
|
path: {
|
||||||
|
gift_id: currentItemId
|
||||||
|
}
|
||||||
|
}).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined),
|
||||||
|
enabled: !!currentItemId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchItemById = (id: string) => {
|
||||||
|
setCurrentItemId(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create Item Mutation
|
||||||
|
const createItemMutation = useMutation({
|
||||||
|
mutationFn: (data: GiftItemCreate) =>
|
||||||
|
createGiftItem({ body: data }).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Item Mutation
|
||||||
|
const updateItemMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
data
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: GiftItemUpdate;
|
||||||
|
}) =>
|
||||||
|
updateGiftItem({
|
||||||
|
path: { gift_id: id },
|
||||||
|
body: data
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentItemId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItem", currentItemId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete Item Mutation
|
||||||
|
const deleteItemMutation = useMutation({
|
||||||
|
mutationFn: (id: string) =>
|
||||||
|
deleteGiftItem({
|
||||||
|
path: { gift_id: id }
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Item Status Mutation
|
||||||
|
const updateItemStatusMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
status: GiftStatus;
|
||||||
|
}) =>
|
||||||
|
updateGiftItemStatus({
|
||||||
|
path: { gift_id: id },
|
||||||
|
body: { status }
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentItemId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItem", currentItemId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reserve Item Mutation
|
||||||
|
const reserveItemMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
guestId,
|
||||||
|
quantity
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
guestId: string;
|
||||||
|
quantity?: number;
|
||||||
|
}) =>
|
||||||
|
reserveGiftItem({
|
||||||
|
path: { gift_id: id },
|
||||||
|
body: {
|
||||||
|
guest_id: guestId,
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentItemId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItem", currentItemId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cancel Reservation Mutation
|
||||||
|
const cancelReservationMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
id,
|
||||||
|
guestId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
guestId: string;
|
||||||
|
}) =>
|
||||||
|
cancelGiftReservation({
|
||||||
|
path: {
|
||||||
|
gift_id: id,
|
||||||
|
guest_id: guestId
|
||||||
|
}
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItems", null, currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentItemId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItem", currentItemId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Associate Category With Event Mutation
|
||||||
|
const associateCategoryWithEventMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
categoryId,
|
||||||
|
eventId,
|
||||||
|
displayOrder,
|
||||||
|
isVisible
|
||||||
|
}: {
|
||||||
|
categoryId: string;
|
||||||
|
eventId: string;
|
||||||
|
displayOrder?: number;
|
||||||
|
isVisible?: boolean;
|
||||||
|
}) =>
|
||||||
|
associateCategoryWithEvent({
|
||||||
|
path: {
|
||||||
|
category_id: categoryId,
|
||||||
|
event_id: eventId
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
display_order: displayOrder,
|
||||||
|
is_visible: isVisible
|
||||||
|
}
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Category Event Settings Mutation
|
||||||
|
const updateCategoryEventSettingsMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
categoryId,
|
||||||
|
eventId,
|
||||||
|
displayOrder,
|
||||||
|
isVisible
|
||||||
|
}: {
|
||||||
|
categoryId: string;
|
||||||
|
eventId: string;
|
||||||
|
displayOrder?: number;
|
||||||
|
isVisible?: boolean;
|
||||||
|
}) =>
|
||||||
|
updateCategoryEventSettings({
|
||||||
|
path: {
|
||||||
|
category_id: categoryId,
|
||||||
|
event_id: eventId
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
display_order: displayOrder,
|
||||||
|
is_visible: isVisible
|
||||||
|
}
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategory", currentCategoryId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get Events For Category Query
|
||||||
|
const getEventsForCategoryQuery = async (categoryId: string) => {
|
||||||
|
return getEventsForCategory({
|
||||||
|
path: { category_id: categoryId }
|
||||||
|
}).then((res) => res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reorder Gifts In Category Mutation
|
||||||
|
const reorderGiftsInCategoryMutation = useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
categoryId,
|
||||||
|
giftIds
|
||||||
|
}: {
|
||||||
|
categoryId: string;
|
||||||
|
giftIds: string[];
|
||||||
|
}) =>
|
||||||
|
reorderGiftsInCategory({
|
||||||
|
path: { category_id: categoryId },
|
||||||
|
body: { gift_ids: giftIds }
|
||||||
|
}).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentCategoryId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategory", currentCategoryId] });
|
||||||
|
}
|
||||||
|
if (currentEventId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftCategories", currentEventId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch all purchases for a gift or guest
|
||||||
|
const {
|
||||||
|
data: purchases,
|
||||||
|
isLoading: isLoadingPurchases,
|
||||||
|
error: purchasesError,
|
||||||
|
refetch: refetchPurchasesInternal,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftPurchases", currentItemId, null],
|
||||||
|
queryFn: () =>
|
||||||
|
currentItemId
|
||||||
|
? readGiftPurchasesByGift({
|
||||||
|
path: { gift_id: currentItemId }
|
||||||
|
}).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined),
|
||||||
|
enabled: !!currentItemId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const refetchPurchases = async (giftId?: string, guestId?: string) => {
|
||||||
|
if (giftId) {
|
||||||
|
setCurrentItemId(giftId);
|
||||||
|
}
|
||||||
|
return refetchPurchasesInternal();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch specific purchase
|
||||||
|
const {
|
||||||
|
data: purchase,
|
||||||
|
isLoading: isLoadingPurchase,
|
||||||
|
error: purchaseError,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["giftPurchase", currentPurchaseId],
|
||||||
|
queryFn: () =>
|
||||||
|
currentPurchaseId
|
||||||
|
? readGiftPurchase({
|
||||||
|
path: { purchase_id: currentPurchaseId }
|
||||||
|
}).then((res) => res.data)
|
||||||
|
: Promise.resolve(undefined),
|
||||||
|
enabled: !!currentPurchaseId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchPurchaseById = (id: string) => {
|
||||||
|
setCurrentPurchaseId(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create Purchase Mutation
|
||||||
|
const createPurchaseMutation = useMutation({
|
||||||
|
mutationFn: (data: GiftPurchaseCreate) =>
|
||||||
|
createGiftPurchase({ body: data }).then((res) => res.data),
|
||||||
|
onSuccess: () => {
|
||||||
|
if (currentItemId) {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftPurchases", currentItemId] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["giftItem", currentItemId] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch Purchases By Gift
|
||||||
|
const fetchPurchasesByGiftQuery = async (giftId: string) => {
|
||||||
|
return readGiftPurchasesByGift({
|
||||||
|
path: { gift_id: giftId }
|
||||||
|
}).then((res) => res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch Purchases By Guest
|
||||||
|
const fetchPurchasesByGuestQuery = async (guestId: string) => {
|
||||||
|
return readGiftPurchasesByGuest({
|
||||||
|
path: { guest_id: guestId }
|
||||||
|
}).then((res) => res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextValue: GiftContextState = {
|
||||||
|
// Gift Categories
|
||||||
|
categories,
|
||||||
|
category,
|
||||||
|
isLoadingCategories,
|
||||||
|
isLoadingCategory,
|
||||||
|
refetchCategories,
|
||||||
|
|
||||||
|
fetchCategoryById,
|
||||||
|
createCategory: createCategoryMutation.mutateAsync,
|
||||||
|
updateCategory: (id, data, eventId) =>
|
||||||
|
updateCategoryMutation.mutateAsync({ id, data, eventId }),
|
||||||
|
deleteCategory: (id, eventId) =>
|
||||||
|
deleteCategoryMutation.mutateAsync({ id, eventId }),
|
||||||
|
|
||||||
|
// Gift Items
|
||||||
|
items,
|
||||||
|
item,
|
||||||
|
isLoadingItems,
|
||||||
|
isLoadingItem,
|
||||||
|
refetchItems,
|
||||||
|
|
||||||
|
fetchItemById,
|
||||||
|
createItem: createItemMutation.mutateAsync,
|
||||||
|
updateItem: (id, data) =>
|
||||||
|
updateItemMutation.mutateAsync({ id, data }),
|
||||||
|
deleteItem: deleteItemMutation.mutateAsync,
|
||||||
|
updateItemStatus: (id, status) =>
|
||||||
|
updateItemStatusMutation.mutateAsync({ id, status }),
|
||||||
|
reserveItem: (id, guestId, quantity) =>
|
||||||
|
reserveItemMutation.mutateAsync({ id, guestId, quantity }),
|
||||||
|
cancelReservation: (id, guestId) =>
|
||||||
|
cancelReservationMutation.mutateAsync({ id, guestId }),
|
||||||
|
|
||||||
|
// Gift Categories additional methods
|
||||||
|
associateCategoryWithEvent: (categoryId, eventId, displayOrder, isVisible) =>
|
||||||
|
associateCategoryWithEventMutation.mutateAsync({ categoryId, eventId, displayOrder, isVisible }),
|
||||||
|
updateCategoryEventSettings: (categoryId, eventId, displayOrder, isVisible) =>
|
||||||
|
updateCategoryEventSettingsMutation.mutateAsync({ categoryId, eventId, displayOrder, isVisible }),
|
||||||
|
getEventsForCategory: getEventsForCategoryQuery,
|
||||||
|
reorderGiftsInCategory: (categoryId, giftIds) =>
|
||||||
|
reorderGiftsInCategoryMutation.mutateAsync({ categoryId, giftIds }),
|
||||||
|
|
||||||
|
// Gift Purchases
|
||||||
|
purchases,
|
||||||
|
purchase,
|
||||||
|
isLoadingPurchases,
|
||||||
|
isLoadingPurchase,
|
||||||
|
refetchPurchases,
|
||||||
|
|
||||||
|
fetchPurchaseById,
|
||||||
|
createPurchase: createPurchaseMutation.mutateAsync,
|
||||||
|
fetchPurchasesByGift: fetchPurchasesByGiftQuery,
|
||||||
|
fetchPurchasesByGuest: fetchPurchasesByGuestQuery,
|
||||||
|
|
||||||
|
// Current selections
|
||||||
|
currentCategoryId,
|
||||||
|
setCurrentCategoryId,
|
||||||
|
currentItemId,
|
||||||
|
setCurrentItemId,
|
||||||
|
currentPurchaseId,
|
||||||
|
setCurrentPurchaseId,
|
||||||
|
currentEventId,
|
||||||
|
setCurrentEventId,
|
||||||
|
|
||||||
|
error: (categoriesError || categoryError || itemsError || itemError || purchasesError || purchaseError) as Error | null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GiftContext.Provider value={contextValue}>{children}</GiftContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -3,13 +3,16 @@ 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";
|
import { RSVPProvider } from "@/context/rsvp-context";
|
||||||
import { GuestsProvider } from "@/context/guest-context";
|
import { GuestsProvider } from "@/context/guest-context";
|
||||||
|
import { GiftProvider } from "@/context/gift-context";
|
||||||
|
|
||||||
export function DataProviders({ children }: { children: React.ReactNode }) {
|
export function DataProviders({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<EventThemesProvider>
|
<EventThemesProvider>
|
||||||
<EventsProvider>
|
<EventsProvider>
|
||||||
<GuestsProvider>
|
<GuestsProvider>
|
||||||
<RSVPProvider>{children}</RSVPProvider>
|
<GiftProvider>
|
||||||
|
<RSVPProvider>{children}</RSVPProvider>
|
||||||
|
</GiftProvider>
|
||||||
</GuestsProvider>
|
</GuestsProvider>
|
||||||
</EventsProvider>
|
</EventsProvider>
|
||||||
</EventThemesProvider>
|
</EventThemesProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user