Vitron-Front/app/requestHandler/use-cart-hooks.ts
2026-04-29 01:44:16 +03:30

257 lines
6.9 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useAuthToken } from "../hooks/use-root-data";
import { useEffect, useState } from "react";
import { createShoppingCartApi } from "~/utils/api-client-factory";
// Hook to get all carts
export function useGetAllCarts() {
const token = useAuthToken();
return useQuery({
queryKey: ["carts", "list"],
queryFn: async () => {
console.log("📥 Fetching cart list...");
try {
const cartApi = createShoppingCartApi(token);
const result = await cartApi.apiShoppingcartV1CartList();
return result;
} catch (error) {
console.error("❌ Error fetching carts:", error);
return [];
}
},
// Run even without token for guest carts
retry: 1,
staleTime: 30 * 60 * 1000, // 30 seconds - balance between freshness and performance
refetchOnWindowFocus: false,
});
}
// Hook to get cart count
export function useGetCartCount() {
const token = useAuthToken();
return useQuery({
queryKey: ["carts", "count"],
queryFn: async () => {
try {
if (!token) return 0;
const cartApi = createShoppingCartApi(token);
const carts = await cartApi.apiShoppingcartV1CartList();
// Calculate total items across all carts
return carts.reduce((total, cart) => {
return total + (cart.items?.length || 0);
}, 0);
} catch (error) {
console.error("Error getting cart count:", error);
return 0;
}
},
enabled: !!token, // Only run if user is authenticated
staleTime: 2 * 60 * 1000, // 2 minutes - cart count doesn't change often
gcTime: 5 * 60 * 1000, // 5 minutes
retry: 1,
});
}
// Hook to add item to cart
export function useAddToCart() {
const token = useAuthToken();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
variantId,
quantity,
}: {
variantId: string;
quantity: number;
}) => {
try {
const cartApi = createShoppingCartApi(token);
await cartApi.apiShoppingcartV1CartAddCreate({
data: {
productVariantId: variantId,
quantity: quantity,
},
});
return true;
} catch (error) {
console.error("Failed to add item to cart:", error);
return false;
}
},
onSuccess: async () => {
// Invalidate and refetch cart queries immediately
await Promise.all([
queryClient.invalidateQueries({
queryKey: ["carts", "list"],
refetchType: "all", // Refetch all queries, not just active ones
}),
queryClient.invalidateQueries({
queryKey: ["carts", "count"],
refetchType: "all",
}),
]);
},
onError: (error) => {
console.error("Failed to add item to cart:", error);
},
});
}
// Hook to update cart item quantity
export function useUpdateCartItemQuantity() {
const token = useAuthToken();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
itemId,
quantity,
}: {
itemId: string;
quantity: number;
}) => {
try {
const cartApi = createShoppingCartApi(token);
await cartApi.apiShoppingcartV1CartEditPartialUpdate({
data: {
itemId,
quantity,
},
});
return true;
} catch (error) {
console.error("Error updating cart item quantity:", error);
return false;
}
},
onSuccess: async () => {
// Invalidate and refetch all cart queries immediately
await Promise.all([
queryClient.invalidateQueries({
queryKey: ["carts", "list"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "count"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "detail"],
refetchType: "all",
}),
]);
},
});
}
// Hook to remove item from cart
export function useRemoveFromCart() {
const token = useAuthToken();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (itemId: string) => {
try {
const cartApi = createShoppingCartApi(token);
await cartApi.apiShoppingcartV1CartRemoveDelete({ itemId });
return true;
} catch (error) {
console.error("Error removing item from cart:", error);
return false;
}
},
onSuccess: async () => {
// Invalidate and refetch all cart queries immediately
await Promise.all([
queryClient.invalidateQueries({
queryKey: ["carts", "list"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "count"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "detail"],
refetchType: "all",
}),
]);
},
});
}
// Hook to clear cart
export function useClearCart() {
const token = useAuthToken();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (cartId: string) => {
try {
const cartApi = createShoppingCartApi(token);
await cartApi.apiShoppingcartV1CartClearCreate({ cartId });
return true;
} catch (error) {
console.error("Error clearing cart:", error);
return false;
}
},
onSuccess: async () => {
// Invalidate and refetch all cart queries immediately
await Promise.all([
queryClient.invalidateQueries({
queryKey: ["carts", "list"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "count"],
refetchType: "all",
}),
queryClient.invalidateQueries({
queryKey: ["carts", "detail"],
refetchType: "all",
}),
]);
},
});
}
// Hook to get details of a specific cart
export function useGetCartDetails(cartId: string) {
const token = useAuthToken();
return useQuery({
queryKey: ["carts", "detail", cartId],
queryFn: async () => {
try {
const cartApi = createShoppingCartApi(token);
return await cartApi.apiShoppingcartV1CartRead({ cartId });
} catch (error) {
console.error(`Error fetching cart ${cartId}:`, error);
return null;
}
},
enabled: !!cartId, // Only run if we have a cart ID
retry: 1,
staleTime: 30 * 60 * 1000, // 30 seconds - balance between freshness and performance
refetchOnWindowFocus: false,
});
}
export const useCartCount = () => {
const [count, setCount] = useState(0);
const { data: cartCount, isLoading } = useGetCartCount();
// Update local state whenever the query data changes
useEffect(() => {
if (!isLoading && cartCount !== undefined) {
setCount(cartCount);
}
}, [cartCount, isLoading]);
return count;
};