department-of-veterans-affairs/vets-website

View on GitHub
src/applications/income-and-asset-statement/config/chapters/05-owned-assets/ownedAssetPages.js

Summary

Maintainability
F
3 days
Test Coverage
import React from 'react';
import merge from 'lodash/merge';
import {
  arrayBuilderItemFirstPageTitleUI,
  arrayBuilderItemSubsequentPageTitleUI,
  arrayBuilderYesNoSchema,
  arrayBuilderYesNoUI,
  radioUI,
  radioSchema,
  textSchema,
} from '~/platform/forms-system/src/js/web-component-patterns';
import currencyUI from 'platform/forms-system/src/js/definitions/currency';
import { VaTextInputField } from 'platform/forms-system/src/js/web-component-fields';
import { arrayBuilderPages } from '~/platform/forms-system/src/js/patterns/array-builder';
import {
  formatCurrency,
  otherRecipientRelationshipExplanationRequired,
  recipientNameRequired,
  showRecipientName,
} from '../../../helpers';
import { relationshipLabels, ownedAssetTypeLabels } from '../../../labels';
import {
  RequestPropertyOrBusinessIncomeFormAlert,
  RequestFarmIncomeFormAlert,
} from '../../../components/FormAlerts';

/** @type {ArrayBuilderOptions} */
const options = {
  arrayPath: 'ownedAssets',
  nounSingular: 'income and net worth associated with owned assets',
  nounPlural: 'incomes and net worth associated with owned assets',
  required: false,
  isItemIncomplete: item =>
    !item?.recipientRelationship ||
    !item.grossMonthlyIncome ||
    !item.ownedPortionValue ||
    !item.assetType, // include all required fields here
  maxItems: 5,
  text: {
    getItemName: item => relationshipLabels[item.recipientRelationship],
    cardDescription: item =>
      item && (
        <ul className="u-list-no-bullets vads-u-padding-left--0 vads-u-font-weight--normal">
          <li>
            Asset type:{' '}
            <span className="vads-u-font-weight--bold">
              {ownedAssetTypeLabels[item.assetType]}
            </span>
          </li>
          <li>
            Gross monthly income:{' '}
            <span className="vads-u-font-weight--bold">
              {formatCurrency(item.grossMonthlyIncome)}
            </span>
          </li>
          <li>
            Owned portion value:{' '}
            <span className="vads-u-font-weight--bold">
              {formatCurrency(item.ownedPortionValue)}
            </span>
          </li>
        </ul>
      ),
    reviewAddButtonText: 'Add another owned asset',
    alertMaxItems:
      'You have added the maximum number of allowed incomes for this application. You may edit or delete an income or choose to continue the application.',
    alertItemUpdated: 'Your owned asset information has been updated',
    alertItemDeleted: 'Your owned asset information has been deleted',
    cancelAddTitle: 'Cancel adding this owned asset',
    cancelAddButtonText: 'Cancel adding this owned asset',
    cancelAddYes: 'Yes, cancel adding this owned asset',
    cancelAddNo: 'No',
    cancelEditTitle: 'Cancel editing this owned asset',
    cancelEditYes: 'Yes, cancel editing this owned asset',
    cancelEditNo: 'No',
    deleteTitle: 'Delete this owned asset',
    deleteYes: 'Yes, delete this owned asset',
    deleteNo: 'No',
  },
};

/**
 * Cards are populated on this page above the uiSchema if items are present
 *
 * @returns {PageSchema}
 */
const summaryPage = {
  uiSchema: {
    'view:isAddingOwnedAssets': arrayBuilderYesNoUI(
      options,
      {
        title:
          'Are you or your dependents receiving or expecting to receive any income in the next 12 months generated by owned property or other physical assets?',
        labels: {
          Y: 'Yes, I have an owned asset to report',
          N: 'No, I don’t have any owned assets to report',
        },
      },
      {
        title: 'Do you have any more owned assets to report?',
        labels: {
          Y: 'Yes, I have another owned asset to report',
          N: 'No, I don’t have anymore owned assets to report',
        },
      },
    ),
  },
  schema: {
    type: 'object',
    properties: {
      'view:isAddingOwnedAssets': arrayBuilderYesNoSchema,
    },
    required: ['view:isAddingOwnedAssets'],
  },
};

