From 39205809943f02b40997e3f7caf46d7b7a5ea325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Thu, 1 Apr 2021 10:36:08 +0200 Subject: [PATCH 01/10] [#177560087] Changed pick psp screen UI --- locales/en/index.yml | 10 +- locales/it/index.yml | 10 +- ts/components/core/typography/Label.tsx | 2 +- ts/components/core/typography/LabelSmall.tsx | 2 +- ts/screens/wallet/payment/PickPspScreen.tsx | 133 ++++++++++++------- 5 files changed, 98 insertions(+), 59 deletions(-) diff --git a/locales/en/index.yml b/locales/en/index.yml index 148b6e64541..72dbdba3847 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1028,10 +1028,12 @@ wallet: thanks: "✓ Thank you!" endPayment: Your payment has been completed successfully pickPsp: - title: Choose the provider - infoBold: Choose the Payment Service Provider - info2: (PSP) which will have to manage your payment. - link: Find out more + headerTitle: "Choose the provider" + title: Which provider do you want to pay with? + info: Each provider proposes a transaction cost. + info2: In this list you will find all the providers + info2Bold: compatible with your method, even if you are not their client. + provider: Provider maxFee: Maximum fee onUpdateWalletPspFailure: Operation failed, please retry contextualHelpTitle: Select a provider diff --git a/locales/it/index.yml b/locales/it/index.yml index 1a77123710a..156ee0b64ee 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1054,10 +1054,12 @@ wallet: thanks: "✓ Grazie!" endPayment: Il tuo pagamento è concluso pickPsp: - title: Scegli il gestore - infoBold: Scegli il soggetto - info2: (PSP) che dovrà gestire la tua transazione. - link: Per saperne di più + headerTitle: "Seleziona un gestore" + title: Con quale gestore vuoi pagare? + info: Ogni gestore propone un costo di transazione. + info2: In questa lista trovi tutti i gestori + info2Bold: compatibili con il tuo metodo, anche se non sei loro cliente. + provider: Gestore maxFee: Costo di transazione onUpdateWalletPspFailure: Operazione fallita, riprova contextualHelpTitle: Scelta del gestore diff --git a/ts/components/core/typography/Label.tsx b/ts/components/core/typography/Label.tsx index 0fd3e9b64ec..f0e419f13a2 100644 --- a/ts/components/core/typography/Label.tsx +++ b/ts/components/core/typography/Label.tsx @@ -6,7 +6,7 @@ import { typographyFactory } from "./Factory"; type AllowedColors = Extract< IOColorType, - "blue" | "bluegrey" | "white" | "red" + "blue" | "bluegrey" | "white" | "red" | "bluegreyDark" >; type AllowedWeight = Extract; type OwnProps = ExternalTypographyProps< diff --git a/ts/components/core/typography/LabelSmall.tsx b/ts/components/core/typography/LabelSmall.tsx index 03f2cadd5a9..7ea5525830e 100644 --- a/ts/components/core/typography/LabelSmall.tsx +++ b/ts/components/core/typography/LabelSmall.tsx @@ -9,7 +9,7 @@ type AllowedColors = Extract< // tslint:disable-next-line:max-union-size "blue" | "bluegrey" | "red" | "white" >; -type AllowedWeight = Extract; +type AllowedWeight = Extract; type OwnProps = ExternalTypographyProps< TypographyProps diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index ee18dad70aa..12b31b3f14a 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -1,35 +1,36 @@ import { AmountInEuroCents, RptId } from "italia-pagopa-commons/lib/pagopa"; import * as pot from "italia-ts-commons/lib/pot"; -import { Content, Text, View } from "native-base"; +import { Content, View, H3 } from "native-base"; import * as React from "react"; import { FlatList, Image, ListRenderItemInfo, StyleSheet } from "react-native"; import { NavigationInjectedProps } from "react-navigation"; import { connect } from "react-redux"; import { PaymentRequestsGetResponse } from "../../../../definitions/backend/PaymentRequestsGetResponse"; -import { ContextualHelp } from "../../../components/ContextualHelp"; +import { LabelSmall } from "../../../components/core/typography/LabelSmall"; +import { Label } from "../../../components/core/typography/Label"; import { withLightModalContext } from "../../../components/helpers/withLightModalContext"; import { withLoadingSpinner } from "../../../components/helpers/withLoadingSpinner"; import ItemSeparatorComponent from "../../../components/ItemSeparatorComponent"; import BaseScreenComponent, { ContextualHelpPropsMarkdown } from "../../../components/screens/BaseScreenComponent"; -import { EdgeBorderComponent } from "../../../components/screens/EdgeBorderComponent"; import TouchableDefaultOpacity from "../../../components/TouchableDefaultOpacity"; import IconFont from "../../../components/ui/IconFont"; import { LightModalContextInterface } from "../../../components/ui/LightModal"; -import Markdown from "../../../components/ui/Markdown"; import I18n from "../../../i18n"; import { Dispatch } from "../../../store/actions/types"; import { paymentFetchAllPspsForPaymentId } from "../../../store/actions/wallet/payment"; import { GlobalState } from "../../../store/reducers/types"; import { allPspsSelector } from "../../../store/reducers/wallet/payment"; -import variables from "../../../theme/variables"; import customVariables from "../../../theme/variables"; import { Psp, Wallet } from "../../../types/pagopa"; import { orderPspByAmount } from "../../../utils/payment"; import { showToast } from "../../../utils/showToast"; import { formatNumberCentsToAmount } from "../../../utils/stringBuilder"; import { dispatchUpdatePspForWalletAndConfirm } from "./common"; +import FooterWithButtons from "../../../components/ui/FooterWithButtons"; +import { navigateBack } from "../../../store/actions/navigation"; +import { Body } from "../../../components/core/typography/Body"; type NavigationParams = Readonly<{ rptId: RptId; @@ -59,11 +60,11 @@ const styles = StyleSheet.create({ alignItems: "center", justifyContent: "space-between" }, - feeText: { - color: variables.brandDarkGray + feeContainer: { + flexDirection: "row", + alignItems: "center" }, - - flexStart: { + imageProvider: { width: 100, height: 50 }, @@ -77,21 +78,22 @@ const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { const ICON_SIZE = 24; +type State = { + hasImageLoadingError: boolean; +}; /** * Select a PSP to be used for a the current selected wallet */ -class PickPspScreen extends React.Component { - private showHelp = () => { - this.props.showModal( - ( - {I18n.t("wallet.pickPsp.contextualHelpContent")} - )} - /> - ); - }; +class PickPspScreen extends React.Component { + constructor(props: Props) { + super(props); + this.state = { + hasImageLoadingError: false + }; + } + + private onErrorImageLoading = () => + this.setState({ hasImageLoadingError: true }); public componentDidMount() { // load all psp in order to offer to the user the complete psps list @@ -102,31 +104,49 @@ class PickPspScreen extends React.Component { this.props.loadAllPsp(idWallet, idPayment); } + private headerItem = ( + + + + {I18n.t("wallet.pickPsp.provider")} + + + {`${I18n.t("wallet.pickPsp.maxFee")} (€)`} + + + + + + ); + private getListItem = (psp: ListRenderItemInfo) => { const { item } = psp; + return ( this.props.pickPsp(item.id, this.props.allPsps)} style={styles.itemContainer} > - - + {!this.state.hasImageLoadingError ? ( + + ) : ( + {item.serviceName} + )} + + + + - - {`${I18n.t("wallet.pickPsp.maxFee")} `} - - {formatNumberCentsToAmount(item.fixedCost.amount)} - - ); }; @@ -134,34 +154,48 @@ class PickPspScreen extends React.Component { public render(): React.ReactNode { const availablePsps = orderPspByAmount(this.props.allPsps); + const backButtonProps = { + block: true, + primary: true, + bordered: true, + onPress: this.props.navigateBack, + title: I18n.t("global.buttons.back") + }; + return ( - - + + - - {`${I18n.t("wallet.pickPsp.infoBold")} `} - {`${I18n.t("wallet.pickPsp.info2")} `} - - - {I18n.t("wallet.pickPsp.link")} - +

{I18n.t("wallet.pickPsp.title")}

+ + + - + } removeClippedSubviews={false} data={availablePsps} keyExtractor={item => item.id.toString()} renderItem={this.getListItem} - ListFooterComponent={} + ListHeaderComponent={this.headerItem} + ListFooterComponent={() => } />
+
); } @@ -177,6 +211,7 @@ const mapStateToProps = (state: GlobalState) => { }; const mapDispatchToProps = (dispatch: Dispatch, props: OwnProps) => ({ + navigateBack: () => dispatch(navigateBack()), loadAllPsp: (idWallet: string, idPayment: string) => { dispatch( paymentFetchAllPspsForPaymentId.request({ From 523e5f9837a09ca90ee8bee6db3751934b640d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Thu, 1 Apr 2021 15:00:46 +0200 Subject: [PATCH 02/10] [#177560087] fixed eslint error --- ts/screens/wallet/payment/PickPspScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index 12b31b3f14a..df38d1888b3 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -27,10 +27,10 @@ import { Psp, Wallet } from "../../../types/pagopa"; import { orderPspByAmount } from "../../../utils/payment"; import { showToast } from "../../../utils/showToast"; import { formatNumberCentsToAmount } from "../../../utils/stringBuilder"; -import { dispatchUpdatePspForWalletAndConfirm } from "./common"; import FooterWithButtons from "../../../components/ui/FooterWithButtons"; import { navigateBack } from "../../../store/actions/navigation"; import { Body } from "../../../components/core/typography/Body"; +import { dispatchUpdatePspForWalletAndConfirm } from "./common"; type NavigationParams = Readonly<{ rptId: RptId; From 65b506437e142e585c19f06ae2bc181d7d8bf286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Fri, 2 Apr 2021 09:45:59 +0200 Subject: [PATCH 03/10] [#177560087] Changed serviceName with businessName --- ts/screens/wallet/payment/PickPspScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index df38d1888b3..c816662e39a 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -136,7 +136,7 @@ class PickPspScreen extends React.Component { onError={this.onErrorImageLoading} /> ) : ( - {item.serviceName} + {item.businessName} )} From c091a769d749052924da67dd787c342d3c006eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Fri, 2 Apr 2021 18:14:45 +0200 Subject: [PATCH 04/10] [#177560087] Using correct core components and using image resize hook to show psp logo --- ts/components/PspComponent.tsx | 87 ++++++++++++ ts/components/core/typography/Label.tsx | 2 +- ts/components/core/typography/LabelSmall.tsx | 2 +- ts/screens/wallet/payment/PickPspScreen.tsx | 134 ++++++------------- 4 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 ts/components/PspComponent.tsx diff --git a/ts/components/PspComponent.tsx b/ts/components/PspComponent.tsx new file mode 100644 index 00000000000..199338dff30 --- /dev/null +++ b/ts/components/PspComponent.tsx @@ -0,0 +1,87 @@ +import React, { FC } from "react"; +import { + ImageStyle, + ListRenderItemInfo, + StyleProp, + StyleSheet, + View, + Image +} from "react-native"; +import { useImageResize } from "../features/wallet/onboarding/bancomat/screens/hooks/useImageResize"; +import customVariables from "../theme/variables"; +import { Psp } from "../types/pagopa"; +import { formatNumberCentsToAmount } from "../utils/stringBuilder"; +import { Body } from "./core/typography/Body"; +import { H4 } from "./core/typography/H4"; +import TouchableDefaultOpacity from "./TouchableDefaultOpacity"; +import IconFont from "./ui/IconFont"; + +const ICON_SIZE = 24; +const IMAGE_WIDTH = 100; +const IMAGE_HEIGHT = 50; + +const styles = StyleSheet.create({ + itemContainer: { + paddingVertical: 16, + paddingHorizontal: customVariables.contentPadding, + flexDirection: "column" + }, + line1: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between" + }, + feeContainer: { + flexDirection: "row", + alignItems: "center" + } +}); + +type Props = { + psp: ListRenderItemInfo; + pickPsp: (idPsp: number, psps: ReadonlyArray) => any; + allPsps: ReadonlyArray; +}; + +export const PspComponent: FC = ({ psp, pickPsp, allPsps }) => { + const { item } = psp; + const imageResize = useImageResize(IMAGE_WIDTH, IMAGE_HEIGHT, item.logoPSP); + const cost = formatNumberCentsToAmount(item.fixedCost.amount); + + const renderImage = imageResize.fold( + {item.businessName}, + size => { + const imageStyle: StyleProp = { + width: size[0], + height: size[1], + resizeMode: "contain" + }; + + return ( + + ); + } + ); + + const onPress = () => pickPsp(item.id, allPsps); + + return ( + + + {renderImage} + +

{cost}

+ +
+
+
+ ); +}; diff --git a/ts/components/core/typography/Label.tsx b/ts/components/core/typography/Label.tsx index f0e419f13a2..0fd3e9b64ec 100644 --- a/ts/components/core/typography/Label.tsx +++ b/ts/components/core/typography/Label.tsx @@ -6,7 +6,7 @@ import { typographyFactory } from "./Factory"; type AllowedColors = Extract< IOColorType, - "blue" | "bluegrey" | "white" | "red" | "bluegreyDark" + "blue" | "bluegrey" | "white" | "red" >; type AllowedWeight = Extract; type OwnProps = ExternalTypographyProps< diff --git a/ts/components/core/typography/LabelSmall.tsx b/ts/components/core/typography/LabelSmall.tsx index 7ea5525830e..03f2cadd5a9 100644 --- a/ts/components/core/typography/LabelSmall.tsx +++ b/ts/components/core/typography/LabelSmall.tsx @@ -9,7 +9,7 @@ type AllowedColors = Extract< // tslint:disable-next-line:max-union-size "blue" | "bluegrey" | "red" | "white" >; -type AllowedWeight = Extract; +type AllowedWeight = Extract; type OwnProps = ExternalTypographyProps< TypographyProps diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index c816662e39a..431364bedbc 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -1,21 +1,24 @@ import { AmountInEuroCents, RptId } from "italia-pagopa-commons/lib/pagopa"; import * as pot from "italia-ts-commons/lib/pot"; -import { Content, View, H3 } from "native-base"; +import { View, H3 } from "native-base"; import * as React from "react"; -import { FlatList, Image, ListRenderItemInfo, StyleSheet } from "react-native"; +import { + FlatList, + StyleSheet, + SafeAreaView, + ListRenderItemInfo +} from "react-native"; import { NavigationInjectedProps } from "react-navigation"; import { connect } from "react-redux"; import { PaymentRequestsGetResponse } from "../../../../definitions/backend/PaymentRequestsGetResponse"; -import { LabelSmall } from "../../../components/core/typography/LabelSmall"; -import { Label } from "../../../components/core/typography/Label"; +import { H5 } from "../../../components/core/typography/H5"; +import { H4 } from "../../../components/core/typography/H4"; import { withLightModalContext } from "../../../components/helpers/withLightModalContext"; import { withLoadingSpinner } from "../../../components/helpers/withLoadingSpinner"; import ItemSeparatorComponent from "../../../components/ItemSeparatorComponent"; import BaseScreenComponent, { ContextualHelpPropsMarkdown } from "../../../components/screens/BaseScreenComponent"; -import TouchableDefaultOpacity from "../../../components/TouchableDefaultOpacity"; -import IconFont from "../../../components/ui/IconFont"; import { LightModalContextInterface } from "../../../components/ui/LightModal"; import I18n from "../../../i18n"; import { Dispatch } from "../../../store/actions/types"; @@ -26,11 +29,12 @@ import customVariables from "../../../theme/variables"; import { Psp, Wallet } from "../../../types/pagopa"; import { orderPspByAmount } from "../../../utils/payment"; import { showToast } from "../../../utils/showToast"; -import { formatNumberCentsToAmount } from "../../../utils/stringBuilder"; import FooterWithButtons from "../../../components/ui/FooterWithButtons"; import { navigateBack } from "../../../store/actions/navigation"; -import { Body } from "../../../components/core/typography/Body"; +import { IOStyles } from "../../../components/core/variables/IOStyles"; import { dispatchUpdatePspForWalletAndConfirm } from "./common"; +import { cancelButtonProps } from "../../../features/bonus/bonusVacanze/components/buttons/ButtonConfigurations"; +import { PspComponent } from "../../../components/PspComponent"; type NavigationParams = Readonly<{ rptId: RptId; @@ -50,24 +54,11 @@ type Props = ReturnType & OwnProps; const styles = StyleSheet.create({ - itemContainer: { - paddingVertical: 16, - paddingHorizontal: customVariables.contentPadding, - flexDirection: "column" - }, line1: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, - feeContainer: { - flexDirection: "row", - alignItems: "center" - }, - imageProvider: { - width: 100, - height: 50 - }, padded: { paddingHorizontal: customVariables.contentPadding } }); @@ -76,25 +67,10 @@ const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { body: "wallet.pickPsp.contextualHelpContent" }; -const ICON_SIZE = 24; - -type State = { - hasImageLoadingError: boolean; -}; /** * Select a PSP to be used for a the current selected wallet */ -class PickPspScreen extends React.Component { - constructor(props: Props) { - super(props); - this.state = { - hasImageLoadingError: false - }; - } - - private onErrorImageLoading = () => - this.setState({ hasImageLoadingError: true }); - +class PickPspScreen extends React.Component { public componentDidMount() { // load all psp in order to offer to the user the complete psps list const idWallet = this.props.navigation @@ -104,64 +80,32 @@ class PickPspScreen extends React.Component { this.props.loadAllPsp(idWallet, idPayment); } + private renderItem = (item: ListRenderItemInfo) => ( + + ); + private headerItem = ( - +
{I18n.t("wallet.pickPsp.provider")} - - - {`${I18n.t("wallet.pickPsp.maxFee")} (€)`} - +
+
{`${I18n.t( + "wallet.pickPsp.maxFee" + )} (€)`}
); - private getListItem = (psp: ListRenderItemInfo) => { - const { item } = psp; - - return ( - this.props.pickPsp(item.id, this.props.allPsps)} - style={styles.itemContainer} - > - - {!this.state.hasImageLoadingError ? ( - - ) : ( - {item.businessName} - )} - - - - - - - ); - }; - public render(): React.ReactNode { const availablePsps = orderPspByAmount(this.props.allPsps); - const backButtonProps = { - block: true, - primary: true, - bordered: true, - onPress: this.props.navigateBack, - title: I18n.t("global.buttons.back") - }; - return ( { contextualHelpMarkdown={contextualHelpMarkdown} faqCategories={["payment"]} > - +

{I18n.t("wallet.pickPsp.title")}

- { removeClippedSubviews={false} data={availablePsps} keyExtractor={item => item.id.toString()} - renderItem={this.getListItem} + renderItem={this.renderItem} ListHeaderComponent={this.headerItem} ListFooterComponent={() => } /> -
- + +
); } From a283d0503e88cbc9d766d491e6a07fa56aeb971c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Fri, 2 Apr 2021 18:19:00 +0200 Subject: [PATCH 05/10] [#177560087] Solved eslint error --- ts/screens/wallet/payment/PickPspScreen.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index 431364bedbc..8ff14b0298d 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -32,9 +32,9 @@ import { showToast } from "../../../utils/showToast"; import FooterWithButtons from "../../../components/ui/FooterWithButtons"; import { navigateBack } from "../../../store/actions/navigation"; import { IOStyles } from "../../../components/core/variables/IOStyles"; -import { dispatchUpdatePspForWalletAndConfirm } from "./common"; -import { cancelButtonProps } from "../../../features/bonus/bonusVacanze/components/buttons/ButtonConfigurations"; import { PspComponent } from "../../../components/PspComponent"; +import { cancelButtonProps } from "../../../features/bonus/bonusVacanze/components/buttons/ButtonConfigurations"; +import { dispatchUpdatePspForWalletAndConfirm } from "./common"; type NavigationParams = Readonly<{ rptId: RptId; From 2bdd3d9c9c6d5eaa470e85f2ff4ab41900c94eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Thu, 8 Apr 2021 11:53:06 +0200 Subject: [PATCH 06/10] [#177560087] added testing and refactored components to match tests --- ts/components/PspComponent.tsx | 63 +++++++---------- ts/components/__tests__/PspComponent.test.tsx | 43 ++++++++++++ ts/screens/wallet/payment/PickPspScreen.tsx | 25 +++---- .../payment/__tests__/PickPspScreen.test.tsx | 70 +++++++++++++++++++ 4 files changed, 149 insertions(+), 52 deletions(-) create mode 100644 ts/components/__tests__/PspComponent.test.tsx create mode 100644 ts/screens/wallet/payment/__tests__/PickPspScreen.test.tsx diff --git a/ts/components/PspComponent.tsx b/ts/components/PspComponent.tsx index 199338dff30..f36c4ad7dfb 100644 --- a/ts/components/PspComponent.tsx +++ b/ts/components/PspComponent.tsx @@ -1,12 +1,5 @@ import React, { FC } from "react"; -import { - ImageStyle, - ListRenderItemInfo, - StyleProp, - StyleSheet, - View, - Image -} from "react-native"; +import { ImageStyle, StyleProp, StyleSheet, View, Image } from "react-native"; import { useImageResize } from "../features/wallet/onboarding/bancomat/screens/hooks/useImageResize"; import customVariables from "../theme/variables"; import { Psp } from "../types/pagopa"; @@ -38,41 +31,39 @@ const styles = StyleSheet.create({ }); type Props = { - psp: ListRenderItemInfo; - pickPsp: (idPsp: number, psps: ReadonlyArray) => any; - allPsps: ReadonlyArray; + psp: Psp; + onPress: () => void; }; -export const PspComponent: FC = ({ psp, pickPsp, allPsps }) => { - const { item } = psp; - const imageResize = useImageResize(IMAGE_WIDTH, IMAGE_HEIGHT, item.logoPSP); - const cost = formatNumberCentsToAmount(item.fixedCost.amount); +export const PspComponent: FC = ({ psp, onPress }) => { + const imgDimensions = useImageResize(IMAGE_WIDTH, IMAGE_HEIGHT, psp.logoPSP); + const cost = formatNumberCentsToAmount(psp.fixedCost.amount); - const renderImage = imageResize.fold( - {item.businessName}, - size => { - const imageStyle: StyleProp = { - width: size[0], - height: size[1], - resizeMode: "contain" - }; - - return ( - - ); - } + const imageStyle: StyleProp | undefined = imgDimensions.fold( + undefined, + imgDim => ({ + width: imgDim[0], + height: imgDim[1], + resizeMode: "contain" + }) ); - const onPress = () => pickPsp(item.id, allPsps); - return ( - + - {renderImage} + {psp.logoPSP && imageStyle ? ( + + ) : ( + {psp.businessName} + )}

{cost}

{ + it("should call onPress if psp button is pressed", () => { + const onPress = jest.fn(); + const component = renderComponent(onPress); + + fireEvent.press(component.getByTestId("psp-0")); + expect(onPress).toHaveBeenCalled(); + }); + it("should show the logoPSP if there is one and useImageResize return some value", () => { + jest.spyOn(hooks, "useImageResize").mockReturnValue(some([15, 15])); + const onPress = jest.fn(); + const component = renderComponent(onPress); + const logoPSP = component.queryByTestId("logoPSP"); + + expect(logoPSP).not.toBeNull(); + expect(logoPSP).toHaveProp("source", { uri: psp.logoPSP }); + }); + it("should show the businessName if there isn't logoPSP", () => { + jest.spyOn(hooks, "useImageResize").mockReturnValue(none); + const onPress = jest.fn(); + const component = renderComponent(onPress); + const businessName = component.queryByTestId("businessName"); + + expect(businessName).not.toBeNull(); + }); +}); + +const renderComponent = (onPress: () => void) => + render(); diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index 8ff14b0298d..f45b922d5ec 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -2,12 +2,7 @@ import { AmountInEuroCents, RptId } from "italia-pagopa-commons/lib/pagopa"; import * as pot from "italia-ts-commons/lib/pot"; import { View, H3 } from "native-base"; import * as React from "react"; -import { - FlatList, - StyleSheet, - SafeAreaView, - ListRenderItemInfo -} from "react-native"; +import { FlatList, StyleSheet, SafeAreaView } from "react-native"; import { NavigationInjectedProps } from "react-navigation"; import { connect } from "react-redux"; import { PaymentRequestsGetResponse } from "../../../../definitions/backend/PaymentRequestsGetResponse"; @@ -80,14 +75,6 @@ class PickPspScreen extends React.Component { this.props.loadAllPsp(idWallet, idPayment); } - private renderItem = (item: ListRenderItemInfo) => ( - - ); - private headerItem = ( @@ -113,7 +100,7 @@ class PickPspScreen extends React.Component { contextualHelpMarkdown={contextualHelpMarkdown} faqCategories={["payment"]} > - +

{I18n.t("wallet.pickPsp.title")}

@@ -130,11 +117,17 @@ class PickPspScreen extends React.Component {
} removeClippedSubviews={false} data={availablePsps} keyExtractor={item => item.id.toString()} - renderItem={this.renderItem} + renderItem={({ item }) => ( + this.props.pickPsp(item.id, this.props.allPsps)} + /> + )} ListHeaderComponent={this.headerItem} ListFooterComponent={() => } /> diff --git a/ts/screens/wallet/payment/__tests__/PickPspScreen.test.tsx b/ts/screens/wallet/payment/__tests__/PickPspScreen.test.tsx new file mode 100644 index 00000000000..7171fbe55af --- /dev/null +++ b/ts/screens/wallet/payment/__tests__/PickPspScreen.test.tsx @@ -0,0 +1,70 @@ +import { NavigationParams } from "react-navigation"; +import configureMockStore from "redux-mock-store"; +import { AmountInEuroCents, RptId } from "italia-pagopa-commons/lib/pagopa"; +import { applicationChangeState } from "../../../../store/actions/application"; +import { appReducer } from "../../../../store/reducers"; +import { GlobalState } from "../../../../store/reducers/types"; +import { renderScreenFakeNavRedux } from "../../../../utils/testWrapper"; +import PickPspScreen from "../PickPspScreen"; +import { PaymentRequestsGetResponse } from "../../../../../definitions/backend/PaymentRequestsGetResponse"; +import { Psp, Wallet } from "../../../../types/pagopa"; +import ROUTES from "../../../../navigation/routes"; + +const rptId = {} as RptId; +const initialAmount = "300" as AmountInEuroCents; +const verifica = {} as PaymentRequestsGetResponse; +const idPayment = "123"; +const psps = [ + { + id: 0, + fixedCost: { amount: 10 }, + logoPSP: + "https://acardste.vaservices.eu:1443/pp-restapi/v1/resources/psp/43188" + } +] as ReadonlyArray; +const wallet = { + idWallet: 38404 +} as Wallet; + +describe("Test PickPspScreen", () => { + jest.useFakeTimers(); + + it("rendering PickPspScreen, all the required components should be defined", () => { + const { component } = renderComponent(); + + expect(component.queryByTestId("PickPspScreen")).not.toBeNull(); + }); + it("should show the pspList if there is at least one psp", () => { + const { component } = renderComponent(); + + const pspList = component.queryByTestId("pspList"); + + expect(pspList).not.toBeNull(); + }); +}); + +const renderComponent = () => { + const globalState = appReducer(undefined, applicationChangeState("active")); + + const mockStore = configureMockStore(); + const store: ReturnType = mockStore({ + ...globalState + } as GlobalState); + + return { + component: renderScreenFakeNavRedux( + PickPspScreen, + ROUTES.PAYMENT_PICK_PSP, + { + rptId, + initialAmount, + verifica, + idPayment, + psps, + wallet + }, + store + ), + store + }; +}; From 3b36c839a5e935141f5d89df17016e7985a5e394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Tue, 13 Apr 2021 15:34:11 +0200 Subject: [PATCH 07/10] [#177560087] Code and tree folder improvements --- ts/components/__tests__/PspComponent.test.tsx | 2 +- .../{ => wallet/payment}/PspComponent.tsx | 18 ++++++++--------- ts/screens/wallet/payment/PickPspScreen.tsx | 20 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) rename ts/components/{ => wallet/payment}/PspComponent.tsx (76%) diff --git a/ts/components/__tests__/PspComponent.test.tsx b/ts/components/__tests__/PspComponent.test.tsx index 96162a6758a..610d9bf3bbf 100644 --- a/ts/components/__tests__/PspComponent.test.tsx +++ b/ts/components/__tests__/PspComponent.test.tsx @@ -2,7 +2,7 @@ import { fireEvent, render } from "@testing-library/react-native"; import React from "react"; import { none, some } from "fp-ts/lib/Option"; import { Psp } from "../../types/pagopa"; -import { PspComponent } from "../PspComponent"; +import { PspComponent } from "../wallet/payment/PspComponent"; import * as hooks from "../../features/wallet/onboarding/bancomat/screens/hooks/useImageResize"; const psp: Psp = { diff --git a/ts/components/PspComponent.tsx b/ts/components/wallet/payment/PspComponent.tsx similarity index 76% rename from ts/components/PspComponent.tsx rename to ts/components/wallet/payment/PspComponent.tsx index f36c4ad7dfb..e96e2f039f1 100644 --- a/ts/components/PspComponent.tsx +++ b/ts/components/wallet/payment/PspComponent.tsx @@ -1,13 +1,13 @@ import React, { FC } from "react"; import { ImageStyle, StyleProp, StyleSheet, View, Image } from "react-native"; -import { useImageResize } from "../features/wallet/onboarding/bancomat/screens/hooks/useImageResize"; -import customVariables from "../theme/variables"; -import { Psp } from "../types/pagopa"; -import { formatNumberCentsToAmount } from "../utils/stringBuilder"; -import { Body } from "./core/typography/Body"; -import { H4 } from "./core/typography/H4"; -import TouchableDefaultOpacity from "./TouchableDefaultOpacity"; -import IconFont from "./ui/IconFont"; +import { useImageResize } from "../../../features/wallet/onboarding/bancomat/screens/hooks/useImageResize"; +import customVariables from "../../../theme/variables"; +import { Psp } from "../../../types/pagopa"; +import { formatNumberCentsToAmount } from "../../../utils/stringBuilder"; +import { Body } from "../../core/typography/Body"; +import { H4 } from "../../core/typography/H4"; +import TouchableDefaultOpacity from "../../TouchableDefaultOpacity"; +import IconFont from "../../ui/IconFont"; const ICON_SIZE = 24; const IMAGE_WIDTH = 100; @@ -55,7 +55,7 @@ export const PspComponent: FC = ({ psp, onPress }) => { testID={`psp-${psp.id}`} > - {psp.logoPSP && imageStyle ? ( + {imageStyle ? ( & OwnProps; const styles = StyleSheet.create({ - line1: { + header: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" @@ -77,7 +77,7 @@ class PickPspScreen extends React.Component { private headerItem = ( - +
{I18n.t("wallet.pickPsp.provider")}
@@ -131,14 +131,14 @@ class PickPspScreen extends React.Component { ListHeaderComponent={this.headerItem} ListFooterComponent={() => } /> +
- ); } From 25cb7e2e942c11c35f1113ab93a77304ba12508a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Mon, 19 Apr 2021 17:25:04 +0200 Subject: [PATCH 08/10] [#177560087] Added loading error component --- ts/screens/wallet/payment/PickPspScreen.tsx | 97 ++++++++++++--------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index e4517d3a93a..17ac319acc3 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -9,7 +9,6 @@ import { PaymentRequestsGetResponse } from "../../../../definitions/backend/Paym import { H5 } from "../../../components/core/typography/H5"; import { H4 } from "../../../components/core/typography/H4"; import { withLightModalContext } from "../../../components/helpers/withLightModalContext"; -import { withLoadingSpinner } from "../../../components/helpers/withLoadingSpinner"; import ItemSeparatorComponent from "../../../components/ItemSeparatorComponent"; import BaseScreenComponent, { ContextualHelpPropsMarkdown @@ -29,6 +28,7 @@ import { navigateBack } from "../../../store/actions/navigation"; import { IOStyles } from "../../../components/core/variables/IOStyles"; import { PspComponent } from "../../../components/wallet/payment/PspComponent"; import { cancelButtonProps } from "../../../features/bonus/bonusVacanze/components/buttons/ButtonConfigurations"; +import { LoadingErrorComponent } from "../../../features/bonus/bonusVacanze/components/loadingErrorScreen/LoadingErrorComponent"; import { dispatchUpdatePspForWalletAndConfirm } from "./common"; type NavigationParams = Readonly<{ @@ -100,45 +100,61 @@ class PickPspScreen extends React.Component { contextualHelpMarkdown={contextualHelpMarkdown} faqCategories={["payment"]} > - - - -

{I18n.t("wallet.pickPsp.title")}

- -

- {I18n.t("wallet.pickPsp.info")} -

-

- {I18n.t("wallet.pickPsp.info2")} -

{` ${I18n.t( - "wallet.pickPsp.info2Bold" - )}`}

- -
- - } - removeClippedSubviews={false} - data={availablePsps} - keyExtractor={item => item.id.toString()} - renderItem={({ item }) => ( - this.props.pickPsp(item.id, this.props.allPsps)} - /> - )} - ListHeaderComponent={this.headerItem} - ListFooterComponent={() => } + {this.props.isLoading || this.props.hasError ? ( + { + const idWallet = this.props.navigation + .getParam("wallet") + .idWallet.toString(); + const idPayment = this.props.navigation.getParam("idPayment"); + this.props.loadAllPsp(idWallet, idPayment); + }} + loadingCaption={I18n.t("wallet.pickPsp.loadingPsps")} /> - -
+ ) : ( + + + +

{I18n.t("wallet.pickPsp.title")}

+ +

+ {I18n.t("wallet.pickPsp.info")} +

+

+ {I18n.t("wallet.pickPsp.info2")} +

{` ${I18n.t( + "wallet.pickPsp.info2Bold" + )}`}

+ +
+ + } + removeClippedSubviews={false} + data={availablePsps} + keyExtractor={item => item.id.toString()} + renderItem={({ item }) => ( + + this.props.pickPsp(item.id, this.props.allPsps) + } + /> + )} + ListHeaderComponent={this.headerItem} + ListFooterComponent={() => } + /> + +
+ )} ); } @@ -149,6 +165,7 @@ const mapStateToProps = (state: GlobalState) => { return { isLoading: pot.isLoading(state.wallet.wallets.walletById) || pot.isLoading(psps), + hasError: pot.isError(state.wallet.wallets.walletById) || pot.isError(psps), allPsps: pot.getOrElse(psps, []) }; }; @@ -180,4 +197,4 @@ const mapDispatchToProps = (dispatch: Dispatch, props: OwnProps) => ({ export default connect( mapStateToProps, mapDispatchToProps -)(withLightModalContext(withLoadingSpinner(PickPspScreen))); +)(withLightModalContext(PickPspScreen)); From b8217e165413bf5c1c18106ca376af80f9fd164b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Mon, 19 Apr 2021 17:34:20 +0200 Subject: [PATCH 09/10] [#177560087] Solved eslint error --- ts/screens/wallet/payment/PickPspScreen.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ts/screens/wallet/payment/PickPspScreen.tsx b/ts/screens/wallet/payment/PickPspScreen.tsx index 17ac319acc3..32e2641ef18 100644 --- a/ts/screens/wallet/payment/PickPspScreen.tsx +++ b/ts/screens/wallet/payment/PickPspScreen.tsx @@ -104,11 +104,10 @@ class PickPspScreen extends React.Component { { - const idWallet = this.props.navigation - .getParam("wallet") - .idWallet.toString(); - const idPayment = this.props.navigation.getParam("idPayment"); - this.props.loadAllPsp(idWallet, idPayment); + this.props.loadAllPsp( + this.props.navigation.getParam("wallet").idWallet.toString(), + this.props.navigation.getParam("idPayment") + ); }} loadingCaption={I18n.t("wallet.pickPsp.loadingPsps")} /> From b57e37d5ad72b4d0864853cbdde6d69ede0d8094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Favar=C3=B2?= Date: Tue, 20 Apr 2021 09:53:33 +0200 Subject: [PATCH 10/10] [#177560087] Added translations --- locales/en/index.yml | 1 + locales/it/index.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/locales/en/index.yml b/locales/en/index.yml index 72dbdba3847..174c19290f7 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1035,6 +1035,7 @@ wallet: info2Bold: compatible with your method, even if you are not their client. provider: Provider maxFee: Maximum fee + loadingPsps: Loading providers in progress... onUpdateWalletPspFailure: Operation failed, please retry contextualHelpTitle: Select a provider contextualHelpContent: !include pick_psp.md diff --git a/locales/it/index.yml b/locales/it/index.yml index 156ee0b64ee..28c71eb57e0 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1061,6 +1061,7 @@ wallet: info2Bold: compatibili con il tuo metodo, anche se non sei loro cliente. provider: Gestore maxFee: Costo di transazione + loadingPsps: Caricamento gestori in corso... onUpdateWalletPspFailure: Operazione fallita, riprova contextualHelpTitle: Scelta del gestore contextualHelpContent: !include pick_psp.md