department-of-veterans-affairs/vets-website

View on GitHub
src/applications/vaos/appointment-list/components/AppointmentsPage/RequestListItem.jsx

Summary

Maintainability
B
5 hrs
Test Coverage
import React from 'react';
import { useHistory } from 'react-router-dom';
import { focusElement } from '@department-of-veterans-affairs/platform-utilities/ui';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { sentenceCase } from '../../../utils/formatters';
import { getPreferredCommunityCareProviderName } from '../../../services/appointment';
import { APPOINTMENT_STATUS, SPACE_BAR } from '../../../utils/constants';
import { selectFeatureBreadcrumbUrlUpdate } from '../../../redux/selectors';

function handleClick({ history, link, idClickable }) {
  return () => {
    if (!window.getSelection().toString()) {
      focusElement(`#${idClickable}`);
      history.push(link);
    }
  };
}

function handleKeyDown({ history, link, idClickable }) {
  return event => {
    if (!window.getSelection().toString() && event.keyCode === SPACE_BAR) {
      focusElement(`#${idClickable}`);
      history.push(link);
    }
  };
}

export default function RequestListItem({ appointment, facility }) {
  const history = useHistory();
  const isCC = appointment.vaos.isCommunityCare;
  const typeOfCareText = sentenceCase(appointment.type?.coding?.[0]?.display);
  const ccFacilityName = getPreferredCommunityCareProviderName(appointment);
  const canceled = appointment.status === APPOINTMENT_STATUS.cancelled;
  const preferredDate = appointment?.preferredDate;
  const idClickable = `id-${appointment.id?.replace('.', '\\.')}`;

  const featureBreadcrumbUrlUpdate = useSelector(state =>
    selectFeatureBreadcrumbUrlUpdate(state),
  );
  const link = `${featureBreadcrumbUrlUpdate ? 'pending' : 'requests'}/${
    appointment.id
  }`;

  return (
    <li
      id={idClickable}
      data-request-id={appointment.id}
      className="vaos-appts__card--clickable vads-u-margin-bottom--3"
      data-cy="requested-appointment-list-item"
    >
      {/* Disabling for now since add role=button and tab=0 fails another accessiblity check: */}
      {/* Nested interactive controls are not announced by screen readers */}
      {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
      <div
        className="vads-u-padding--2 vads-u-display--flex vads-u-align-items--left vads-u-flex-direction--column medium-screen:vads-u-padding--3 medium-screen:vads-u-flex-direction--row medium-screen:vads-u-align-items--center"
        onClick={handleClick({
          history,
          link,
          idClickable,
        })}
        onKeyDown={handleKeyDown({
          history,
          link,
          idClickable,
        })}
      >
        <div className="vads-u-flex--1 vads-u-margin-y--neg0p5">
          {canceled && (
            <div className="vads-u-margin-bottom--1">
              <span className="usa-label">Canceled</span>
            </div>
          )}
          <h3 className="vads-u-margin-y--0 vads-u-margin-bottom--0p25">
            {sentenceCase(typeOfCareText)}
          </h3>
          {!!facility && !isCC && facility.name}
          {isCC && ccFacilityName}
        </div>
        <div className="vads-u-flex--auto vads-u-padding-top--0p5 medium-screen:vads-u-padding-top--0 vaos-hide-for-print">
          <va-link
            className="vaos-appts__focus--hide-outline"
            aria-label={`Details for ${
              canceled ? 'canceled ' : ''
            }${typeOfCareText}request for ${preferredDate}`}
            href={link}
            text="Details"
            data-testid="appointment-detail-link"
          />
          <span className="vads-u-color--link-default vads-u-margin-left--1">
            <va-icon icon="navigate_next" size="3" aria-hidden="true" />
          </span>
        </div>
      </div>
    </li>
  );
}
RequestListItem.propTypes = {
  appointment: PropTypes.object.isRequired,
  facility: PropTypes.object,
};