Skip to content

Commit

Permalink
Merge pull request #82 from degica/task/MOB-63-loading-integration
Browse files Browse the repository at this point in the history
loading animation integration
  • Loading branch information
tharindu-rhino authored Sep 25, 2024
2 parents 5b0b966 + d2e71f2 commit 1c11faa
Show file tree
Hide file tree
Showing 23 changed files with 401 additions and 157 deletions.
Binary file added src/assets/images/loader_animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/lock_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/success_animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/assets/languages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"SESSION_EXPIRED_MSG": "このセッションは既に期限切れです。再度お試しください。",
"PAYMENT_WAITING": "支払い待ち",
"PAYMENT_WAITING_MSG": "支払いは完了していません。支払い方法の詳細をメールアドレス宛にお送りしていますのでご確認ください。",
"LOADING_TEXT": "処理...",

"PAYMENT_VIA_ALI_PAY": "Alipayによる支払い",
"ALI_PAY_REDIRECT_MESSAGE": "支払いを完了するには、Alipay にリダイレクトされます。",
Expand Down
73 changes: 73 additions & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<TouchableOpacity
testID={testID}
style={[styles.buttonWrapper, style]}
onPress={onSubmit}
disabled={disabled}
>
<Text style={styles.label}>
{labelSuffix ? `${t(label)} ${labelSuffix}` : t(label)}
</Text>
{children}
</TouchableOpacity>
);
};

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",
},
});
};
16 changes: 12 additions & 4 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useContext } from "react";

