useAddToCart.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. "use client";
  2. import { useCustomToast } from "./useToast";
  3. import { useAppDispatch } from "@/store/hooks";
  4. import { addItem, clearCart } from "@/store/slices/cart-slice";
  5. import { isObject } from "@utils/type-guards";
  6. import { getCartToken } from "@utils/getCartToken";
  7. import { getCookie, setCookie, deleteCookie } from "@utils/cookie-tools";
  8. import { encodeJWT } from "@/utils/jwt-cookie";
  9. import { useGuestCartToken } from "./useGuestCartToken";
  10. import { IS_GUEST,GUEST_CART_TOKEN,GUEST_CART_ID } from "@/utils/constants";
  11. import { useMutation } from "@apollo/client/react";
  12. import {
  13. CREATE_ADD_PRODUCT_IN_CART,
  14. REMOVE_CART_ITEM,
  15. UPDATE_CART_ITEM,
  16. } from "@/graphql";
  17. import { formatCartDetail } from "@/utils/cartDetailTools";
  18. import {handleApolloBusinessError} from "@/lib/ApolloErrorHandler";
  19. export const useAddProduct = () => {
  20. const dispatch = useAppDispatch();
  21. const { createGuestToken } = useGuestCartToken();
  22. const { showToast } = useCustomToast();
  23. const [mutateAsync, { loading: isCartLoading }] = useMutation(
  24. CREATE_ADD_PRODUCT_IN_CART,
  25. {
  26. onCompleted: (res) => {
  27. console.log('useAddToCart onCompleted run ----- 0');
  28. const responseData = res?.createAddProductInCart?.addProductInCart;
  29. if (!responseData?.success) {
  30. showToast(responseData?.message || "Error adding to cart", "danger");
  31. return;
  32. }
  33. if (responseData) {
  34. if (responseData.success) {
  35. /** 兜底代码 start*/
  36. // 游客加购,然后清空购物车,然后刷新页面,然后再加购,然后再刷新页面,购物车会失效,所以添加兜底代码
  37. const isGuest = getCookie(IS_GUEST) !== "false";// 'true' 是游客
  38. // 如果之前的cartToken有效,responseCartId和responseCartToken的值是一样的都是cart id; 否则两者不相等
  39. const responseCartId = responseData.id;
  40. const responseCartToken = responseData.cartToken;
  41. if(isGuest && responseCartId !== responseCartToken) {
  42. const newToken = encodeJWT({
  43. sessionToken: responseCartToken,
  44. cartId: responseCartId,
  45. isGuest: isGuest,
  46. });
  47. setCookie(GUEST_CART_TOKEN, newToken,{encode: false});
  48. setCookie(GUEST_CART_ID, responseCartId);
  49. setCookie(IS_GUEST, String(isGuest));
  50. }
  51. /** 兜底代码 end*/
  52. const cartDetail = formatCartDetail(responseData);
  53. dispatch(addItem(cartDetail));
  54. showToast("Product added to cart successfully", "success");
  55. }
  56. }
  57. },
  58. onError: (err) => {
  59. handleApolloBusinessError(err,(error) => {
  60. showToast(error.message, "danger");
  61. });
  62. },
  63. },
  64. );
  65. const onAddToCart = async ({
  66. productId,
  67. quantity,
  68. variantId
  69. }: {
  70. productId: string;
  71. quantity: number;
  72. variantId?: number;
  73. token?: string;
  74. cartId?: number | string;
  75. }) => {
  76. // Ensure token exists - create if needed
  77. let token = getCartToken(); // 从cookie获取token
  78. if (!token) {
  79. // 没有token,则创建一个并写入cookie
  80. token = await createGuestToken();
  81. if (!token) {
  82. showToast("Failed to create cart session", "danger");
  83. return;
  84. }
  85. }
  86. const param : { productId: number; quantity:number; variantId?: number; } = {
  87. productId: parseInt(productId),
  88. quantity,
  89. };
  90. if(variantId) {
  91. param.variantId = variantId;
  92. }
  93. const result = await mutateAsync({
  94. variables: param,
  95. });
  96. return {
  97. data: result.data,
  98. error: result.error,
  99. };
  100. };
  101. //--------Remove Cart Product Quantity--------//
  102. const [removeFromCart, { loading: isRemoveLoading }] = useMutation(
  103. REMOVE_CART_ITEM,
  104. {
  105. onCompleted: async (response) => {
  106. const responseData = response?.createRemoveCartItem?.removeCartItem;
  107. if (isObject(responseData)) {
  108. const message = "Cart item removed successfully";
  109. const cartDetail = formatCartDetail(responseData);
  110. dispatch(addItem(cartDetail));
  111. showToast(message as string, "warning");
  112. if (!responseData?.itemsQty) {
  113. dispatch(clearCart());
  114. const isGuest = getCookie(IS_GUEST);
  115. if (isGuest === "true") {
  116. deleteCookie(GUEST_CART_TOKEN);
  117. deleteCookie(GUEST_CART_ID);
  118. }
  119. }
  120. } else {
  121. showToast("Something went wrong", "warning");
  122. }
  123. },
  124. onError: (error) => {
  125. handleApolloBusinessError(error,(err) => {
  126. showToast(err.message, "danger");
  127. });
  128. },
  129. },
  130. );
  131. const onAddToRemove = async (productId: string) => {
  132. await removeFromCart({
  133. variables: {
  134. cartItemId: parseInt(productId),
  135. },
  136. });
  137. };
  138. //---------Update Cart Product Quantity--------//
  139. const [updateCartItem, { loading: isUpdateLoading }] = useMutation(
  140. UPDATE_CART_ITEM,
  141. {
  142. onCompleted: (response) => {
  143. const responseData = response?.createUpdateCartItem?.updateCartItem;
  144. if (isObject(responseData)) {
  145. const cartDetail = formatCartDetail(responseData);
  146. dispatch(addItem(cartDetail));
  147. } else {
  148. showToast("Something went wrong!", "warning");
  149. }
  150. },
  151. onError: (error) => {
  152. handleApolloBusinessError(error,(err) => {
  153. showToast(err.message, "danger");
  154. });
  155. },
  156. },
  157. );
  158. const onUpdateCart = async ({
  159. cartItemId,
  160. quantity,
  161. }: {
  162. cartItemId: number;
  163. quantity: number;
  164. }) => {
  165. if (quantity < 1) {
  166. showToast("Quantity must be at least 1", "warning");
  167. return;
  168. }
  169. await updateCartItem({
  170. variables: {
  171. cartItemId: cartItemId,
  172. quantity,
  173. },
  174. });
  175. };
  176. return {
  177. isCartLoading,
  178. onAddToCart,
  179. isRemoveLoading,
  180. onAddToRemove,
  181. onUpdateCart,
  182. isUpdateLoading,
  183. };
  184. };