From 80dee74dd6c12713e12d1b0fabce947773268b35 Mon Sep 17 00:00:00 2001 From: Colin O'Sullivan <143013011+cosu419@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:20:04 -0800 Subject: [PATCH] Fixed scroll/focus logic on close of modal (#28266) * Fixed scroll/focus logic on close of modal * Updated feature toggle references to "find_a_representative_enabled" * Refactored scroll/focus logic. Now focuses alert when reports increase * Added new feature flag * Setting csrfToken on successful fetch. Using apiRequest utility rather than fetch. * Updated error verbiage * Setting report object properties to snake case items for API * Moved formatting logic to dedicated formatReportBody. Added unit test. --- .../reports/submitRepresentativeReport.js | 2 +- .../api/RepresentativeFinderApi.js | 28 ++++++--------- .../components/results/ReportModal.jsx | 15 ++++---- .../components/results/SearchResult.jsx | 34 +++++++++++++++---- .../representative-search/config.js | 27 ++++++++++++++- .../representative-search/containers/App.jsx | 4 +-- .../mocks/feature-toggles/index.js | 6 ++-- ...pi-url-parameters.railsEngine.unit.spec.js | 25 +++++++++++++- .../tests/e2e/accessibility.cypress.spec.js | 4 +-- .../tests/e2e/geolocation.cypress.spec.js | 4 +-- .../tests/e2e/mobile.cypress.spec.js | 4 +-- .../e2e/representativeSearch.cypress.spec.js | 4 +-- .../tests/e2e/serverErrors.cypress.spec.js | 4 +-- .../feature-toggles/featureFlagNames.js | 1 + 14 files changed, 106 insertions(+), 56 deletions(-) diff --git a/src/applications/representative-search/actions/reports/submitRepresentativeReport.js b/src/applications/representative-search/actions/reports/submitRepresentativeReport.js index f8295188e87e..b9ad630dbf31 100644 --- a/src/applications/representative-search/actions/reports/submitRepresentativeReport.js +++ b/src/applications/representative-search/actions/reports/submitRepresentativeReport.js @@ -63,7 +63,7 @@ export const submitRepresentativeReport = newReport => { } catch (error) { Sentry.withScope(scope => { scope.setExtra('error', error); - Sentry.captureMessage('Error fetching accredited representatives'); + Sentry.captureMessage('Error submitting representative report'); }); dispatch({ diff --git a/src/applications/representative-search/api/RepresentativeFinderApi.js b/src/applications/representative-search/api/RepresentativeFinderApi.js index 6074a8e8f997..26e5cebf6d00 100644 --- a/src/applications/representative-search/api/RepresentativeFinderApi.js +++ b/src/applications/representative-search/api/RepresentativeFinderApi.js @@ -1,4 +1,9 @@ -import { fetchAndUpdateSessionExpiration as fetch } from '@department-of-veterans-affairs/platform-utilities/api'; +/* eslint-disable camelcase */ + +import { + fetchAndUpdateSessionExpiration as fetch, + apiRequest, +} from '@department-of-veterans-affairs/platform-utilities/api'; import { getApi, resolveParamsWithUrl, endpointOptions } from '../config'; class RepresentativeFinderApi { @@ -41,6 +46,9 @@ class RepresentativeFinderApi { if (!response.ok) { throw Error(response.statusText); } + const csrf = response.headers.get('X-CSRF-Token'); + localStorage.setItem('csrfToken', csrf); + return response.json(); }) .then(res => { @@ -57,30 +65,16 @@ class RepresentativeFinderApi { } static reportResult(newReport) { - const reportRequestBody = { - representativeId: newReport.representativeId, - flags: [], - }; - const startTime = new Date().getTime(); - for (const [flagType, flaggedValue] of Object.entries(newReport.reports)) { - if (flaggedValue !== null) { - reportRequestBody.flags.push({ - flagType, - flaggedValue, - }); - } - } - const { requestUrl, apiSettings } = getApi( endpointOptions.flagReps, 'POST', - reportRequestBody, + newReport, ); return new Promise((resolve, reject) => { - fetch(requestUrl, apiSettings) + apiRequest(requestUrl, apiSettings) .then(response => { if (!response.ok) { throw Error(response.statusText); diff --git a/src/applications/representative-search/components/results/ReportModal.jsx b/src/applications/representative-search/components/results/ReportModal.jsx index 7f91b80c07b7..f6666fa8975a 100644 --- a/src/applications/representative-search/components/results/ReportModal.jsx +++ b/src/applications/representative-search/components/results/ReportModal.jsx @@ -1,10 +1,11 @@ +/* eslint-disable camelcase */ + import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { VaModal, VaCheckboxGroup, } from '@department-of-veterans-affairs/component-library/dist/react-bindings'; -import { snakeCase } from 'lodash'; const ReportModal = ({ representativeName, @@ -78,17 +79,15 @@ const ReportModal = ({ }; const onSubmitModal = () => { - const formattedReportObject = { representativeId, reports: {} }; + const formattedReportObject = { + representativeId, + reports: {}, + }; // push non-null items to reports object Object.keys(reportObject).forEach(prop => { if (reportObject[prop] !== null) { - if (prop === 'phone') { - formattedReportObject.reports[snakeCase('phoneNumber')] = - reportObject.phone; - } else { - formattedReportObject.reports[prop] = reportObject[prop]; - } + formattedReportObject.reports[prop] = reportObject[prop]; } }); diff --git a/src/applications/representative-search/components/results/SearchResult.jsx b/src/applications/representative-search/components/results/SearchResult.jsx index a900421a47e6..816367820f62 100644 --- a/src/applications/representative-search/components/results/SearchResult.jsx +++ b/src/applications/representative-search/components/results/SearchResult.jsx @@ -1,6 +1,9 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; -import { scrollTo } from 'platform/utilities/ui'; +import { + focusElement, + scrollTo, +} from '@department-of-veterans-affairs/platform-utilities/ui'; import ReportModal from './ReportModal'; import { parsePhoneNumber } from '../../utils/phoneNumbers'; @@ -24,9 +27,9 @@ const SearchResult = ({ }) => { const [reportModalIsShowing, setReportModalIsShowing] = useState(false); - const { contact, extension } = parsePhoneNumber(phone); + const prevReportCount = useRef(reports?.length || 0); - const scrollElementId = `result-${representativeId}`; + const { contact, extension } = parsePhoneNumber(phone); const addressExists = addressLine1 || city || stateCode || zipCode; @@ -45,9 +48,20 @@ const SearchResult = ({ const closeReportModal = () => { setReportModalIsShowing(false); - scrollTo(scrollElementId); + scrollTo(`#report-button-${representativeId}`); + focusElement(`#report-button-${representativeId}`); }; + useEffect( + () => { + if (reports?.length > prevReportCount) { + scrollTo(`#thank-you-alert-${representativeId}`); + focusElement(`#thank-you-alert-${representativeId}`); + } + }, + [reports], + ); + return (
+
Thanks for reporting outdated information.