Skip to content

Commit

Permalink
chore: [IOBP-498] Adds stepper in payment's screens header (#5525)
Browse files Browse the repository at this point in the history
## Short description
This PR adds the stepper component in payment's screens header.

## List of changes proposed in this pull request
- Added `WalltPaymentHeader` component, to handle back navigation and
display `Stepper` in the payment flow screens
- Added `react-navigation-view-pager` to handle navigation between
screens in the payment flow
- Added `currentStep` to redux store with actions and selector to read
and update it.
- Added `WalletPaymentMakeScreen` which displays the `ViewPager` with
the payment flow screens.

## How to test
Within Wallet Payment Playgrounds, start a new payment flow and check
that the stepper is correctly rendered

## Previews

| IOs | Android |
| --- | --- |
| <video
src="https://github.com/pagopa/io-app/assets/6160324/71781d0f-801b-47fe-a03d-3a763285d926"
/> | <video
src="https://github.com/pagopa/io-app/assets/6160324/79af2822-c973-4d4c-a918-26226a033a13"
/> |

---------

Co-authored-by: Martino Cesari Tomba <[email protected]>
  • Loading branch information
mastro993 and forrest57 authored Feb 23, 2024
1 parent 9d33b39 commit d09e9b0
Show file tree
Hide file tree
Showing 14 changed files with 197 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ import {
VSpacer
} from "@pagopa/io-app-design-system";
import { openAuthenticationSession } from "@pagopa/io-react-native-login-utils";
import { useNavigation } from "@react-navigation/native";
import React from "react";
import { Bundle } from "../../../../../definitions/pagopa/ecommerce/Bundle";
import { PaymentRequestsGetResponse } from "../../../../../definitions/pagopa/ecommerce/PaymentRequestsGetResponse";
import I18n from "../../../../i18n";
import {
AppParamsList,
IOStackNavigationProp
} from "../../../../navigation/params/AppParamsList";
import { useIODispatch } from "../../../../store/hooks";
import { format } from "../../../../utils/dates";
import { formatNumberCentsToAmount } from "../../../../utils/stringBuilder";
import { capitalize } from "../../../../utils/strings";
Expand All @@ -24,7 +20,7 @@ import {
getPaymentLogo
} from "../../common/utils";
import { UIWalletInfoDetails } from "../../details/types/UIWalletInfoDetails";
import { WalletPaymentRoutes } from "../navigation/routes";
import { walletPaymentSetCurrentStep } from "../store/actions/orchestration";
import { WalletPaymentTotalAmount } from "./WalletPaymentTotalAmount";

