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; updateQuantity: (id: string, quantity: number) => Promise; removeItem: (id: string) => Promise; clearCart: () => void; isLoading: boolean; } const CartContext = createContext(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 ( {children} ); } export function useCart() { const context = useContext(CartContext); if (context === undefined) { throw new Error('useCart must be used within a CartProvider'); } return context; }