diff --git a/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentRecipient.tsx b/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentRecipient.tsx index e80079bde5..b8eeb09d8e 100644 --- a/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentRecipient.tsx +++ b/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentRecipient.tsx @@ -1,4 +1,4 @@ -import React, { Fragment, memo, useEffect, useState } from 'react'; +import React, { memo, useEffect, useState } from 'react'; import { Download } from '@mui/icons-material/'; import { Alert, Box, Button, Link, RadioGroup, Typography } from '@mui/material'; @@ -14,6 +14,7 @@ import { PaymentStatus, PaymentsData, } from '../../models'; +import { PaymentTpp } from '../../models/NotificationDetail'; import { formatEurocentToCurrency } from '../../utility'; import { getLocalizedOrDefaultLabel } from '../../utility/localization.utility'; import { getPaymentCache, setPaymentCache } from '../../utility/paymentCaching.utility'; @@ -26,6 +27,7 @@ const FAQ_NOTIFICATION_CANCELLED_REFUND = '/faq#notifica-pagata-rimborso'; type Props = { payments: PaymentsData; + paymentTpp?: PaymentTpp; isCancelled: boolean; timerF24: number; landingSiteUrl: string; @@ -38,18 +40,21 @@ type Props = { unwrap: () => Promise; }; onPayClick: (noticeCode?: string, creditorTaxId?: string, amount?: number) => void; + onPayTppClick?: (noticeCode?: string, creditorTaxId?: string, retrievalId?: string) => void; handleTrackEvent?: (event: EventPaymentRecipientType, param?: object) => void; handleFetchPaymentsInfo: (payment: Array) => void; }; const NotificationPaymentRecipient: React.FC = ({ payments, + paymentTpp, isCancelled, timerF24, landingSiteUrl, iun, getPaymentAttachmentAction, onPayClick, + onPayTppClick, handleTrackEvent, handleFetchPaymentsInfo, }) => { @@ -137,9 +142,17 @@ const NotificationPaymentRecipient: React.FC = ({ } }; - const handleCheckPaymentSelected = () => { + const handleCheckPaymentSelected = (paymentType: 'default' | 'tpp') => { if (selectedPayment.pagoPa) { setErrorOnPayment(false); + if (paymentType === 'tpp') { + onPayTppClick?.( + selectedPayment?.pagoPa?.noticeCode, + selectedPayment?.pagoPa?.creditorTaxId, + paymentTpp?.retrievalId + ); + return; + } onPayClick( selectedPayment.pagoPa.noticeCode, selectedPayment.pagoPa.creditorTaxId, @@ -233,57 +246,19 @@ const NotificationPaymentRecipient: React.FC = ({ )} {!allPaymentsIsPaid && ( - - - {selectedPayment?.pagoPa?.attachment && ( - - )} - {selectedPayment?.f24 ? ( - - - handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD) - } - handleTrackDownloadF24Success={() => - handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD_SUCCESS) - } - handleTrackDownloadF24Timeout={() => - handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD_TIMEOUT) - } - timerF24={timerF24} - disableDownload={areOtherDowloading} - handleDownload={setAreOtherDowloading} - /> - - ) : null} - + )} )} @@ -323,3 +298,101 @@ const NotificationPaymentRecipient: React.FC = ({ }; export default memo(NotificationPaymentRecipient); + +type PaymentButtonsProps = Pick< + Props, + 'paymentTpp' | 'iun' | 'getPaymentAttachmentAction' | 'timerF24' +> & { + selectedPayment?: PaymentDetails | { pagoPa: null; f24?: null }; + areOtherDowloading: boolean; + errorOnPayment: boolean; + setAreOtherDowloading: (value: boolean) => void; + downloadAttachment: (attachmentName: PaymentAttachmentSName) => void; + handleTrackEventFn: (event: EventPaymentRecipientType, param?: object) => void; + handleCheckPaymentSelected: (paymentType: 'default' | 'tpp') => void; +}; + +const PaymentButtons = ({ + paymentTpp, + iun, + selectedPayment, + timerF24, + areOtherDowloading, + errorOnPayment, + setAreOtherDowloading, + downloadAttachment, + getPaymentAttachmentAction, + handleTrackEventFn, + handleCheckPaymentSelected, +}: PaymentButtonsProps) => { + const hasPaymentTpp = paymentTpp?.iun === iun; + return ( + <> + {hasPaymentTpp && ( + + )} + + {selectedPayment?.pagoPa?.attachment && ( + + )} + {selectedPayment?.f24 && ( + + + handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD) + } + handleTrackDownloadF24Success={() => + handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD_SUCCESS) + } + handleTrackDownloadF24Timeout={() => + handleTrackEventFn(EventPaymentRecipientType.SEND_F24_DOWNLOAD_TIMEOUT) + } + timerF24={timerF24} + disableDownload={areOtherDowloading} + handleDownload={setAreOtherDowloading} + /> + + )} + + ); +}; diff --git a/packages/pn-commons/src/components/NotificationDetail/__test__/NotificationPaymentRecipient.test.tsx b/packages/pn-commons/src/components/NotificationDetail/__test__/NotificationPaymentRecipient.test.tsx index 2ac828b8bd..402b0319c2 100644 --- a/packages/pn-commons/src/components/NotificationDetail/__test__/NotificationPaymentRecipient.test.tsx +++ b/packages/pn-commons/src/components/NotificationDetail/__test__/NotificationPaymentRecipient.test.tsx @@ -432,4 +432,52 @@ describe('NotificationPaymentRecipient Component', () => { fireEvent.click(f24ButtonToCheck); expect(getPaymentAttachmentActionMk).toBeCalledTimes(1); }); + + it('should show tpp button if payments tpp is present and click onPayTppClick', () => { + const onPayTppClick = vi.fn(); + const paymentTpp = { + retrievalId: 'retrievalId', + iun, + paymentButton: 'paymentButton', + }; + const { getByTestId, queryAllByTestId } = render( + {}} + onPayTppClick={onPayTppClick} + handleFetchPaymentsInfo={() => {}} + landingSiteUrl="" + /> + ); + const payTppButton = getByTestId('tpp-pay-button'); + expect(payTppButton).toBeInTheDocument(); + + const payButton = getByTestId('pay-button'); + expect(payButton).toHaveTextContent('detail.payment.pay-with-other-methods'); + + const pageSelector = getByTestId('pageSelector'); + const pageButtons = pageSelector?.querySelectorAll('button'); + fireEvent.click(pageButtons[1]); + + // select payment + const paymentIndex = paymentsData.pagoPaF24.findIndex( + (payment) => payment.pagoPa?.status === PaymentStatus.REQUIRED + ); + const item = queryAllByTestId('pagopa-item')[paymentIndex]; + const radioButton = item.querySelector('[data-testid="radio-button"] input'); + fireEvent.click(radioButton!); + + // click pay + fireEvent.click(payTppButton); + expect(onPayTppClick).toHaveBeenCalledWith( + paymentsData.pagoPaF24[paymentIndex].pagoPa?.noticeCode, + paymentsData.pagoPaF24[paymentIndex].pagoPa?.creditorTaxId, + paymentTpp.retrievalId + ); + }); }); diff --git a/packages/pn-commons/src/models/NotificationDetail.ts b/packages/pn-commons/src/models/NotificationDetail.ts index b8ae38e635..5f567e85bf 100644 --- a/packages/pn-commons/src/models/NotificationDetail.ts +++ b/packages/pn-commons/src/models/NotificationDetail.ts @@ -23,6 +23,12 @@ export interface NotificationDetail { radd?: INotificationDetailTimeline; } +export type PaymentTpp = { + paymentButton: string; + retrievalId: string; + iun: string; +}; + export type PaymentsData = { pagoPaF24: Array; f24Only: Array; diff --git a/packages/pn-personafisica-webapp/openapitools.json b/packages/pn-personafisica-webapp/openapitools.json index 9706144975..2393e611f2 100644 --- a/packages/pn-personafisica-webapp/openapitools.json +++ b/packages/pn-personafisica-webapp/openapitools.json @@ -39,7 +39,7 @@ }, "bff-payments": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-payments.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0857ea8cbecae4f892bbb2ed19f24f91db2fcbb2/docs/openapi/api-external-pn-bff-payments.yaml", "output": "./src/generated-client/payments", "additionalProperties": { "supportsES6": true, diff --git a/packages/pn-personafisica-webapp/public/locales/it/notifiche.json b/packages/pn-personafisica-webapp/public/locales/it/notifiche.json index d61aa1e880..0f8f8bf465 100644 --- a/packages/pn-personafisica-webapp/public/locales/it/notifiche.json +++ b/packages/pn-personafisica-webapp/public/locales/it/notifiche.json @@ -80,6 +80,8 @@ "summary-in-progress": "Pagamento in corso", "amount": "Importo", "submit": "Paga", + "submit-tpp": "Paga con {{name}}", + "pay-with-other-methods": "Paga con altri metodi di pagamento", "download-f24": "Scarica F24", "pay-with-f24": "Se preferisci, puoi pagare tramite F24.", "download-f24-in-progress": "Documento in elaborazione", diff --git a/packages/pn-personafisica-webapp/src/navigation/RapidAccessGuard.tsx b/packages/pn-personafisica-webapp/src/navigation/RapidAccessGuard.tsx index 274541fb0e..da4b58b3ac 100644 --- a/packages/pn-personafisica-webapp/src/navigation/RapidAccessGuard.tsx +++ b/packages/pn-personafisica-webapp/src/navigation/RapidAccessGuard.tsx @@ -16,11 +16,8 @@ import { NotificationDetailRouteState } from '../models/NotificationDetail'; import { NotificationId } from '../models/Notifications'; import { PFEventsType } from '../models/PFEventsType'; import { useAppDispatch } from '../redux/hooks'; -import { - NOTIFICATION_ACTIONS, - exchangeNotificationQrCode, - exchangeNotificationRetrievalId, -} from '../redux/notification/actions'; +import { NOTIFICATION_ACTIONS, exchangeNotificationQrCode } from '../redux/notification/actions'; +import { exchangeNotificationRetrievalId } from '../redux/sidemenu/actions'; import { ServerResponseErrorCode } from '../utility/AppError/types'; import PFEventStrategyFactory from '../utility/MixpanelUtils/PFEventStrategyFactory'; import { diff --git a/packages/pn-personafisica-webapp/src/pages/NotificationDetail.page.tsx b/packages/pn-personafisica-webapp/src/pages/NotificationDetail.page.tsx index 32bfdadb81..82487ab0d9 100644 --- a/packages/pn-personafisica-webapp/src/pages/NotificationDetail.page.tsx +++ b/packages/pn-personafisica-webapp/src/pages/NotificationDetail.page.tsx @@ -50,9 +50,11 @@ import { getReceivedNotificationDocument, getReceivedNotificationPayment, getReceivedNotificationPaymentInfo, + getReceivedNotificationPaymentTppUrl, getReceivedNotificationPaymentUrl, } from '../redux/notification/actions'; import { resetState } from '../redux/notification/reducers'; +import { exchangeNotificationRetrievalId } from '../redux/sidemenu/actions'; import { RootState } from '../redux/store'; import { getConfiguration } from '../services/configuration.service'; import PFEventStrategyFactory from '../utility/MixpanelUtils/PFEventStrategyFactory'; @@ -90,6 +92,7 @@ const NotificationDetail: React.FC = () => { const currentRecipient = notification?.currentRecipient; const userPayments = useAppSelector((state: RootState) => state.notificationState.paymentsData); + const paymentTpp = useAppSelector((state: RootState) => state.generalInfoState.paymentTpp); const unfilteredDetailTableRows: Array<{ label: string; @@ -270,6 +273,26 @@ const NotificationDetail: React.FC = () => { } }; + const onPayTppClick = (noticeCode?: string, creditorTaxId?: string, retrievalId?: string) => { + if (noticeCode && creditorTaxId && retrievalId) { + PFEventStrategyFactory.triggerEvent(PFEventsType.SEND_START_PAYMENT); + dispatch( + getReceivedNotificationPaymentTppUrl({ + noticeCode, + creditorTaxId, + retrievalId, + }) + ) + .unwrap() + .then((res) => { + if (res.paymentUrl) { + window.location.assign(res.paymentUrl); + } + }) + .catch(() => undefined); + } + }; + const hasNotificationReceivedApiError = hasApiErrors( NOTIFICATION_ACTIONS.GET_RECEIVED_NOTIFICATION ); @@ -351,6 +374,20 @@ const NotificationDetail: React.FC = () => { return () => void dispatch(resetState()); }, []); + /* if retrievalId is in user token and payment info is not in redux, get payment info PN-13915 */ + useEffect(() => { + if (!checkIfUserHasPayments) { + return; + } + if (!currentUser.source?.retrievalId) { + return; + } + if (currentUser.source?.retrievalId === paymentTpp.retrievalId) { + return; + } + void dispatch(exchangeNotificationRetrievalId(currentUser.source.retrievalId)); + }, [currentUser, checkIfUserHasPayments]); + /* function which loads relevant information about donwtimes */ const fetchDowntimeEvents = useCallback((fromDate: string, toDate: string | undefined) => { const fetchParams: GetDowntimeHistoryParams = { @@ -511,10 +548,12 @@ const NotificationDetail: React.FC = () => { > { configurable: true, value: { href: '', assign: mockAssignFn }, }); + initLocalizationForTest(); }); afterEach(() => { @@ -919,4 +922,40 @@ describe('NotificationDetail Page', async () => { expect(alertRadd).toBeInTheDocument(); expect(alertRadd).toHaveTextContent('detail.timeline.radd.title'); }); + + it('should show pay tpp button after call check-tpp api with retrievalId in user token', async () => { + const mockRetrievalId = 'retrieval-id'; + mock.onGet(`/bff/v1/notifications/received/${notificationDTO.iun}`).reply(200, notificationDTO); + mock + .onGet(`/bff/v1/notifications/received/check-tpp?retrievalId=${mockRetrievalId}`) + .reply(200, { + originId: notificationDTO.iun, + retrievalId: mockRetrievalId, + paymentButton: 'MOCK BANK', + } as BffCheckTPPResponse); + + await act(async () => { + result = render(, { + preloadedState: { + userState: { + user: { + fiscal_number: notificationDTO.recipients[2].taxId, + source: { + channel: 'TPP', + details: 'mock-tpp-id', + retrievalId: mockRetrievalId, + }, + }, + }, + }, + }); + }); + + expect( + mock.history.get.find(({ url }) => url?.includes('bff/v1/notifications/received/check-tpp')) + ).toBeDefined(); + const tppPayButton = await waitFor(() => result.getByTestId('tpp-pay-button')); + expect(tppPayButton).toBeInTheDocument(); + expect(tppPayButton).toHaveTextContent('MOCK BANK'); + }); }); diff --git a/packages/pn-personafisica-webapp/src/redux/notification/__test__/reducers.test.ts b/packages/pn-personafisica-webapp/src/redux/notification/__test__/reducers.test.ts index 036da52e63..09a433d843 100644 --- a/packages/pn-personafisica-webapp/src/redux/notification/__test__/reducers.test.ts +++ b/packages/pn-personafisica-webapp/src/redux/notification/__test__/reducers.test.ts @@ -25,11 +25,9 @@ import { } from '../../../__mocks__/NotificationDetail.mock'; import { createMockedStore } from '../../../__test__/test-utils'; import { apiClient } from '../../../api/apiClients'; -import { BffCheckTPPResponse } from '../../../generated-client/notifications'; import { getDowntimeLegalFact } from '../../appStatus/actions'; import { store } from '../../store'; import { - exchangeNotificationRetrievalId, getDowntimeHistory, getReceivedNotification, getReceivedNotificationDocument, @@ -63,7 +61,6 @@ const initialState = { paymentsData: { pagoPaF24: [], f24Only: [], - tpp: {}, }, downtimeEvents: [], }; @@ -443,19 +440,4 @@ describe('Notification detail redux state tests', () => { expect(action.type).toBe('getDowntimeLegalFact/fulfilled'); expect(action.payload).toEqual(mockResponse); }); - - it('Should be able to set paymentsData tpp', async () => { - const mockRetrievalId = 'mocked-retrieval-id'; - const mockResponse: BffCheckTPPResponse = { - paymentButton: 'Hype', - retrievalId: mockRetrievalId, - originId: 'mocked-iun', - }; - mock - .onGet(`/bff/v1/notifications/received/check-tpp?retrievalId=${mockRetrievalId}`) - .reply(200, mockResponse); - const action = await store.dispatch(exchangeNotificationRetrievalId(mockRetrievalId)); - expect(action.type).toBe('exchangeNotificationRetrievalId/fulfilled'); - expect(action.payload).toEqual(mockResponse); - }); }); diff --git a/packages/pn-personafisica-webapp/src/redux/notification/actions.ts b/packages/pn-personafisica-webapp/src/redux/notification/actions.ts index cc05cd52b2..0db094f719 100644 --- a/packages/pn-personafisica-webapp/src/redux/notification/actions.ts +++ b/packages/pn-personafisica-webapp/src/redux/notification/actions.ts @@ -25,10 +25,9 @@ import { DowntimeApiFactory } from '../../generated-client/downtime-logs'; import { BffCheckAarRequest, BffCheckAarResponse, - BffCheckTPPResponse, NotificationReceivedApiFactory, } from '../../generated-client/notifications'; -import { PaymentsApiFactory } from '../../generated-client/payments'; +import { BffPaymentTppResponse, PaymentsApiFactory } from '../../generated-client/payments'; import { NotificationDetailForRecipient } from '../../models/NotificationDetail'; import { PFEventsType } from '../../models/PFEventsType'; import PFEventStrategyFactory from '../../utility/MixpanelUtils/PFEventStrategyFactory'; @@ -44,7 +43,6 @@ export enum NOTIFICATION_ACTIONS { GET_RECEIVED_NOTIFICATION_PAYMENT_URL = 'getReceivedNotificationPaymentUrl', GET_DOWNTIME_HISTORY = 'getNotificationDowntimeHistory', EXCHANGE_NOTIFICATION_QR_CODE = 'exchangeNotificationQrCode', - EXCHANGE_NOTIFICATION_RETRIEVAL_ID = 'exchangeNotificationRetrievalId', } export const getReceivedNotification = createAsyncThunk< @@ -282,16 +280,29 @@ export const exchangeNotificationQrCode = createAsyncThunk( - NOTIFICATION_ACTIONS.EXCHANGE_NOTIFICATION_RETRIEVAL_ID, - async (retrievalId: string, { rejectWithValue }) => { +export const getReceivedNotificationPaymentTppUrl = createAsyncThunk< + BffPaymentTppResponse, + { retrievalId: string; noticeCode: string; creditorTaxId: string } +>( + 'getReceivedNotificationPaymentTppUrl', + async ({ retrievalId, noticeCode, creditorTaxId }, { rejectWithValue }) => { try { - const notificationReceivedApiFactory = NotificationReceivedApiFactory( - undefined, - undefined, - apiClient + const paymentsApiFactory = PaymentsApiFactory(undefined, undefined, apiClient); + const iun = store.getState().notificationState.notification.iun; + setPaymentCache( + { + currentPayment: { + noticeCode, + creditorTaxId, + }, + }, + iun + ); + const response = await paymentsApiFactory.paymentsTppV1( + retrievalId, + noticeCode, + creditorTaxId ); - const response = await notificationReceivedApiFactory.checkTppV1(retrievalId); return response.data; } catch (e: any) { return rejectWithValue(parseError(e)); diff --git a/packages/pn-personafisica-webapp/src/redux/notification/reducers.ts b/packages/pn-personafisica-webapp/src/redux/notification/reducers.ts index e3ada9e6cb..d3b38794d8 100644 --- a/packages/pn-personafisica-webapp/src/redux/notification/reducers.ts +++ b/packages/pn-personafisica-webapp/src/redux/notification/reducers.ts @@ -10,6 +10,7 @@ import { PaymentDetails, PaymentInfoDetail, PaymentStatus, + PaymentsData, RecipientType, TimelineCategory, getF24Payments, @@ -18,10 +19,8 @@ import { } from '@pagopa-pn/pn-commons'; import { createSlice } from '@reduxjs/toolkit'; -import { BffCheckTPPResponse } from '../../generated-client/notifications'; import { NotificationDetailForRecipient } from '../../models/NotificationDetail'; import { - exchangeNotificationRetrievalId, getDowntimeHistory, getReceivedNotification, getReceivedNotificationPaymentInfo, @@ -52,8 +51,7 @@ const initialState = { paymentsData: { pagoPaF24: [] as Array, f24Only: [] as Array, - tpp: {} as BffCheckTPPResponse, - }, + } as PaymentsData, downtimeEvents: [] as Array, }; @@ -159,9 +157,6 @@ const notificationSlice = createSlice({ builder.addCase(getDowntimeHistory.fulfilled, (state, action) => { state.downtimeEvents = action.payload.result; }); - builder.addCase(exchangeNotificationRetrievalId.fulfilled, (state, action) => { - state.paymentsData.tpp = action.payload; - }); }, }); diff --git a/packages/pn-personafisica-webapp/src/redux/sidemenu/__test__/reducers.test.ts b/packages/pn-personafisica-webapp/src/redux/sidemenu/__test__/reducers.test.ts index f6b0d7a156..0940d54fe0 100644 --- a/packages/pn-personafisica-webapp/src/redux/sidemenu/__test__/reducers.test.ts +++ b/packages/pn-personafisica-webapp/src/redux/sidemenu/__test__/reducers.test.ts @@ -7,14 +7,16 @@ import { createMockedStore } from '../../../__test__/test-utils'; import { apiClient } from '../../../api/apiClients'; import { acceptMandate, rejectMandate } from '../../delegation/actions'; import { store } from '../../store'; -import { getDomicileInfo, getSidemenuInformation } from '../actions'; +import { exchangeNotificationRetrievalId, getDomicileInfo, getSidemenuInformation } from '../actions'; import { closeDomicileBanner } from '../reducers'; +import { BffCheckTPPResponse } from '../../../generated-client/notifications'; const initialState = { pendingDelegators: 0, delegators: [], digitalAddresses: [], domicileBannerOpened: true, + paymentTpp: {}, }; const pendingDelegators = mandatesByDelegate.filter((d) => d.status === 'pending'); @@ -121,4 +123,19 @@ describe('Sidemenu redux state tests', () => { expect(action.type).toBe('getDomicileInfo/fulfilled'); expect(action.payload).toEqual(digitalAddresses); }); + + it('Should be able to set tpp info from retrievalId', async () => { + const mockRetrievalId = 'mocked-retrieval-id'; + const mockResponse: BffCheckTPPResponse = { + paymentButton: 'Hype', + retrievalId: mockRetrievalId, + originId: 'mocked-iun', + }; + mock + .onGet(`/bff/v1/notifications/received/check-tpp?retrievalId=${mockRetrievalId}`) + .reply(200, mockResponse); + const action = await store.dispatch(exchangeNotificationRetrievalId(mockRetrievalId)); + expect(action.type).toBe('exchangeNotificationRetrievalId/fulfilled'); + expect(action.payload).toEqual(mockResponse); + }); }); diff --git a/packages/pn-personafisica-webapp/src/redux/sidemenu/actions.ts b/packages/pn-personafisica-webapp/src/redux/sidemenu/actions.ts index b754789d02..a89300da68 100644 --- a/packages/pn-personafisica-webapp/src/redux/sidemenu/actions.ts +++ b/packages/pn-personafisica-webapp/src/redux/sidemenu/actions.ts @@ -4,12 +4,17 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import { apiClient } from '../../api/apiClients'; import { AddressesApiFactory } from '../../generated-client/digital-addresses'; import { MandateApiFactory } from '../../generated-client/mandate'; +import { + BffCheckTPPResponse, + NotificationReceivedApiFactory, +} from '../../generated-client/notifications'; import { AddressType, DigitalAddress } from '../../models/contacts'; import { Delegator } from '../delegation/types'; export enum SIDEMENU_ACTIONS { GET_SIDEMENU_INFORMATION = 'getSidemenuInformation', GET_DOMICILE_INFO = 'getDomicileInfo', + EXCHANGE_NOTIFICATION_RETRIEVAL_ID = 'exchangeNotificationRetrievalId', } export const getSidemenuInformation = createAsyncThunk>( @@ -39,3 +44,24 @@ export const getDomicileInfo = createAsyncThunk>( } } ); + +/** + * TPP + */ + +export const exchangeNotificationRetrievalId = createAsyncThunk( + SIDEMENU_ACTIONS.EXCHANGE_NOTIFICATION_RETRIEVAL_ID, + async (retrievalId: string, { rejectWithValue }) => { + try { + const notificationReceivedApiFactory = NotificationReceivedApiFactory( + undefined, + undefined, + apiClient + ); + const result = await notificationReceivedApiFactory.checkTppV1(retrievalId); + return result.data; + } catch (e: any) { + return rejectWithValue(parseError(e)); + } + } +); diff --git a/packages/pn-personafisica-webapp/src/redux/sidemenu/reducers.ts b/packages/pn-personafisica-webapp/src/redux/sidemenu/reducers.ts index 6f16f77a7c..62af538bb5 100644 --- a/packages/pn-personafisica-webapp/src/redux/sidemenu/reducers.ts +++ b/packages/pn-personafisica-webapp/src/redux/sidemenu/reducers.ts @@ -1,11 +1,21 @@ +import { PaymentTpp } from '@pagopa-pn/pn-commons/src/models/NotificationDetail'; import { createSlice } from '@reduxjs/toolkit'; import { AddressType, ChannelType, DigitalAddress, IOAllowedValues } from '../../models/contacts'; import { removeAddress, updateAddressesList } from '../../utility/contacts.utility'; -import { createOrUpdateAddress, deleteAddress, disableIOAddress, enableIOAddress } from '../contact/actions'; +import { + createOrUpdateAddress, + deleteAddress, + disableIOAddress, + enableIOAddress, +} from '../contact/actions'; import { acceptMandate, rejectMandate } from '../delegation/actions'; import { Delegator } from '../delegation/types'; -import { getDomicileInfo, getSidemenuInformation } from './actions'; +import { + exchangeNotificationRetrievalId, + getDomicileInfo, + getSidemenuInformation, +} from './actions'; /* eslint-disable functional/immutable-data */ const generalInfoSlice = createSlice({ @@ -15,6 +25,7 @@ const generalInfoSlice = createSlice({ delegators: [] as Array, digitalAddresses: [] as Array, domicileBannerOpened: true, + paymentTpp: {} as PaymentTpp, }, reducers: { closeDomicileBanner: (state) => { @@ -84,6 +95,13 @@ const generalInfoSlice = createSlice({ state.pendingDelegators--; // so we also need to update pendingDelegators state } }); + builder.addCase(exchangeNotificationRetrievalId.fulfilled, (state, action) => { + state.paymentTpp = { + retrievalId: action.payload.retrievalId, + paymentButton: action.payload.paymentButton || '', + iun: action.payload.originId || '', + }; + }); }, });