department-of-veterans-affairs/vets-website

View on GitHub
src/applications/terms-of-use/containers/TermsOfUse.jsx

Summary

Maintainability
D
2 days
Test Coverage
import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { apiRequest } from '@department-of-veterans-affairs/platform-utilities/exports';
import { VaModal } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import {
  isAuthenticatedWithOAuth,
  isAuthenticatedWithSSOe,
  AUTHN_SETTINGS,
} from '@department-of-veterans-affairs/platform-user/exports';
import ContactCenterInformation from 'platform/user/authentication/components/ContactCenterInformation';
import TermsAcceptance from '../components/TermsAcceptanceAction';
import {
  parseRedirectUrl,
  declineAndLogout,
  validateWhichRedirectUrlToUse,
  touUpdatedDate,
} from '../helpers';
import { touStyles, errorMessages } from '../constants';
import touData from '../touData';

export default function TermsOfUse() {
  const isAuthenticatedWithSiS = useSelector(isAuthenticatedWithOAuth);
  const isAuthenticatedWithIAM = useSelector(isAuthenticatedWithSSOe);
  const [isDisabled, setIsDisabled] = useState(false);
  const [isMiddleAuth, setIsMiddleAuth] = useState(true);
  const [showDeclineModal, setShowDeclineModal] = useState(false);
  const [error, setError] = useState({ isError: false, message: '' });
  const [buttonPushed, setButtonPushed] = useState(0);
  const redirectLocation = new URL(window.location);
  const termsCodeExists =
    redirectLocation.searchParams.get('terms_code')?.length > 1;
  const redirectUrl = validateWhichRedirectUrlToUse(redirectLocation);
  const shouldRedirectToMobile = sessionStorage.getItem('ci') === 'vamobile';
  const isFullyAuthenticated = isAuthenticatedWithIAM || isAuthenticatedWithSiS;
  const isUnauthenticated = !isMiddleAuth && !isFullyAuthenticated;

  useEffect(
    () => {
      if (!termsCodeExists) {
        apiRequest('/terms_of_use_agreements/v1/latest').catch(response => {
          const [{ code, title }] = response.errors;
          if (code === '401' || title?.includes('Not authorized')) {
            setIsMiddleAuth(false);
          }
        });
      }

      if (redirectUrl) {
        sessionStorage.setItem(
          AUTHN_SETTINGS.RETURN_URL,
          parseRedirectUrl(redirectUrl),
        );
      }
    },
    [termsCodeExists, redirectUrl],
  );

  useEffect(
    () => {
      let timeoutId;
      const resetButton = () => {
        setButtonPushed(0);
        setIsDisabled(false);
        setError({ isError: false, message: '' });
      };

      if (error.isError && buttonPushed >= 3) {
        timeoutId = setTimeout(resetButton, 25000);
      }

      return () => {
        clearTimeout(timeoutId);
      };
    },
    [error, buttonPushed],
  );

  const handleTouClick = async type => {
    const termsCode = termsCodeExists
      ? `?terms_code=${redirectLocation.searchParams.get('terms_code')}`
      : '';

    setButtonPushed(buttonPushed + 1);

    try {
      if (buttonPushed >= 3) {
        setError({
          isError: true,
          message: errorMessages.tooManyRequests,
        });
        return;
      }

      setIsDisabled(true);
      const response = await apiRequest(
        `/terms_of_use_agreements/v1/${type}${termsCode}`,
        {
          method: 'POST',
          credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
        },
      );

      if (Object.keys(response?.termsOfUseAgreement).length) {
        // if the type was accept
        if (type === 'accept') {
          setIsDisabled(false);
          window.location = parseRedirectUrl(redirectUrl);
        }

        if (type === 'decline') {
          setShowDeclineModal(false);
          setIsDisabled(false);
          declineAndLogout({
            termsCodeExists,
            shouldRedirectToMobile,
            isAuthenticatedWithSiS,
          });
        }
      }
    } catch (err) {
      if (type === 'decline') setShowDeclineModal(true);
      setError({ isError: true, message: errorMessages.network });
      setIsDisabled(false);
    }
  };

  return (
    <>
      {isMiddleAuth &&
        !isFullyAuthenticated &&
        !isUnauthenticated && <style>{touStyles}</style>}
      <section className="usa-grid usa-grid-full">
        <article className="usa-content vads-u-padding-x--1 medium-screen:vads-u-padding-x--0">
          <h1>VA online services terms of use</h1>
          <p className="va-introtext">
            {isUnauthenticated &&
              'We’ve recently updated our terms of use for VA.gov and other VA online services. Read the updated terms on this page. If you haven’t yet accepted these terms, you can sign in and accept them now.'}
            {isMiddleAuth &&
              !isFullyAuthenticated &&
              !isUnauthenticated &&
              'To sign in, you’ll need to accept the updated terms of use. Read the updated terms on this page. Then confirm if you accept.'}
            {isFullyAuthenticated &&
              'You previously accepted these terms of use. If you want to change your answer, you can decline the terms on this page.'}
          </p>
          {isUnauthenticated && (
            <div className="vads-u-margin-y--2p5">
              <a
                className="vads-c-action-link--blue"
                href="/terms-of-use/?next=loginModal"
              >
                Sign in to VA.gov
              </a>
            </div>
          )}
          <div>
            <p>
              Version: 1<br />
              Last updated: {touUpdatedDate}
            </p>
          </div>
          <h2 id="terms-of-use">Terms of use</h2>
          <div>
            <va-accordion bordered>
              {touData.map(({ header, content }, i) => (
                <va-accordion-item
                  header={header}
                  level={3}
                  key={header}
                  part={`item-${i}`}
                >
                  {content}
                </va-accordion-item>
              ))}
            </va-accordion>
          </div>
          <h2 id="getting-va-benefits-and-services">
            Getting VA benefits and services if you don’t accept
          </h2>
          <p>
            Your decision to decline these terms won’t affect your eligibility
            for VA health care and benefits in any way. You can still get VA
            health care and benefits without using online services. If you need
            help or have questions, <ContactCenterInformation /> We’re here
            24/7.
          </p>
          <va-alert status="warning" visible>
            <h3 slot="headline" id="what-happens-if-you-decline">
              What will happen if you decline
            </h3>
            <p>
              If you decline these terms, we’ll sign you out. You can still get
              VA health care and benefits by phone, by mail, or in person. But
              you won't be able to use some VA online services until you sign in
              again and accept the terms. That includes these services:
            </p>
            <ul>
              <li>VA.gov</li>
              <li>My HealtheVet</li>
              <li>My VA Health</li>
              <li>VA: Health and Benefits mobile app</li>
            </ul>
            <p>
              This means you won’t be able to do these types of things using VA
              online services:
            </p>
            <ul>
              <li>Apply for some benefits</li>
              <li>Check your claim status</li>
              <li>Send messages to your VA health care providers</li>
              <li>Refill your prescriptions</li>
              <li>Update your personal information</li>
            </ul>
            <h4>If you have a My HealtheVet user ID and password</h4>
            <p>
              If you decline these terms, you’ll no longer be able to use your{' '}
              <strong>My HealtheVet</strong> user ID and password.
            </p>
            <p>
              To manage your benefits and care online again, you’ll need to sign
              in with a <strong>Login.gov</strong> or <strong>ID.me</strong>{' '}
              account and accept these terms. If you don’t have one of these
              accounts, you’ll need to create one.
            </p>
          </va-alert>
          <TermsAcceptance
            error={error}
            isMiddleAuth={isMiddleAuth}
            handleTouClick={handleTouClick}
            setShowDeclineModal={setShowDeclineModal}
            isFullyAuthenticated={isFullyAuthenticated}
            isUnauthenticated={isUnauthenticated}
            isDisabled={isDisabled}
          />
        </article>
        <VaModal
          visible={showDeclineModal}
          clickToClose
          onCloseEvent={() => setShowDeclineModal(false)}
          modalTitle="Decline the terms of use and sign out?"
          data-testid="modal-show"
        >
          {error.isError && (
            <va-alert
              status="error"
              slim
              visible
              uswds
              class="vads-u-margin-y--1p5"
            >
              {error.message}
            </va-alert>
          )}
          <p>
            Remember, if you have a <strong>My HealtheVet</strong> user ID and
            password, you’ll no longer be able to use it.
          </p>
          <p>
            To manage your benefits and care online again, you’ll need to sign
            in with a <strong>Login.gov</strong> or <strong>ID.me</strong>{' '}
            account and accept these terms. If you don’t have one of these
            accounts, you’ll need to create one.
          </p>
          <va-button
            onClick={() => handleTouClick('decline')}
            disabled={isDisabled}
            text="Decline and sign out"
          />
          <va-button
            onClick={() => setShowDeclineModal(false)}
            text="Go back"
            secondary
            disabled={isDisabled}
          />
        </VaModal>
      </section>
    </>
  );
}