department-of-veterans-affairs/vets-website

View on GitHub
src/applications/representative-search/components/results/SearchResult.jsx

Summary

Maintainability
F
4 days
Test Coverage
/* eslint-disable @department-of-veterans-affairs/prefer-button-component */

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import {
  focusElement,
  scrollTo,
} from '@department-of-veterans-affairs/platform-utilities/ui';
import { useFeatureToggle } from '~/platform/utilities/feature-toggles/useFeatureToggle';

import { recordEvent } from '@department-of-veterans-affairs/platform-monitoring/exports';
import ReportModal from './ReportModal';
import { parsePhoneNumber } from '../../utils/phoneNumbers';

const SearchResult = ({
  officer,
  key,
  addressLine1,
  addressLine2,
  addressLine3,
  city,
  stateCode,
  zipCode,
  phone,
  distance,
  email,
  associatedOrgs,
  submitRepresentativeReport,
  initializeRepresentativeReport,
  cancelRepresentativeReport,
  reportSubmissionStatus,
  reports,
  representativeId,
  searchResults,
  query,
  setReportModalTester,
}) => {
  const [reportModalIsShowing, setReportModalIsShowing] = useState(false);

  const { useToggleValue, TOGGLE_NAMES } = useFeatureToggle();

  const reportFeatureEnabled = useToggleValue(
    TOGGLE_NAMES.findARepresentativeFlagResultsEnabled,
  );

  const { contact, extension } = parsePhoneNumber(phone);

  const addressExists = addressLine1 || city || stateCode || zipCode;

  // concatenating address for ReportModal
  const address =
    [
      (addressLine1 || '').trim(),
      (addressLine2 || '').trim(),
      (addressLine3 || '').trim(),
    ]
      .filter(Boolean)
      .join(' ') +
    (city ? ` ${city},` : '') +
    (stateCode ? ` ${stateCode}` : '') +
    (zipCode ? ` ${zipCode}` : '');

  const onCloseReportModal = () => {
    setReportModalIsShowing(false);
  };

  const recordContactLinkClick = () => {
    recordEvent({
      // prettier-ignore
      'event': 'far-search-results-click',
      'search-query': query?.locationQueryString,
      'search-filters-list': {
        'representative-type': query?.representativeType,
        'search-radius': query?.searchArea,
        'representative-name': query?.representativeQueryString,
      },
      'search-selection': 'Find VA Accredited Rep',
      'search-results-id': representativeId,
      'search-results-total-count':
        searchResults?.meta?.pagination?.totalEntries,
      'search-results-total-pages': searchResults?.meta?.pagination?.totalPages,
      'search-result-position': key,
      'search-result-page': searchResults?.meta?.pagination?.currentPage,
    });
  };

  const recordReportButtonClick = () => {
    recordEvent({
      // prettier-ignore
      'event': 'far-search-results-outdated',
      'search-query': query?.locationQueryString,
      'search-filters-list': {
        'representative-type': query?.representativeType,
        'search-radius': query?.searchArea,
        'representative-name': query?.representativeQueryString,
      },
      'search-selection': 'Find VA Accredited Rep',
      'search-results-id': representativeId,
      'search-results-total-count':
        searchResults?.meta?.pagination?.totalEntries,
      'search-results-total-pages': searchResults?.meta?.pagination?.totalPages,
      'search-result-position': key,
      'search-result-page': searchResults?.meta?.pagination?.currentPage,
    });
  };

  useEffect(
    () => {
      if (reportSubmissionStatus === 'SUCCESS') {
        scrollTo(`#thank-you-alert-${representativeId}`);
        focusElement(`#thank-you-alert-${representativeId}`);
      } else if (reportSubmissionStatus === 'CANCELLED') {
        scrollTo(`#report-button-${representativeId}`);
        focusElement(`#report-button-${representativeId}`);
      }
      initializeRepresentativeReport();
    },
    [reportModalIsShowing],
  );

  return (
    <div className="report-outdated-information-modal">
      {/* Trigger methods for unit testing - temporary workaround for shadow root issues */}
      {setReportModalTester ? (
        <button
          id="open-modal-test-button"
          label="open-modal-test-button"
          type="button"
          onClick={() => {
            recordReportButtonClick();
            setReportModalIsShowing(true);
          }}
        />
      ) : null}
      {reportModalIsShowing && (
        <ReportModal
          representativeName={officer}
          representativeId={representativeId}
          address={address}
          phone={phone}
          email={email}
          existingReports={reports}
          onCloseReportModal={onCloseReportModal}
          submitRepresentativeReport={submitRepresentativeReport}
          cancelRepresentativeReport={cancelRepresentativeReport}
        />
      )}
      <va-card class="representative-result-card vads-u-padding--4">
        <div className="representative-result-card-content">
          <div className="representative-info-heading">
            {distance && (
              <div
                id={`representative-${representativeId}`}
                className="vads-u-font-weight--bold vads-u-font-family--serif"
              >
                {parseFloat(JSON.parse(distance).toFixed(2))} Mi
              </div>
            )}
            {officer && (
              <>
                <div
                  className="vads-u-font-family--serif vads-u-margin-top--2p5"
                  id={`result-${representativeId}`}
                >
                  <h3 aria-describedby={`representative-${representativeId}`}>
                    {officer}
                  </h3>
                </div>
                {associatedOrgs?.length === 1 && (
                  <p style={{ marginTop: 0 }}>{associatedOrgs[0]}</p>
                )}
              </>
            )}
          </div>
          {associatedOrgs?.length > 1 && (
            <div className="associated-organizations-info vads-u-margin-top--1p5">
              <va-additional-info
                trigger="See associated organizations"
                disable-border
                uswds
              >
                {associatedOrgs?.map((org, index) => {
                  return (
                    <>
                      <p>{org}</p>
                      {index < associatedOrgs.length - 1 ? (
                        <br style={{ lineHeight: '0.625rem' }} />
                      ) : null}
                    </>
                  );
                })}
              </va-additional-info>
            </div>
          )}

          <div className="representative-contact-section vads-u-margin-top--3">
            {addressExists && (
              <div className="address-link">
                <a
                  href={`https://maps.google.com?saddr=${
                    query?.context?.location
                  }&daddr=${address}`}
                  tabIndex="0"
                  className="address-anchor"
                  onClick={() => recordContactLinkClick()}
                  target="_blank"
                  rel="noreferrer"
                  aria-label={`${address} (opens in a new tab)`}
                >
                  {addressLine1}{' '}
                  {addressLine2 ? (
                    <>
                      <br /> {addressLine2}
                    </>
                  ) : null}{' '}
                  <br />
                  {city}, {stateCode} {zipCode}
                </a>
              </div>
            )}
            {phone && (
              <div className="vads-u-margin-top--1p5">
                <va-telephone
                  contact={contact}
                  extension={extension}
                  onClick={() => recordContactLinkClick()}
                  disable-analytics
                />
              </div>
            )}
            {email && (
              <div className="vads-u-margin-top--1p5">
                <a
                  href={`mailto:${email}`}
                  onClick={() => recordContactLinkClick()}
                >
                  {email}
                </a>
              </div>
            )}
          </div>
          {reportFeatureEnabled && (
            <div className="experimental-parent">
              {reports && (
                <div className="report-thank-you-alert">
                  <va-alert
                    class="thank-you-alert vads-u-margin-bottom--2"
                    id={`thank-you-alert-${representativeId}`}
                    close-btn-aria-label="Close notification"
                    disable-analytics="false"
                    full-width="false"
                    slim
                    status="info"
                    uswds
                    visible="true"
                  >
                    <p className="vads-u-margin-y--0">
                      Thanks for reporting outdated information.
                    </p>
                  </va-alert>
                </div>
              )}
              <div className="report-outdated-information-button">
                <va-button
                  onClick={() => {
                    recordReportButtonClick();
                    setReportModalIsShowing(true);
                  }}
                  id={`report-button-${representativeId}`}
                  secondary
                  text="Report outdated information"
                  label={`Report outdated information for ${officer}`}
                  uswds
                  disable-analytics
                />
              </div>
            </div>
          )}
        </div>
      </va-card>
    </div>
  );
};

