diff --git a/ts/features/messages/components/Home/DS/MessageListItem.tsx b/ts/features/messages/components/Home/DS/MessageListItem.tsx
index f2b1249452f..cdd616093c1 100644
--- a/ts/features/messages/components/Home/DS/MessageListItem.tsx
+++ b/ts/features/messages/components/Home/DS/MessageListItem.tsx
@@ -49,6 +49,7 @@ const styles = StyleSheet.create({
type MessageListItemProps = WithTestID<{
accessibilityLabel: string;
badgeText?: string;
+ badgeVariant?: "legalMessage" | "success";
doubleAvatar?: boolean;
formattedDate: string;
isRead: boolean;
@@ -80,6 +81,7 @@ const BadgeComponent = ({ color, width = 14 }: BadgeComponentProps) => (
export const MessageListItem = ({
accessibilityLabel,
badgeText,
+ badgeVariant,
doubleAvatar,
formattedDate,
isRead,
@@ -144,11 +146,15 @@ export const MessageListItem = ({
)}
- {badgeText && (
+ {badgeText && badgeVariant && (
-
-
-
+
+ {badgeVariant === "legalMessage" && (
+ <>
+
+
+ >
+ )}
)}
diff --git a/ts/features/messages/components/Home/WrappedMessageListItem.tsx b/ts/features/messages/components/Home/WrappedMessageListItem.tsx
index 8f980a63eb3..9572dfaab88 100644
--- a/ts/features/messages/components/Home/WrappedMessageListItem.tsx
+++ b/ts/features/messages/components/Home/WrappedMessageListItem.tsx
@@ -7,6 +7,8 @@ import { convertDateToWordDistance } from "../../utils/convertDateToWordDistance
import { useIONavigation } from "../../../../navigation/params/AppParamsList";
import { MESSAGES_ROUTES } from "../../navigation/routes";
import { logoForService } from "../../../services/home/utils";
+import { useIOSelector } from "../../../../store/hooks";
+import { isPaymentMessageWithPaidNoticeSelector } from "../../store/reducers/allPaginated";
import { accessibilityLabelForMessageItem } from "./homeUtils";
import { MessageListItem } from "./DS/MessageListItem";
@@ -23,6 +25,10 @@ export const WrappedMessageListItem = ({
const serviceId = message.serviceId;
const organizationFiscalCode = message.organizationFiscalCode;
+ const isPaymentMessageWithPaidNotice = useIOSelector(state =>
+ isPaymentMessageWithPaidNoticeSelector(state, message.category)
+ );
+
const messageCategoryTag = message.category.tag;
const doubleAvatar = messageCategoryTag === PaymentTagEnum.PAYMENT;
const serviceLogoUriSources = useMemo(
@@ -42,6 +48,14 @@ export const WrappedMessageListItem = ({
const badgeText =
messageCategoryTag === SENDTagEnum.PN
? I18n.t("features.pn.details.badge.legalValue")
+ : isPaymentMessageWithPaidNotice
+ ? I18n.t("messages.badge.paid")
+ : undefined;
+ const badgeVariant =
+ messageCategoryTag === SENDTagEnum.PN
+ ? "legalMessage"
+ : isPaymentMessageWithPaidNotice
+ ? "success"
: undefined;
const accessibilityLabel = useMemo(
() => accessibilityLabelForMessageItem(message),
@@ -65,16 +79,17 @@ export const WrappedMessageListItem = ({
return (
undefined}
onPress={onPressCallback}
- serviceLogos={serviceLogoUriSources}
- badgeText={badgeText}
- isRead={isRead}
organizationName={organizationName}
- formattedDate={messageDate}
+ serviceLogos={serviceLogoUriSources}
+ serviceName={serviceName}
testID={`wrapped_message_list_item_${index}`}
/>
);
diff --git a/ts/features/messages/components/Home/__tests__/WrappedMessageListItem.test.tsx b/ts/features/messages/components/Home/__tests__/WrappedMessageListItem.test.tsx
index b5374551750..0c137d666fa 100644
--- a/ts/features/messages/components/Home/__tests__/WrappedMessageListItem.test.tsx
+++ b/ts/features/messages/components/Home/__tests__/WrappedMessageListItem.test.tsx
@@ -12,6 +12,7 @@ import { TagEnum as SENDTagEnum } from "../../../../../../definitions/backend/Me
import { TagEnum as PaymentTagEnum } from "../../../../../../definitions/backend/MessageCategoryPayment";
import { WrappedMessageListItem } from "../WrappedMessageListItem";
import { TagEnum } from "../../../../../../definitions/backend/MessageCategoryBase";
+import { GlobalState } from "../../../../../store/reducers/types";
const mockNavigate = jest.fn();
jest.mock("@react-navigation/native", () => ({
@@ -38,14 +39,36 @@ describe("WrappedMessageListItem", () => {
const component = renderComponent(message);
expect(component.toJSON()).toMatchSnapshot();
});
- it("should match snapshot, not from SEND, contains payment, unread message", () => {
- const message = messageGenerator(true, false, false);
- const component = renderComponent(message);
+ it("should match snapshot, not from SEND, contains unpaid payment, unread message", () => {
+ const message = messageGenerator(
+ true,
+ false,
+ false,
+ "00123456789001122334455667788"
+ );
+ const component = renderComponent(message, "00987654321009922994499667799");
expect(component.toJSON()).toMatchSnapshot();
});
- it("should match snapshot, not from SEND, contains payment, read message", () => {
- const message = messageGenerator(true, false, true);
- const component = renderComponent(message);
+ it("should match snapshot, not from SEND, contains unpaid payment, read message", () => {
+ const message = messageGenerator(
+ true,
+ false,
+ true,
+ "00123456789001122334455667788"
+ );
+ const component = renderComponent(message, "00987654321009922994499667799");
+ expect(component.toJSON()).toMatchSnapshot();
+ });
+ it("should match snapshot, not from SEND, contains paid payment, unread message", () => {
+ const paymentId = "00123456789001122334455667788";
+ const message = messageGenerator(true, false, false, paymentId);
+ const component = renderComponent(message, paymentId);
+ expect(component.toJSON()).toMatchSnapshot();
+ });
+ it("should match snapshot, not from SEND, contains paid payment, read message", () => {
+ const paymentId = "00123456789001122334455667788";
+ const message = messageGenerator(true, false, true, paymentId);
+ const component = renderComponent(message, paymentId);
expect(component.toJSON()).toMatchSnapshot();
});
it("should match snapshot, from SEND, unread message", () => {
@@ -78,7 +101,8 @@ describe("WrappedMessageListItem", () => {
const messageGenerator = (
hasPayment: boolean,
isFromSend: boolean,
- isRead: boolean
+ isRead: boolean,
+ rptId: string | undefined = undefined
): UIMessage =>
({
createdAt: new Date(1990, 0, 2, 3, 4),
@@ -93,17 +117,33 @@ const messageGenerator = (
? SENDTagEnum.PN
: hasPayment
? PaymentTagEnum.PAYMENT
- : TagEnum.GENERIC
+ : TagEnum.GENERIC,
+ rptId
}
} as UIMessage);
-const renderComponent = (message: UIMessage) => {
+const renderComponent = (
+ message: UIMessage,
+ paymentId: string = "09173824650012345678991378264"
+) => {
const initialState = appReducer(undefined, applicationChangeState("active"));
const designSystemState = appReducer(
initialState,
preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true })
);
- const store = createStore(appReducer, designSystemState as any);
+ const stateWithPayment = {
+ ...designSystemState,
+ entities: {
+ ...designSystemState.entities,
+ paymentByRptId: {
+ ...designSystemState.entities.paymentByRptId,
+ [paymentId]: {
+ kind: "COMPLETED"
+ }
+ }
+ }
+ } as GlobalState;
+ const store = createStore(appReducer, stateWithPayment as any);
return renderScreenWithNavigationStoreContext(
() => ,
MESSAGES_ROUTES.MESSAGES_HOME,
diff --git a/ts/features/messages/components/Home/__tests__/__snapshots__/WrappedMessageListItem.test.tsx.snap b/ts/features/messages/components/Home/__tests__/__snapshots__/WrappedMessageListItem.test.tsx.snap
index c8076104231..a172e8073ae 100644
--- a/ts/features/messages/components/Home/__tests__/__snapshots__/WrappedMessageListItem.test.tsx.snap
+++ b/ts/features/messages/components/Home/__tests__/__snapshots__/WrappedMessageListItem.test.tsx.snap
@@ -268,7 +268,7 @@ exports[`WrappedMessageListItem should match snapshot, from SEND, read message 1
`;
-exports[`WrappedMessageListItem should match snapshot, not from SEND, contains payment, read message 1`] = `
+exports[`WrappedMessageListItem should match snapshot, not from SEND, contains paid payment, read message 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MESSAGES_HOME
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Organization name
+
+
+ 01/02/90
+
+
+
+
+
+ Service name
+
+
+ •
+
+
+ Message title
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Paid
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`WrappedMessageListItem should match snapshot, not from SEND, contains paid payment, unread message 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MESSAGES_HOME
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Organization name
+
+
+ 01/02/90
+
+
+
+
+
+ Service name
+
+
+ •
+
+
+ Message title
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Paid
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`WrappedMessageListItem should match snapshot, not from SEND, contains unpaid payment, read message 1`] = `
`;
-exports[`WrappedMessageListItem should match snapshot, not from SEND, contains payment, unread message 1`] = `
+exports[`WrappedMessageListItem should match snapshot, not from SEND, contains unpaid payment, unread message 1`] = `
- isNoticePaidSelector(state, category)
+ isPaymentMessageWithPaidNoticeSelector(state, category)
);
const maybeItemBadge = getMaybeItemBadge({
paid: hasPaidBadge,
diff --git a/ts/features/messages/screens/legacy/LegacyMessageDetailScreen.tsx b/ts/features/messages/screens/legacy/LegacyMessageDetailScreen.tsx
index 4aab6057158..9d37515e327 100644
--- a/ts/features/messages/screens/legacy/LegacyMessageDetailScreen.tsx
+++ b/ts/features/messages/screens/legacy/LegacyMessageDetailScreen.tsx
@@ -20,7 +20,6 @@ import BaseScreenComponent, {
ContextualHelpPropsMarkdown
} from "../../../../components/screens/BaseScreenComponent";
import I18n from "../../../../i18n";
-import { isNoticePaidSelector } from "../../../../store/reducers/entities/payments";
import {
loadMessageDetails,
resetGetMessageDataAction
@@ -40,6 +39,7 @@ import {
import { toUIService } from "../../../../store/reducers/entities/services/transformers";
import { useOnFirstRender } from "../../../../utils/hooks/useOnFirstRender";
import { useIODispatch, useIOSelector } from "../../../../store/hooks";
+import { isPaymentMessageWithPaidNoticeSelector } from "../../store/reducers/allPaginated";
const styles = StyleSheet.create({
notFullStateContainer: {
@@ -100,7 +100,9 @@ const LegacyMessageDetailScreen = () => {
serviceMetadataByIdSelector(state, serviceId)
);
const hasPaidBadge: boolean = useIOSelector(state =>
- message ? isNoticePaidSelector(state, message.category) : false
+ message
+ ? isPaymentMessageWithPaidNoticeSelector(state, message.category)
+ : false
);
useOnFirstRender(() => {
diff --git a/ts/features/messages/store/reducers/__tests__/allPaginated.test.ts b/ts/features/messages/store/reducers/__tests__/allPaginated.test.ts
index ff0a22a7cad..146e7f5d1aa 100644
--- a/ts/features/messages/store/reducers/__tests__/allPaginated.test.ts
+++ b/ts/features/messages/store/reducers/__tests__/allPaginated.test.ts
@@ -36,7 +36,8 @@ import reducer, {
shouldShowFooterListComponentSelector,
LastRequestType,
messagePagePotFromCategorySelector,
- shouldShowRefreshControllOnListSelector
+ shouldShowRefreshControllOnListSelector,
+ isPaymentMessageWithPaidNoticeSelector
} from "../allPaginated";
import { pageSize } from "../../../../../config";
import { UIMessage } from "../../../types";
@@ -46,6 +47,8 @@ import { applicationChangeState } from "../../../../../store/actions/application
import { MessageListCategory } from "../../../types/messageListCategory";
import { emptyMessageArray } from "../../../utils";
import { isSomeLoadingOrSomeUpdating } from "../../../../../utils/pot";
+import { PaymentByRptIdState } from "../../../../../store/reducers/entities/payments";
+import { MessageCategory } from "../../../../../../definitions/backend/MessageCategory";
import { nextPageLoadingWaitMillisecondsGenerator } from "../../../components/Home/homeUtils";
describe("allPaginated reducer", () => {
@@ -1773,6 +1776,128 @@ describe("shouldShowRefreshControllOnListSelector", () => {
);
});
+describe("isPaymentMessageWithPaidNoticeSelector", () => {
+ it("should return 'false' for GENERIC category", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "GENERIC"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'false' for EU_COVID_CERT category", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "EU_COVID_CERT"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'false' for LEGAL_MESSAGE category", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "LEGAL_MESSAGE"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'false' for SEND category", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "PN"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'false' for PAYMENT category, unmatching rptId", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "PAYMENT",
+ rptId: "00123456789001122334455667799"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'false' for PAYMENT category, matching rptId, undefined value", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": undefined
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "PAYMENT",
+ rptId: "00123456789001122334455667799"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(false);
+ });
+ it("should return 'true' for PAYMENT category, matching rptId, 'DUPLICATED' value", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": { kind: "DUPLICATED" }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "PAYMENT",
+ rptId: "00123456789001122334455667788"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(true);
+ });
+ it("should return 'true' for PAYMENT category, matching rptId, 'COMPLETED' value", () => {
+ const state = {
+ entities: {
+ paymentByRptId: {
+ "00123456789001122334455667788": {
+ kind: "COMPLETED",
+ transactionId: undefined
+ }
+ } as PaymentByRptIdState
+ }
+ } as GlobalState;
+ const category = {
+ tag: "PAYMENT",
+ rptId: "00123456789001122334455667788"
+ } as MessageCategory;
+ const isPaid = isPaymentMessageWithPaidNoticeSelector(state, category);
+ expect(isPaid).toBe(true);
+ });
+});
+
const generateAllPaginatedDataStateForCategory = (
category: MessageListCategory,
data: MessagePagePot,
diff --git a/ts/features/messages/store/reducers/allPaginated.ts b/ts/features/messages/store/reducers/allPaginated.ts
index 7e84b7d8abf..89a1ef1b715 100644
--- a/ts/features/messages/store/reducers/allPaginated.ts
+++ b/ts/features/messages/store/reducers/allPaginated.ts
@@ -25,6 +25,9 @@ import { GlobalState } from "../../../../store/reducers/types";
import { UIMessage } from "../../types";
import { foldK, isSomeLoadingOrSomeUpdating } from "../../../../utils/pot";
import { emptyMessageArray } from "../../utils";
+import { MessageCategory } from "../../../../../definitions/backend/MessageCategory";
+import { foldMessageCategoryK } from "../../utils/messageCategory";
+import { paymentsByRptIdSelector } from "../../../../store/reducers/entities/payments";
import { TranslationKeys } from "../../../../../locales/locales";
export type MessagePage = {
@@ -827,6 +830,35 @@ export const messagePagePotFromCategorySelector =
messageCollection => messageCollection.data
);
+/**
+ * This method checks if there is a local record of a processed payment
+ * for the given message category's rptId (ricevuta pagamento telematico).
+ *
+ * Be aware that such record is persisted on the device and it is not synchronized
+ * with server so it is lost upon device change / app folder cleaning / app uninstall.
+ *
+ * @param state Redux global state
+ * @param category The enriched message category, returned by the `GET /messages?enrich_result_data=true` endpoint, that contains the rptId
+ * @returns true if there is a matching paid transaction
+ */
+export const isPaymentMessageWithPaidNoticeSelector = (
+ state: GlobalState,
+ category: MessageCategory
+) =>
+ pipe(
+ category,
+ foldMessageCategoryK(
+ constFalse,
+ paymentCategory =>
+ pipe(
+ state,
+ paymentsByRptIdSelector,
+ paymentRecord => !!paymentRecord[paymentCategory.rptId]
+ ),
+ constFalse
+ )
+ );
+
const messageCollectionFromCategory =
(category: MessageListCategory) => (state: GlobalState) =>
pipe(state.entities.messages.allPaginated, allPaginated =>
diff --git a/ts/features/messages/store/reducers/thirdPartyById.ts b/ts/features/messages/store/reducers/thirdPartyById.ts
index c88aa3d83d4..e68dcbf4721 100644
--- a/ts/features/messages/store/reducers/thirdPartyById.ts
+++ b/ts/features/messages/store/reducers/thirdPartyById.ts
@@ -100,7 +100,7 @@ export const thirdPartyMessageAttachments = (
O.chainNullableK(
thirdPartyMessage => thirdPartyMessage.third_party_message.attachments
),
- O.getOrElse>(() => [])
+ O.getOrElse>(() => RA.empty)
);
export const thirdPartyMessageAttachment =
diff --git a/ts/features/messages/utils/__tests__/messageCategory.test.ts b/ts/features/messages/utils/__tests__/messageCategory.test.ts
new file mode 100644
index 00000000000..d5f7c2a83a9
--- /dev/null
+++ b/ts/features/messages/utils/__tests__/messageCategory.test.ts
@@ -0,0 +1,99 @@
+import { MessageCategory } from "../../../../../definitions/backend/MessageCategory";
+import { foldMessageCategoryK } from "../messageCategory";
+
+describe("foldMessageCategoryK", () => {
+ it("should call 'onGeneral' callback with 'LEGAL_MESSAGE' tag for legal message category", () => {
+ const category = {
+ tag: "LEGAL_MESSAGE"
+ } as MessageCategory;
+ const mockGeneralCategoryFN = jest.fn();
+ const mockPaymentCategoryFN = jest.fn();
+ const mockSendCategoryFN = jest.fn();
+ foldMessageCategoryK(
+ mockGeneralCategoryFN,
+ mockPaymentCategoryFN,
+ mockSendCategoryFN
+ )(category);
+ expect(mockGeneralCategoryFN.mock.calls.length).toBe(1);
+ expect(mockGeneralCategoryFN.mock.calls[0][0]).toStrictEqual(category.tag);
+ expect(mockPaymentCategoryFN.mock.calls.length).toBe(0);
+ expect(mockSendCategoryFN.mock.calls.length).toBe(0);
+ });
+ it("should call 'onGeneral' callback with 'EU_COVID_CERT' tag for green pass category", () => {
+ const category = {
+ tag: "EU_COVID_CERT",
+ rptId: "00123456789001122334455667788"
+ } as MessageCategory;
+ const mockGeneralCategoryFN = jest.fn();
+ const mockPaymentCategoryFN = jest.fn();
+ const mockSendCategoryFN = jest.fn();
+ foldMessageCategoryK(
+ mockGeneralCategoryFN,
+ mockPaymentCategoryFN,
+ mockSendCategoryFN
+ )(category);
+ expect(mockGeneralCategoryFN.mock.calls.length).toBe(1);
+ expect(mockGeneralCategoryFN.mock.calls[0][0]).toStrictEqual(category.tag);
+ expect(mockPaymentCategoryFN.mock.calls.length).toBe(0);
+ expect(mockSendCategoryFN.mock.calls.length).toBe(0);
+ });
+ it("should call 'onGeneral' callback with 'GENERIC' tag for generic category", () => {
+ const category = {
+ tag: "GENERIC"
+ } as MessageCategory;
+ const mockGeneralCategoryFN = jest.fn();
+ const mockPaymentCategoryFN = jest.fn();
+ const mockSendCategoryFN = jest.fn();
+ foldMessageCategoryK(
+ mockGeneralCategoryFN,
+ mockPaymentCategoryFN,
+ mockSendCategoryFN
+ )(category);
+ expect(mockGeneralCategoryFN.mock.calls.length).toBe(1);
+ expect(mockGeneralCategoryFN.mock.calls[0][0]).toStrictEqual(category.tag);
+ expect(mockPaymentCategoryFN.mock.calls.length).toBe(0);
+ expect(mockSendCategoryFN.mock.calls.length).toBe(0);
+ });
+ it("should call 'onPayment' callback with the category instance for payment category", () => {
+ const category = {
+ tag: "PAYMENT"
+ } as MessageCategory;
+ const mockGeneralCategoryFN = jest.fn();
+ const mockPaymentCategoryFN = jest.fn();
+ const mockSendCategoryFN = jest.fn();
+ foldMessageCategoryK(
+ mockGeneralCategoryFN,
+ mockPaymentCategoryFN,
+ mockSendCategoryFN
+ )(category);
+ expect(mockGeneralCategoryFN.mock.calls.length).toBe(0);
+ expect(mockPaymentCategoryFN.mock.calls.length).toBe(1);
+ expect(mockPaymentCategoryFN.mock.calls[0][0]).toStrictEqual(category);
+ expect(mockSendCategoryFN.mock.calls.length).toBe(0);
+ });
+ it("should call 'onSend' callback with the category instance for SEND category", () => {
+ const category = {
+ tag: "PN",
+ id: "1",
+ original_sender: "01J0XCKH2XWRQTS2YBZ2XT3DS5",
+ original_receipt_date: new Date(),
+ has_attachments: true,
+ has_remote_content: true,
+ has_precondition: "ALWAYS",
+ summary: "This is the summary",
+ configuration_id: "01J0XCFED9HC3W5Y1TH80MEN6A"
+ } as MessageCategory;
+ const mockGeneralCategoryFN = jest.fn();
+ const mockPaymentCategoryFN = jest.fn();
+ const mockSendCategoryFN = jest.fn();
+ foldMessageCategoryK(
+ mockGeneralCategoryFN,
+ mockPaymentCategoryFN,
+ mockSendCategoryFN
+ )(category);
+ expect(mockGeneralCategoryFN.mock.calls.length).toBe(0);
+ expect(mockPaymentCategoryFN.mock.calls.length).toBe(0);
+ expect(mockSendCategoryFN.mock.calls.length).toBe(1);
+ expect(mockSendCategoryFN.mock.calls[0][0]).toStrictEqual(category);
+ });
+});
diff --git a/ts/features/messages/utils/messageCategory.ts b/ts/features/messages/utils/messageCategory.ts
new file mode 100644
index 00000000000..bfd17433a78
--- /dev/null
+++ b/ts/features/messages/utils/messageCategory.ts
@@ -0,0 +1,24 @@
+import { MessageCategory } from "../../../../definitions/backend/MessageCategory";
+import { TagEnum } from "../../../../definitions/backend/MessageCategoryBase";
+import { MessageCategoryPN } from "../../../../definitions/backend/MessageCategoryPN";
+import { MessageCategoryPayment } from "../../../../definitions/backend/MessageCategoryPayment";
+
+export const foldMessageCategoryK =
+ (
+ onGeneral: (baseCategoryEnum: TagEnum) => A,
+ onPayment: (category: MessageCategoryPayment) => A,
+ onSend: (category: MessageCategoryPN) => A
+ ) =>
+ (category: MessageCategory) => {
+ switch (category.tag) {
+ case "PAYMENT":
+ return onPayment(category);
+ case "PN":
+ return onSend(category);
+ case "LEGAL_MESSAGE":
+ return onGeneral(TagEnum.LEGAL_MESSAGE);
+ case "EU_COVID_CERT":
+ return onGeneral(TagEnum.EU_COVID_CERT);
+ }
+ return onGeneral(TagEnum.GENERIC);
+ };
diff --git a/ts/store/reducers/entities/payments.ts b/ts/store/reducers/entities/payments.ts
index a43ba870af4..378b2540e0c 100644
--- a/ts/store/reducers/entities/payments.ts
+++ b/ts/store/reducers/entities/payments.ts
@@ -3,16 +3,12 @@
* It only manages SUCCESS actions because all UI state properties (like * loading/error)
* are managed by different global reducers.
*/
-
import { getType } from "typesafe-actions";
import { RptIdFromString } from "@pagopa/io-pagopa-commons/lib/pagopa";
-import { createSelector } from "reselect";
-
import { Action } from "../../actions/types";
import { paymentCompletedSuccess } from "../../actions/wallet/payment";
import { GlobalState } from "../types";
import { differentProfileLoggedIn } from "../../actions/crossSessions";
-import { UIMessage } from "../../../features/messages/types";
export type PaidReason = Readonly<
| {
@@ -69,20 +65,3 @@ export const paymentByRptIdReducer = (
export const paymentsByRptIdSelector = (
state: GlobalState
): PaymentByRptIdState => state.entities.paymentByRptId;
-
-/**
- * Given an rptId as a string, return true if there is a matching paid transaction.
- * TODO: just a placeholder for now, see https://pagopa.atlassian.net/browse/IA-417
- */
-export const isNoticePaidSelector = createSelector(
- [
- paymentsByRptIdSelector,
- (_: GlobalState, category: UIMessage["category"]) => category
- ],
- (paymentByRptId, category) => {
- if (category.tag === "PAYMENT") {
- return !!paymentByRptId[category.rptId];
- }
- return false;
- }
-);