Skip to content

Commit

Permalink
feat: [IOCOM-450,IOCOM-449,IOCOM-508] Bottom sheet for multiple payme…
Browse files Browse the repository at this point in the history
…nts on SEND message details screen (#5153)

⚠️ This PR depends on #5152 ⚠️

## Short description
This PR adds handling of SEND message multiple payments using a bottom
sheet.
![Screenshot 2023-10-23 at 10 18
41](https://github.com/pagopa/io-app/assets/5150343/a671c4ac-81f1-4eca-84a0-68d7714d87f7)

## List of changes proposed in this pull request
- Bottom sheet with Flat List for multiple payments on SEND message
(more than five payments)
- Handling of single payment (no bottom sheet but direct navigation to
the payment)
- Cancellation of PN payment's updates
- Cancellation of PN payments' statuses on global message reload

## How to test
Using the same configurations of the io-dev-api-server in #5152, try the
bottom sheet.

---------

Co-authored-by: Alessandro Dell'Oste <[email protected]>
  • Loading branch information
Vangaorth and adelloste authored Oct 27, 2023
1 parent efc732d commit c5a8e47
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 170 deletions.
2 changes: 1 addition & 1 deletion locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3021,8 +3021,8 @@ features:
paymentSection:
legacyTitle: Avviso di pagamento
title: Avvisi pagoPA
notice: "Alcuni avvisi possono includere i costi di notifica."
morePayments: "Vedi tutti gli avvisi"
bottomSheetTitle: "Quale avviso vuoi pagare?"
attachmentsSection:
title: Allegati
f24Section:
Expand Down
2 changes: 1 addition & 1 deletion locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3021,8 +3021,8 @@ features:
paymentSection:
legacyTitle: Avviso di pagamento
title: "Avvisi pagoPA"
notice: "Alcuni avvisi possono includere i costi di notifica."
morePayments: "Vedi tutti gli avvisi"
bottomSheetTitle: "Quale avviso vuoi pagare?"
attachmentsSection:
title: Allegati
f24Section:
Expand Down
16 changes: 15 additions & 1 deletion ts/features/pn/components/MessageDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useNavigation } from "@react-navigation/native";
import React, { useCallback, createRef, useRef } from "react";
import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import * as RA from "fp-ts/lib/ReadonlyArray";
import * as SEP from "fp-ts/lib/Separated";
import React, { createRef, useCallback } from "react";
import { View } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import {
Expand Down Expand Up @@ -43,6 +43,7 @@ import { PnMessageTimelineCTA } from "./PnMessageTimelineCTA";
import { MessageF24 } from "./MessageF24";
import { MessagePayments } from "./MessagePayments";
import { MessageFooter } from "./MessageFooter";
import { MessagePaymentBottomSheet } from "./MessagePaymentBottomSheet";

type Props = Readonly<{
messageId: UIMessageId;
Expand All @@ -61,6 +62,8 @@ export const MessageDetails = ({
}: Props) => {
const navigation = useNavigation();
const viewRef = createRef<View>();
const presentPaymentsBottomSheetRef = useRef<() => void>();
const dismissPaymentsBottomSheetRef = useRef<() => void>();
const frontendUrl = useIOSelector(pnFrontendUrlSelector);

const partitionedAttachments = pipe(
Expand Down Expand Up @@ -142,6 +145,7 @@ export const MessageDetails = ({
payments={payments}
completedPaymentNoticeCodes={completedPaymentNoticeCodes}
maxVisiblePaymentCount={maxVisiblePaymentCount}
presentPaymentsBottomSheetRef={presentPaymentsBottomSheetRef}
/>

{RA.isNonEmpty(f24List) && (
Expand Down Expand Up @@ -174,11 +178,21 @@ export const MessageDetails = ({
</PnMessageDetailsSection>
</ScrollView>

{payments && (
<MessagePaymentBottomSheet
messageId={messageId}
payments={payments}
presentPaymentsBottomSheetRef={presentPaymentsBottomSheetRef}
dismissPaymentsBottomSheetRef={dismissPaymentsBottomSheetRef}
/>
)}

<MessageFooter
messageId={messageId}
payments={payments}
maxVisiblePaymentCount={maxVisiblePaymentCount}
isCancelled={isCancelled}
presentPaymentsBottomSheetRef={presentPaymentsBottomSheetRef}
/>
</>
);
Expand Down
25 changes: 22 additions & 3 deletions ts/features/pn/components/MessageFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import React from "react";
import React, { MutableRefObject, useCallback } from "react";
import { StyleSheet, View } from "react-native";
import { ButtonSolid, IOStyles } from "@pagopa/io-app-design-system";
import I18n from "i18n-js";
import { useDispatch } from "react-redux";
import { NotificationPaymentInfo } from "../../../../definitions/pn/NotificationPaymentInfo";
import { useIOSelector } from "../../../store/hooks";
import { UIMessageId } from "../../../store/reducers/entities/messages/types";
import { paymentsButtonStateSelector } from "../store/reducers/payments";
import variables from "../../../theme/variables";
import { initializeAndNavigateToWalleForPayment } from "../utils";
import { getRptIdStringFromPayment } from "../utils/rptId";
import { useIOToast } from "../../../components/Toast";

const styles = StyleSheet.create({
container: {
Expand All @@ -21,13 +25,15 @@ type MessageFooterProps = {
payments: ReadonlyArray<NotificationPaymentInfo> | undefined;
maxVisiblePaymentCount: number;
isCancelled: boolean;
presentPaymentsBottomSheetRef: MutableRefObject<(() => void) | undefined>;
};

export const MessageFooter = ({
messageId,
payments,
maxVisiblePaymentCount,
isCancelled
isCancelled,
presentPaymentsBottomSheetRef
}: MessageFooterProps) => {
const buttonState = useIOSelector(state =>
paymentsButtonStateSelector(
Expand All @@ -37,6 +43,19 @@ export const MessageFooter = ({
maxVisiblePaymentCount
)
);
const dispatch = useDispatch();
const toast = useIOToast();
const onFooterPressCallback = useCallback(() => {
if (payments?.length === 1) {
const firstPayment = payments[0];
const paymentId = getRptIdStringFromPayment(firstPayment);
initializeAndNavigateToWalleForPayment(paymentId, dispatch, () =>
toast.error(I18n.t("genericError"))
);
} else {
presentPaymentsBottomSheetRef.current?.();
}
}, [dispatch, payments, presentPaymentsBottomSheetRef, toast]);
if (isCancelled || buttonState === "hidden") {
return null;
}
Expand All @@ -51,7 +70,7 @@ export const MessageFooter = ({
loading={isLoading}
color="primary"
label={I18n.t("wallet.continue")}
onPress={() => undefined}
onPress={onFooterPressCallback}
accessibilityLabel={I18n.t("wallet.continue")}
/>
</View>
Expand Down
130 changes: 0 additions & 130 deletions ts/features/pn/components/MessagePayment.tsx

This file was deleted.

55 changes: 55 additions & 0 deletions ts/features/pn/components/MessagePaymentBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { MutableRefObject } from "react";
import { Dimensions, View } from "react-native";
import I18n from "i18n-js";
import { useDispatch } from "react-redux";
import { NotificationPaymentInfo } from "../../../../definitions/pn/NotificationPaymentInfo";
import { UIMessageId } from "../../../store/reducers/entities/messages/types";
import { useIOBottomSheetModal } from "../../../utils/hooks/bottomSheet";
import { cancelQueuedPaymentUpdates } from "../store/actions";
import { MessagePaymentItem } from "./MessagePaymentItem";

export type MessagePaymentBottomSheetProps = {
messageId: UIMessageId;
payments: ReadonlyArray<NotificationPaymentInfo>;
presentPaymentsBottomSheetRef: MutableRefObject<(() => void) | undefined>;
dismissPaymentsBottomSheetRef: MutableRefObject<(() => void) | undefined>;
};

export const MessagePaymentBottomSheet = ({
messageId,
payments,
presentPaymentsBottomSheetRef,
dismissPaymentsBottomSheetRef
}: MessagePaymentBottomSheetProps) => {
// console.log(`=== Bottom Sheet: re-rendering`);
const dispatch = useDispatch();
const windowHeight = Dimensions.get("window").height;
const snapPoint = (payments.length > 5 ? 0.75 : 0.5) * windowHeight;
// TODO replace with FlatList, check IOCOM-636 for further details
const { present, dismiss, bottomSheet } = useIOBottomSheetModal({
component: (
<>
{payments.map((payment, index) => (
<MessagePaymentItem
index={index}
key={`LI_${index}`}
messageId={messageId}
payment={payment}
noSpaceOnTop={index === 0}
willNavigateToPayment={() => dismiss()}
/>
))}
</>
),
title: I18n.t("features.pn.details.paymentSection.bottomSheetTitle"),
snapPoint: [snapPoint],
footer: <View></View>,
onDismiss: () => dispatch(cancelQueuedPaymentUpdates())
});
// eslint-disable-next-line functional/immutable-data
presentPaymentsBottomSheetRef.current = present;
// eslint-disable-next-line functional/immutable-data
dismissPaymentsBottomSheetRef.current = dismiss;
// console.log(`=== Bottom Sheet: re-rendering`);
return bottomSheet;
};
Loading

0 comments on commit c5a8e47

Please sign in to comment.