department-of-veterans-affairs/vets-website

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

Summary

Maintainability
A
1 hr
Test Coverage
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import moment from 'moment';
import AppointmentColumn from './AppointmentColumn';
import AppointmentRow from './AppointmentRow';
import {
  selectAppointmentLocality,
  selectIsCanceled,
  selectModalityText,
  selectModalityIcon,
  selectStartDate,
  selectTimeZoneAbbr,
  selectApptDetailAriaText,
  selectApptDateAriaText,
  selectTypeOfCareAriaText,
  selectModalityAriaText,
  selectIsCommunityCare,
} from '../../redux/selectors';

export default function AppointmentColumnLayout({
  data,
  first,
  grouped,
  link,
}) {
  const appointmentLocality = useSelector(() =>
    selectAppointmentLocality(data),
  );
  const isCanceled = useSelector(() => selectIsCanceled(data));
  const isCommunityCare = useSelector(() => selectIsCommunityCare(data));
  const modalityText = useSelector(() => selectModalityText(data));
  const modalityIcon = useSelector(() => selectModalityIcon(data));
  const startDate = useSelector(() => selectStartDate(data));
  const parsedDate = moment.parseZone(startDate);
  const timezoneAbbr = useSelector(() => selectTimeZoneAbbr(data));

  const detailAriaLabel = useSelector(() => selectApptDetailAriaText(data));
  const dateAriaLabel = useSelector(() => selectApptDateAriaText(data));
  const typeOfCareAriaLabel = useSelector(() => selectTypeOfCareAriaText(data));
  const modalityAriaLabel = useSelector(() => selectModalityAriaText(data));

  return (
    <>
      {/* Column 1 */}
      <AppointmentColumn
        size="1"
        className={classNames(
          'vads-u-flex--auto',
          'xsmall-screen:vads-u-padding-top--1',
          'medium-screen:vads-u-padding-top--0',
        )}
        aria-label={dateAriaLabel}
      >
        <AppointmentRow
          className={classNames(
            'vaos-appts__column--alignItems',
            'vaos-appts__column-gap--1',
            'mobile:vads-u-text-align--center',
            'small-screen:vads-u-flex-direction--row',
            'medium-screen:vads-u-padding-y--2',
          )}
        >
          <AppointmentColumn
            size="1"
            className={classNames(
              'small-screen:vads-u-flex--auto',
              'small-screen:vads-u-order--first',
              'small-screen:vads-u-padding-top--0',
              'medium-screen:vaos-appts__minWidth',
              'medium-screen:vaos-appts__maxWidth',
            )}
          >
            <h3
              className={classNames(
                'vads-u-text-align--center',
                'vads-u-margin-top--0',
                'vads-u-margin-bottom--0',
                { 'vads-u-display--none': !first },
              )}
            >
              <span aria-hidden="false">{parsedDate.format('D')}</span>
            </h3>
          </AppointmentColumn>
          <AppointmentColumn
            className={classNames(
              'vads-u-text-align--left',
              'xsmall-screen:vads-u-order--first',
              'xsmall-screen:margin-top--1',
            )}
            size="1"
            style={{
              minWidth: '30px',
              maxWidth: '30px',
              alignSelf: 'center',
            }}
          >
            <span
              className={classNames({ 'vads-u-display--none': !first })}
              aria-hidden="true"
              data-testid="day"
            >
              {parsedDate.format('ddd')}
            </span>
          </AppointmentColumn>
        </AppointmentRow>
      </AppointmentColumn>

      {/* Column 2 */}
      <AppointmentColumn
        className={classNames(
          'vads-u-padding-right--1',
          'vads-u-border-color--gray-medium',
          'xsmall-screen:vads-u-padding-top--1',
          'medium-screen:vads-u-padding-top--0',
          {
            'vads-u-border-top--1px': grouped && !first,
          },
        )}
        size="1"
      >
        <AppointmentRow
          className={classNames(
            'vaos-appts__column--alignItems',
            'small-screen:vads-u-flex-direction--row',
            'small-screen:vaos-appts__column-gap--3',
            // padding below determines the appointment row height
            'medium-screen:vads-u-padding-y--2',
          )}
        >
          <AppointmentColumn
            size="1"
            canceled={isCanceled}
            style={{ minWidth: '100px', maxWidth: '100px' }}
          >
            <span aria-hidden="true">
              {`${parsedDate.format('h:mm')} ${parsedDate.format(
                'a',
              )} ${timezoneAbbr}`}{' '}
            </span>
          </AppointmentColumn>

          <AppointmentColumn size="1" className="vads-u-flex--4">
            <AppointmentRow
              className={classNames(
                'vaos-appts__column-gap--3',
                'small-screen:vads-u-flex-direction--column',
              )}
            >
              <AppointmentColumn
                padding="0"
                size="2"
                className="vads-u-font-weight--bold vaos-appts__display--table"
                canceled={isCanceled}
                aria-label={typeOfCareAriaLabel}
              >
                <span
                  className={classNames(
                    'vaos-appts__display--table-cell',
                    'vaos-appts__text--truncate',
                  )}
                >
                  {appointmentLocality}
                </span>
              </AppointmentColumn>

              <AppointmentColumn
                padding="0"
                size="3"
                className="vaos-appts__display--table"
                canceled={isCanceled}
                aria-label={modalityAriaLabel}
              >
                <span className="vaos-appts__display--table-cell vads-u-display--flex vads-u-align-items--center">
                  {!isCommunityCare && (
                    <span
                      className={classNames(
                        'vads-u-color--gray',
                        'icon-width',
                        {
                          'vaos-appts__text--line-through': isCanceled,
                        },
                      )}
                    >
                      <va-icon
                        icon={modalityIcon}
                        size="3"
                        aria-hidden="true"
                      />
                    </span>
                  )}
                  <span className="vaos-appts__text--truncate">
                    {modalityText}
                  </span>
                </span>
              </AppointmentColumn>
            </AppointmentRow>
          </AppointmentColumn>

          <AppointmentColumn
            id={`vaos-appts__detail-${data.id}`}
            className="vaos-hide-for-print"
            padding="0"
            size="1"
          >
            <a
              className="vaos-appts__focus--hide-outline"
              aria-label={detailAriaLabel}
              href={link}
              onClick={e => e.preventDefault()}
            >
              Details
            </a>
          </AppointmentColumn>
        </AppointmentRow>
      </AppointmentColumn>
    </>
  );
}

AppointmentColumnLayout.propTypes = {
  /** Appointment data */
  data: PropTypes.object,

  /** First column flag */
  first: PropTypes.bool,

  /** Is this row of appointments part of a group? Ex. Multiply appointments on the same day. */
  grouped: PropTypes.bool,

  /** Last column flag */
  last: PropTypes.bool,

  /** Link to appointment detail */
  link: PropTypes.string,
};