From f047adb0aaf24a1c86ba51982d2ae9799e8378f0 Mon Sep 17 00:00:00 2001 From: Tharindu Kumarasiri Date: Wed, 25 Sep 2024 09:13:52 +0530 Subject: [PATCH 1/2] loading animation added --- src/assets/images/loader_animation.gif | Bin 0 -> 5284 bytes src/assets/images/lock_image.png | Bin 0 -> 1132 bytes src/assets/images/success_animation.gif | Bin 0 -> 30162 bytes src/assets/languages/en.json | 1 + src/assets/languages/ja.json | 1 + src/components/Button.tsx | 73 ++++++++++++ src/components/Input.tsx | 16 ++- src/components/PaymentModal.tsx | 18 ++- src/components/ResponseScreen.tsx | 4 +- src/components/SheetContent.tsx | 16 ++- src/components/SubmitButton.tsx | 105 +++++++++++----- src/components/sections/CardSection.tsx | 2 +- src/context/MainStateProvider.tsx | 9 +- src/context/state.ts | 4 + src/hooks/useBackgroundHandler.tsx | 20 +++- src/hooks/useDeepLinkHandler.tsx | 22 +++- src/hooks/useMainStateUtils.tsx | 66 ++++++++-- src/hooks/usePaymentUiUtils.tsx | 152 ++++++++++++------------ src/hooks/useSessionPayHandler.tsx | 23 +++- src/hooks/useThreeDSecureHandler.tsx | 5 +- src/theme/defaultColorTheme.ts | 2 + src/util/helpers.ts | 6 + src/util/types.ts | 13 +- 23 files changed, 401 insertions(+), 157 deletions(-) create mode 100644 src/assets/images/loader_animation.gif create mode 100644 src/assets/images/lock_image.png create mode 100644 src/assets/images/success_animation.gif create mode 100644 src/components/Button.tsx diff --git a/src/assets/images/loader_animation.gif b/src/assets/images/loader_animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4f43772ff3d6fa86b954c3246d89e02d40cb157 GIT binary patch literal 5284 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/lock_image.png b/src/assets/images/lock_image.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd562e921afe279cd80809c8987064675ed5796 GIT binary patch literal 1132 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWNia>m~RfIy|l#?#P;!|HdN;a^v*wL|g zbu*uyi;Pc6h~Y8EyFMm{EexLw0-M#Gj<`2EzQiJP=})!xp(9yS%IICD5@EO}`0U9faj=+{+YJ5Plyoe=d^DKVK(dkQ0iV#uoHh3o8J z%n9pkx$hNw;kd30HD(@< z+Zr@`8S{x3Kfy|`Lf@eQ}pEAJcgUrvsm3?XV!1_dHQpIyh~++O~c8% zcKd6d8*jd{MB8RFv%oX4atX(r2Q15FpJw|pEZcFWG>t*xvFQ7qLerUhkG__xaFI3^ z=t$enVP5&>>_qbhNjW3S=~2uK!X-zZDXTLG_o#gBHJWMNppfcW>#cc8)j{~o(`gZH znO)lVH}NnW&*;fEFSs*Xc|C(^%+gDFp+&v3?l3vXKHV1QH#gk;9%EYYmLjGJ3s0S_ z*4w~wi)UK7{k`-BQ*yWMn|tXFvq)hl8`s8+CyTawbNso=Y`w!@y|rbqyR;NPIYxaq^g^1AbR43F=fI=w|G@ea>|`S;c^e7TUHpxW|n#qp=VcgT0X zSSoeb?#Ca-duCm0eSaEW2WB_b64!{5l*E!$tK_0oAjM#0U}U0eV5w_l8e(8Pn(Dj&D8CgIqVKRI6 Q8K{TB)78&qol`;+0Ew2_A^-pY literal 0 HcmV?d00001 diff --git a/src/assets/images/success_animation.gif b/src/assets/images/success_animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..3579ee9ad33d2d555cee223dcfb7b2e947ed88c1 GIT binary patch literal 30162 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 H*2(_>KqFfM literal 0 HcmV?d00001 diff --git a/src/assets/languages/en.json b/src/assets/languages/en.json index f46ee07..033e897 100644 --- a/src/assets/languages/en.json +++ b/src/assets/languages/en.json @@ -51,6 +51,7 @@ "SESSION_EXPIRED_MSG": "This session has already expired. Please try again.", "PAYMENT_WAITING": "Awaiting Payment", "PAYMENT_WAITING_MSG": "Your payment has not been completed yet. We have e-mailed you the instructions on how to complete your purchase.", + "LOADING_TEXT": "Processing...", "PAYMENT_VIA_ALI_PAY": "Payment via Alipay", "ALI_PAY_REDIRECT_MESSAGE": "You will be redirected to Alipay to complete the payment", diff --git a/src/assets/languages/ja.json b/src/assets/languages/ja.json index ab2fc53..40f104b 100644 --- a/src/assets/languages/ja.json +++ b/src/assets/languages/ja.json @@ -51,6 +51,7 @@ "SESSION_EXPIRED_MSG": "このセッションは既に期限切れです。再度お試しください。", "PAYMENT_WAITING": "支払い待ち", "PAYMENT_WAITING_MSG": "支払いは完了していません。支払い方法の詳細をメールアドレス宛にお送りしていますのでご確認ください。", + "LOADING_TEXT": "処理...", "PAYMENT_VIA_ALI_PAY": "Alipayによる支払い", "ALI_PAY_REDIRECT_MESSAGE": "支払いを完了するには、Alipay にリダイレクトされます。", diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..57adab7 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,73 @@ +import { StyleSheet, Text, TouchableOpacity, Keyboard } from "react-native"; + +import { useTranslation } from "react-i18next"; + +import { ThemeSchemeType } from "../util/types"; + +import { resizeFonts, responsiveScale } from "../theme/scalling"; +import { useCurrentTheme } from "../theme/useCurrentTheme"; +import { ReactNode } from "react"; + +type Props = { + onPress: () => void; + label: string; + labelSuffix?: string; + testID?: string; + style?: object; + disabled?: boolean; + children?: ReactNode; +}; + +const Button = ({ + label, + labelSuffix, + onPress, + testID, + style, + disabled = false, + children, +}: Props) => { + const { t } = useTranslation(); + const theme = useCurrentTheme(); + const styles = getStyles(theme); + + const onSubmit = () => { + Keyboard.dismiss(); + onPress(); + }; + + return ( + + + {labelSuffix ? `${t(label)} ${labelSuffix}` : t(label)} + + {children} + + ); +}; + +export default Button; + +const getStyles = (theme: ThemeSchemeType) => { + return StyleSheet.create({ + buttonWrapper: { + backgroundColor: theme.PRIMARY_COLOR, + borderRadius: responsiveScale(8), + height: responsiveScale(50), + marginHorizontal: responsiveScale(16), + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + label: { + color: "white", + fontSize: resizeFonts(16), + fontWeight: "bold", + }, + }); +}; diff --git a/src/components/Input.tsx b/src/components/Input.tsx index 626b5a8..b5b8b5a 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useContext } from "react"; import { View, @@ -13,10 +13,11 @@ import { import { useTranslation } from "react-i18next"; -import { ThemeSchemeType } from "../util/types"; +import { ResponseScreenStatuses, ThemeSchemeType } from "../util/types"; import { resizeFonts, responsiveScale } from "../theme/scalling"; import { useCurrentTheme } from "../theme/useCurrentTheme"; +import { StateContext } from "../context/state"; interface InputProps extends TextInputProps { value: string; @@ -42,6 +43,8 @@ const Input: React.FC = ({ keyboardType, ...rest }: InputProps) => { + const { loading, paymentState } = useContext(StateContext); + const { t } = useTranslation(); const theme = useCurrentTheme(); const styles = getStyles(theme); @@ -57,11 +60,14 @@ const Input: React.FC = ({ placeholderTextColor={theme.INPUT_PLACEHOLDER} style={[ styles.input, - styles.withBorder, error && styles.withErrorBorder, + (loading?.payment || + paymentState === ResponseScreenStatuses.SUCCESS) && + styles.disabledStyles, inputStyle, ]} testID={testID} + editable={!loading?.payment} {...rest} /> {error && errorText && ( @@ -99,7 +105,9 @@ const getStyles = (theme: ThemeSchemeType) => { color: theme.ERROR, zIndex: 2, }, - withBorder: {}, + disabledStyles: { + color: theme.INPUT_PLACEHOLDER, + }, }); }; diff --git a/src/components/PaymentModal.tsx b/src/components/PaymentModal.tsx index 747cda3..d88243c 100644 --- a/src/components/PaymentModal.tsx +++ b/src/components/PaymentModal.tsx @@ -1,14 +1,8 @@ import { Dispatch, SetStateAction } from "react"; -import { - TouchableOpacity, - Modal, - View, - Image, - StyleSheet, -} from "react-native"; +import { TouchableOpacity, Modal, View, Image, StyleSheet } from "react-native"; -import { ThemeSchemeType } from "../util/types"; +import { PaymentMode, sessionDataType, ThemeSchemeType } from "../util/types"; import closeIcon from "../assets/images/close.png"; @@ -34,6 +28,7 @@ const PaymentModal: React.FC = ({ const { paymentState, paymentType, + sessionData, closeSheet, getCtaText, ctaOnPress, @@ -43,6 +38,9 @@ const PaymentModal: React.FC = ({ const theme = useCurrentTheme(); const styles = getStyles(theme); + const SessionData = sessionData as sessionDataType; + const isCustomerMode = SessionData?.mode === PaymentMode.Customer; + const handleClose = () => { closeSheet(shouldShowAlert(), () => setModalVisible(false)); }; @@ -59,13 +57,13 @@ const PaymentModal: React.FC = ({ - {!paymentState ? "PAYMENT_OPTIONS" : ""} + {!paymentState || isCustomerMode ? "PAYMENT_OPTIONS" : ""} - {paymentState ? ( + {paymentState && !isCustomerMode ? ( ctaOnPress(() => setModalVisible(false))} diff --git a/src/components/ResponseScreen.tsx b/src/components/ResponseScreen.tsx index a371b42..d43d380 100644 --- a/src/components/ResponseScreen.tsx +++ b/src/components/ResponseScreen.tsx @@ -12,7 +12,7 @@ import { resizeFonts, responsiveScale } from "../theme/scalling"; import { useCurrentTheme } from "../theme/useCurrentTheme"; import KomojuText from "./KomojuText"; -import SubmitButton from "./SubmitButton"; +import Button from "./Button"; import successIcon from "../assets/images/success.png"; import errorIcon from "../assets/images/error.png"; @@ -104,7 +104,7 @@ const ResponseScreen = ({ {renderIcon} {renderMessageContent} - + ); }; -export default SubmitButton; - -const getStyles = (theme: ThemeSchemeType) => { +const getStyles = () => { return StyleSheet.create({ - buttonWrapper: { - backgroundColor: theme.PRIMARY_COLOR, - borderRadius: responsiveScale(8), - height: responsiveScale(50), - marginHorizontal: responsiveScale(16), - flex: 1, - justifyContent: "center", - alignItems: "center", + indicatorContainer: { + position: "absolute", + }, + iconLock: { + position: "absolute", + right: responsiveScale(20), + width: responsiveScale(15), + height: responsiveScale(15), + resizeMode: "contain", }, - label: { - color: "white", - fontSize: resizeFonts(16), - fontWeight: "bold", + iconAnimation: { + width: responsiveScale(30), + height: responsiveScale(30), + resizeMode: "contain", }, }); }; + +export default SubmitButton; diff --git a/src/components/sections/CardSection.tsx b/src/components/sections/CardSection.tsx index 044644f..f748535 100644 --- a/src/components/sections/CardSection.tsx +++ b/src/components/sections/CardSection.tsx @@ -60,7 +60,7 @@ const CardSection = (): JSX.Element => { if (isValid) { const cardDataObj: CardDetailsType = { - cardholderName: cardData?.cardNumber, + cardholderName: cardData?.cardholderName, cardCVV: cardData?.cardCVV, cardNumber: cardData?.cardNumber, cardExpiredDate: cardData?.cardExpiredDate, diff --git a/src/context/MainStateProvider.tsx b/src/context/MainStateProvider.tsx index b9c97b2..9ea8a47 100644 --- a/src/context/MainStateProvider.tsx +++ b/src/context/MainStateProvider.tsx @@ -56,10 +56,14 @@ export const MainStateProvider = (props: KomojuProviderIprops) => { useMainStateUtils(); // Handle deep-links of the module - useDeepLinkHandler(setIsDeepLinkOpened); + useDeepLinkHandler(setIsDeepLinkOpened, closePaymentSheet); // Handle events when module goes foreground - useBackgroundHandler(isDeepLinkOpened, setIsDeepLinkOpened); + useBackgroundHandler( + isDeepLinkOpened, + setIsDeepLinkOpened, + closePaymentSheet + ); // Handle validations of the session const { validateSession } = useValidationHandler({ @@ -118,6 +122,7 @@ export const MainStateProvider = (props: KomojuProviderIprops) => { createPayment, showPaymentSheetUI, initializeKomoju, + closePaymentSheet, }} > {renderChildren} diff --git a/src/context/state.ts b/src/context/state.ts index e899770..bf1e876 100644 --- a/src/context/state.ts +++ b/src/context/state.ts @@ -140,6 +140,10 @@ const defaultValue = { // TODO: Fix this type error // eslint-disable-next-line @typescript-eslint/no-unused-vars initializeKomoju: (_data: InitPrams) => {}, + /** + * Function to close the payment sheet manually. + */ + closePaymentSheet: noop, }; /** * State context for the Komoju payment system. diff --git a/src/hooks/useBackgroundHandler.tsx b/src/hooks/useBackgroundHandler.tsx index 72a7579..f377620 100644 --- a/src/hooks/useBackgroundHandler.tsx +++ b/src/hooks/useBackgroundHandler.tsx @@ -13,9 +13,12 @@ import { getTokenResult } from "../services/secureTokenService"; import payForSession from "../services/payForSessionService"; import useMainStateUtils from "./useMainStateUtils"; +let timeoutId: NodeJS.Timeout; + const useBackgroundHandler = ( isDeepLinkOpened: boolean, - setIsDeepLinkOpened: Dispatch> + setIsDeepLinkOpened: Dispatch>, + closePaymentSheet: () => void ) => { const { paymentType, tokenId, providerPropsData, sessionData } = useContext(StateContext); @@ -23,7 +26,7 @@ const useBackgroundHandler = ( const SessionData = sessionData as CreatePaymentFuncType; const { - startLoading, + startPaymentLoading, stopLoading, onPaymentAwaiting, onPaymentCancelled, @@ -44,6 +47,14 @@ const useBackgroundHandler = ( }; }, [providerPropsData, paymentType, tokenId, SessionData, isDeepLinkOpened]); + useEffect(() => { + () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + }, []); + const handleSessionPaymentResponse = async () => { // if this is a session flow, check until session response changes from 'pending' to 'completed' or 'error' const sessionShowPayload = { @@ -61,6 +72,9 @@ const useBackgroundHandler = ( sessionResponse.mode === PaymentMode.Customer ) { onPaymentSuccess(); + if (sessionResponse.mode === PaymentMode.Customer) { + timeoutId = setTimeout(() => closePaymentSheet(), 2000); + } } else { onPaymentAwaiting(); } // calling user passed onComplete method with session response data @@ -110,7 +124,7 @@ const useBackgroundHandler = ( const handleBackgroundStateChange = async (status: AppStateStatus) => { if (status === "active" && !isDeepLinkOpened) { - startLoading(); + startPaymentLoading(); if (paymentType === PaymentType.CREDIT) { await handleSecureTokenPaymentResponse(); diff --git a/src/hooks/useDeepLinkHandler.tsx b/src/hooks/useDeepLinkHandler.tsx index 317d62e..5cc9407 100644 --- a/src/hooks/useDeepLinkHandler.tsx +++ b/src/hooks/useDeepLinkHandler.tsx @@ -14,15 +14,18 @@ import { extractParameterFromUrl } from "../util/helpers"; import payForSession from "../services/payForSessionService"; import useMainStateUtils from "./useMainStateUtils"; +let timeoutId: NodeJS.Timeout; + const useDeepLinkHandler = ( - setIsDeepLinkOpened: Dispatch> + setIsDeepLinkOpened: Dispatch>, + closePaymentSheet: () => void ) => { const { paymentType, providerPropsData, sessionData } = useContext(StateContext); const SessionData = sessionData as CreatePaymentFuncType; const { - startLoading, + startPaymentLoading, stopLoading, onPaymentAwaiting, onPaymentCancelled, @@ -42,8 +45,16 @@ const useDeepLinkHandler = ( }; }, [paymentType, providerPropsData, sessionData]); + useEffect(() => { + () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + }, []); + const handleSessionPaymentResponse = async () => { - startLoading(); + startPaymentLoading(); // if this is a session flow, check until session response changes from 'pending' to 'completed' or 'error' const sessionShowPayload = { @@ -71,6 +82,9 @@ const useDeepLinkHandler = ( sessionResponse.mode === PaymentMode.Customer ) { onPaymentSuccess(); + if (sessionResponse.mode === PaymentMode.Customer) { + timeoutId = setTimeout(() => closePaymentSheet(), 2000); + } } else { onPaymentAwaiting(); } @@ -87,7 +101,7 @@ const useDeepLinkHandler = ( }; const handleSecureTokenPaymentResponse = async (token: string) => { - startLoading(); + startPaymentLoading(); const tokenResponse = await getTokenResult({ publishableKey: providerPropsData.publishableKey, diff --git a/src/hooks/useMainStateUtils.tsx b/src/hooks/useMainStateUtils.tsx index 34d54d7..1a49ff9 100644 --- a/src/hooks/useMainStateUtils.tsx +++ b/src/hooks/useMainStateUtils.tsx @@ -1,27 +1,53 @@ -import { useContext } from "react"; +import { useContext, useEffect } from "react"; import { Actions, DispatchContext, StateContext } from "../context/state"; import { - initialState, ResponseScreenStatuses, CreatePaymentFuncType, + sessionDataType, + PaymentMode, } from "../util/types"; import sessionShow from "../services/sessionShow"; +import { getInitialStateWithoutProviderPropsData } from "../util/helpers"; + +let timeoutId: NodeJS.Timeout; const useMainStateUtils = () => { const dispatch = useContext(DispatchContext); const { providerPropsData, sessionData } = useContext(StateContext); - const SessionData = sessionData as CreatePaymentFuncType; + const SessionData = sessionData as CreatePaymentFuncType & sessionDataType; - const resetGlobalStates = () => - dispatch({ - type: Actions.RESET_STATES, - payload: initialState, - }); + const isCustomerMode = SessionData?.mode === PaymentMode.Customer; + + useEffect(() => { + () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + }, []); + + const resetGlobalStates = (withTimeout = false) => { + if (withTimeout) { + timeoutId = setTimeout( + () => + dispatch({ + type: Actions.RESET_STATES, + payload: getInitialStateWithoutProviderPropsData(), + }), + 3000 + ); + } else { + dispatch({ + type: Actions.RESET_STATES, + payload: getInitialStateWithoutProviderPropsData(), + }); + } + }; // when payment is success global state is rest and invoking the success screen const onPaymentSuccess = () => { - resetGlobalStates(); + resetGlobalStates(isCustomerMode); dispatch({ type: Actions.SET_PAYMENT_STATE, payload: ResponseScreenStatuses.SUCCESS, @@ -37,7 +63,7 @@ const useMainStateUtils = () => { // when payment is cancelled by the user const onPaymentCancelled = () => { - resetGlobalStates(); + resetGlobalStates(isCustomerMode); dispatch({ type: Actions.SET_PAYMENT_STATE, payload: ResponseScreenStatuses.CANCELLED, @@ -80,14 +106,29 @@ const useMainStateUtils = () => { const startLoading = () => dispatch({ type: Actions.SET_LOADING, - payload: true, + payload: { + app: true, + payment: false, + }, + }); + + const startPaymentLoading = () => + dispatch({ + type: Actions.SET_LOADING, + payload: { + app: false, + payment: true, + }, }); // Hiding overlay loading indicator const stopLoading = () => dispatch({ type: Actions.SET_LOADING, - payload: false, + payload: { + app: false, + payment: false, + }, }); return { @@ -98,6 +139,7 @@ const useMainStateUtils = () => { onSessionExpired, onUserCancel, startLoading, + startPaymentLoading, stopLoading, resetGlobalStates, }; diff --git a/src/hooks/usePaymentUiUtils.tsx b/src/hooks/usePaymentUiUtils.tsx index 2db1f7c..4999693 100644 --- a/src/hooks/usePaymentUiUtils.tsx +++ b/src/hooks/usePaymentUiUtils.tsx @@ -2,86 +2,90 @@ import { useCallback, useContext } from "react"; import { Alert, Keyboard } from "react-native"; import { useTranslation } from "react-i18next"; import { Actions, DispatchContext, StateContext } from "../context/state"; -import { - paymentFailedCtaText, - paymentSuccessCtaText, -} from "../util/constants"; +import { paymentFailedCtaText, paymentSuccessCtaText } from "../util/constants"; import { ResponseScreenStatuses } from "../util/types"; export const usePaymentUiUtils = (onDismiss?: () => void) => { - const { t } = useTranslation(); - const { paymentState, paymentType } = useContext(StateContext); - const dispatch = useContext(DispatchContext); + const { t } = useTranslation(); + const { paymentState, paymentType, sessionData } = useContext(StateContext); + const dispatch = useContext(DispatchContext); - const closeSheet = useCallback((showAlert = true, onClose: () => void) => { - Keyboard.dismiss(); + const closeSheet = useCallback( + (showAlert = true, onClose: () => void) => { + Keyboard.dismiss(); - if (showAlert) { - Alert.alert(`${t("CANCEL_PAYMENT")}?`, "", [ - { - text: t("NO"), - style: "cancel", - }, - { - text: t("YES"), - onPress: () => { - onDismiss && onDismiss(); - onClose(); - }, - }, - ]); - } else { - onDismiss && onDismiss(); - onClose(); - } - }, [onDismiss, t]); + if (showAlert) { + Alert.alert(`${t("CANCEL_PAYMENT")}?`, "", [ + { + text: t("NO"), + style: "cancel", + }, + { + text: t("YES"), + onPress: () => { + onDismiss && onDismiss(); + onClose(); + }, + }, + ]); + } else { + onDismiss && onDismiss(); + onClose(); + } + }, + [onDismiss, t] + ); - const getCtaText = useCallback(() => { - switch (paymentState) { - case ResponseScreenStatuses.SUCCESS: - case ResponseScreenStatuses.COMPLETE: - case ResponseScreenStatuses.CANCELLED: - case ResponseScreenStatuses.EXPIRED: - return paymentSuccessCtaText; - case ResponseScreenStatuses.FAILED: - return paymentFailedCtaText; - default: - return ""; - } - }, [paymentState]); + const getCtaText = useCallback(() => { + switch (paymentState) { + case ResponseScreenStatuses.SUCCESS: + case ResponseScreenStatuses.COMPLETE: + case ResponseScreenStatuses.CANCELLED: + case ResponseScreenStatuses.EXPIRED: + return paymentSuccessCtaText; + case ResponseScreenStatuses.FAILED: + return paymentFailedCtaText; + default: + return ""; + } + }, [paymentState]); - const ctaOnPress = useCallback((onClose: () => void) => { - switch (paymentState) { - case ResponseScreenStatuses.SUCCESS: - case ResponseScreenStatuses.COMPLETE: - case ResponseScreenStatuses.CANCELLED: - case ResponseScreenStatuses.EXPIRED: - return closeSheet(false, onClose); - case ResponseScreenStatuses.FAILED: - return dispatch({ - type: Actions.SET_PAYMENT_STATE, - payload: "", - }); - default: - return ""; - } - }, [paymentState, dispatch, closeSheet]); + const ctaOnPress = useCallback( + (onClose: () => void) => { + switch (paymentState) { + case ResponseScreenStatuses.SUCCESS: + case ResponseScreenStatuses.COMPLETE: + case ResponseScreenStatuses.CANCELLED: + case ResponseScreenStatuses.EXPIRED: + return closeSheet(false, onClose); + case ResponseScreenStatuses.FAILED: + return dispatch({ + type: Actions.SET_PAYMENT_STATE, + payload: "", + }); + default: + return ""; + } + }, + [paymentState, dispatch, closeSheet] + ); - const shouldShowAlert = useCallback(() => { - return !( - paymentState === ResponseScreenStatuses.SUCCESS || - paymentState === ResponseScreenStatuses.CANCELLED || - paymentState === ResponseScreenStatuses.COMPLETE || - paymentState === ResponseScreenStatuses.EXPIRED - ); - }, [paymentState]); + const shouldShowAlert = useCallback(() => { + return !( + paymentState === ResponseScreenStatuses.SUCCESS || + paymentState === ResponseScreenStatuses.CANCELLED || + paymentState === ResponseScreenStatuses.COMPLETE || + paymentState === ResponseScreenStatuses.EXPIRED + ); + }, [paymentState]); - return { - paymentState, - paymentType, - closeSheet, - getCtaText, - ctaOnPress, - shouldShowAlert, - }; -}; \ No newline at end of file + return { + paymentState, + paymentType, + sessionData, + closeSheet, + getCtaText, + ctaOnPress, + shouldShowAlert, + }; +}; diff --git a/src/hooks/useSessionPayHandler.tsx b/src/hooks/useSessionPayHandler.tsx index e8ce87e..2a4dd45 100644 --- a/src/hooks/useSessionPayHandler.tsx +++ b/src/hooks/useSessionPayHandler.tsx @@ -1,4 +1,4 @@ -import { useContext } from "react"; +import { useContext, useEffect } from "react"; import { CreatePaymentFuncType, @@ -7,17 +7,29 @@ import { sessionPayProps, TokenResponseStatuses, } from "../util/types"; -import { StateContext } from "../context/state"; +import { StateContext, KomojuContext } from "../context/state"; import { openURL } from "../util/helpers"; import payForSession from "../services/payForSessionService"; import useMainStateUtils from "./useMainStateUtils"; +let timeoutId: NodeJS.Timeout; + const useSessionPayHandler = () => { const { sessionData, providerPropsData } = useContext(StateContext); + const { closePaymentSheet } = useContext(KomojuContext); + const SessionData = sessionData as CreatePaymentFuncType; + useEffect(() => { + () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + }, []); + const { - startLoading, + startPaymentLoading, stopLoading, onPaymentAwaiting, onPaymentFailed, @@ -30,7 +42,7 @@ const useSessionPayHandler = () => { paymentDetails, }: sessionPayProps) => { // Start of the payment handling method - startLoading(); + startPaymentLoading(); // initiate payment for the session ID with payment details const response = await payForSession({ @@ -50,6 +62,9 @@ const useSessionPayHandler = () => { response?.customer?.resource === PaymentMode.Customer ) { onPaymentSuccess(); + if (response?.customer?.resource === PaymentMode.Customer) { + timeoutId = setTimeout(() => closePaymentSheet(), 2000); + } } else if (response?.payment?.payment_details?.instructions_url) { openURL(response?.payment?.payment_details?.instructions_url); onPaymentAwaiting(); diff --git a/src/hooks/useThreeDSecureHandler.tsx b/src/hooks/useThreeDSecureHandler.tsx index 9515119..de8e8ce 100644 --- a/src/hooks/useThreeDSecureHandler.tsx +++ b/src/hooks/useThreeDSecureHandler.tsx @@ -15,11 +15,12 @@ const useThreeDSecureHandler = () => { const dispatch = useContext(DispatchContext); const { sessionData, providerPropsData } = useContext(StateContext); - const { startLoading, stopLoading, onPaymentFailed } = useMainStateUtils(); + const { startPaymentLoading, stopLoading, onPaymentFailed } = + useMainStateUtils(); const SessionData = sessionData as sessionDataType; const threeDSecurePayment = async (paymentDetails: CardDetailsType) => { - startLoading(); + startPaymentLoading(); const { month, year } = getMonthYearFromExpiry( paymentDetails?.cardExpiredDate || "" diff --git a/src/theme/defaultColorTheme.ts b/src/theme/defaultColorTheme.ts index adfc3de..59d3dc8 100644 --- a/src/theme/defaultColorTheme.ts +++ b/src/theme/defaultColorTheme.ts @@ -1,6 +1,7 @@ const darkTheme = { PRIMARY_COLOR: "#0071D7", BACKGROUND_COLOR: "#1E1E1E", + SUCCESS_COLOR: "#3CC239", ERROR: "#fc4747", TEXT_COLOR: "#fff", INPUT_BACKGROUND: "#2C2C2C", @@ -18,6 +19,7 @@ const darkTheme = { const lightTheme = { PRIMARY_COLOR: "#0B82EE", BACKGROUND_COLOR: "#FFFFFF", + SUCCESS_COLOR: "#3CC239", ERROR: "#fc5d5d", TEXT_COLOR: "#172E44", INPUT_BACKGROUND: "#FFFFFF", diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b8235bb..5d6c5c5 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -6,6 +6,7 @@ import { CardTypes, CurrencySign, CurrencyTypes, + initialState, KonbiniType, PaymentType, sessionShowPaymentMethodType, @@ -222,3 +223,8 @@ export function fromUserFriendlyTheme( return acc; }, {} as Partial); } + +export const getInitialStateWithoutProviderPropsData = () => { + const { providerPropsData, ...stateWithoutProviderProps } = initialState; + return stateWithoutProviderProps; +}; diff --git a/src/util/types.ts b/src/util/types.ts index c9ba9de..449b5a1 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -240,6 +240,11 @@ export type brandType = { icon: string; }; +export type LoadingTypes = { + app?: boolean; + payment?: boolean; +}; + export type sessionDataType = { /** * Amount for the payment @@ -267,7 +272,7 @@ export type State = KonbiniDetailsType & { /** * Global loading state. to display loading animation over sdk and disable buttons. */ - loading: boolean; + loading: LoadingTypes; /** * All credit card related data */ @@ -315,7 +320,10 @@ export type sessionPayProps = { // Define the initial state export const initialState: State = { paymentType: PaymentType.CREDIT, - loading: false, + loading: { + app: false, + payment: false, + }, /** credit card payment related states start */ cardData: { @@ -363,6 +371,7 @@ export type ActionType = { type: string; payload: State[keyof State] }; export interface ThemeSchemeType { PRIMARY_COLOR: string; BACKGROUND_COLOR: string; + SUCCESS_COLOR: string; ERROR: string; TEXT_COLOR: string; INPUT_BACKGROUND: string; From d2e71f26121b61c64b865afd794ef66c50b2322b Mon Sep 17 00:00:00 2001 From: Tharindu Kumarasiri Date: Wed, 25 Sep 2024 12:33:44 +0530 Subject: [PATCH 2/2] Center success check mark --- src/components/SubmitButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SubmitButton.tsx b/src/components/SubmitButton.tsx index 6e4d030..84819b2 100644 --- a/src/components/SubmitButton.tsx +++ b/src/components/SubmitButton.tsx @@ -39,7 +39,7 @@ const SubmitButton = ({ label, labelSuffix, onPress, testID }: Props) => { const moveToCenter = () => { Animated.timing(moveAnim, { - toValue: (SCREEN_WIDTH - responsiveScale(40)) * 0.5, + toValue: (SCREEN_WIDTH - responsiveScale(60)) * 0.5, duration: 400, useNativeDriver: false, }).start(() => setAnimationComplete(true));