import {
View,
Expand All @@ -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;
Expand All @@ -42,6 +43,8 @@ const Input: React.FC<InputProps> = ({
keyboardType,
...rest
}: InputProps) => {
const { loading, paymentState } = useContext(StateContext);

const { t } = useTranslation();
const theme = useCurrentTheme();
const styles = getStyles(theme);
Expand All @@ -57,11 +60,14 @@ const Input: React.FC<InputProps> = ({
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 && (
Expand Down Expand Up @@ -99,7 +105,9 @@ const getStyles = (theme: ThemeSchemeType) => {
color: theme.ERROR,
zIndex: 2,
},
withBorder: {},
disabledStyles: {
color: theme.INPUT_PLACEHOLDER,
},
});
};

Expand Down
18 changes: 8 additions & 10 deletions src/components/PaymentModal.tsx
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -34,6 +28,7 @@ const PaymentModal: React.FC<PaymentModalProps> = ({
const {
paymentState,
paymentType,
sessionData,
closeSheet,
getCtaText,
ctaOnPress,
Expand All @@ -43,6 +38,9 @@ const PaymentModal: React.FC<PaymentModalProps> = ({
const theme = useCurrentTheme();
const styles = getStyles(theme);

const SessionData = sessionData as sessionDataType;
const isCustomerMode = SessionData?.mode === PaymentMode.Customer;

const handleClose = () => {
closeSheet(shouldShowAlert(), () => setModalVisible(false));
};
Expand All @@ -59,13 +57,13 @@ const PaymentModal: React.FC<PaymentModalProps> = ({
<View style={styles.bottomSheetContainer}>
<View style={styles.line}>
<KomojuText style={styles.headerLabel}>
{!paymentState ? "PAYMENT_OPTIONS" : ""}
{!paymentState || isCustomerMode ? "PAYMENT_OPTIONS" : ""}
</KomojuText>
<TouchableOpacity style={styles.crossBtn} onPress={handleClose}>
<Image source={closeIcon} />
</TouchableOpacity>
</View>
{paymentState ? (
{paymentState && !isCustomerMode ? (
<ResponseScreen
status={paymentState}
onPress={() => ctaOnPress(() => setModalVisible(false))}
Expand Down
4 changes: 2 additions & 2 deletions src/components/ResponseScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -104,7 +104,7 @@ const ResponseScreen = ({
<View style={styles.imageContainer}>{renderIcon}</View>
{renderMessageContent}
<View style={styles.bottomButton}>
<SubmitButton onPress={memoizedOnPress} label={onPressLabel} />
<Button onPress={memoizedOnPress} label={onPressLabel} />
</View>
</View>
);
Expand Down
16 changes: 11 additions & 5 deletions src/components/SheetContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ const SheetContent = () => {
dispatch({ type: Actions.SET_PAYMENT_OPTION, payload: type });
};

const renderLoading = loading ? <Loader /> : null;

const getBaseScreenByPaymentType = (paymentType: PaymentType) => {
switch (paymentType) {
case PaymentType.CREDIT:
Expand Down Expand Up @@ -76,9 +74,17 @@ const SheetContent = () => {
const renderItem = () => {
return (
<View style={styles.item}>
<PillContainer onSelect={handlePillSelect} selectedItem={paymentType} />
{getBaseScreenByPaymentType(paymentType)}
{renderLoading}
{loading?.app ? (
<Loader />
) : (
<>
<PillContainer
onSelect={handlePillSelect}
selectedItem={paymentType}
/>
{getBaseScreenByPaymentType(paymentType)}
</>
)}
</View>
);
};
Expand Down
105 changes: 73 additions & 32 deletions src/components/SubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { StyleSheet, Text, TouchableOpacity, Keyboard } from "react-native";
import { useContext, useEffect, useRef, useState } from "react";
import { Animated, Dimensions, Image, StyleSheet } from "react-native";

import { useTranslation } from "react-i18next";
import { ResponseScreenStatuses } from "../util/types";
import { StateContext } from "../context/state";
import { useCurrentTheme } from "../theme/useCurrentTheme";
import Button from "./Button";
import { responsiveScale } from "../theme/scalling";

import { ThemeSchemeType } from "../util/types";
import Lock from "../assets/images/lock_image.png";
import SuccessAnimation from "../assets/images/success_animation.gif";
import LoadingAnimation from "../assets/images/loader_animation.gif";

import { resizeFonts, responsiveScale } from "../theme/scalling";
import { useCurrentTheme } from "../theme/useCurrentTheme";
const { width: SCREEN_WIDTH } = Dimensions.get("window");

type Props = {
onPress: () => void;
Expand All @@ -15,45 +21,80 @@ type Props = {
};

const SubmitButton = ({ label, labelSuffix, onPress, testID }: Props) => {
const { t } = useTranslation();
const theme = useCurrentTheme();
const styles = getStyles(theme);
const { loading, paymentState } = useContext(StateContext);
const [animationComplete, setAnimationComplete] = useState(false);

const moveAnim = useRef(new Animated.Value(responsiveScale(20))).current;

const styles = getStyles();

const isPaymentSuccess = paymentState === ResponseScreenStatuses.SUCCESS;

useEffect(() => {
if (paymentState === ResponseScreenStatuses.SUCCESS) {
moveToCenter();
}
}, [paymentState]);

const onSubmit = () => {
Keyboard.dismiss();
onPress();
const moveToCenter = () => {
Animated.timing(moveAnim, {
toValue: (SCREEN_WIDTH - responsiveScale(60)) * 0.5,
duration: 400,
useNativeDriver: false,
}).start(() => setAnimationComplete(true));
};

return (
<TouchableOpacity
<Button
testID={testID}
style={styles.buttonWrapper}
onPress={onSubmit}
onPress={onPress}
style={isPaymentSuccess ? { backgroundColor: theme.SUCCESS_COLOR } : {}}
disabled={loading?.payment}
label={
!isPaymentSuccess ? (loading?.payment ? "LOADING_TEXT" : label) : ""
}
labelSuffix={!loading?.payment ? labelSuffix : ""}
>
<Text style={styles.label}>
{labelSuffix ? `${t(label)} ${labelSuffix}` : t(label)}
</Text>
</TouchableOpacity>
{loading?.payment || isPaymentSuccess ? (
<Animated.View
style={[
styles.indicatorContainer,
{
right: moveAnim,
},
]}
>
<Image
source={animationComplete ? SuccessAnimation : LoadingAnimation}
style={styles.iconAnimation}
/>
</Animated.View>
) : (
<Image source={Lock} style={styles.iconLock} />
)}
</Button>
);
};

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;
2 changes: 1 addition & 1 deletion src/components/sections/CardSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 1c11faa

Please sign in to comment.