Commit b7457249 by G

refactor: navigations flow. planning for screens to take the full object instead…

refactor: navigations flow. planning for screens to take the full object instead of selective properties. This is to avoid basic crashes that may happen when one piece of data is missing through the navigation. and some biome formatting. refactor: navigations flow. planning for screens to take the full object instead of selective properties. This is to avoid basic crashes that may happen when one piece of data is missing through the navigation. Some files where impacted so changes where applied there too.
parent 18e1098c
import { useModalsManagerContext } from "@/contexts/ModalsManagerContext";
import type { IpaymentStackNavigator } from "@/navigations/Types";
import {
type IorangePaymentStarter,
getTransactionStatus,
getTransactionsData,
} from "@/utils/requests/orangePayment";
import ErrorModal from "@components/modals/ErrorModal"; import ErrorModal from "@components/modals/ErrorModal";
import LoadingModal from "@components/modals/LoadingModal"; import LoadingModal from "@components/modals/LoadingModal";
import { LOG } from "@logger"; import { LOG } from "@logger";
import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import * as WebBrowser from "expo-web-browser"; import * as WebBrowser from "expo-web-browser";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { AppState, Platform } from "react-native"; import { AppState, Platform } from "react-native";
import { useModalsManagerContext } from "@/contexts/ModalsManagerContext";
import type { IpaymentStackNavigator } from "@/navigations/types";
import {
getTransactionStatus,
getTransactionsData,
type IorangePaymentStarter,
} from "@/utils/requests/orangePayment";
const log = LOG.extend("useOrangeMoney"); const log = LOG.extend("useOrangeMoney");
...@@ -40,7 +38,7 @@ const useOrangeMoney = ( ...@@ -40,7 +38,7 @@ const useOrangeMoney = (
const [isBrowserOpen, setIsBrowserOpen] = useState(false); const [isBrowserOpen, setIsBrowserOpen] = useState(false);
const { showModal, closeModal } = useModalsManagerContext(); const { showModal, closeModal } = useModalsManagerContext();
const appState = useRef(AppState.currentState); const appState = useRef(AppState.currentState);
const [appStateVisible, setAppStateVisible] = useState(appState.current); const [_appStateVisible, _setAppStateVisiblee] = useState(appState.current);
const handlePaymentUsingBrowser = async (url: string) => { const handlePaymentUsingBrowser = async (url: string) => {
setIsBrowserOpen(true); setIsBrowserOpen(true);
...@@ -56,7 +54,7 @@ const useOrangeMoney = ( ...@@ -56,7 +54,7 @@ const useOrangeMoney = (
...paymentObjectDefault, ...paymentObjectDefault,
montant: amount, montant: amount,
}), }),
onSuccess: (data) => { onSuccess: (_data) => {
// return data.payment_url // return data.payment_url
log.debug("orangeTransactionInitializerMutation request success, opening browser..."); log.debug("orangeTransactionInitializerMutation request success, opening browser...");
queryClient.invalidateQueries({ queryKey: ["transactionsHistory"] }); queryClient.invalidateQueries({ queryKey: ["transactionsHistory"] });
...@@ -69,8 +67,8 @@ const useOrangeMoney = ( ...@@ -69,8 +67,8 @@ const useOrangeMoney = (
}, },
}); });
const maxRetry = 3; const _maxRetry = 3;
const retryDelay = 5000; const _retryDelay = 5000;
const transactionsStatusMutation = useMutation({ const transactionsStatusMutation = useMutation({
mutationFn: (orderId: string) => getTransactionStatus(orderId), mutationFn: (orderId: string) => getTransactionStatus(orderId),
......
import { useModalsManagerContext } from "@/contexts/ModalsManagerContext";
import type { IpaymentStackNavigator } from "@/navigations/Types";
import {
type IwavePaymentStarter,
getTransactionStatus,
initTransaction,
} from "@/utils/requests/wavePayment";
import ErrorModal from "@components/modals/ErrorModal"; import ErrorModal from "@components/modals/ErrorModal";
import LoadingModal from "@components/modals/LoadingModal"; import LoadingModal from "@components/modals/LoadingModal";
import { LOG } from "@logger"; import { LOG } from "@logger";
...@@ -12,6 +5,13 @@ import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; ...@@ -12,6 +5,13 @@ import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQueryClient } from "@tanstack/react-query";
import * as WebBrowser from "expo-web-browser"; import * as WebBrowser from "expo-web-browser";
import { useState } from "react"; import { useState } from "react";
import { useModalsManagerContext } from "@/contexts/ModalsManagerContext";
import type { IpaymentStackNavigator } from "@/navigations/types";
import {
getTransactionStatus,
type IwavePaymentStarter,
initTransaction,
} from "@/utils/requests/wavePayment";
const log = LOG.extend("useWave"); const log = LOG.extend("useWave");
...@@ -31,9 +31,9 @@ const useWave = ( ...@@ -31,9 +31,9 @@ const useWave = (
>, >,
) => { ) => {
const { showModal, closeModal } = useModalsManagerContext(); const { showModal, closeModal } = useModalsManagerContext();
const [isBrowserOpen, setIsBrowserOpen] = useState(false); const [_isBrowserOpen, setIsBrowserOpen] = useState(false);
const queryClient = useQueryClient(); const _queryClient = useQueryClient();
// Mutations // Mutations
...@@ -43,7 +43,7 @@ const useWave = ( ...@@ -43,7 +43,7 @@ const useWave = (
...paymentObjectDefault, ...paymentObjectDefault,
montant: amount, montant: amount,
}), }),
onSuccess: (data) => {}, onSuccess: (_data) => {},
onError: (err) => { onError: (err) => {
log.error("waveTransactionInitializerMutation |", err); log.error("waveTransactionInitializerMutation |", err);
}, },
...@@ -51,7 +51,7 @@ const useWave = ( ...@@ -51,7 +51,7 @@ const useWave = (
const waveTransactionStatusMutation = useMutation({ const waveTransactionStatusMutation = useMutation({
mutationFn: (orderId: string) => getTransactionStatus(orderId), mutationFn: (orderId: string) => getTransactionStatus(orderId),
onSuccess: (data) => { onSuccess: (_data) => {
log.debug("waveTransactionStatusMutation request success"); log.debug("waveTransactionStatusMutation request success");
}, },
onError: (err) => { onError: (err) => {
...@@ -71,7 +71,7 @@ const useWave = ( ...@@ -71,7 +71,7 @@ const useWave = (
setIsBrowserOpen(false); setIsBrowserOpen(false);
}; };
const openBrowserThenCheckStatus = async (paymentUrl: string, orderId: string) => { const _openBrowserThenCheckStatus = async (paymentUrl: string, orderId: string) => {
try { try {
await handlePaymentUsingBrowser(paymentUrl); await handlePaymentUsingBrowser(paymentUrl);
log.info("openBrowserThenCheckStatus | Verifying transaction status..."); log.info("openBrowserThenCheckStatus | Verifying transaction status...");
...@@ -128,7 +128,7 @@ const useWave = ( ...@@ -128,7 +128,7 @@ const useWave = (
log.info("handlePaymentVerification |", id); log.info("handlePaymentVerification |", id);
try { try {
showModal(<LoadingModal message="Vérification du statut de la transaction..." />); showModal(<LoadingModal message="Vérification du statut de la transaction..." />);
const response = await waveTransactionStatusMutation.mutateAsync(id); const _response = await waveTransactionStatusMutation.mutateAsync(id);
closeModal(); closeModal();
} catch (error) { } catch (error) {
log.error("handlePaymentVerification |", error); log.error("handlePaymentVerification |", error);
......
...@@ -8,7 +8,7 @@ import { memo } from "react"; ...@@ -8,7 +8,7 @@ import { memo } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import type { RootState } from "@/redux"; import type { RootState } from "@/redux";
import { AppBottomTabsNavigator } from "./AppBottomTabsNavigator"; import { AppBottomTabsNavigator } from "./AppBottomTabsNavigator";
import type { ImainStackNavigator } from "./Types"; import type { ImainStackNavigator } from "./types";
const Stack = createNativeStackNavigator<ImainStackNavigator>(); const Stack = createNativeStackNavigator<ImainStackNavigator>();
......
...@@ -2,7 +2,7 @@ import { createNativeStackNavigator } from "@react-navigation/native-stack"; ...@@ -2,7 +2,7 @@ import { createNativeStackNavigator } from "@react-navigation/native-stack";
import HomePageWithPaymentOptions from "@screens/HomePageWithPaymentOptions"; import HomePageWithPaymentOptions from "@screens/HomePageWithPaymentOptions";
import NumberAndOtpForPaymentScreen from "@screens/NumberAndOtpForPaymentScreen"; import NumberAndOtpForPaymentScreen from "@screens/NumberAndOtpForPaymentScreen";
import PaymentAmountInputScreen from "@screens/PaymentAmountInputScreen"; import PaymentAmountInputScreen from "@screens/PaymentAmountInputScreen";
import type { IpaymentStackNavigator } from "./Types"; import type { IpaymentStackNavigator } from "./types";
const Stack = createNativeStackNavigator<IpaymentStackNavigator>(); const Stack = createNativeStackNavigator<IpaymentStackNavigator>();
......
import type { PaymentCode } from "@/utils/requests/types";
import type { IwaveStarterRespone } from "@/utils/requests/wavePayment";
import type { NativeStackScreenProps } from "@react-navigation/native-stack"; import type { NativeStackScreenProps } from "@react-navigation/native-stack";
import type { PaymentType } from "@/features/pay/types";
import type { IwaveStarterRespone } from "@/utils/requests/wavePayment";
export type IpaymentStackNavigator = { export type IpaymentStackNavigator = {
homePageWithPaymentOptions: undefined; homePageWithPaymentOptions: undefined;
numberAndOtpForPaymentScreen: undefined; numberAndOtpForPaymentScreen: {
paymentType: PaymentType;
amount: number;
};
paymentAmountInputScreen: { paymentAmountInputScreen: {
paymentType: PaymentCode; paymentType: PaymentType;
}; };
}; };
......
import type { PaymentStackScreenComponentProps } from "@/navigations/Types"; import { asp as g } from "@asp/asp";
import getPaymentTypes from "@/utils/requests/getPaymentTypes"; import { Balance } from "@components/Balance";
import BalanceContainer from "@components/BalanceContainer"; import { BarnoinPayBackground } from "@components/BarnoinPayBackground";
import BarWithBeasyAndNotificationsIcon from "@components/BarWithBeasyAndNotificationsIcon"; import BeasyLogoIcon from "@components/BeasyLogoIcon";
import PaymentOption from "@components/PaymentOption";
import Box from "@components/bases/Box";
import WrapperWithDefaultBeasyBackgroundAndSafeAreaTopLeftRight from "@components/wrappers/WrapperWithDefaultBeasyBackgroundAndSafeAreaTopLeftRight";
import { LOG } from "@logger"; import { LOG } from "@logger";
import Card from "@re-card";
import Text from "@re-text";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react"; import { Text, View } from "react-native";
import { Dimensions } from "react-native"; import { getPaymentTypes } from "@/features/pay/api";
import PaymentType from "@/features/pay/components/PaymentType";
import type { PaymentStackScreenComponentProps } from "@/navigations/types";
const log = LOG.extend("HomePageWithPaymentOptions"); const log = LOG.extend("HomePageWithPaymentOptions");
const HomePageWithPaymentOptions: PaymentStackScreenComponentProps<"homePageWithPaymentOptions"> = const HomePageWithPaymentOptions: PaymentStackScreenComponentProps<
({ navigation }) => { "homePageWithPaymentOptions"
log.debug("HomePageWithPaymentOptions"); > = ({ navigation }) => {
const { data, isLoading, error } = useQuery({ log.debug("HomePageWithPaymentOptions");
queryKey: ["paymentTypes"], const paymentTypesQuery = useQuery({
queryFn: getPaymentTypes, queryKey: ["paymentTypes"],
enabled: true, queryFn: getPaymentTypes,
}); });
// getting valid payments supported const paymentTypes = paymentTypesQuery.isSuccess
const paymentTypesWithActiveStatus = useMemo(() => { ? Object.keys(paymentTypesQuery.data.data.results)
log.info("Filtering payment types"); .map((key) => paymentTypesQuery.data.data.results[key])
const paymentTypes = data?.results || []; .filter((item) => item.etat === true)
return paymentTypes.filter((paymentType) => paymentType.etat === true); : [];
}, [data]);
log.info( return (
"payment types to render", <BarnoinPayBackground style={[g.flex_col, g.relative]}>
paymentTypesWithActiveStatus.map((paymentType) => paymentType.code), <View style={[g.px_lg]}>
); <BeasyLogoIcon />
</View>
return (
<WrapperWithDefaultBeasyBackgroundAndSafeAreaTopLeftRight>
<Box style={{ height: "100%" }} flexDirection={"column"}>
<BarWithBeasyAndNotificationsIcon />
<Card
variant={"curvedTopContainer"}
height={Dimensions.get("window").height / 2 + 150}
style={{ marginTop: "auto" }}
padding={"l"}
>
<Box position={"relative"} top={-120}>
<Box alignSelf={"center"}>
<BalanceContainer balance={78000} label="Total des ventes" />
</Box>
<Box marginVertical={"l"}>
<Text fontSize={20} fontWeight={"bold"}>
Types de paiement
</Text>
</Box>
<Box
flex={1}
flexDirection={"row"}
justifyContent={"space-between"}
flexWrap={"wrap"}
rowGap={"m"}
>
{isLoading && (
<Box flex={1}>
<Text textAlign={"center"}>
Chargement des méthodes de paiement...
</Text>
</Box>
)}
{!isLoading &&
!error &&
paymentTypesWithActiveStatus.map((paymentType) => (
<PaymentOptionContainer key={paymentType.id}>
<PaymentOption
// key={paymentType.id}
onPress={() =>
navigation.navigate(
"paymentAmountInputScreen",
{
paymentType: paymentType.code,
},
)
}
paymentMethod={paymentType.code}
/>
</PaymentOptionContainer>
))}
</Box>
</Box>
</Card>
</Box>
</WrapperWithDefaultBeasyBackgroundAndSafeAreaTopLeftRight>
);
};
export default HomePageWithPaymentOptions; <View
style={[
g.absolute,
g.z_10,
g.align_center,
g.justify_center,
g.w_full,
{ top: 120 },
]}
>
<Balance />
</View>
const screenWidth = Dimensions.get("window").width; <View
const paymentOptionCardWidth = screenWidth / 2 - 30; style={[
const paymentOptionCardHeight = paymentOptionCardWidth * 0.65; g.px_lg,
const PaymentOptionContainer = ({ children }: { children: React.ReactNode }) => { g.pb_lg,
return ( g.gap_lg,
<Box {
width={paymentOptionCardWidth} backgroundColor: "white",
height={paymentOptionCardHeight} height: "80%",
borderRadius={30} marginTop: "auto",
overflow={"hidden"} borderTopRightRadius: 30,
> borderTopLeftRadius: 30,
{children} paddingTop: 150,
</Box> },
]}
>
<Text style={[g.text_2xl, g.font_bold]}>Types de paiement</Text>
<View style={[g.flex_1, g.flex_wrap, g.flex_row, g.gap_lg, g.justify_between]}>
{paymentTypes.map((paymentType) => {
return (
<PaymentType
onPress={() => {
navigation.navigate("paymentAmountInputScreen", {
paymentType,
});
}}
key={paymentType.reference}
style={[{ width: "47%" }]}
type={paymentType.code}
/>
);
})}
</View>
</View>
</BarnoinPayBackground>
); );
}; };
export default HomePageWithPaymentOptions;
...@@ -2,7 +2,7 @@ import { asp as g } from "@asp/asp"; ...@@ -2,7 +2,7 @@ import { asp as g } from "@asp/asp";
import * as Button from "@components/ButtonNew"; import * as Button from "@components/ButtonNew";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
import type { MainStackScreenComponentProps } from "@/navigations/Types"; import type { MainStackScreenComponentProps } from "@/navigations/types";
const HomeUserNotLoggedIn: MainStackScreenComponentProps<"homeUserNotLoggedIn"> = ({ const HomeUserNotLoggedIn: MainStackScreenComponentProps<"homeUserNotLoggedIn"> = ({
navigation, navigation,
......
import type { PaymentStackScreenComponentProps } from "@/navigations/Types"; import { asp as g } from "@asp/asp";
import { BarnoinPayBackground } from "@components/BarnoinPayBackground";
import BeasyLogoIcon from "@components/BeasyLogoIcon"; import BeasyLogoIcon from "@components/BeasyLogoIcon";
import Button from "@components/Button"; import * as Button from "@components/ButtonNew";
import GoBackIconButton from "@components/GoBackIconButton"; import * as Input from "@components/InputNew";
import InputWithTopLabel from "@components/InputWithTopLabel"; import AntDesign from "@expo/vector-icons/AntDesign";
import PaymentOption from "@components/PaymentOption";
import BackgroundGreenWhiteContentArea from "@components/backgrounds/BackgroundGreenWhiteContentArea";
import Box from "@components/bases/Box";
import Text from "@components/bases/Text";
import { LOG } from "@logger"; import { LOG } from "@logger";
import { SafeAreaView } from "react-native-safe-area-context"; import { Text, View } from "react-native";
import PaymentType from "@/features/pay/components/PaymentType";
import type { PaymentStackScreenComponentProps } from "@/navigations/types";
const log = LOG.extend("NumberAndOtpForPaymentScreen"); const _log = LOG.extend("NumberAndOtpForPaymentScreen");
const NumberAndOtpForPaymentScreen: PaymentStackScreenComponentProps< const NumberAndOtpForPaymentScreen: PaymentStackScreenComponentProps<
"numberAndOtpForPaymentScreen" "numberAndOtpForPaymentScreen"
> = ({ navigation }) => { > = ({ navigation, route }) => {
console.debug("NumberAndOtpForPaymentScreen");
return ( return (
<BackgroundGreenWhiteContentArea> <BarnoinPayBackground style={[g.flex_col, g.gap_lg, g.relative]}>
<SafeAreaView> <View style={[g.px_lg, g.flex_row, g.align_center, g.justify_between]}>
<Box style={{ height: "100%", width: "100%" }}> <BeasyLogoIcon />
<Box <AntDesign
px={"l"} name="arrowleft"
flexDirection={"row"} size={24}
justifyContent={"space-between"} color="black"
alignItems={"center"} onPress={() => navigation.goBack()}
> />
<BeasyLogoIcon /> </View>
<GoBackIconButton onPress={() => navigation.goBack()} />
</Box> <View style={[g.px_lg, g.align_center, g.justify_center]}>
<Box height={122} alignItems={"center"} justifyContent={"center"}> <Text style={[g.font_bold, g.text_2xl, { color: "white" }]}>Montant à payé </Text>
<Text color={"white"}>Montant à payer</Text> <Text style={[g.font_bold, g.text_2xl, { color: "white" }]}>
<Text color={"white"} fontSize={30}> {route.params.amount}
78000 </Text>
</Text> </View>
</Box>
<Box p={"l"}> <View
<Box width={100} height={70} mb={"l"}> style={[
<PaymentOption onPress={() => {}} paymentMethod={"OM"} /> g.flex_1,
</Box> g.p_5xl,
<Box mb={"l"}> g.gap_5xl,
<InputWithTopLabel { backgroundColor: "white", borderTopLeftRadius: 20, borderTopRightRadius: 20 },
label="Entrez le numero" ]}
keyboardType="numeric" >
textVariants={"black"} <PaymentType type={route.params.paymentType.code} />
/> <Input.Container>
<InputWithTopLabel <Input.Header>Entrer le numéro</Input.Header>
label="Code OTP" <Input.FieldContainer>
keyboardType="numeric" <Input.Field keyboardType="number-pad" />
textVariants={"black"} </Input.FieldContainer>
/> </Input.Container>
</Box>
<Button <Input.Container>
onPress={() => {}} <Input.Header>Code OTP</Input.Header>
variant={"full"} <Input.FieldContainer>
textVariants={"primary"} <Input.Field keyboardType="number-pad" />
label="Confirmer" </Input.FieldContainer>
/> </Input.Container>
</Box>
</Box> <Button.Container>
</SafeAreaView> <Button.Label>Confirmer</Button.Label>
</BackgroundGreenWhiteContentArea> </Button.Container>
</View>
</BarnoinPayBackground>
); );
}; };
......
import type { MainStackScreenComponentProps } from "@/navigations/Types";
import BeasyLogoIcon from "@components/BeasyLogoIcon"; import BeasyLogoIcon from "@components/BeasyLogoIcon";
import Button from "@components/Button"; import Button from "@components/Button";
import GoBackIconButton from "@components/GoBackIconButton";
import BeasyDefaultBackgroundWrapper from "@components/backgrounds/BeasyDefaultBackground"; import BeasyDefaultBackgroundWrapper from "@components/backgrounds/BeasyDefaultBackground";
import Box from "@components/bases/Box"; import Box from "@components/bases/Box";
import Text from "@components/bases/Text"; import Text from "@components/bases/Text";
import GoBackIconButton from "@components/GoBackIconButton";
import CheckIcon from "@components/icons/CheckIcon"; import CheckIcon from "@components/icons/CheckIcon";
import { LOG } from "@logger"; import { LOG } from "@logger";
import { CommonActions } from "@react-navigation/native"; import { CommonActions } from "@react-navigation/native";
// import { Text } from "react-native"; // import { Text } from "react-native";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context"; import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import type { MainStackScreenComponentProps } from "@/navigations/types";
const log = LOG.extend("PaymentResultScreen"); const log = LOG.extend("PaymentResultScreen");
......
...@@ -2,7 +2,7 @@ import { asp as g } from "@asp/asp"; ...@@ -2,7 +2,7 @@ import { asp as g } from "@asp/asp";
import { LOG } from "@logger"; import { LOG } from "@logger";
import { ImageBackground, View } from "react-native"; import { ImageBackground, View } from "react-native";
import { LoginForm } from "@/features/auth/components/LoginForm"; import { LoginForm } from "@/features/auth/components/LoginForm";
import type { MainStackScreenComponentProps } from "@/navigations/Types"; import type { MainStackScreenComponentProps } from "@/navigations/types";
const log = LOG.extend("UserLoginScreen"); const log = LOG.extend("UserLoginScreen");
const UserLoginScreen: MainStackScreenComponentProps<"userLoginScreen"> = ({ navigation }) => { const UserLoginScreen: MainStackScreenComponentProps<"userLoginScreen"> = ({ navigation }) => {
......
import type { MainStackScreenComponentProps } from "@/navigations/Types";
import Button from "@components/Button"; import Button from "@components/Button";
import BackgroundWithBeasyIconAndWhiteContentArea from "@components/backgrounds/BackgroundWithBeasyIconAndWhiteContentArea"; import BackgroundWithBeasyIconAndWhiteContentArea from "@components/backgrounds/BackgroundWithBeasyIconAndWhiteContentArea";
import Box from "@components/bases/Box"; import Box from "@components/bases/Box";
...@@ -8,6 +7,7 @@ import { LOG } from "@logger"; ...@@ -8,6 +7,7 @@ import { LOG } from "@logger";
import { Dimensions } from "react-native"; import { Dimensions } from "react-native";
// biome-ignore lint/style/useNamingConvention: <explanation> // biome-ignore lint/style/useNamingConvention: <explanation>
import QRCode from "react-native-qrcode-svg"; import QRCode from "react-native-qrcode-svg";
import type { MainStackScreenComponentProps } from "@/navigations/types";
const log = LOG.extend("WaveQrCodePaymentScreen"); const log = LOG.extend("WaveQrCodePaymentScreen");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment