diff --git a/ts/features/design-system/core/DSCards.tsx b/ts/features/design-system/core/DSCards.tsx
index 9e4b1991c35..e82163501f0 100644
--- a/ts/features/design-system/core/DSCards.tsx
+++ b/ts/features/design-system/core/DSCards.tsx
@@ -32,13 +32,13 @@ const cardsDataForCarousel: PaymentCardsCarouselProps = {
cards: [
{
hpan: "9999",
- isError: false,
+ expireDate: new Date(2021, 10),
brand: "maestro",
onPress
},
{
holderEmail: "test@test.it",
- isError: true,
+ expireDate: new Date(2021, 10),
onPress
},
{
@@ -52,7 +52,7 @@ const cardsDataForCarousel: PaymentCardsCarouselProps = {
},
{
hpan: "9999",
- isError: true,
+ expireDate: new Date(2021, 10),
onPress
},
{
@@ -146,7 +146,11 @@ export const DSCards = () => (
-
+
@@ -163,7 +167,7 @@ export const DSCards = () => (
brand="pagoBancomat"
bankName="Intesa San Paolo"
onPress={onPress}
- isError
+ expireDate={new Date(2021, 10)}
/>
@@ -177,7 +181,7 @@ export const DSCards = () => (
@@ -193,7 +197,7 @@ export const DSCards = () => (
bankName="Intesa San Paolo"
brand="maestro"
onPress={onPress}
- isError
+ expireDate={new Date(2021, 10)}
/>
@@ -209,7 +213,7 @@ export const DSCards = () => (
holderName="Anna Verdi"
holderPhone="+39 340 *** **62"
onPress={onPress}
- isError
+ expireDate={new Date(2021, 10)}
/>
diff --git a/ts/features/payments/common/components/PaymentCardSmall.tsx b/ts/features/payments/common/components/PaymentCardSmall.tsx
index 2bacc3c953e..6e8d383ee5b 100644
--- a/ts/features/payments/common/components/PaymentCardSmall.tsx
+++ b/ts/features/payments/common/components/PaymentCardSmall.tsx
@@ -5,11 +5,14 @@ import {
Icon,
VSpacer
} from "@pagopa/io-app-design-system";
+import * as O from "fp-ts/lib/Option";
+import { pipe } from "fp-ts/lib/function";
import * as React from "react";
import { StyleSheet, View } from "react-native";
import Placeholder from "rn-placeholder";
import { LogoPaymentWithFallback } from "../../../../components/ui/utils/components/LogoPaymentWithFallback";
import { WithTestID } from "../../../../types/WithTestID";
+import { isExpiredDate } from "../../../../utils/dates";
import { PaymentCardProps } from "./PaymentCard";
import { PaymentCardPressableBase } from "./PaymentCardPressableBase";
@@ -17,7 +20,6 @@ export type PaymentCardSmallProps = WithTestID<
PaymentCardProps & {
bankName?: string;
onPress?: () => void;
- isError?: boolean;
accessibilityLabel?: string;
}
>;
@@ -25,7 +27,6 @@ export type PaymentCardSmallProps = WithTestID<
const PaymentCardSmall = ({
testID,
onPress,
- isError,
accessibilityLabel,
...props
}: PaymentCardSmallProps) => {
@@ -61,16 +62,26 @@ const PaymentCardSmall = ({
return props.brand;
}, [props]);
+ const isExpired = pipe(
+ props.expireDate,
+ O.fromNullable,
+ O.chainNullableK(isExpiredDate),
+ O.getOrElse(() => false)
+ );
+
return (
-
+
- {isError && (
+ {isExpired && (
{labelText}
diff --git a/ts/features/payments/common/components/__tests__/PaymentCardSmall.test.tsx b/ts/features/payments/common/components/__tests__/PaymentCardSmall.test.tsx
index a1e3e481579..084820b5dc1 100644
--- a/ts/features/payments/common/components/__tests__/PaymentCardSmall.test.tsx
+++ b/ts/features/payments/common/components/__tests__/PaymentCardSmall.test.tsx
@@ -44,9 +44,9 @@ describe("PaymentCardSmall", () => {
const { queryByText, queryByTestId } = renderCard({
hpan: "9900",
brand: "maestro",
+ expireDate: new Date(2023, 10),
onPress: () => undefined,
- testID,
- isError: true
+ testID
});
expect(queryByText("•••• 9900")).not.toBeNull();
expect(queryByTestId(`${testID}-errorIcon`)).not.toBeNull();
diff --git a/ts/features/payments/common/components/__tests__/__snapshots__/PaymentCardSmall.test.tsx.snap b/ts/features/payments/common/components/__tests__/__snapshots__/PaymentCardSmall.test.tsx.snap
index 0d45a3982e5..d220816565a 100644
--- a/ts/features/payments/common/components/__tests__/__snapshots__/PaymentCardSmall.test.tsx.snap
+++ b/ts/features/payments/common/components/__tests__/__snapshots__/PaymentCardSmall.test.tsx.snap
@@ -360,7 +360,7 @@ exports[`PaymentCardSmall should match the snapshot 1`] = `
"padding": 16,
"width": 127,
},
- undefined,
+ false,
]
}
testID="PaymentCardSmallTestID"
diff --git a/ts/features/payments/common/utils/index.ts b/ts/features/payments/common/utils/index.ts
index 61d88efd94e..15a353f18b9 100644
--- a/ts/features/payments/common/utils/index.ts
+++ b/ts/features/payments/common/utils/index.ts
@@ -11,10 +11,11 @@ import { Bundle } from "../../../../../definitions/pagopa/ecommerce/Bundle";
import { WalletApplicationStatusEnum } from "../../../../../definitions/pagopa/walletv3/WalletApplicationStatus";
import { WalletInfo } from "../../../../../definitions/pagopa/walletv3/WalletInfo";
import { PaymentSupportStatus } from "../../../../types/paymentMethodCapabilities";
-import { isExpiredDate } from "../../../../utils/dates";
+import { getDateFromExpiryDate, isExpiredDate } from "../../../../utils/dates";
import { findFirstCaseInsensitive } from "../../../../utils/object";
import { WalletPaymentPspSortType } from "../../checkout/types";
import { UIWalletInfoDetails } from "../types/UIWalletInfoDetails";
+import { PaymentCardProps } from "../components/PaymentCard";
/**
* A simple function to get the corresponding translated badge text,
@@ -49,7 +50,7 @@ export const isPaymentMethodExpired = (
): boolean =>
pipe(
details?.expiryDate,
- O.fromNullable,
+ O.chainNullableK(getDateFromExpiryDate),
O.map(isExpiredDate),
O.getOrElse(() => false)
);
@@ -146,3 +147,18 @@ export const getSortedPspList = (
return _.orderBy(pspList, ["onUs", "taxPayerFee"]);
}
};
+
+export const getPaymentCardPropsFromWalletInfo = (
+ wallet: WalletInfo
+): PaymentCardProps => {
+ const details = wallet.details as UIWalletInfoDetails;
+
+ return {
+ hpan: details.lastFourDigits,
+ abiCode: "", // TODO IOBP-622 refactor payment card
+ brand: details.brand,
+ expireDate: getDateFromExpiryDate(details.expiryDate),
+ holderEmail: details.maskedEmail,
+ holderPhone: details.maskedNumber
+ };
+};
diff --git a/ts/features/payments/details/screens/PaymentsMethodDetailsScreen.tsx b/ts/features/payments/details/screens/PaymentsMethodDetailsScreen.tsx
index ef2b65f0327..73805d65f77 100644
--- a/ts/features/payments/details/screens/PaymentsMethodDetailsScreen.tsx
+++ b/ts/features/payments/details/screens/PaymentsMethodDetailsScreen.tsx
@@ -2,15 +2,13 @@ import { VSpacer } from "@pagopa/io-app-design-system";
import * as pot from "@pagopa/ts-commons/lib/pot";
import { RouteProp, useRoute } from "@react-navigation/native";
import * as React from "react";
-import { WalletInfo } from "../../../../../definitions/pagopa/walletv3/WalletInfo";
import { useIODispatch, useIOSelector } from "../../../../store/hooks";
import { isIdPayEnabledSelector } from "../../../../store/reducers/backendStatus";
-import { getDateFromExpiryDate } from "../../../../utils/dates";
import { capitalize } from "../../../../utils/strings";
import { idPayInitiativesFromInstrumentGet } from "../../../idpay/wallet/store/actions";
import { idPayAreInitiativesFromInstrumentLoadingSelector } from "../../../idpay/wallet/store/reducers";
-import { PaymentCardProps } from "../../common/components/PaymentCard";
import { UIWalletInfoDetails } from "../../common/types/UIWalletInfoDetails";
+import { getPaymentCardPropsFromWalletInfo } from "../../common/utils";
import { PaymentsMethodDetailsBaseScreenComponent } from "../components/PaymentsMethodDetailsBaseScreenComponent";
import { PaymentsMethodDetailsDeleteButton } from "../components/PaymentsMethodDetailsDeleteButton";
import { PaymentsMethodDetailsErrorContent } from "../components/PaymentsMethodDetailsErrorContent";
@@ -66,7 +64,7 @@ const PaymentsMethodDetailsScreen = () => {
if (pot.isSome(walletDetailsPot) && !isLoading) {
const paymentMethod = walletDetailsPot.value;
- const cardProps = getPaymentCardPropsFromWallet(paymentMethod);
+ const cardProps = getPaymentCardPropsFromWalletInfo(paymentMethod);
const headerTitle = getCardHeaderTitle(paymentMethod.details);
return (
@@ -95,19 +93,4 @@ const getCardHeaderTitle = (details?: UIWalletInfoDetails) => {
return "";
};
-const getPaymentCardPropsFromWallet = (
- wallet: WalletInfo
-): PaymentCardProps => {
- const details = wallet.details as UIWalletInfoDetails;
-
- return {
- hpan: details.lastFourDigits,
- abiCode: details.abi,
- brand: details.brand,
- expireDate: getDateFromExpiryDate(details.expiryDate),
- holderEmail: details.maskedEmail,
- holderPhone: details.maskedNumber
- };
-};
-
export default PaymentsMethodDetailsScreen;
diff --git a/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx b/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx
index 46939d79d15..95a57ee0a76 100644
--- a/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx
+++ b/ts/features/payments/home/components/PaymentsHomeUserMethodsList.tsx
@@ -13,7 +13,7 @@ import I18n from "../../../../i18n";
import { useIONavigation } from "../../../../navigation/params/AppParamsList";
import { useIODispatch, useIOSelector } from "../../../../store/hooks";
import { PaymentCardSmallProps } from "../../common/components/PaymentCardSmall";
-import { UIWalletInfoDetails } from "../../common/types/UIWalletInfoDetails";
+import { getPaymentCardPropsFromWalletInfo } from "../../common/utils";
import { PaymentsMethodDetailsRoutes } from "../../details/navigation/routes";
import { PaymentsOnboardingRoutes } from "../../onboarding/navigation/routes";
import { getPaymentsWalletUserMethods } from "../../wallet/store/actions";
@@ -69,19 +69,10 @@ const PaymentsHomeUserMethodsList = ({ enforcedLoadingState }: Props) => {
};
const userMethods = paymentMethods.map(
- (method: WalletInfo): PaymentCardSmallProps => {
- const details = method.details as UIWalletInfoDetails;
-
- return {
- onPress: handleOnMethodPress(method.walletId),
- abiCode: details.abi,
- brand: details.brand,
- bankName: details.bankName,
- holderEmail: details.maskedEmail,
- holderPhone: details.maskedNumber,
- hpan: details.lastFourDigits
- };
- }
+ (method: WalletInfo): PaymentCardSmallProps => ({
+ ...getPaymentCardPropsFromWalletInfo(method),
+ onPress: handleOnMethodPress(method.walletId)
+ })
);
if (!isLoading && isEmpty) {
diff --git a/ts/features/payments/home/components/__tests__/PaymentCardsCarousel.test.tsx b/ts/features/payments/home/components/__tests__/PaymentCardsCarousel.test.tsx
index 44869aaddd3..4ecac09268c 100644
--- a/ts/features/payments/home/components/__tests__/PaymentCardsCarousel.test.tsx
+++ b/ts/features/payments/home/components/__tests__/PaymentCardsCarousel.test.tsx
@@ -17,14 +17,13 @@ const cardsDataForCarousel: PaymentCardsCarouselProps = {
cards: [
{
hpan: "9900",
- isError: false,
brand: "maestro",
onPress,
testID: "card-1"
},
{
holderEmail: "test@test.it",
- isError: true,
+ expireDate: new Date(2023, 10),
onPress,
testID: "card-2"
},
diff --git a/ts/utils/__tests__/dates.test.ts b/ts/utils/__tests__/dates.test.ts
index 2d44f9b2a0f..14d78bb135a 100644
--- a/ts/utils/__tests__/dates.test.ts
+++ b/ts/utils/__tests__/dates.test.ts
@@ -1,7 +1,12 @@
-import { getMonth, getYear } from "date-fns";
+import { format, getMonth, getYear } from "date-fns";
import * as E from "fp-ts/lib/Either";
import MockDate from "mockdate";
-import { getExpireStatus, isExpired } from "../dates";
+import {
+ getDateFromExpiryDate,
+ getExpireStatus,
+ isExpired,
+ isExpiredDate
+} from "../dates";
describe("getExpireStatus", () => {
it("should be VALID", () => {
@@ -73,3 +78,38 @@ describe("getExpireStatus", () => {
).toEqual(E.right(false));
});
});
+
+describe("isExpiredDate", () => {
+ it("should mark the card as valid, not expired", () => {
+ const today = new Date();
+ expect(isExpiredDate(today)).toEqual(false);
+ });
+
+ it("should mark the card as expired, not valid", () => {
+ const today = new Date();
+ expect(
+ isExpiredDate(new Date(today.getFullYear(), today.getMonth() - 1))
+ ).toEqual(true);
+ });
+});
+
+describe("getDateFromExpiryDate", () => {
+ it("should return undefined is invalid input", () => {
+ const date = getDateFromExpiryDate("invalid");
+ expect(date).toBeUndefined();
+ });
+
+ it("should mark the card as valid, not expired", () => {
+ const today = new Date();
+ const date = getDateFromExpiryDate(format(today, "YYYYMM"));
+ expect(isExpiredDate(date!)).toEqual(false);
+ });
+
+ it("should mark the card as expired, not valid", () => {
+ const today = new Date();
+ const date = getDateFromExpiryDate(
+ format(new Date(today.getFullYear(), today.getMonth() - 1), "YYYYMM")
+ );
+ expect(isExpiredDate(date!)).toEqual(true);
+ });
+});
diff --git a/ts/utils/dates.ts b/ts/utils/dates.ts
index faba844cd94..ac7d69af32b 100644
--- a/ts/utils/dates.ts
+++ b/ts/utils/dates.ts
@@ -227,16 +227,13 @@ export const isExpired = (
};
/**
- * This function returns true or false is the provided expiryDate in format "YYYYMM" is expired or not
+ * This function returns true or false is the provided expiryDate is expired or not
* @param expiryDate
*/
-export const isExpiredDate = (expiryDate: string): boolean => {
- const year = +expiryDate.slice(0, 4);
- const month = +expiryDate.slice(4, 6);
+export const isExpiredDate = (expiryDate: Date): boolean => {
const now = new Date();
- const nowYearMonth = new Date(now.getFullYear(), now.getMonth() + 1);
- const cardExpirationDate = new Date(year, month);
- return nowYearMonth > cardExpirationDate;
+ const nowYearMonth = new Date(now.getFullYear(), now.getMonth());
+ return nowYearMonth > expiryDate;
};
/**
@@ -329,7 +326,8 @@ export const getDateFromExpiryDate = (expiryDate: string): Date | undefined => {
try {
const year = +expiryDate.slice(0, 4);
const month = +expiryDate.slice(4, 6);
- return new Date(year, month - 1);
+ const date = new Date(year, month - 1);
+ return isNaN(date.getDate()) ? undefined : date;
} catch {
return undefined;
}