department-of-veterans-affairs/vets-website

View on GitHub
src/applications/verify-your-enrollment/containers/ChangeOfAddressWrapper.jsx

Summary

Maintainability
F
5 days
Test Coverage
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import '../sass/change-of-address-wrapper.scss';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import LoadingButton from '~/platform/site-wide/loading-button/LoadingButton';
import ChangeOfAddressForm from '../components/ChangeOfAddressForm';
import {
  compareAddressObjects,
  formatAddress,
  hasAddressFormChanged,
  prepareAddressData,
  removeCommas,
  scrollToElement,
} from '../helpers';
import {
  CHANGE_OF_ADDRESS_TITLE,
  ADDRESS_BUTTON_TEXT,
} from '../constants/index';
import { handleSuggestedAddressPicked, validateAddress } from '../actions';
import Alert from '../components/Alert';
import Loader from '../components/Loader';
import SuggestedAddress from '../components/SuggestedAddress';
import AlertModal from '../components/AlertModal';

const ChangeOfAddressWrapper = ({ mailingAddress, loading, applicantName }) => {
  const { loading: isLoading, error, data: response } = useSelector(
    state => state.updateAddress,
  );
  const {
    addressValidationData,
    validationError,
    isLoadingValidateAddress,
  } = useSelector(state => state.addressValidation);
  const address = addressValidationData?.addresses[0]?.address;
  const confidenceScore =
    addressValidationData?.addresses[0]?.addressMetaData?.confidenceScore;
  const addressType =
    addressValidationData?.addresses[0]?.addressMetaData?.addressType;
  const [toggleAddressForm, setToggleAddressForm] = useState(false);
  const [formData, setFormData] = useState({});
  const [editFormData, setEditFormData] = useState({});
  const [beforeDditFormData, setBeforeEditFormData] = useState({});
  const [suggestedAddressPicked, setSuggestedAddressPicked] = useState(false);
  const [newAddress, setNewAddress] = useState({});
  const [goBackToEdit, setGoBackToEdit] = useState(false);
  const [showModal, setShowModal] = useState(false);
  const dispatch = useDispatch();
  const PREFIX = 'GI-Bill-Chapters-';
  const location = useLocation();
  const scrollToTopOfForm = () => {
    scrollToElement('Contact information');
  };
  useEffect(() => {
    document.title =
      'Your Montgomery GI Bill benefits information | Veterans Affairs';
  }, []);

  // This Effcet to defalut setNewAddress to mailingAddress
  useEffect(
    () => {
      setNewAddress(mailingAddress);
    },
    [mailingAddress],
  );
  const handleCloseForm = useCallback(
    () => {
      setFormData({});
      if (confidenceScore === 100 && response) {
        const stateAndZip = {
          stateCode: address.stateCode,
          zipCode: address.zipCode,
        };
        setNewAddress({
          street: `${address.addressLine1} ${address.addressLine2 || ''}`,
          city: address.city,
          ...stateAndZip,
        });
      }
      sessionStorage.setItem('address', JSON.stringify(address));
      setToggleAddressForm(false);
      scrollToTopOfForm();
    },
    [confidenceScore, response, address],
  );

  // called when submitting form
  const saveAddressInfo = async () => {
    setBeforeEditFormData(formData);
    if (Object.keys(formData).length === 0) {
      Object.assign(formData, editFormData);
    }

    const addressData = prepareAddressData(formData);
    const fields = {
      address: addressData,
    };
    try {
      dispatch(validateAddress(removeCommas(fields), applicantName));
    } catch (err) {
      throw new Error(err);
    }
    if (validationError) {
      setEditFormData({});
    }
    scrollToTopOfForm();
  };

  // This Effcet to close form after loading is done
  useEffect(
    () => {
      if (
        !isLoading &&
        !isLoadingValidateAddress &&
        (addressValidationData || validationError)
      ) {
        handleCloseForm();
        setSuggestedAddressPicked(false);
      }
    },
    [
      addressValidationData,
      handleCloseForm,
      isLoading,
      isLoadingValidateAddress,
      validationError,
    ],
  );
  const setAddressToUI = value => {
    setNewAddress(value);
  };

  // This effect to reset setEditFormData and remove address from sessionStorage
  // When there is error, resonse or validationError
  useEffect(
    () => {
      setEditFormData({});
      sessionStorage.removeItem('address');
      dispatch({ type: 'RESET_ADDRESS_VALIDATIONS' });
      dispatch(handleSuggestedAddressPicked(false));
    },
    [dispatch, error, response, validationError],
  );
  useEffect(
    () => {
      dispatch({ type: 'RESET_ADDRESS_VALIDATIONS' });
      dispatch({ type: 'RESET_SUCCESS_MESSAGE' });
      dispatch({ type: 'RESET_ERROR' });
      dispatch({ type: 'RESET_ADDRESS_VALIDATIONS_ERROR' });
    },
    [dispatch, location.pathname],
  );
  const addressDescription = () => {
    return (
      <>
        {loading ? (
          <va-loading-indicator
            label="Loading"
            message="Loading mailing address..."
            aria-hidden="true"
          />
        ) : (
          <div className="vads-u-margin-bottom--1">
            {(error || validationError) && (
              <Alert
                status="error"
                message="We’re sorry. We can’t update your information right now. We’re working to fix this problem. Please try again later."
              />
            )}
            {response?.ok && (
              <Alert
                status="success"
                message="We’ve successfully updated your mailing address for Montgomery GI Bill benefits."
              />
            )}
            <h3 className="vads-u-line-height--4 vads-u-font-size--base vads-u-font-family--sans vads-u-margin-y--0">
              Mailing address
            </h3>
            <p>
              <>
                <span className="vads-u-display--block">
                  {newAddress?.street ?? ''}
                  {newAddress?.street2 && <br />}
                  {newAddress?.street2 ?? ''}
                </span>
                <span className="vads-u-display--block">
                  {formatAddress(newAddress)}
                </span>
              </>
            </p>
          </div>
        )}
      </>
    );
  };

  const handleAddNewClick = event => {
    event?.preventDefault();
    setFormData({});
    setToggleAddressForm(true);
    scrollToTopOfForm();
    dispatch({ type: 'RESET_ERROR' });
    setGoBackToEdit(false);
  };
  const cancelEditClick = () => {
    setShowModal(false);
    setEditFormData({});
    dispatch({ type: 'RESET_ADDRESS_VALIDATIONS' });
    handleCloseForm();
  };
  const onCancleButtonClicked = () => {
    if (
      (hasAddressFormChanged(formData) && !goBackToEdit) ||
      (goBackToEdit && compareAddressObjects(editFormData, beforeDditFormData))
    ) {
      setShowModal(true);
    } else {
      cancelEditClick();
    }
  };

  const updateAddressData = data => {
    const tempData = { ...data };
    if (tempData?.['view:livesOnMilitaryBase']) {
      tempData.countryCodeIso3 = 'USA';
    }
    if (
      !tempData?.['view:livesOnMilitaryBase'] &&
      (tempData?.city === 'APO' ||
        tempData?.city === 'FPO' ||
        tempData?.city === 'DPO')
    ) {
      tempData.city = '';
    }

    setFormData(tempData);
    setEditFormData(tempData);
  };

  return (
    <div id={CHANGE_OF_ADDRESS_TITLE}>
      <h2 className="vads-u-font-family--serif vads-u-margin-y--4">
        {CHANGE_OF_ADDRESS_TITLE}
      </h2>
      <div
        className="vads-u-border-color--gray-lighter
            vads-u-color-gray-dark
            vads-u-display--flex
            vads-u-flex-direction--column
            vads-u-padding-x--2
            vads-u-padding-y--1p5
            medium-screen:vads-u-padding--4
            vads-u-border--1px"
      >
        {!toggleAddressForm && (
          <>
            {suggestedAddressPicked ||
            confidenceScore < (addressType === 'International' ? 96 : 100) ? (
              <SuggestedAddress
                formData={editFormData}
                address={JSON.parse(sessionStorage.getItem('address'))}
                handleAddNewClick={event => handleAddNewClick(event)}
                setFormData={setFormData}
                setAddressToUI={setAddressToUI}
                setSuggestedAddressPicked={setSuggestedAddressPicked}
                suggestedAddressPicked={suggestedAddressPicked}
                setGoBackToEdit={setGoBackToEdit}
                scrollToTopOfForm={scrollToTopOfForm}
                applicantName={applicantName}
              />
            ) : (
              <>
                {addressDescription()}
                <va-button
                  id="VYE-mailing-address-button"
                  onClick={event => handleAddNewClick(event)}
                  text={ADDRESS_BUTTON_TEXT}
                />
              </>
            )}
            <div>
              <p>
                <span className="vads-u-font-weight--bold">Note: </span> Any
                updates you make here will affect your Montgomery GI Bill
                benefits only.
              </p>
              <va-link
                href="/resources/change-your-address-on-file-with-va/"
                text="Learn how to update your mailing address for other VA benefits"
              />
            </div>
          </>
        )}
        {toggleAddressForm && (
          <div className="address-change-form-container">
            <h3 className="vads-u-margin-y--2 vads-u-line-height--4 vads-u-font-size--base vads-u-font-family--sans">
              Change mailing address
            </h3>
            {(isLoadingValidateAddress || isLoading) && (
              <Loader className="loader" message="updating..." />
            )}
            <AlertModal
              showModal={showModal}
              setShowModal={setShowModal}
              cancelEditClick={cancelEditClick}
              formType=" mailing address"
            />

            <ChangeOfAddressForm
              addressFormData={formData}
              formChange={addressData => updateAddressData(addressData)}
              formPrefix={PREFIX}
              formSubmit={saveAddressInfo}
              formData={editFormData}
            >
              <div className="button-container">
                <LoadingButton
                  aria-label="save your mailing address for GI Bill benefits"
                  type="submit"
                  loadingText="saving Mailling address"
                  className="usa-button-primary vads-u-margin-top--0 address-submit-btn-auto-width"
                >
                  Save
                </LoadingButton>
                <va-button
                  text="Cancel"
                  secondary
                  label="cancel updating your mailing address for GI Bill benefits"
                  onClick={onCancleButtonClicked}
                  data-qa="cancel-button"
                  data-testid={`${PREFIX}form-cancel-button`}
                />
              </div>
            </ChangeOfAddressForm>
          </div>
        )}
      </div>
    </div>
  );
};
ChangeOfAddressWrapper.propTypes = {
  applicantName: PropTypes.string,
  loading: PropTypes.bool,
  mailingAddress: PropTypes.object,
};
export default ChangeOfAddressWrapper;