/** @returns {PageSchema} */
const ownedAssetRecipientPage = {
  uiSchema: {
    ...arrayBuilderItemFirstPageTitleUI({
      title: 'Income and net worth associated with owned assets',
      nounSingular: options.nounSingular,
    }),
    recipientRelationship: radioUI({
      title:
        'What is the type of income recipient’s relationship to the Veteran?',
      labels: relationshipLabels,
    }),
    otherRecipientRelationshipType: {
      'ui:title': 'Tell us the type of relationship',
      'ui:webComponentField': VaTextInputField,
      'ui:options': {
        expandUnder: 'recipientRelationship',
        expandUnderCondition: 'OTHER',
      },
      'ui:required': (formData, index) =>
        otherRecipientRelationshipExplanationRequired(
          formData,
          index,
          'ownedAssets',
        ),
    },
    recipientName: {
      'ui:title': 'Tell us the income recipient’s name',
      'ui:webComponentField': VaTextInputField,
      'ui:options': {
        hint: 'Only needed if child, parent, custodian of child, or other',
        expandUnder: 'recipientRelationship',
        expandUnderCondition: showRecipientName,
      },
      'ui:required': (formData, index) =>
        recipientNameRequired(formData, index, 'ownedAssets'),
    },
  },
  schema: {
    type: 'object',
    properties: {
      recipientRelationship: radioSchema(Object.keys(relationshipLabels)),
      otherRecipientRelationshipType: { type: 'string' },
      recipientName: textSchema,
    },
    required: ['recipientRelationship'],
  },
};

/** @returns {PageSchema} */
const ownedAssetTypePage = {
  uiSchema: {
    ...arrayBuilderItemSubsequentPageTitleUI(
      'Income and net worth associated with owned assets',
    ),
    assetType: radioUI({
      title: 'What is the type of the owned asset?',
      labels: ownedAssetTypeLabels,
    }),
    'view:propertyOrBusinessFormRequestAlert': {
      'ui:description': RequestPropertyOrBusinessIncomeFormAlert,
      'ui:options': {
        expandUnder: 'assetType',
        expandUnderCondition: assetType =>
          assetType === 'RENTAL_PROPERTY' || assetType === 'BUSINESS',
      },
    },
    'view:farmFormRequestAlert': {
      'ui:description': RequestFarmIncomeFormAlert,
      'ui:options': {
        expandUnder: 'assetType',
        expandUnderCondition: 'FARM',
      },
    },
    grossMonthlyIncome: merge({}, currencyUI('Gross monthly income'), {
      'ui:options': {
        classNames: 'schemaform-currency-input-v3',
      },
    }),
    ownedPortionValue: merge(
      {},
      currencyUI('Value of your portion of the property'),
      {
        'ui:options': {
          classNames: 'schemaform-currency-input-v3',
        },
      },
    ),
  },
  schema: {
    type: 'object',
    properties: {
      assetType: radioSchema(Object.keys(ownedAssetTypeLabels)),
      'view:propertyOrBusinessFormRequestAlert': {
        type: 'object',
        properties: {},
      },
      'view:farmFormRequestAlert': { type: 'object', properties: {} },
      grossMonthlyIncome: { type: 'number' },
      ownedPortionValue: { type: 'number' },
    },
    required: ['assetType', 'grossMonthlyIncome', 'ownedPortionValue'],
  },
};

export const ownedAssetPages = arrayBuilderPages(options, pageBuilder => ({
  ownedAssetPagesSummary: pageBuilder.summaryPage({
    title: 'Income and net worth associated with owned assets',
    path: 'owned-assets-summary',
    uiSchema: summaryPage.uiSchema,
    schema: summaryPage.schema,
  }),
  ownedAssetRecipientPage: pageBuilder.itemPage({
    title: 'Owned asset recipient',
    path: 'owned-assets/:index/income-recipient',
    uiSchema: ownedAssetRecipientPage.uiSchema,
    schema: ownedAssetRecipientPage.schema,
  }),
  ownedAssetTypePage: pageBuilder.itemPage({
    title: 'Owned asset type',
    path: 'owned-assets/:index/income-type',
    uiSchema: ownedAssetTypePage.uiSchema,
    schema: ownedAssetTypePage.schema,
  }),
}));