department-of-veterans-affairs/vets-website

View on GitHub
src/applications/financial-status-report/components/monetary/CashInBank.jsx

Summary

Maintainability
D
1 day
Test Coverage
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { setData } from 'platform/forms-system/src/js/actions';
import FormNavButtons from 'platform/forms-system/src/js/components/FormNavButtons';
import { VaTextInput } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { safeNumber } from '../../utils/calculateIncome';
import { currency as currencyFormatter } from '../../utils/helpers';
import { isStreamlinedShortForm } from '../../utils/streamlinedDepends';
import ReviewPageHeader from '../shared/ReviewPageHeader';

const CASH_IN_BANK = 'Cash in a bank (savings and checkings)';
const CASH_ON_HAND = 'Cash on hand (not in bank)';

const CashInBank = ({
  contentBeforeButtons,
  contentAfterButtons,
  data,
  goBack,
  goForward,
  setFormData,
}) => {
  const { assets, gmtData } = data;
  const { monetaryAssets = [] } = assets;

  const cashInBankTotal = monetaryAssets.find(f => f.name === CASH_IN_BANK) ?? {
    amount: '',
  };
  const cashOnHandTotal = monetaryAssets.find(f => f.name === CASH_ON_HAND) ?? {
    amount: '',
  };

  const [cash, setCash] = useState(cashInBankTotal.amount);
  const ERR_MSG = 'Please enter a valid dollar amount';
  const [error, setError] = useState(null);

  const updateFormData = () => {
    if (!isValidCurrency(cash)) {
      return setError(ERR_MSG);
    }

    const newMonetaryAssetsArray = monetaryAssets.filter(
      asset => asset.name !== CASH_IN_BANK,
    );

    const liquidCash = safeNumber(cash) + safeNumber(cashOnHandTotal.amount);

    // update form data & gmtIsShort
    setFormData({
      ...data,
      assets: {
        ...assets,
        monetaryAssets: [
          ...newMonetaryAssetsArray,
          { name: CASH_IN_BANK, amount: cash },
        ],
      },
      gmtData: {
        ...gmtData,
        liquidAssetsBelowGmt: liquidCash < gmtData?.assetThreshold,
      },
    });

    return setError(null);
  };

  const onBlur = () => {
    if (!isValidCurrency(cash)) {
      setError(ERR_MSG);
    } else {
      setError(null);
    }
  };

  const onSubmit = event => {
    event.preventDefault();
    if (!error) {
      goForward(data);
    }
  };

  return (
    <form onSubmit={onSubmit}>
      <fieldset className="vads-u-margin-y--2">
        <legend className="schemaform-block-title">
          <h3 className="vads-u-margin--0">Cash in bank</h3>
        </legend>
        <VaTextInput
          currency
          error={error}
          hint={null}
          id="cash"
          inputmode="decimal"
          type="decimal"
          label="What is the total amount you have in all checking and savings accounts?"
          name="cash"
          onBlur={onBlur}
          onInput={({ target }) => setCash(target.value)}
          required
          value={cash}
          width="md"
        />
        {contentBeforeButtons}
        <FormNavButtons
          goBack={goBack}
          goForward={updateFormData}
          submitToContinue
        />
        {contentAfterButtons}
      </fieldset>
    </form>
  );
};

CashInBank.propTypes = {
  contentAfterButtons: PropTypes.object,
  contentBeforeButtons: PropTypes.object,
  data: PropTypes.shape({
    assets: PropTypes.shape({
      monetaryAssets: PropTypes.array,
    }),
    gmtData: PropTypes.shape({
      assetThreshold: PropTypes.number,
    }),
  }),
  goBack: PropTypes.func,
  goForward: PropTypes.func,
  setFormData: PropTypes.func,
};

// This review section should only show for SW short form
//  otherwise the assets will show in the monetary assets section
const CashInBankReview = ({ data, goToPath }) => {
  const dispatch = useDispatch();
  const {
    assets,
    gmtData,
    'view:reviewPageNavigationToggle': showReviewNavigation,
  } = data;
  const { monetaryAssets = [] } = assets;

  // we want this to show if a short form exited early and they have no other monetary assets where it
  //  would normally render the monetary asset list
  const noOtherMonetaryAssets =
    monetaryAssets.filter(
      asset =>
        asset?.name?.toLowerCase() !== 'cash on hand (not in bank)' &&
        asset?.name?.toLowerCase() !== 'cash in a bank (savings and checkings)',
    ).length === 0;

  // set reviewNavigation to true to show the review page alert
  const onReviewClick = () => {
    dispatch(
      setData({
        ...data,
        reviewNavigation: true,
      }),
    );

    // if the user saw cash on hand/in bank, they should be routed to
    //  cash on hand page since it's the head of the chapter
    const gmtDepends =
      (gmtData?.isEligibleForStreamlined && gmtData?.incomeBelowGmt) ||
      (gmtData?.isEligibleForStreamlined &&
        gmtData?.incomeBelowOneFiftyGmt &&
        data['view:streamlinedWaiverAssetUpdate']);

    if (gmtDepends || data['view:reviewPageNavigationToggle']) {
      return goToPath('/cash-on-hand');
    }
    return goToPath('/monetary-asset-checklist');
  };

  return isStreamlinedShortForm(data) || noOtherMonetaryAssets ? (
    <>
      {showReviewNavigation ? (
        <ReviewPageHeader title="household assets" goToPath={onReviewClick} />
      ) : null}
      <div className="form-review-panel-page">
        <div className="form-review-panel-page-header-row">
          <h4 className="form-review-panel-page-header vads-u-font-size--h5">
            Monetary assets
          </h4>
        </div>
        <dl className="review">
          {monetaryAssets.map((income, index) => {
            return (
              <div
                className="review-row"
                key={income.name + income.amount + index}
              >
                <dt>{income.name}</dt>
                <dd>{currencyFormatter(income.amount)}</dd>
              </div>
            );
          })}
        </dl>
      </div>
    </>
  ) : null;
};

CashInBankReview.propTypes = {
  data: PropTypes.shape({
    'view:reviewPageNavigationToggle': PropTypes.bool,
    assets: PropTypes.shape({
      monetaryAssets: PropTypes.array,
    }),
    gmtData: PropTypes.shape({
      incomeBelowGmt: PropTypes.bool,
      isEligibleForStreamlined: PropTypes.bool,
      incomeBelowOneFiftyGmt: PropTypes.bool,
    }),
    'view:streamlinedWaiverAssetUpdate': PropTypes.bool,
  }),
};

export { CashInBank, CashInBankReview };