All files / src/features/Merchants/MerchantSidePanel/hooks useResendButtonState.ts

75% Statements 27/36
61.53% Branches 16/26
66.66% Functions 4/6
74.28% Lines 26/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114            116x 116x 116x   116x   116x 686x   350x     116x       584x           584x                     116x           584x 584x     584x           584x       584x 584x 584x           584x   584x         584x 102x 102x                                 584x     584x       584x                          
import { useEffect, useState } from "react";
import { useQueryClient } from "react-query";
import { useCountdown } from "hooks/useCountdown";
import { MERCHANT_SIDE_PANEL_PREVIEW_API_KEYS } from "@features/Merchants/MerchantSidePanel/constants";
import { millisecondsToHHMMSS } from "@utils/index";
 
const SAFE_GRACE_PERIOD = 15000; // 15s buffer to avoid inconsistencies
const SHORT_COOLDOWN = 300000; //5 minutes
const LONG_COOLDOWN = 259200000; //72 hours
 
export const LONG_COOLDOWN_MESSAGE = "Resend invitation limit was reached";
 
const getTimeRemaining = (cooldownEndsAt: number | undefined) => {
  if (!cooldownEndsAt) return 0;
 
  return new Date(Number(`${cooldownEndsAt}000`)).getTime() - Date.now();
};
 
const checkIfSendNewEmail = (
  sentEmailCount: number,
  cooldownEndsAt: number,
) => {
  Iif (
    sentEmailCount === 5 &&
    new Date(Number(`${cooldownEndsAt}000`)).getTime() - Date.now() < 0
  ) {
    return true;
  } else {
    return false;
  }
};
 
type TProps = {
  cooldownEndsAt: number | undefined;
  sentEmailCount?: number;
  inviteStatus: string;
  isUndeliverable?: boolean;
};
 
export const useResendButtonState = ({
  cooldownEndsAt = 0,
  sentEmailCount = 0,
  inviteStatus,
  isUndeliverable,
}: TProps) => {
  const queryClient = useQueryClient();
  const [isDisableResend, setIsDisableResend] = useState(
    isUndeliverable && inviteStatus === "invited",
  );
  const onCountdownEnd = () => {
    setIsDisableResend(false);
    setIsActionJustPerformed(false);
    queryClient.invalidateQueries(MERCHANT_SIDE_PANEL_PREVIEW_API_KEYS.GET);
  };
 
  const { startCountDown: startCount, timeLeft } = useCountdown({
    onCountdownEnd,
  });
 
  const [isActionJustPerformed, setIsActionJustPerformed] = useState(false);
  const modifiedInviteStatus = isDisableResend ? "invited" : inviteStatus;
  const shouldSendNewEmail = checkIfSendNewEmail(
    sentEmailCount,
    cooldownEndsAt,
  );
 
  const isSend =
    shouldSendNewEmail || !["invited", "joined"].includes(modifiedInviteStatus);
 
  const startCountDown = (remainingTime: number) => {
    startCount({ duration: remainingTime });
    queryClient.invalidateQueries(MERCHANT_SIDE_PANEL_PREVIEW_API_KEYS.GET);
  };
 
  useEffect(() => {
    const timeRemaining = getTimeRemaining(cooldownEndsAt);
    Iif (timeRemaining > 0) {
      setIsDisableResend(true);
 
      // To provide a consistent UX, we are setting the countdown time manually based on the BE response.
      // BE sometimes returns a time when countdown starts that is always not same, which creates random countdown start time.
      // This logic will only take effect when the user clicks the resend button.
      const countdownTime = !isActionJustPerformed
        ? timeRemaining
        : timeRemaining <= SHORT_COOLDOWN + 5000 // Add 5000s buffer to avoid incorrectly set long cooldown
        ? SHORT_COOLDOWN
        : LONG_COOLDOWN;
 
      startCountDown(Math.ceil(countdownTime / 1000));
    }
  }, [cooldownEndsAt]);
 
  const isLongCooldownActive =
    timeLeft * 1000 > SHORT_COOLDOWN + SAFE_GRACE_PERIOD;
 
  const timeRemainingLabel =
    timeLeft > 0
      ? `${millisecondsToHHMMSS(timeLeft * 1000, isLongCooldownActive)}`
      : "";
 
  return {
    isDisableResend,
    setIsDisableResend,
    timeLeft,
    isLongCooldownActive,
    inviteButtonText: isSend ? "Send" : "Resend",
    shouldSendNewEmail,
    isSend,
    setIsActionJustPerformed,
    timeRemainingLabel:
      getTimeRemaining(cooldownEndsAt) < 0 ? "" : timeRemainingLabel, // if the count is expired return 0
  };
};