SearchResult.propTypes = {
  addressLine1: PropTypes.string,
  addressLine2: PropTypes.string,
  addressLine3: PropTypes.string,
  associatedOrgs: PropTypes.array,
  city: PropTypes.string,
  distance: PropTypes.string,
  email: PropTypes.string,
  initializeRepresentativeReport: PropTypes.func,
  key: PropTypes.number,
  officer: PropTypes.string,
  phone: PropTypes.string,
  query: PropTypes.shape({
    context: PropTypes.shape({
      location: PropTypes.string,
    }),
    locationQueryString: PropTypes.string,
    representativeType: PropTypes.string,
    searchArea: PropTypes.string,
    representativeQueryString: PropTypes.string,
  }),
  reportSubmissionStatus: PropTypes.string,
  reports: PropTypes.shape({
    phone: PropTypes.string,
    email: PropTypes.string,
    address: PropTypes.string,
    other: PropTypes.string,
  }),
  representativeId: PropTypes.string,
  searchResults: PropTypes.shape({
    meta: PropTypes.shape({
      pagination: PropTypes.shape({
        totalEntries: PropTypes.number,
        totalPages: PropTypes.number,
        currentPage: PropTypes.number,
      }),
    }),
  }),
  setReportModalTester: PropTypes.func,
  stateCode: PropTypes.string,
  submitRepresentativeReport: PropTypes.func,
  type: PropTypes.string,
  zipCode: PropTypes.string,
};

export default SearchResult;