ecom / client /src /hooks /use-cart.tsx
shashwatIDR's picture
Upload 147 files
b89a86e verified
import { createContext, useContext, useState, useEffect, ReactNode } from "react";
import { CartItem } from "@/types";
import { cartApi } from "@/lib/api";
import { useAuth } from "./use-auth";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
interface CartContextType {
items: CartItem[];
itemCount: number;
subtotal: number;
tax: number;
total: number;
addItem: (productId: string, quantity?: number) => Promise<void>;
updateQuantity: (id: string, quantity: number) => Promise<void>;
removeItem: (id: string) => Promise<void>;
clearCart: () => void;
isLoading: boolean;
}
const CartContext = createContext<CartContextType | undefined>(undefined);
export function CartProvider({ children }: { children: ReactNode }) {
const { user, isAuthenticated } = useAuth();
const queryClient = useQueryClient();
const { data: items = [], isLoading } = useQuery({
queryKey: ['/api/cart'],
queryFn: async () => {
if (!isAuthenticated || !user) return [];
const response = await cartApi.get();
return response.json();
},
enabled: isAuthenticated && !!user,
});
const addMutation = useMutation({
mutationFn: (data: { productId: string; quantity: number }) => cartApi.add(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/cart'] });
},
});
const updateMutation = useMutation({
mutationFn: ({ id, quantity }: { id: string; quantity: number }) =>
cartApi.update(id, { quantity }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/cart'] });
},
});
const removeMutation = useMutation({
mutationFn: (id: string) => cartApi.remove(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/cart'] });
},
});
const addItem = async (productId: string, quantity = 1) => {
if (!user) return;
await addMutation.mutateAsync({ productId, quantity });
};
const updateQuantity = async (id: string, quantity: number) => {
await updateMutation.mutateAsync({ id, quantity });
};
const removeItem = async (id: string) => {
await removeMutation.mutateAsync(id);
};
const clearCart = () => {
queryClient.setQueryData(['/api/cart'], []);
};
const itemCount = items.reduce((count: number, item: CartItem) => count + item.quantity, 0);
const subtotal = items.reduce((total: number, item: CartItem) => {
const price = parseFloat(item.product?.price || '0');
return total + (price * item.quantity);
}, 0);
const tax = subtotal * 0.08; // 8% tax
const total = subtotal + tax;
return (
<CartContext.Provider value={{
items,
itemCount,
subtotal,
tax,
total,
addItem,
updateQuantity,
removeItem,
clearCart,
isLoading,
}}>
{children}
</CartContext.Provider>
);
}
export function useCart() {
const context = useContext(CartContext);
if (context === undefined) {
throw new Error('useCart must be used within a CartProvider');
}
return context;
}