useGuestCartToken.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. "use client";
  2. import { useEffect, useState, useRef } from "react";
  3. import { fetchHandler } from "../fetch-handler";
  4. import { GUEST_CART_ID, GUEST_CART_TOKEN, IS_GUEST } from "@/utils/constants";
  5. import { encodeJWT, decodeJWT } from "@/utils/jwt-cookie";
  6. import { setCookie, deleteCookie, getCookie } from "@/utils/cookie-tools";
  7. // ---------------------------
  8. // Main Hook
  9. // ---------------------------
  10. export const useGuestCartToken = () => {
  11. const [token, setToken] = useState<string | null>(null);
  12. const [cartId, setCartId] = useState<number | null>(null);
  13. const [isReady, setIsReady] = useState(false);
  14. const isResettingRef = useRef(false);
  15. const tokenCreatedRef = useRef(false);
  16. const tokenPromiseRef = useRef<Promise<string | null> | null>(null);
  17. const createGuestToken = async (): Promise<string | null> => {
  18. if (tokenPromiseRef.current) return tokenPromiseRef.current;
  19. tokenPromiseRef.current = (async () => {
  20. if (tokenCreatedRef.current) {
  21. // Return existing raw token from cookie
  22. const cookieVal = getCookie(GUEST_CART_TOKEN);
  23. if (cookieVal) {
  24. const isGuest = getCookie(IS_GUEST) !== "false";
  25. const decoded = decodeJWT<{ sessionToken: string }>(cookieVal, isGuest);
  26. return decoded?.sessionToken ?? null;
  27. }
  28. return null;
  29. }
  30. tokenCreatedRef.current = true;
  31. try {
  32. const res = await fetchHandler({
  33. url: "graphql",
  34. method: "POST",
  35. body: { operationName: "CreateCart" },
  36. contentType: true,
  37. });
  38. const cart = res?.data?.createCartToken?.cartToken;
  39. if (!cart) {
  40. tokenCreatedRef.current = false;
  41. return null;
  42. }
  43. const newToken = encodeJWT({
  44. sessionToken: cart.sessionToken,
  45. cartId: cart.id,
  46. isGuest: cart.isGuest,
  47. });
  48. const newCartId = Number(cart.id);
  49. setCookie(GUEST_CART_TOKEN, newToken,{encode: false});
  50. setCookie(GUEST_CART_ID, String(newCartId));
  51. setCookie(IS_GUEST, String(cart?.isGuest));
  52. // State and return should be the RAW token
  53. setToken(cart.sessionToken);
  54. setCartId(newCartId);
  55. return cart.sessionToken;
  56. } catch (e) {
  57. console.error("Error creating guest token:", e);
  58. tokenCreatedRef.current = false;
  59. return null;
  60. } finally {
  61. tokenPromiseRef.current = null;
  62. }
  63. })();
  64. return tokenPromiseRef.current;
  65. };
  66. const resetGuestToken = async () => {
  67. if (isResettingRef.current) return;
  68. isResettingRef.current = true;
  69. tokenCreatedRef.current = false;
  70. // delete old
  71. deleteCookie(GUEST_CART_TOKEN);
  72. deleteCookie(GUEST_CART_ID);
  73. await createGuestToken();
  74. isResettingRef.current = false;
  75. };
  76. useEffect(() => {
  77. const cookieToken = getCookie(GUEST_CART_TOKEN);
  78. if (cookieToken) {
  79. const isGuest = getCookie(IS_GUEST) !== "false";
  80. const decoded = decodeJWT<{
  81. sessionToken: string;
  82. cartId: number;
  83. isGuest: boolean;
  84. }>(cookieToken, isGuest);
  85. if (decoded) {
  86. setToken(decoded.sessionToken);
  87. setCartId(decoded.cartId);
  88. }
  89. }
  90. setIsReady(true);
  91. }, []);
  92. return {
  93. token,
  94. cartId,
  95. isReady,
  96. createGuestToken,
  97. resetGuestToken,
  98. deleteCookie,
  99. };
  100. };