useAddToCart.ts 5.7 KB

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