department-of-veterans-affairs/vets-website

View on GitHub
src/applications/vaos/new-appointment/components/CommunityCareProviderSelectionPage/ProviderSortVariant.jsx

Summary

Maintainability
B
5 hrs
Test Coverage
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { VaSelect } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { FACILITY_SORT_METHODS, FETCH_STATUS } from '../../../utils/constants';
import { selectProviderSelectionInfo } from '../../redux/selectors';
import {
  requestProvidersList,
  updateCCProviderSortMethod,
} from '../../redux/actions';
import { scrollAndFocus } from '../../../utils/scrollAndFocus';
import InfoAlert from '../../../components/InfoAlert';
import NoAddressNote from '../NoAddressNote';

export default function ProviderSortVariant({
  currentlyShownProvidersList,
  notLoading,
}) {
  const dispatch = useDispatch();
  const {
    address,
    ccEnabledSystems,
    communityCareProviderList,
    currentLocation,
    requestLocationStatus,
    requestStatus,
    selectedCCFacility,
    sortMethod,
  } = useSelector(selectProviderSelectionInfo, shallowEqual);

  const [selectedSortMethod, setSelectedSortMethod] = useState(sortMethod);
  const sortOptions = [
    {
      value: FACILITY_SORT_METHODS.distanceFromCurrentLocation,
      label: 'Your current location',
    },
    ...ccEnabledSystems.map(facility => {
      return {
        value: facility.id,
        label: `${facility.address?.city}, ${facility.address?.state}`,
      };
    }),
  ];

  useEffect(
    () => {
      if (sortMethod === FACILITY_SORT_METHODS.distanceFromCurrentLocation) {
        dispatch(requestProvidersList(currentLocation));
      } else if (sortMethod === FACILITY_SORT_METHODS.distanceFromResidential) {
        dispatch(requestProvidersList(address));
      } else {
        dispatch(requestProvidersList(selectedCCFacility?.position));
      }

      if (communityCareProviderList) {
        scrollAndFocus('#providerSelectionHeader');
      }
    },
    [selectedCCFacility, sortMethod],
  );

  const onValueChange = option => {
    if (Object.values(FACILITY_SORT_METHODS).includes(option.detail.value)) {
      setSelectedSortMethod(option.detail.value);
      dispatch(updateCCProviderSortMethod(option.detail.value));
    } else {
      const selectedFacility = ccEnabledSystems.find(
        facility => facility.id === option.detail.value,
      );
      setSelectedSortMethod(selectedFacility.id);
      dispatch(
        updateCCProviderSortMethod(
          FACILITY_SORT_METHODS.distanceFromFacility,
          selectedFacility,
        ),
      );
    }
  };
  const hasUserAddress = address && !!Object.keys(address).length;
  const requestLocationStatusFailed =
    requestLocationStatus === FETCH_STATUS.failed;
  const requestProvidersFailed = requestStatus === FETCH_STATUS.failed;

  if (hasUserAddress) {
    sortOptions.unshift({
      value: FACILITY_SORT_METHODS.distanceFromResidential,
      label: 'Your home address',
    });
  } else {
    sortOptions.push({
      value: FACILITY_SORT_METHODS.distanceFromCurrentLocation,
      label: 'Your current location',
    });
  }

  // format optons for new component
  const options = sortOptions.map((s, i) => {
    return (
      <option key={i} value={s.value}>
        {s.label}
      </option>
    );
  });

  return (
    <div className="vads-u-margin-bottom--3">
      {notLoading &&
        !requestProvidersFailed &&
        currentlyShownProvidersList.length > 0 && (
          <p
            className="vads-u-margin--0"
            id="provider-list-status"
            role="status"
            aria-live="polite"
            aria-atomic="true"
          >
            Displaying {currentlyShownProvidersList.length} of{' '}
            {communityCareProviderList.length} providers
          </p>
        )}
      <VaSelect
        label="Show providers nearest to this location:"
        name="sort"
        onVaSelect={onValueChange}
        value={selectedSortMethod}
        data-testid="providersSelect"
        uswds
      >
        {hasUserAddress ? options : options.slice(1)}
      </VaSelect>
      {!hasUserAddress && <NoAddressNote />}
      {requestLocationStatusFailed && (
        <div
          id="providerSelectionBlockedLocation"
          className="vads-u-margin-top--3"
        >
          <InfoAlert
            status="warning"
            headline="Your browser is blocked from finding your current location."
            className="vads-u-background-color--gold-lightest vads-u-font-size--base"
            level="3"
          >
            <>
              <p>Make sure your browser’s location feature is turned on.</p>

              <button
                className="va-button-link"
                onClick={() =>
                  dispatch(
                    updateCCProviderSortMethod(
                      FACILITY_SORT_METHODS.distanceFromCurrentLocation,
                    ),
                  )
                }
              >
                Retry searching based on current location
              </button>
            </>
          </InfoAlert>
        </div>
      )}
    </div>
  );
}

ProviderSortVariant.propTypes = {
  currentlyShownProvidersList: PropTypes.array,
  notLoading: PropTypes.bool,
};