"use client"; import { useCallback } from "react"; import { useCustomToast } from "./useToast"; import { useAppDispatch } from "@/store/hooks"; import { addItem, clearCart } from "@/store/slices/cart-slice"; import { isObject } from "@utils/type-guards"; import { setCookie, getIsGuest, getGuestCartToken, deleteGuestCookie } from "@utils/cookie-tools"; import { useGuestCartToken } from "./useGuestCartToken"; import { IS_GUEST,GUEST_CART_TOKEN,GUEST_CART_ID } from "@/utils/constants"; import { useMutation, useApolloClient } from "@apollo/client/react"; import { CREATE_ADD_PRODUCT_IN_CART, REMOVE_CART_ITEM, UPDATE_CART_ITEM, } from "@/graphql"; import { formatCartDetail } from "@/utils/cartDetailTools"; import {handleApolloBusinessError} from "@/lib/ApolloErrorHandler"; export const useAddProduct = () => { const dispatch = useAppDispatch(); const { createGuestToken } = useGuestCartToken(); const { showToast } = useCustomToast(); const apolloClient = useApolloClient(); const [mutateAsync, { loading: isCartLoading }] = useMutation( CREATE_ADD_PRODUCT_IN_CART, { onCompleted: (res) => { console.log('useAddToCart onCompleted run ----- 0'); const responseData = res?.createAddProductInCart?.addProductInCart; if (!responseData?.success) { showToast(responseData?.message || "Error adding to cart", "danger"); return; } if (responseData) { if (responseData.success) { /** 兜底代码 start*/ // 游客加购,然后清空购物车,然后刷新页面,然后再加购,然后再刷新页面,购物车会失效,所以添加兜底代码 const isGuest = getIsGuest();// true 是游客 // 如果之前的cartToken有效,responseCartId和responseCartToken的值是一样的都是cart id; 否则两者不相等 const responseCartId = responseData.id; const responseCartToken = responseData.cartToken; if(isGuest && responseCartId !== responseCartToken) { setCookie(GUEST_CART_TOKEN, responseCartToken,{encode: false}); setCookie(GUEST_CART_ID, responseCartId); setCookie(IS_GUEST, String(isGuest)); } /** 兜底代码 end*/ const cartDetail = formatCartDetail(responseData); dispatch(addItem(cartDetail)); showToast("Product added to cart successfully", "success"); } } }, onError: (err) => { handleApolloBusinessError(err,(error) => { showToast(error.message, "danger"); }); }, }, ); const onAddToCart = async ({ productId, quantity, variantId }: { productId: string; quantity: number; variantId?: number; token?: string; cartId?: number | string; }) => { // Ensure token exists - create if needed let token = getGuestCartToken(); // 从cookie获取token const isGuest = getIsGuest(); if (!token && isGuest) { // 没有token,则创建一个并写入cookie token = await createGuestToken(); if (!token) { showToast("Failed to create cart session", "danger"); return; } } const param : { productId: number; quantity:number; variantId?: number; } = { productId: parseInt(productId), quantity, }; if(variantId) { param.variantId = variantId; } const result = await mutateAsync({ variables: param, }); return { data: result.data, error: result.error, }; }; // 删除购物车中的产品 const deleteProductFromCart = useCallback((cartItemId: number) => { return apolloClient.mutate({ mutation: REMOVE_CART_ITEM, variables: { cartItemId: cartItemId }, }).then((res) => { const resCatData = res.data?.createRemoveCartItem?.removeCartItem ?? null; if(resCatData && resCatData.itemsQty) { const cartDetail = formatCartDetail(resCatData); dispatch(addItem(cartDetail)); showToast('Cart item removed successfully', "warning"); } if(!resCatData || !resCatData?.itemsQty) { dispatch(clearCart()); // @todo 可以优化为通过接口或者server action 删除cookie const isGuest = getIsGuest(); if (isGuest) { deleteGuestCookie(); } } return { data: resCatData?.itemsQty ? formatCartDetail(resCatData) : null, error: false, msg: "" }; }).catch((err) => { return { data: null, error: true, msg: err.message, } }); },[apolloClient]); // 修改购物车中产品的数量 const editProductQtyFromCart = useCallback((cartItemId: number,quantity:number) => { if (quantity < 1) { showToast("Quantity must be at least 1", "warning"); return { data: null, error: true, msg: "Quantity must be at least 1", }; } return apolloClient.mutate({ mutation: UPDATE_CART_ITEM, variables: { cartItemId: cartItemId, quantity: quantity }, }).then((res) => { const resCatData = res.data?.createUpdateCartItem?.updateCartItem ?? null; if(resCatData) { const cartDetail = formatCartDetail(resCatData); dispatch(addItem(cartDetail)); } return { data: resCatData ? formatCartDetail(resCatData) : null, error: false, msg: "" }; }).catch((err) => { return { data: null, error: true, msg: err.message, } }); },[apolloClient]); //--------Remove Cart Product Quantity--------// const [removeFromCart, { loading: isRemoveLoading }] = useMutation( REMOVE_CART_ITEM, { onCompleted: async (response) => { const responseData = response?.createRemoveCartItem?.removeCartItem; if (isObject(responseData)) { const message = "Cart item removed successfully"; const cartDetail = formatCartDetail(responseData); dispatch(addItem(cartDetail)); showToast(message as string, "warning"); if (!responseData?.itemsQty) { dispatch(clearCart()); const isGuest = getIsGuest(); if (isGuest) { deleteGuestCookie(); } } } else { showToast("Something went wrong", "warning"); } }, onError: (error) => { handleApolloBusinessError(error,(err) => { showToast(err.message, "danger"); }); }, }, ); const onAddToRemove = async (productId: string) => { await removeFromCart({ variables: { cartItemId: parseInt(productId), }, }); }; //---------Update Cart Product Quantity--------// const [updateCartItem, { loading: isUpdateLoading }] = useMutation( UPDATE_CART_ITEM, { onCompleted: (response) => { const responseData = response?.createUpdateCartItem?.updateCartItem; if (isObject(responseData)) { const cartDetail = formatCartDetail(responseData); dispatch(addItem(cartDetail)); } else { showToast("Something went wrong!", "warning"); } }, onError: (error) => { handleApolloBusinessError(error,(err) => { showToast(err.message, "danger"); }); }, }, ); const onUpdateCart = async ({ cartItemId, quantity, }: { cartItemId: number; quantity: number; }) => { if (quantity < 1) { showToast("Quantity must be at least 1", "warning"); return; } await updateCartItem({ variables: { cartItemId: cartItemId, quantity, }, }); }; return { isCartLoading, onAddToCart, isRemoveLoading, onAddToRemove, onUpdateCart, isUpdateLoading, deleteProductFromCart, editProductQtyFromCart }; };