export type WalletPaymentConfirmContentProps = {
Expand All @@ -42,7 +38,7 @@ export const WalletPaymentConfirmContent = ({
isLoading,
onConfirm
}: WalletPaymentConfirmContentProps) => {
const navigation = useNavigation<IOStackNavigationProp<AppParamsList>>();
const dispatch = useIODispatch();

const taxFee = selectedPsp.taxPayerFee ?? 0;

Expand Down Expand Up @@ -76,11 +72,7 @@ export const WalletPaymentConfirmContent = ({
paymentLogo={getPaymentLogo(paymentMethodDetails)}
title={getPaymentTitle(paymentMethodDetails)}
subtitle={getPaymentSubtitle(paymentMethodDetails)}
onPress={() =>
navigation.navigate(WalletPaymentRoutes.WALLET_PAYMENT_MAIN, {
screen: WalletPaymentRoutes.WALLET_PAYMENT_PICK_METHOD
})
}
onPress={() => dispatch(walletPaymentSetCurrentStep(1))}
/>
<VSpacer size={24} />
<ListItemHeader
Expand All @@ -94,11 +86,7 @@ export const WalletPaymentConfirmContent = ({
subtitle={`${I18n.t("payment.confirm.feeAppliedBy")} ${
selectedPsp.bundleName
}`}
onPress={() =>
navigation.navigate(WalletPaymentRoutes.WALLET_PAYMENT_MAIN, {
screen: WalletPaymentRoutes.WALLET_PAYMENT_PICK_PSP
})
}
onPress={() => dispatch(walletPaymentSetCurrentStep(2))}
/>
<VSpacer size={24} />
<WalletPaymentTotalAmount totalAmount={totalAmount} />
Expand Down
70 changes: 70 additions & 0 deletions ts/features/payments/payment/components/WalletPaymentHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
ActionProp,
HeaderSecondLevel,
Stepper,
VSpacer
} from "@pagopa/io-app-design-system";
import React from "react";
import { useStartSupportRequest } from "../../../../hooks/useStartSupportRequest";
import I18n from "../../../../i18n";
import { useIONavigation } from "../../../../navigation/params/AppParamsList";
import { useIODispatch } from "../../../../store/hooks";
import { emptyContextualHelp } from "../../../../utils/emptyContextualHelp";
import { useWalletPaymentGoBackHandler } from "../hooks/useWalletPaymentGoBackHandler";
import { walletPaymentSetCurrentStep } from "../store/actions/orchestration";
import { useHardwareBackButton } from "../../../../hooks/useHardwareBackButton";
import { WALLET_PAYMENT_STEP_MAX } from "../store/reducers";

type WalletPaymentHeaderProps = {
currentStep: number;
};

const WalletPaymentHeader = ({ currentStep }: WalletPaymentHeaderProps) => {
const navigation = useIONavigation();
const dispatch = useIODispatch();
const goBackHandler = useWalletPaymentGoBackHandler();

const startSupportRequest = useStartSupportRequest({
faqCategories: ["payment"],
contextualHelp: emptyContextualHelp
});

const handleGoBack = React.useCallback(() => {
if (currentStep === 1 && goBackHandler) {
return goBackHandler();
}

if (currentStep === 1) {
return navigation.goBack();
}

dispatch(walletPaymentSetCurrentStep(currentStep - 1));
}, [navigation, dispatch, goBackHandler, currentStep]);

useHardwareBackButton(() => {
handleGoBack();
return true;
});

return (
<>
<HeaderSecondLevel
title=""
type="singleAction"
goBack={handleGoBack}
backAccessibilityLabel={I18n.t("global.buttons.back")}
firstAction={{
icon: "help" as ActionProp["icon"],
onPress: startSupportRequest,
accessibilityLabel: I18n.t(
"global.accessibility.contextualHelp.open.label"
)
}}
/>
<Stepper steps={WALLET_PAYMENT_STEP_MAX} currentStep={currentStep} />
<VSpacer size={16} />
</>
);
};

export { WalletPaymentHeader };
25 changes: 5 additions & 20 deletions ts/features/payments/payment/navigation/navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import { isGestureEnabled } from "../../../../utils/navigation";
import { WalletPaymentDetailScreen } from "../screens/WalletPaymentDetailScreen";
import { WalletPaymentInputFiscalCodeScreen } from "../screens/WalletPaymentInputFiscalCodeScreen";
import { WalletPaymentInputNoticeNumberScreen } from "../screens/WalletPaymentInputNoticeNumberScreen";
import { WalletPaymentPickMethodScreen } from "../screens/WalletPaymentPickMethodScreen";
import { WalletPaymentMakeScreen } from "../screens/WalletPaymentMakeScreen";
import { WalletPaymentOutcomeScreen } from "../screens/WalletPaymentOutcomeScreen";
import { WalletPaymentPickPspScreen } from "../screens/WalletPaymentPickPspScreen";
import { WalletPaymentConfirmScreen } from "../screens/WalletPaymentConfirmScreen";
import { WalletPaymentParamsList } from "./params";
import { WalletPaymentRoutes } from "./routes";

Expand Down Expand Up @@ -48,24 +46,11 @@ export const WalletPaymentNavigator = () => (
}}
/>
<Stack.Screen
name={WalletPaymentRoutes.WALLET_PAYMENT_PICK_METHOD}
component={WalletPaymentPickMethodScreen}
name={WalletPaymentRoutes.WALLET_PAYMENT_MAKE}
component={WalletPaymentMakeScreen}
options={{
gestureEnabled: isGestureEnabled
}}
/>
<Stack.Screen
name={WalletPaymentRoutes.WALLET_PAYMENT_PICK_PSP}
component={WalletPaymentPickPspScreen}
options={{
gestureEnabled: isGestureEnabled
}}
/>
<Stack.Screen
name={WalletPaymentRoutes.WALLET_PAYMENT_CONFIRM}
component={WalletPaymentConfirmScreen}
options={{
gestureEnabled: isGestureEnabled
gestureEnabled: isGestureEnabled,
headerShown: false
}}
/>
<Stack.Screen
Expand Down
4 changes: 1 addition & 3 deletions ts/features/payments/payment/navigation/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ export type WalletPaymentParamsList = {
[WalletPaymentRoutes.WALLET_PAYMENT_INPUT_NOTICE_NUMBER]: undefined;
[WalletPaymentRoutes.WALLET_PAYMENT_INPUT_FISCAL_CODE]: WalletPaymentInputFiscalCodeScreenNavigationParams;
[WalletPaymentRoutes.WALLET_PAYMENT_DETAIL]: WalletPaymentDetailScreenNavigationParams;
[WalletPaymentRoutes.WALLET_PAYMENT_PICK_METHOD]: undefined;
[WalletPaymentRoutes.WALLET_PAYMENT_PICK_PSP]: undefined;
[WalletPaymentRoutes.WALLET_PAYMENT_CONFIRM]: undefined;
[WalletPaymentRoutes.WALLET_PAYMENT_MAKE]: undefined;
[WalletPaymentRoutes.WALLET_PAYMENT_OUTCOME]: WalletPaymentOutcomeScreenNavigationParams;
};
4 changes: 1 addition & 3 deletions ts/features/payments/payment/navigation/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ export const WalletPaymentRoutes = {
WALLET_PAYMENT_INPUT_NOTICE_NUMBER: "WALLET_PAYMENT_INPUT_NOTICE_NUMBER",
WALLET_PAYMENT_INPUT_FISCAL_CODE: "WALLET_PAYMENT_INPUT_FISCAL_CODE",
WALLET_PAYMENT_DETAIL: "WALLET_PAYMENT_DETAIL",
WALLET_PAYMENT_PICK_METHOD: "WALLET_PAYMENT_PICK_METHOD",
WALLET_PAYMENT_PICK_PSP: "WALLET_PAYMENT_PICK_PSP",
WALLET_PAYMENT_CONFIRM: "WALLET_PAYMENT_CONFIRM",
WALLET_PAYMENT_MAKE: "WALLET_PAYMENT_MAKE",
WALLET_PAYMENT_OUTCOME: "WALLET_PAYMENT_OUTCOME"
} as const;
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,15 @@ import {
VSpacer
} from "@pagopa/io-app-design-system";
import * as pot from "@pagopa/ts-commons/lib/pot";
import { useNavigation } from "@react-navigation/native";
import { sequenceS } from "fp-ts/lib/Apply";
import * as O from "fp-ts/lib/Option";
import { pipe } from "fp-ts/lib/function";
import React from "react";
import { SafeAreaView, StyleSheet } from "react-native";
import { AmountEuroCents } from "../../../../../definitions/pagopa/ecommerce/AmountEuroCents";
import { useHeaderSecondLevel } from "../../../../hooks/useHeaderSecondLevel";
import I18n from "../../../../i18n";
import {
AppParamsList,
IOStackNavigationProp
} from "../../../../navigation/params/AppParamsList";
import { useIONavigation } from "../../../../navigation/params/AppParamsList";
import { useIOSelector } from "../../../../store/hooks";
import { emptyContextualHelp } from "../../../../utils/emptyContextualHelp";
import { WalletPaymentConfirmContent } from "../components/WalletPaymentConfirmContent";
import { useWalletPaymentAuthorizationModal } from "../hooks/useWalletPaymentAuthorizationModal";
import { WalletPaymentRoutes } from "../navigation/routes";
Expand All @@ -35,7 +29,7 @@ import {
} from "../types/PaymentOutcomeEnum";

const WalletPaymentConfirmScreen = () => {
const navigation = useNavigation<IOStackNavigationProp<AppParamsList>>();
const navigation = useIONavigation();

const paymentDetailsPot = useIOSelector(walletPaymentDetailsSelector);
const transactionPot = useIOSelector(walletPaymentTransactionSelector);
Expand All @@ -44,13 +38,6 @@ const WalletPaymentConfirmScreen = () => {
);
const selectedPspOption = useIOSelector(walletPaymentPickedPspSelector);

useHeaderSecondLevel({
title: "",
contextualHelp: emptyContextualHelp,
faqCategories: ["payment"],
supportRequest: true
});

const handleStartPaymentAuthorization = () =>
pipe(
sequenceS(O.Monad)({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ const WalletPaymentDetailContent = ({
contextualHelp: emptyContextualHelp
});

const navigateToMethodSelection = () => {
const navigateToMakePaymentScreen = () => {
navigation.push(WalletPaymentRoutes.WALLET_PAYMENT_MAIN, {
screen: WalletPaymentRoutes.WALLET_PAYMENT_PICK_METHOD
screen: WalletPaymentRoutes.WALLET_PAYMENT_MAKE
});
};

Expand Down Expand Up @@ -200,7 +200,7 @@ const WalletPaymentDetailContent = ({
primaryActionProps={{
label: "Vai al pagamento",
accessibilityLabel: "Vai al pagmento",
onPress: navigateToMethodSelection
onPress: navigateToMakePaymentScreen
}}
>
<ListItemInfo
Expand Down
48 changes: 48 additions & 0 deletions ts/features/payments/payment/screens/WalletPaymentMakeScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import { StyleSheet, View } from "react-native";
import PagerView from "react-native-pager-view";
import { useIOSelector } from "../../../../store/hooks";
import { WalletPaymentHeader } from "../components/WalletPaymentHeader";
import { selectWalletPaymentCurrentStep } from "../store/selectors";
import { WalletPaymentConfirmScreen } from "./WalletPaymentConfirmScreen";
import { WalletPaymentPickMethodScreen } from "./WalletPaymentPickMethodScreen";
import { WalletPaymentPickPspScreen } from "./WalletPaymentPickPspScreen";

const WalletPaymentMakeScreen = () => {
const ref = React.useRef<PagerView>(null);
const currentStep = useIOSelector(selectWalletPaymentCurrentStep);

React.useEffect(() => {
ref.current?.setPage(currentStep - 1);
}, [ref, currentStep]);

return (
<>
<WalletPaymentHeader currentStep={currentStep} />
<PagerView
style={styles.pagerView}
initialPage={0}
ref={ref}
scrollEnabled={false}
>
<View key="1">
<WalletPaymentPickMethodScreen />
</View>
<View key="2">
<WalletPaymentPickPspScreen />
</View>
<View key="3">
<WalletPaymentConfirmScreen />
</View>
</PagerView>
</>
);
};

const styles = StyleSheet.create({
pagerView: {
flex: 1
}
});

export { WalletPaymentMakeScreen };
Loading

0 comments on commit d09e9b0

Please sign in to comment.