diff --git a/ts/features/payments/common/hooks/usePaymentsBackoffRetry.tsx b/ts/features/payments/common/hooks/usePaymentsBackoffRetry.tsx new file mode 100644 index 00000000000..3769c782b1a --- /dev/null +++ b/ts/features/payments/common/hooks/usePaymentsBackoffRetry.tsx @@ -0,0 +1,45 @@ +import { useIOToast } from "@pagopa/io-app-design-system"; +import { useIODispatch, useIOSelector } from "../../../../store/hooks"; +import { paymentsBackoffRetrySelector } from "../store/selectors"; +import { PaymentsBackoffRetry } from "../types/PaymentsBackoffRetry"; +import I18n from "../../../../i18n"; +import { + getTimeRemainingText, + isBackoffRetryTimeElapsed +} from "../utils/backoffRetry"; +import { increasePaymentsBackoffRetry } from "../store/actions"; + +export const usePaymentsBackoffRetry = (id: PaymentsBackoffRetry) => { + const toast = useIOToast(); + const dispatch = useIODispatch(); + const backoff = useIOSelector(paymentsBackoffRetrySelector(id)); + + /** + * This function check if the user can retry the request meaning that the exponential backoff time is elapsed + * If the time is not elapsed, by default a toast error will be shown + * @param showToast If true it shows automatically a toast with the time remaining to retry + * @returns true if the request can be retried, otherwise false + */ + const canRetryRequest = (showToast: boolean = true) => { + if ( + backoff?.allowedRetryTimestamp && + !isBackoffRetryTimeElapsed(backoff?.allowedRetryTimestamp) + ) { + if (showToast) { + toast.error( + I18n.t("features.payments.backoff.retryCountDown", { + time: getTimeRemainingText(backoff?.allowedRetryTimestamp) + }) + ); + } + return false; + } + dispatch(increasePaymentsBackoffRetry(id)); + return true; + }; + + return { + backoff, + canRetryRequest + }; +}; diff --git a/ts/features/payments/common/utils/backoffRetry.ts b/ts/features/payments/common/utils/backoffRetry.ts index 003866012ab..f128c3e34d2 100644 --- a/ts/features/payments/common/utils/backoffRetry.ts +++ b/ts/features/payments/common/utils/backoffRetry.ts @@ -40,5 +40,7 @@ export const getTimeRemainingText = (targetDate: number | Date): string => { }); }; -export const canRetry = (allowRetryTimestamp?: number): boolean => +export const isBackoffRetryTimeElapsed = ( + allowRetryTimestamp?: number +): boolean => allowRetryTimestamp === undefined || allowRetryTimestamp < Date.now(); diff --git a/ts/features/payments/home/components/PaymentsHomeTransactionsList.tsx b/ts/features/payments/home/components/PaymentsHomeTransactionsList.tsx index 8d3db5d614f..8efd774633b 100644 --- a/ts/features/payments/home/components/PaymentsHomeTransactionsList.tsx +++ b/ts/features/payments/home/components/PaymentsHomeTransactionsList.tsx @@ -2,8 +2,7 @@ import { Divider, IOStyles, ListItemHeader, - ListItemTransaction, - useIOToast + ListItemTransaction } from "@pagopa/io-app-design-system"; import * as pot from "@pagopa/ts-commons/lib/pot"; import * as React from "react"; @@ -21,15 +20,8 @@ import { useOnFirstRender } from "../../../../utils/hooks/useOnFirstRender"; import { BannerErrorState } from "../../../../components/ui/BannerErrorState"; import { useIONavigation } from "../../../../navigation/params/AppParamsList"; import { PaymentsTransactionBizEventsRoutes } from "../../bizEventsTransaction/navigation/routes"; -import { paymentsBackoffRetrySelector } from "../../common/store/selectors"; -import { - clearPaymentsBackoffRetry, - increasePaymentsBackoffRetry -} from "../../common/store/actions"; -import { - canRetry, - getTimeRemainingText -} from "../../common/utils/backoffRetry"; +import { usePaymentsBackoffRetry } from "../../common/hooks/usePaymentsBackoffRetry"; +import { clearPaymentsBackoffRetry } from "../../common/store/actions"; import { PaymentsBackoffRetry } from "../../common/types/PaymentsBackoffRetry"; import { PaymentsHomeEmptyScreenContent } from "./PaymentsHomeEmptyScreenContent"; @@ -47,10 +39,9 @@ const PaymentsHomeTransactionsList = ({ enforcedLoadingState }: Props) => { const latestTransactionsPot = useIOSelector( walletLatestTransactionsBizEventsListPotSelector ); - const transactionsBackoff = useIOSelector( - paymentsBackoffRetrySelector(PAYMENTS_HOME_TRANSACTIONS_LIST_BACKOFF) + const { canRetryRequest } = usePaymentsBackoffRetry( + PAYMENTS_HOME_TRANSACTIONS_LIST_BACKOFF ); - const toast = useIOToast(); const isLoading = (!pot.isSome(latestTransactionsPot) && @@ -96,21 +87,9 @@ const PaymentsHomeTransactionsList = ({ enforcedLoadingState }: Props) => { ); const handleOnRetry = () => { - if ( - transactionsBackoff?.allowedRetryTimestamp && - !canRetry(transactionsBackoff?.allowedRetryTimestamp) - ) { - toast.error( - I18n.t("features.payments.backoff.retryCountDown", { - time: getTimeRemainingText(transactionsBackoff?.allowedRetryTimestamp) - }) - ); - return; + if (canRetryRequest()) { + dispatch(getPaymentsLatestBizEventsTransactionsAction.request()); } - dispatch( - increasePaymentsBackoffRetry(PAYMENTS_HOME_TRANSACTIONS_LIST_BACKOFF) - ); - dispatch(getPaymentsLatestBizEventsTransactionsAction.request()); }; const handleNavigateToTransactionList = () => { diff --git a/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx b/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx index 0bcfa257017..45a276bb801 100644 --- a/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx +++ b/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx @@ -2,7 +2,6 @@ import { Banner, IOVisualCostants, ListItemHeader, - useIOToast, VSpacer } from "@pagopa/io-app-design-system"; import * as pot from "@pagopa/ts-commons/lib/pot"; @@ -24,15 +23,8 @@ import { isAddMethodsBannerVisibleSelector } from "../store/selectors"; import { useOnFirstRender } from "../../../../utils/hooks/useOnFirstRender"; import { paymentAnalyticsDataSelector } from "../../history/store/selectors"; import { BannerErrorState } from "../../../../components/ui/BannerErrorState"; -import { paymentsBackoffRetrySelector } from "../../common/store/selectors"; -import { - clearPaymentsBackoffRetry, - increasePaymentsBackoffRetry -} from "../../common/store/actions"; -import { - canRetry, - getTimeRemainingText -} from "../../common/utils/backoffRetry"; +import { usePaymentsBackoffRetry } from "../../common/hooks/usePaymentsBackoffRetry"; +import { clearPaymentsBackoffRetry } from "../../common/store/actions"; import { PaymentCardsCarousel, PaymentCardsCarouselSkeleton @@ -49,7 +41,6 @@ const PaymentsHomeUserMethodsList = ({ enforcedLoadingState }: Props) => { const navigation = useIONavigation(); const dispatch = useIODispatch(); - const toast = useIOToast(); const shouldShowAddMethodsBanner = useIOSelector( isAddMethodsBannerVisibleSelector @@ -57,8 +48,8 @@ const PaymentsHomeUserMethodsList = ({ enforcedLoadingState }: Props) => { const paymentMethodsPot = useIOSelector(paymentsWalletUserMethodsSelector); const paymentMethods = pot.getOrElse(paymentMethodsPot, []); const paymentAnalyticsData = useIOSelector(paymentAnalyticsDataSelector); - const paymentsUserMethodsBackoff = useIOSelector( - paymentsBackoffRetrySelector(PAYMENTS_HOME_USER_METHODS_BACKOFF) + const { canRetryRequest } = usePaymentsBackoffRetry( + PAYMENTS_HOME_USER_METHODS_BACKOFF ); const isError = React.useMemo( () => pot.isError(paymentMethodsPot) && !pot.isSome(paymentMethodsPot), @@ -108,22 +99,10 @@ const PaymentsHomeUserMethodsList = ({ enforcedLoadingState }: Props) => { }; const handleOnRetry = React.useCallback(() => { - if ( - paymentsUserMethodsBackoff?.allowedRetryTimestamp && - !canRetry(paymentsUserMethodsBackoff?.allowedRetryTimestamp) - ) { - toast.error( - I18n.t("features.payments.backoff.retryCountDown", { - time: getTimeRemainingText( - paymentsUserMethodsBackoff?.allowedRetryTimestamp - ) - }) - ); - return; + if (canRetryRequest()) { + dispatch(getPaymentsWalletUserMethods.request()); } - dispatch(increasePaymentsBackoffRetry(PAYMENTS_HOME_USER_METHODS_BACKOFF)); - dispatch(getPaymentsWalletUserMethods.request()); - }, [dispatch, paymentsUserMethodsBackoff, toast]); + }, [dispatch, canRetryRequest]); const userMethods = paymentMethods.map( (method: WalletInfo): PaymentCardSmallProps => ({