diff --git a/packages/pn-personafisica-webapp/src/api/notifications/Notifications.api.ts b/packages/pn-personafisica-webapp/src/api/notifications/Notifications.api.ts deleted file mode 100644 index 8e0d42c6f4..0000000000 --- a/packages/pn-personafisica-webapp/src/api/notifications/Notifications.api.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NotificationId } from '../../models/Notifications'; -import { apiClient } from '../apiClients'; -import { NOTIFICATION_ID_FROM_QRCODE } from './notifications.routes'; - -export const NotificationsApi = { - /** - * Get notification iun and mandate id from aar link - * @param {string} qrCode - * @returns Promise - */ - exchangeNotificationQrCode: (qrCode: string): Promise => - apiClient - .post(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: qrCode }) - .then((response) => response.data), -}; diff --git a/packages/pn-personafisica-webapp/src/api/notifications/__test__/Notifications.api.test.ts b/packages/pn-personafisica-webapp/src/api/notifications/__test__/Notifications.api.test.ts deleted file mode 100644 index 9f2ab86a51..0000000000 --- a/packages/pn-personafisica-webapp/src/api/notifications/__test__/Notifications.api.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; - -import { mockAuthentication } from '../../../__mocks__/Auth.mock'; -import { apiClient } from '../../apiClients'; -import { NotificationsApi } from '../Notifications.api'; -import { NOTIFICATION_ID_FROM_QRCODE } from '../notifications.routes'; - -describe('Notifications api tests', () => { - let mock: MockAdapter; - - mockAuthentication(); - - beforeAll(() => { - mock = new MockAdapter(apiClient); - }); - - afterEach(() => { - mock.reset(); - }); - - afterAll(() => { - mock.restore(); - }); - - it('exchangeNotificationQrCode', async () => { - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: 'qr1' }).reply(200, { - iun: 'mock-notification-1', - mandateId: 'mock-mandate-1', - }); - const res = await NotificationsApi.exchangeNotificationQrCode('qr1'); - expect(res).toStrictEqual({ - iun: 'mock-notification-1', - mandateId: 'mock-mandate-1', - }); - }); -}); diff --git a/packages/pn-personafisica-webapp/src/api/notifications/__test__/notifications.routes.test.ts b/packages/pn-personafisica-webapp/src/api/notifications/__test__/notifications.routes.test.ts deleted file mode 100644 index d9b89a38f7..0000000000 --- a/packages/pn-personafisica-webapp/src/api/notifications/__test__/notifications.routes.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NOTIFICATION_ID_FROM_QRCODE } from '../notifications.routes'; - -describe('Notifications routes', () => { - it('should compile NOTIFICATION_ID_FROM_QRCODE', () => { - const route = NOTIFICATION_ID_FROM_QRCODE(); - expect(route).toEqual('/delivery/notifications/received/check-aar-qr-code'); - }); -}); diff --git a/packages/pn-personafisica-webapp/src/api/notifications/notifications.routes.ts b/packages/pn-personafisica-webapp/src/api/notifications/notifications.routes.ts deleted file mode 100644 index ebe0272112..0000000000 --- a/packages/pn-personafisica-webapp/src/api/notifications/notifications.routes.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { compileRoute } from '@pagopa-pn/pn-commons'; - -// Prefixes -const API_DELIVERY_PREFIX = 'delivery'; - -// Segments -const API_NOTIFICATIONS_BASE = 'notifications'; -const API_NOTIFICATIONS_RECEIVED = 'received'; -const API_NOTIFICATIONS_FROM_QRCODE = 'check-aar-qr-code'; - -// Paths -const API_NOTIFICATION_ID_FROM_QRCODE_PATH = `${API_NOTIFICATIONS_BASE}/${API_NOTIFICATIONS_RECEIVED}/${API_NOTIFICATIONS_FROM_QRCODE}`; - -// APIs -export function NOTIFICATION_ID_FROM_QRCODE() { - return compileRoute({ - prefix: API_DELIVERY_PREFIX, - path: API_NOTIFICATION_ID_FROM_QRCODE_PATH, - }); -} diff --git a/packages/pn-personafisica-webapp/src/generated-client/notifications/api.ts b/packages/pn-personafisica-webapp/src/generated-client/notifications/api.ts index 59e1ab4241..d1e003dfc6 100644 --- a/packages/pn-personafisica-webapp/src/generated-client/notifications/api.ts +++ b/packages/pn-personafisica-webapp/src/generated-client/notifications/api.ts @@ -200,6 +200,38 @@ export interface BaseRegisteredLetterDetails { */ 'physicalAddress': PhysicalAddress; } +/** + * Le informazioni fornite per verificare l\'AAR-QR-CodeValue + * @export + * @interface BffCheckAarRequest + */ +export interface BffCheckAarRequest { + /** + * valore del token QR-Code presente sull\'avviso di avvenuta ricezione + * @type {string} + * @memberof BffCheckAarRequest + */ + 'aarQrCodeValue': string; +} +/** + * Le informazioni fornite in risposta alla verifica del AAR-QR-CodeValue con possibile identificativo della delega attiva + * @export + * @interface BffCheckAarResponse + */ +export interface BffCheckAarResponse { + /** + * Identificativo Univoco Notifica + * @type {string} + * @memberof BffCheckAarResponse + */ + 'iun': string; + /** + * identificativo della delega + * @type {string} + * @memberof BffCheckAarResponse + */ + 'mandateId'?: string; +} /** * * @export @@ -2323,6 +2355,19 @@ export interface RefinementDetailsV23 { */ 'eventTimestamp'?: string; } +/** + * Le informazioni fornite per verificare l\'AAR-QR-CodeValue + * @export + * @interface RequestCheckAarMandateDto + */ +export interface RequestCheckAarMandateDto { + /** + * valore del token QR-Code presente sull\'avviso di avvenuta ricezione + * @type {string} + * @memberof RequestCheckAarMandateDto + */ + 'aarQrCodeValue': string; +} /** * * @export @@ -2336,6 +2381,25 @@ export interface RequestRefusedDetailsV23 { */ 'refusalReasons'?: Array; } +/** + * Le informazioni fornite in risposta alla verifica del AAR-QR-CodeValue con possibile identificativo della delega attiva + * @export + * @interface ResponseCheckAarMandateDto + */ +export interface ResponseCheckAarMandateDto { + /** + * Identificativo Univoco Notifica + * @type {string} + * @memberof ResponseCheckAarMandateDto + */ + 'iun': string; + /** + * identificativo della delega + * @type {string} + * @memberof ResponseCheckAarMandateDto + */ + 'mandateId'?: string; +} /** * stato risposta ricevuta da externalChannel * @export @@ -3204,6 +3268,42 @@ export type TimelineElementDetailsV23 = AarCreationRequestDetails | AarGeneratio */ export const NotificationReceivedApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * + * @summary Servizio per la verifica del aar-qr-code + * @param {BffCheckAarRequest} bffCheckAarRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkAarQrCodeV1: async (bffCheckAarRequest: BffCheckAarRequest, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'bffCheckAarRequest' is not null or undefined + assertParamExists('checkAarQrCodeV1', 'bffCheckAarRequest', bffCheckAarRequest) + const localVarPath = `/bff/v1/notifications/received/check-aar-qr-code`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(bffCheckAarRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Questa operazione permette di scaricare qualsiasi documento legato alla notifica. @@ -3525,6 +3625,19 @@ export const NotificationReceivedApiAxiosParamCreator = function (configuration? export const NotificationReceivedApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = NotificationReceivedApiAxiosParamCreator(configuration) return { + /** + * + * @summary Servizio per la verifica del aar-qr-code + * @param {BffCheckAarRequest} bffCheckAarRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async checkAarQrCodeV1(bffCheckAarRequest: BffCheckAarRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.checkAarQrCodeV1(bffCheckAarRequest, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['NotificationReceivedApi.checkAarQrCodeV1']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** * * @summary Questa operazione permette di scaricare qualsiasi documento legato alla notifica. @@ -3625,6 +3738,16 @@ export const NotificationReceivedApiFp = function(configuration?: Configuration) export const NotificationReceivedApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = NotificationReceivedApiFp(configuration) return { + /** + * + * @summary Servizio per la verifica del aar-qr-code + * @param {BffCheckAarRequest} bffCheckAarRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkAarQrCodeV1(bffCheckAarRequest: BffCheckAarRequest, options?: any): AxiosPromise { + return localVarFp.checkAarQrCodeV1(bffCheckAarRequest, options).then((request) => request(axios, basePath)); + }, /** * * @summary Questa operazione permette di scaricare qualsiasi documento legato alla notifica. @@ -3710,6 +3833,18 @@ export const NotificationReceivedApiFactory = function (configuration?: Configur * @extends {BaseAPI} */ export class NotificationReceivedApi extends BaseAPI { + /** + * + * @summary Servizio per la verifica del aar-qr-code + * @param {BffCheckAarRequest} bffCheckAarRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NotificationReceivedApi + */ + public checkAarQrCodeV1(bffCheckAarRequest: BffCheckAarRequest, options?: RawAxiosRequestConfig) { + return NotificationReceivedApiFp(this.configuration).checkAarQrCodeV1(bffCheckAarRequest, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Questa operazione permette di scaricare qualsiasi documento legato alla notifica. diff --git a/packages/pn-personafisica-webapp/src/navigation/AARGuard.tsx b/packages/pn-personafisica-webapp/src/navigation/AARGuard.tsx index 62c47f0a73..41f1b40cb6 100644 --- a/packages/pn-personafisica-webapp/src/navigation/AARGuard.tsx +++ b/packages/pn-personafisica-webapp/src/navigation/AARGuard.tsx @@ -4,9 +4,10 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { AccessDenied, IllusQuestion, LoadingPage } from '@pagopa-pn/pn-commons'; -import { NotificationsApi } from '../api/notifications/Notifications.api'; import { NotificationId } from '../models/Notifications'; import { PFEventsType } from '../models/PFEventsType'; +import { useAppDispatch } from '../redux/hooks'; +import { exchangeNotificationQrCode } from '../redux/notification/actions'; import PFEventStrategyFactory from '../utility/MixpanelUtils/PFEventStrategyFactory'; import { DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM, @@ -23,6 +24,7 @@ function notificationDetailPath(notificationId: NotificationId): string { const AARGuard = () => { const location = useLocation(); + const dispatch = useAppDispatch(); const navigate = useNavigate(); const { t } = useTranslation(['notifiche']); const [fetchError, setFetchError] = useState(false); @@ -34,17 +36,20 @@ const AARGuard = () => { }, [location]); useEffect(() => { - const fetchNotificationFromQrCode = async () => { - if (aar) { - try { - const fetchedData = await NotificationsApi.exchangeNotificationQrCode(aar); - setNotificationId(fetchedData); - } catch { - setFetchError(true); - } - } - }; - void fetchNotificationFromQrCode(); + if (aar) { + const fetchNotificationFromQrCode = () => + dispatch(exchangeNotificationQrCode({ aarQrCodeValue: aar })) + .unwrap() + .then((notification) => { + if (notification) { + setNotificationId(notification); + } + }) + .catch(() => { + setFetchError(true); + }); + void fetchNotificationFromQrCode(); + } }, [aar]); useEffect(() => { diff --git a/packages/pn-personafisica-webapp/src/navigation/__test__/AARGuard.test.tsx b/packages/pn-personafisica-webapp/src/navigation/__test__/AARGuard.test.tsx index 8b01d61092..093ba807e5 100644 --- a/packages/pn-personafisica-webapp/src/navigation/__test__/AARGuard.test.tsx +++ b/packages/pn-personafisica-webapp/src/navigation/__test__/AARGuard.test.tsx @@ -4,7 +4,6 @@ import { vi } from 'vitest'; import { act, render, screen, waitFor } from '../../__test__/test-utils'; import { apiClient } from '../../api/apiClients'; -import { NOTIFICATION_ID_FROM_QRCODE } from '../../api/notifications/notifications.routes'; import AARGuard from '../AARGuard'; import { DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM, @@ -59,19 +58,21 @@ describe('Notification from QR code', async () => { it('QR code requested by a recipient', async () => { const mockQrCode = 'qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply( - () => - new Promise((resolve) => { - setTimeout(() => { - resolve([200, { iun: 'mock-iun' }]); - }, 200); - }) - ); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply( + () => + new Promise((resolve) => { + setTimeout(() => { + resolve([200, { iun: 'mock-iun' }]); + }, 200); + }) + ); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -92,13 +93,13 @@ describe('Notification from QR code', async () => { const mockQrCode = 'qr-code-delegate'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; mock - .onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }) + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) .reply(200, { iun: 'mock-iun', mandateId: 'mock-mandateId' }); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -116,12 +117,14 @@ describe('Notification from QR code', async () => { it('invalid QR code', async () => { const mockQrCode = 'bad-qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply(500); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply(500); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -136,7 +139,9 @@ describe('Notification from QR code', async () => { it('invalid recipient accesses to QR code', async () => { const mockQrCode = 'bad-qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply(404); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply(404); await act(async () => { render(); }); diff --git a/packages/pn-personafisica-webapp/src/redux/notification/actions.ts b/packages/pn-personafisica-webapp/src/redux/notification/actions.ts index 458718eb38..99b124d437 100644 --- a/packages/pn-personafisica-webapp/src/redux/notification/actions.ts +++ b/packages/pn-personafisica-webapp/src/redux/notification/actions.ts @@ -22,7 +22,11 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import { apiClient } from '../../api/apiClients'; import { DowntimeApiFactory } from '../../generated-client/downtime-logs'; -import { NotificationReceivedApiFactory } from '../../generated-client/notifications'; +import { + BffCheckAarRequest, + BffCheckAarResponse, + NotificationReceivedApiFactory, +} from '../../generated-client/notifications'; import { PaymentsApiFactory } from '../../generated-client/payments'; import { NotificationDetailForRecipient } from '../../models/NotificationDetail'; import { PFEventsType } from '../../models/PFEventsType'; @@ -38,6 +42,7 @@ export enum NOTIFICATION_ACTIONS { GET_RECEIVED_NOTIFICATION_PAYMENT_INFO = 'getReceivedNotificationPaymentInfo', GET_RECEIVED_NOTIFICATION_PAYMENT_URL = 'getReceivedNotificationPaymentUrl', GET_DOWNTIME_HISTORY = 'getNotificationDowntimeHistory', + EXCHANGE_NOTIFICATION_QR_CODE = 'exchangeNotificationQrCode', } export const getReceivedNotification = createAsyncThunk< @@ -257,3 +262,20 @@ export const getDowntimeHistory = createAsyncThunk( + NOTIFICATION_ACTIONS.EXCHANGE_NOTIFICATION_QR_CODE, + async (params: BffCheckAarRequest, { rejectWithValue }) => { + try { + const notificationReceivedApiFactory = NotificationReceivedApiFactory( + undefined, + undefined, + apiClient + ); + const response = await notificationReceivedApiFactory.checkAarQrCodeV1(params); + return response.data; + } catch (e: any) { + return rejectWithValue(parseError(e)); + } + } +); diff --git a/packages/pn-personagiuridica-webapp/src/api/notifications/Notifications.api.ts b/packages/pn-personagiuridica-webapp/src/api/notifications/Notifications.api.ts deleted file mode 100644 index 8e0d42c6f4..0000000000 --- a/packages/pn-personagiuridica-webapp/src/api/notifications/Notifications.api.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NotificationId } from '../../models/Notifications'; -import { apiClient } from '../apiClients'; -import { NOTIFICATION_ID_FROM_QRCODE } from './notifications.routes'; - -export const NotificationsApi = { - /** - * Get notification iun and mandate id from aar link - * @param {string} qrCode - * @returns Promise - */ - exchangeNotificationQrCode: (qrCode: string): Promise => - apiClient - .post(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: qrCode }) - .then((response) => response.data), -}; diff --git a/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/Notifications.api.test.ts b/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/Notifications.api.test.ts deleted file mode 100644 index 9f2ab86a51..0000000000 --- a/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/Notifications.api.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; - -import { mockAuthentication } from '../../../__mocks__/Auth.mock'; -import { apiClient } from '../../apiClients'; -import { NotificationsApi } from '../Notifications.api'; -import { NOTIFICATION_ID_FROM_QRCODE } from '../notifications.routes'; - -describe('Notifications api tests', () => { - let mock: MockAdapter; - - mockAuthentication(); - - beforeAll(() => { - mock = new MockAdapter(apiClient); - }); - - afterEach(() => { - mock.reset(); - }); - - afterAll(() => { - mock.restore(); - }); - - it('exchangeNotificationQrCode', async () => { - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: 'qr1' }).reply(200, { - iun: 'mock-notification-1', - mandateId: 'mock-mandate-1', - }); - const res = await NotificationsApi.exchangeNotificationQrCode('qr1'); - expect(res).toStrictEqual({ - iun: 'mock-notification-1', - mandateId: 'mock-mandate-1', - }); - }); -}); diff --git a/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/notifications.routes.test.ts b/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/notifications.routes.test.ts deleted file mode 100644 index d9b89a38f7..0000000000 --- a/packages/pn-personagiuridica-webapp/src/api/notifications/__test__/notifications.routes.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NOTIFICATION_ID_FROM_QRCODE } from '../notifications.routes'; - -describe('Notifications routes', () => { - it('should compile NOTIFICATION_ID_FROM_QRCODE', () => { - const route = NOTIFICATION_ID_FROM_QRCODE(); - expect(route).toEqual('/delivery/notifications/received/check-aar-qr-code'); - }); -}); diff --git a/packages/pn-personagiuridica-webapp/src/api/notifications/notifications.routes.ts b/packages/pn-personagiuridica-webapp/src/api/notifications/notifications.routes.ts deleted file mode 100644 index ac94d1ea8b..0000000000 --- a/packages/pn-personagiuridica-webapp/src/api/notifications/notifications.routes.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { compileRoute } from '@pagopa-pn/pn-commons'; - -// Prefixes -const API_DELIVERY_PREFIX = 'delivery'; - -// Segments -const API_NOTIFICATIONS_BASE = 'notifications'; -const API_NOTIFICATIONS_RECEIVED = 'received'; -const API_NOTIFICATIONS_FROM_QRCODE = 'check-aar-qr-code'; - -// Paths -const API_NOTIFICATION_ID_FROM_QRCODE_PATH = `${API_NOTIFICATIONS_BASE}/${API_NOTIFICATIONS_RECEIVED}/${API_NOTIFICATIONS_FROM_QRCODE}`; -// APIs -export function NOTIFICATION_ID_FROM_QRCODE() { - return compileRoute({ - prefix: API_DELIVERY_PREFIX, - path: API_NOTIFICATION_ID_FROM_QRCODE_PATH, - }); -} diff --git a/packages/pn-personagiuridica-webapp/src/navigation/AARGuard.tsx b/packages/pn-personagiuridica-webapp/src/navigation/AARGuard.tsx index f1e311fa4c..76dae1d36e 100644 --- a/packages/pn-personagiuridica-webapp/src/navigation/AARGuard.tsx +++ b/packages/pn-personagiuridica-webapp/src/navigation/AARGuard.tsx @@ -4,8 +4,9 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { AccessDenied, IllusQuestion, LoadingPage } from '@pagopa-pn/pn-commons'; -import { NotificationsApi } from '../api/notifications/Notifications.api'; import { NotificationId } from '../models/Notifications'; +import { useAppDispatch } from '../redux/hooks'; +import { exchangeNotificationQrCode } from '../redux/notification/actions'; import { DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM, GET_DETTAGLIO_NOTIFICA_DELEGATO_PATH, @@ -21,6 +22,7 @@ function notificationDetailPath(notificationId: NotificationId): string { const AARGuard = () => { const location = useLocation(); + const dispatch = useAppDispatch(); const navigate = useNavigate(); const { t } = useTranslation(['notifiche']); const [fetchError, setFetchError] = useState(false); @@ -32,17 +34,20 @@ const AARGuard = () => { }, [location]); useEffect(() => { - const fetchNotificationFromQrCode = async () => { - if (aar) { - try { - const fetchedData = await NotificationsApi.exchangeNotificationQrCode(aar); - setNotificationId(fetchedData); - } catch { - setFetchError(true); - } - } - }; - void fetchNotificationFromQrCode(); + if (aar) { + const fetchNotificationFromQrCode = () => + dispatch(exchangeNotificationQrCode({ aarQrCodeValue: aar })) + .unwrap() + .then((notification) => { + if (notification) { + setNotificationId(notification); + } + }) + .catch(() => { + setFetchError(true); + }); + void fetchNotificationFromQrCode(); + } }, [aar]); useEffect(() => { diff --git a/packages/pn-personagiuridica-webapp/src/navigation/__test__/AARGuard.test.tsx b/packages/pn-personagiuridica-webapp/src/navigation/__test__/AARGuard.test.tsx index cace95bbaf..25910dcdc0 100644 --- a/packages/pn-personagiuridica-webapp/src/navigation/__test__/AARGuard.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/navigation/__test__/AARGuard.test.tsx @@ -4,7 +4,6 @@ import { vi } from 'vitest'; import { act, render, screen, waitFor } from '../../__test__/test-utils'; import { apiClient } from '../../api/apiClients'; -import { NOTIFICATION_ID_FROM_QRCODE } from '../../api/notifications/notifications.routes'; import AARGuard from '../AARGuard'; import { DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM, @@ -59,19 +58,21 @@ describe('Notification from QR code', async () => { it('QR code requested by a recipient', async () => { const mockQrCode = 'qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply( - () => - new Promise((resolve) => { - setTimeout(() => { - resolve([200, { iun: 'mock-iun' }]); - }, 200); - }) - ); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply( + () => + new Promise((resolve) => { + setTimeout(() => { + resolve([200, { iun: 'mock-iun' }]); + }, 200); + }) + ); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -92,13 +93,13 @@ describe('Notification from QR code', async () => { const mockQrCode = 'qr-code-delegate'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; mock - .onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }) + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) .reply(200, { iun: 'mock-iun', mandateId: 'mock-mandateId' }); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -116,12 +117,14 @@ describe('Notification from QR code', async () => { it('invalid QR code', async () => { const mockQrCode = 'bad-qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply(500); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply(500); await act(async () => { render(); }); expect(mock.history.post).toHaveLength(1); - expect(mock.history.post[0].url).toBe(NOTIFICATION_ID_FROM_QRCODE()); + expect(mock.history.post[0].url).toBe('/bff/v1/notifications/received/check-aar-qr-code'); expect(JSON.parse(mock.history.post[0].data)).toStrictEqual({ aarQrCodeValue: mockQrCode, }); @@ -136,7 +139,9 @@ describe('Notification from QR code', async () => { it('invalid recipient accesses to QR code', async () => { const mockQrCode = 'bad-qr-code'; window.location.search = `?${DETTAGLIO_NOTIFICA_QRCODE_QUERY_PARAM}=${mockQrCode}`; - mock.onPost(NOTIFICATION_ID_FROM_QRCODE(), { aarQrCodeValue: mockQrCode }).reply(404); + mock + .onPost('/bff/v1/notifications/received/check-aar-qr-code', { aarQrCodeValue: mockQrCode }) + .reply(404); await act(async () => { render(); }); diff --git a/packages/pn-personagiuridica-webapp/src/redux/notification/actions.ts b/packages/pn-personagiuridica-webapp/src/redux/notification/actions.ts index 2cfd58b934..f115e07fa2 100644 --- a/packages/pn-personagiuridica-webapp/src/redux/notification/actions.ts +++ b/packages/pn-personagiuridica-webapp/src/redux/notification/actions.ts @@ -21,7 +21,11 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import { apiClient } from '../../api/apiClients'; import { DowntimeApiFactory } from '../../generated-client/downtime-logs'; -import { NotificationReceivedApiFactory } from '../../generated-client/notifications'; +import { + BffCheckAarRequest, + BffCheckAarResponse, + NotificationReceivedApiFactory, +} from '../../generated-client/notifications'; import { PaymentsApiFactory } from '../../generated-client/payments'; import { NotificationDetailForRecipient } from '../../models/NotificationDetail'; import { parseNotificationDetailForRecipient } from '../../utility/notification.utility'; @@ -34,6 +38,7 @@ export enum NOTIFICATION_ACTIONS { GET_RECEIVED_NOTIFICATION_PAYMENT_INFO = 'getReceivedNotificationPaymentInfo', GET_RECEIVED_NOTIFICATION_PAYMENT_URL = 'getReceivedNotificationPaymentUrl', GET_DOWNTIME_HISTORY = 'getNotificationDowntimeHistory', + EXCHANGE_NOTIFICATION_QR_CODE = 'exchangeNotificationQrCode', } export const getReceivedNotification = createAsyncThunk< @@ -240,3 +245,20 @@ export const getDowntimeHistory = createAsyncThunk( + NOTIFICATION_ACTIONS.EXCHANGE_NOTIFICATION_QR_CODE, + async (params: BffCheckAarRequest, { rejectWithValue }) => { + try { + const notificationReceivedApiFactory = NotificationReceivedApiFactory( + undefined, + undefined, + apiClient + ); + const response = await notificationReceivedApiFactory.checkAarQrCodeV1(params); + return response.data; + } catch (e: any) { + return rejectWithValue(parseError(e)); + } + } +);