department-of-veterans-affairs/vets-website

View on GitHub
src/applications/financial-status-report/components/householdIncome/PayrollDeductionInputList.jsx

Summary

Maintainability
F
5 days
Test Coverage
import React, { useState } from 'react';
import { useSelector, connect } from 'react-redux';
import { setData } from 'platform/forms-system/src/js/actions';
import PropTypes from 'prop-types';
import {
  getJobIndex,
  getJobButton,
  jobButtonConstants,
} from '../../utils/session';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
import { isValidCurrency } from '../../utils/validations';
import ButtonGroup from '../shared/ButtonGroup';

const PayrollDeductionInputList = props => {
  const { goToPath, goBack, setFormData } = props;

  const editIndex = getJobIndex();

  const isEditing = editIndex && !Number.isNaN(editIndex);

  const userType = 'veteran';

  const index = isEditing ? Number(editIndex) : 0;

  const formData = useSelector(state => state.form.data);

  const MAXIMUM_DEDUCTION_AMOUNT = 40000;

  const {
    personalData: {
      employmentHistory: {
        veteran: { employmentRecords = [] } = {},
        newRecord = {},
      } = {},
    },
  } = formData;

  const employmentRecord = isEditing ? employmentRecords[index] : newRecord;

  const { employerName, deductions } = employmentRecord;

  const [selectedDeductions, setSelectedDeductions] = useState(deductions);

  const [errors, setErrors] = useState([]);

  const mapDeductions = target => {
    return selectedDeductions.map(deduction => {
      if (deduction.name === target.name) {
        return {
          ...deduction,
          amount: target.value,
        };
      }
      return deduction;
    });
  };

  const onChange = event => {
    const { target } = event;
    const updatedDeductions = mapDeductions(target);
    setSelectedDeductions(updatedDeductions);
    if (
      !isValidCurrency(target.value) ||
      target.value > MAXIMUM_DEDUCTION_AMOUNT
    ) {
      setErrors([...errors, target.name]);
    } else {
      setErrors(errors.filter(error => error !== target.name));
    }
  };

  const getContinueButtonText = () => {
    if (getJobButton() === jobButtonConstants.FIRST_JOB) {
      return 'Continue';
    }

    if (getJobButton() === jobButtonConstants.EDIT_JOB) {
      return 'Update employment record';
    }
    return 'Add employment record';
  };

  const updateFormData = e => {
    e.preventDefault();

    const errorList = selectedDeductions
      .filter(
        item =>
          !isValidCurrency(item.amount) ||
          item.amount > MAXIMUM_DEDUCTION_AMOUNT,
      )
      .map(item => item.name);

    setErrors(errorList);

    if (errorList.length) return;

    if (isEditing) {
      // find the one we are editing in the employeeRecords array
      const updatedRecords = formData.personalData.employmentHistory.veteran.employmentRecords.map(
        (item, arrayIndex) => {
          return arrayIndex === index
            ? {
                ...employmentRecord,
                deductions: selectedDeductions,
              }
            : item;
        },
      );
      // update form data
      setFormData({
        ...formData,
        personalData: {
          ...formData.personalData,
          employmentHistory: {
            ...formData.personalData.employmentHistory,
            [`${userType}`]: {
              ...formData.personalData.employmentHistory[`${userType}`],
              employmentRecords: updatedRecords,
            },
          },
        },
      });
    } else {
      setFormData({
        ...formData,
        personalData: {
          ...formData.personalData,
          employmentHistory: {
            ...formData.personalData.employmentHistory,
            newRecord: { ...BASE_EMPLOYMENT_RECORD },
            [`${userType}`]: {
              ...formData.personalData.employmentHistory[`${userType}`],
              employmentRecords: [
                { ...employmentRecord, deductions: selectedDeductions },
                ...employmentRecords,
              ],
            },
          },
        },
      });
    }
    goToPath(`/employment-history`);
  };

  const navButtons = (
    <ButtonGroup
      buttons={[
        {
          label: 'Back',
          onClick: goBack, // Define this function based on page-specific logic
          isSecondary: true,
        },
        {
          label: getContinueButtonText(),
          onClick: updateFormData,
          isSubmitting: 'prevent', // If this button submits a form
        },
      ]}
    />
  );

  return (
    <form onSubmit={updateFormData}>
      <fieldset className="vads-u-margin-y--2">
        <legend className="schemaform-block-title">
          <h3 className="vads-u-margin--0">Your job at {employerName}</h3>
          <p className="vads-u-margin-bottom--neg1 vads-u-margin-top--3 vads-u-padding-bottom--0p25 vads-u-font-family--sans vads-u-font-weight--normal vads-u-font-size--base">
            How much do you pay monthly for each of your payroll deductions?
          </p>
        </legend>
        {selectedDeductions?.map((deduction, key) => (
          <div key={deduction.name + key}>
            <va-text-input
              label={deduction.name}
              name={deduction.name}
              value={deduction.amount}
              id={deduction.name + key}
              inputmode="decimal"
              type="decimal"
              onInput={onChange}
              required
              currency
              width="md"
              min={0}
              max={MAXIMUM_DEDUCTION_AMOUNT}
              error={
                errors.includes(deduction.name)
                  ? 'Please enter a valid dollar amount below $40,000'
                  : null
              }
            />
          </div>
        ))}
        <va-additional-info
          trigger="How to calculate your monthly deductions"
          class="vads-u-margin-top--2"
        >
          <p>
            First, find the total deduction amount on your pay stub. Then follow
            the step that applies to you:
          </p>
          <ol className="vads-u-margin--0 vads-u-padding-left--4 vads-u-padding-top--2 vads-u-padding-bottom--0p25">
            <li>
              <strong>If you are paid weekly,</strong> multiply your deduction
              amount by 4.
            </li>
            <li>
              <strong>If you are paid every other week,</strong> multiply your
              deduction amount by 26. Then divide the total by 12 to get your
              monthly amount.
            </li>
            <li>
              <strong>If you are paid twice a month,</strong> multiply your
              deduction amount by 2 to get your monthly amount.
            </li>
            <li>
              <strong>If you are paid monthly,</strong> enter the deduction
              amount from your pay stub.
            </li>
          </ol>
        </va-additional-info>
      </fieldset>
      {navButtons}
    </form>
  );
};

const mapStateToProps = ({ form }) => {
  return {
    formData: form.data,
    employmentHistory: form.data.personalData.employmentHistory,
  };
};

const mapDispatchToProps = {
  setFormData: setData,
};

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(PayrollDeductionInputList);

PayrollDeductionInputList.propTypes = {
  goBack: PropTypes.func.isRequired,
  goToPath: PropTypes.func.isRequired,
  setFormData: PropTypes.func.isRequired,
  onReviewPage: PropTypes.bool,
};