190 lines
4.4 KiB
JavaScript
190 lines
4.4 KiB
JavaScript
"use client";
|
|
|
|
import { createContext, useContext, useState, useEffect, useCallback } from "react";
|
|
import { useAuth } from "@/context/AuthContext";
|
|
import {
|
|
fetchCart,
|
|
apiAddToCart,
|
|
apiUpdateCartItem,
|
|
apiRemoveCartItem,
|
|
apiClearCart,
|
|
apiApplyCoupon,
|
|
apiRemoveCoupon,
|
|
apiCheckout,
|
|
apiCancelCheckout,
|
|
} from "@/lib/cartApi";
|
|
|
|
const CartContext = createContext(null);
|
|
|
|
const STORE_KEY = "selected_store_id";
|
|
|
|
export function CartProvider({ children }) {
|
|
const { user, token } = useAuth();
|
|
const [cart, setCart] = useState(null);
|
|
const [selectedStoreId, setSelectedStoreIdState] = useState(null);
|
|
const [cartLoading, setCartLoading] = useState(false);
|
|
const [cartError, setCartError] = useState(null);
|
|
|
|
const setStoreId = useCallback((id) => {
|
|
const parsed = id ? Number(id) : null;
|
|
setSelectedStoreIdState(parsed);
|
|
if (parsed) {
|
|
localStorage.setItem(STORE_KEY, String(parsed));
|
|
}
|
|
|
|
else {
|
|
localStorage.removeItem(STORE_KEY);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const stored = localStorage.getItem(STORE_KEY);
|
|
if (stored) {
|
|
setSelectedStoreIdState(Number(stored));
|
|
}
|
|
}, []);
|
|
|
|
const refreshCart = useCallback(async () => {
|
|
if (!token || !selectedStoreId) {
|
|
setCart(null);
|
|
return;
|
|
}
|
|
setCartLoading(true);
|
|
setCartError(null);
|
|
try {
|
|
const data = await fetchCart(token, selectedStoreId);
|
|
setCart(data);
|
|
}
|
|
|
|
catch (err) {
|
|
setCartError(err.message);
|
|
}
|
|
|
|
finally {
|
|
setCartLoading(false);
|
|
}
|
|
}, [token, selectedStoreId]);
|
|
|
|
useEffect(() => {
|
|
if (user && selectedStoreId) {
|
|
refreshCart();
|
|
}
|
|
|
|
else {
|
|
setCart(null);
|
|
}
|
|
}, [user, selectedStoreId, refreshCart]);
|
|
|
|
const addItem = useCallback(
|
|
async (prodId, quantity = 1) => {
|
|
if (!token || !selectedStoreId) throw new Error("Select a store first");
|
|
const updated = await apiAddToCart(token, { prodId, storeId: selectedStoreId, quantity });
|
|
setCart(updated);
|
|
|
|
return updated;
|
|
},
|
|
[token, selectedStoreId]
|
|
);
|
|
|
|
const updateItem = useCallback(
|
|
async (cartItemId, quantity) => {
|
|
if (!token) return;
|
|
const updated = await apiUpdateCartItem(token, { cartItemId, quantity });
|
|
setCart(updated);
|
|
|
|
return updated;
|
|
},
|
|
[token]
|
|
);
|
|
|
|
const removeItem = useCallback(
|
|
async (cartItemId) => {
|
|
if (!token) return;
|
|
const updated = await apiRemoveCartItem(token, cartItemId);
|
|
setCart(updated);
|
|
|
|
return updated;
|
|
},
|
|
[token]
|
|
);
|
|
|
|
const clearCart = useCallback(async () => {
|
|
if (!token || !selectedStoreId) return;
|
|
await apiClearCart(token, selectedStoreId);
|
|
setCart(null);
|
|
}, [token, selectedStoreId]);
|
|
|
|
const applyCoupon = useCallback(
|
|
async (couponCode) => {
|
|
if (!token || !selectedStoreId) throw new Error("Select a store first");
|
|
const updated = await apiApplyCoupon(token, selectedStoreId, couponCode);
|
|
setCart(updated);
|
|
|
|
return updated;
|
|
},
|
|
[token, selectedStoreId]
|
|
);
|
|
|
|
const removeCoupon = useCallback(
|
|
async () => {
|
|
if (!token || !selectedStoreId) throw new Error("Select a store first");
|
|
const updated = await apiRemoveCoupon(token, selectedStoreId);
|
|
setCart(updated);
|
|
|
|
return updated;
|
|
},
|
|
[token, selectedStoreId]
|
|
);
|
|
|
|
const checkout = useCallback(
|
|
async () => {
|
|
if (!token || !selectedStoreId) throw new Error("Select a store first");
|
|
const result = await apiCheckout(token, { storeId: selectedStoreId });
|
|
|
|
return result;
|
|
},
|
|
[token, selectedStoreId]
|
|
);
|
|
|
|
const cancelCheckout = useCallback(
|
|
async () => {
|
|
if (!token || !selectedStoreId) return;
|
|
await apiCancelCheckout(token, selectedStoreId);
|
|
await refreshCart();
|
|
},
|
|
[token, selectedStoreId, refreshCart]
|
|
);
|
|
|
|
const itemCount = cart?.items?.reduce((sum, i) => sum + i.quantity, 0) ?? 0;
|
|
|
|
return (
|
|
<CartContext.Provider
|
|
value={{
|
|
cart,
|
|
cartLoading,
|
|
cartError,
|
|
itemCount,
|
|
selectedStoreId,
|
|
setStoreId,
|
|
addItem,
|
|
updateItem,
|
|
removeItem,
|
|
clearCart,
|
|
applyCoupon,
|
|
removeCoupon,
|
|
checkout,
|
|
cancelCheckout,
|
|
refreshCart,
|
|
}}
|
|
>
|
|
{children}
|
|
</CartContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useCart() {
|
|
const ctx = useContext(CartContext);
|
|
if (!ctx) throw new Error("useCart must be used within a CartProvider");
|
|
return ctx;
|
|
}
|