Spaces:
Running
Running
File size: 3,088 Bytes
b89a86e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
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;
}
|