department-of-veterans-affairs/vets-website

View on GitHub
src/applications/pre-need/config/form.jsx

Summary

Maintainability
F
4 days
Test Coverage
import React from 'react';

import { merge } from 'lodash';
import get from 'platform/utilities/data/get';

import fullSchemaPreNeed from 'vets-json-schema/dist/40-10007-schema.json';

import environment from 'platform/utilities/environment';
import preSubmitInfo from 'platform/forms/preSubmitInfo';
import { VA_FORM_IDS } from 'platform/forms/constants';
import { useSelector } from 'react-redux';
import { fileUploadUi } from '../utils/upload';
import transformForSubmit from './transformForSubmit';

import emailUI from '../definitions/email';
import * as applicantMilitaryHistory from './pages/applicantMilitaryHistory';
import * as applicantMilitaryName from './pages/applicantMilitaryName';
import * as applicantMilitaryNameInformation from './pages/applicantMilitaryNameInformation';
import * as sponsorDetails from './pages/sponsorDetails';
import * as sponsorDemographics from './pages/sponsorDemographics';
import * as sponsorDeceased from './pages/sponsorDeceased';
import * as sponsorDateOfDeath from './pages/sponsorDateOfDeath';
import * as sponsorMilitaryDetails from './pages/sponsorMilitaryDetails';
import * as sponsorMilitaryHistory from './pages/sponsorMilitaryHistory';
import * as sponsorMilitaryName from './pages/sponsorMilitaryName';
import * as sponsorMilitaryNameInformation from './pages/sponsorMilitaryNameInformation';
import * as burialBenefits from './pages/burialBenefits';
import * as applicantRelationshipToVet from './pages/applicantRelationshipToVet';
import * as veteranApplicantDetails from './pages/veteranApplicantDetails';
import * as nonVeteranApplicantDetails from './pages/nonVeteranApplicantDetails';
import * as applicantDemographics from './pages/applicantDemographics';
import * as militaryDetails from './pages/militaryDetails';
import * as currentlyBuriedPersons from './pages/currentlyBuriedPersons';

import * as address from '../definitions/address';
import Footer from '../components/Footer';

import IntroductionPage from '../components/IntroductionPage';
import ConfirmationPage from '../containers/ConfirmationPage';
import GetFormHelp from '../components/GetFormHelp';
import ErrorText from '../components/ErrorText';
import SubmissionError from '../components/SubmissionError';
import phoneUI from '../components/Phone';
import preparerPhoneUI from '../components/PreparerPhone';

import manifest from '../manifest.json';

import {
  isVeteran,
  isAuthorizedAgent,
  formatName,
  applicantContactInfoDescriptionNonVet,
  applicantContactInfoDescriptionVet,
  isVeteranAndHasServiceName,
  isNotVeteranAndHasServiceName,
  buriedWSponsorsEligibility,
  preparerAddressHasState,
  applicantsMailingAddressHasState,
  sponsorMailingAddressHasState,
  isSponsorDeceased,
} from '../utils/helpers';
import SupportingFilesDescription from '../components/SupportingFilesDescription';
import {
  ContactDetailsTitle,
  PreparerDescription,
  PreparerDetailsTitle,
} from '../components/PreparerHelpers';
import PreparerRadioWidget from '../components/PreparerRadioWidget';

const {
  claimant,
  applicant,
  preneedAttachments,
} = fullSchemaPreNeed.properties.application.properties;

const {
  fullName,
  ssn,
  date,
  dateRange,
  gender,
  email,
  phone,
  files,
  centralMailVaFile,
  race,
} = fullSchemaPreNeed.definitions;

function MailingAddressStateTitle(props) {
  const { elementPath } = props;
  const data = useSelector(state => state.form.data || {});
  const country = get(elementPath, data);
  if (country === 'CAN') {
    return 'Province';
  }
  return 'State or territory';
}

export const applicantMailingAddressStateTitleWrapper = (
  <MailingAddressStateTitle elementPath="application.claimant.address.country" />
);
export const preparerMailingAddressStateTitleWrapper = (
  <MailingAddressStateTitle elementPath="application.applicant.view:applicantInfo.mailingAddress.country" />
);
export const sponsorMailingAddressStateTitleWrapper = (
  <MailingAddressStateTitle elementPath="application.veteran.address.country" />
);

export const applicantContactInfoWrapper = <ApplicantContactInfoDescription />;

const applicantContactInfoSubheader = (
  <h3 className="vads-u-font-size--h5">Applicant’s contact details</h3>
);

function ApplicantContactInfoDescription() {
  const data = useSelector(state => state.form.data || {});
  return isVeteran(data)
    ? applicantContactInfoDescriptionVet
    : applicantContactInfoDescriptionNonVet;
}

/** @type {FormConfig} */
const formConfig = {
  dev: {
    showNavLinks: true,
    collapsibleNavLinks: true,
  },
  rootUrl: manifest.rootUrl,
  urlPrefix: '/',
  submitUrl: `${environment.API_URL}/simple_forms_api/v1/simple_forms`,
  trackingPrefix: 'preneed-',
  transformForSubmit,
  formId: VA_FORM_IDS.FORM_40_10007,
  saveInProgress: {
    messages: {
      inProgress:
        'Your pre-need determination of eligibility in a VA national cemetery application is in progress.',
      // TODO: Fix the expired message
      expired:
        'Your saved pre-need determination of eligibility in a VA national cemetery application has expired. If you want to apply for pre-need determination of eligibility in a VA national cemetery, please start a new application.',
      saved:
        'Your pre-need determination of eligibility in a VA national cemetery application has been saved.',
    },
  },
  prefillEnabled: true,
  verifyRequiredPrefill: false,
  version: 0,
  savedFormMessages: {
    notFound: 'Please start over to apply for pre-need eligibility.',
    noAuth:
      'Please sign in again to resume your application for pre-need eligibility.',
  },
  introduction: IntroductionPage,
  confirmation: ConfirmationPage,
  title: 'Apply for pre-need eligibility determination',
  subTitle: 'Form 40-10007',
  preSubmitInfo,
  footerContent: ({ currentLocation }) => (
    <Footer formConfig={formConfig} currentLocation={currentLocation} />
  ),
  getHelp: GetFormHelp,
  errorText: ErrorText,
  submissionError: SubmissionError,
  defaultDefinitions: {
    fullName,
    ssn,
    date,
    dateRange,
    gender,
    race,
    email,
    phone,
    files,
    centralMailVaFile,
  },
  chapters: {
    applicantInformation: {
      title: 'Applicant information',
      pages: {
        applicantRelationshipToVet: {
          path: 'applicant-relationship-to-vet',
          uiSchema: applicantRelationshipToVet.uiSchema,
          schema: applicantRelationshipToVet.schema,
        },
        veteranApplicantDetails: {
          title: 'Applicant details',
          path: 'veteran-applicant-details',
          depends: isVeteran,
          uiSchema: veteranApplicantDetails.uiSchema,
          schema: veteranApplicantDetails.schema,
        },
        nonVeteranApplicantDetails: {
          title: 'Applicant details',
          path: 'nonVeteran-applicant-details',
          depends: formData => !isVeteran(formData),
          uiSchema: nonVeteranApplicantDetails.uiSchema,
          schema: nonVeteranApplicantDetails.schema,
        },
        applicantDemographics: {
          title: 'Applicant demographics',
          path: 'applicant-demographics',
          depends: isVeteran,
          uiSchema: applicantDemographics.uiSchema,
          schema: applicantDemographics.schema,
        },
        militaryDetails: {
          path: 'applicant-military-details',
          title: 'Military details',
          depends: isVeteran,
          uiSchema: militaryDetails.uiSchema,
          schema: militaryDetails.schema,
        },
      },
    },
    sponsorInformation: {
      title: 'Sponsor information',
      pages: {
        sponsorDetails: {
          title: 'Sponsor details',
          path: 'sponsor-details',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorDetails.uiSchema,
          schema: sponsorDetails.schema,
        },
        sponsorDemographics: {
          title: 'Sponsor demographics',
          path: 'sponsor-demographics',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorDemographics.uiSchema,
          schema: sponsorDemographics.schema,
        },
        sponsorDeceased: {
          path: 'sponsor-deceased',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorDeceased.uiSchema,
          schema: sponsorDeceased.schema,
        },
        sponsorDateOfDeath: {
          path: 'sponsor-date-of-death',
          depends: formData =>
            !isVeteran(formData) && isSponsorDeceased(formData),
          uiSchema: sponsorDateOfDeath.uiSchema,
          schema: sponsorDateOfDeath.schema,
        },
        sponsorMilitaryDetails: {
          title: "Sponsor's military details",
          path: 'sponsor-military-details',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorMilitaryDetails.uiSchema,
          schema: sponsorMilitaryDetails.schema,
        },
      },
    },
    militaryHistory: {
      title: 'Military history',
      pages: {
        // Two sets of military history pages dependent on
        // whether the applicant is the veteran or not.
        // If not, "Sponsor’s" precedes all the field labels.
        applicantMilitaryHistory: {
          title: 'Service period(s)',
          path: 'applicant-military-history',
          depends: isVeteran,
          uiSchema: applicantMilitaryHistory.uiSchema,
          schema: applicantMilitaryHistory.schema,
        },
        applicantMilitaryName: {
          path: 'applicant-military-name',
          depends: isVeteran,
          uiSchema: applicantMilitaryName.uiSchema,
          schema: applicantMilitaryName.schema,
        },
        applicantMilitaryNameInformation: {
          title: 'Previous name',
          path: 'applicant-military-name-information',
          depends: formData => isVeteranAndHasServiceName(formData),
          uiSchema: applicantMilitaryNameInformation.uiSchema,
          schema: applicantMilitaryNameInformation.schema,
        },
        sponsorMilitaryHistory: {
          path: 'sponsor-military-history',
          title: 'Sponsor’s service period(s)',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorMilitaryHistory.uiSchema,
          schema: sponsorMilitaryHistory.schema,
        },
        sponsorMilitaryName: {
          path: 'sponsor-military-name',
          depends: formData => !isVeteran(formData),
          uiSchema: sponsorMilitaryName.uiSchema,
          schema: sponsorMilitaryName.schema,
        },
        sponsorMilitaryNameInformation: {
          title: 'Sponsor’s previous name',
          path: 'sponsor-military-name-information',
          depends: formData => isNotVeteranAndHasServiceName(formData),
          uiSchema: sponsorMilitaryNameInformation.uiSchema,
          schema: sponsorMilitaryNameInformation.schema,
        },
      },
    },
    burialBenefits: {
      title: 'Burial benefits',
      pages: {
        burialBenefits: {
          path: 'burial-benefits',
          uiSchema: burialBenefits.uiSchema,
          schema: burialBenefits.schema,
        },
        currentlyBuriedPersons: {
          title: 'Name of deceased person(s)',
          path: 'current-burial-benefits',
          depends: formData => buriedWSponsorsEligibility(formData),
          uiSchema: currentlyBuriedPersons.uiSchema,
          schema: currentlyBuriedPersons.schema,
        },
      },
    },
    supportingDocuments: {
      title: 'Supporting files',
      pages: {
        supportingDocuments: {
          title: 'Upload supporting files',
          path: 'supporting-documents',
          editModeOnReviewPage: false,
          uiSchema: {
            'ui:description': SupportingFilesDescription,
            application: {
              preneedAttachments: fileUploadUi({}),
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  preneedAttachments,
                },
              },
            },
          },
        },
      },
    },
    contactInformation: {
      title: 'Contact information',
      pages: {
        applicantContactInformation: {
          title: 'Applicant’s contact information',
          path: 'applicant-contact-information',
          uiSchema: {
            application: {
              claimant: {
                address: merge(
                  {},
                  address.uiSchema('Applicant’s mailing address'),
                  {
                    street: {
                      'ui:title': 'Street address',
                    },
                    street2: {
                      'ui:title': 'Street address line 2',
                    },
                    state: {
                      'ui:title': applicantMailingAddressStateTitleWrapper,
                      'ui:options': {
                        hideIf: formData =>
                          !applicantsMailingAddressHasState(formData),
                      },
                    },
                  },
                ),
                'view:applicantContactInfoSubheader': {
                  'ui:description': applicantContactInfoSubheader,
                  'ui:options': {
                    displayEmptyObjectOnReview: true,
                  },
                },
                phoneNumber: phoneUI('Phone number'),
                email: emailUI(),
                'view:contactInfoDescription': {
                  'ui:description': applicantContactInfoWrapper,
                  'ui:options': {
                    displayEmptyObjectOnReview: true,
                  },
                },
              },
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  claimant: {
                    type: 'object',
                    required: ['email', 'phoneNumber'],
                    properties: {
                      address: address.schema(fullSchemaPreNeed, true),
                      'view:applicantContactInfoSubheader': {
                        type: 'object',
                        properties: {},
                      },
                      phoneNumber: claimant.properties.phoneNumber,
                      email: claimant.properties.email,
                      'view:contactInfoDescription': {
                        type: 'object',
                        properties: {},
                      },
                    },
                  },
                },
              },
            },
          },
        },
        sponsorMailingAddress: {
          title: 'Sponsor’s mailing address',
          path: 'sponsor-mailing-address',
          depends: formData => !isVeteran(formData),
          uiSchema: {
            application: {
              veteran: {
                address: merge(
                  {},
                  address.uiSchema('Sponsor’s mailing address'),
                  {
                    street: {
                      'ui:title': 'Street address',
                    },
                    street2: {
                      'ui:title': 'Street address line 2',
                    },
                    state: {
                      'ui:title': sponsorMailingAddressStateTitleWrapper,
                      'ui:options': {
                        hideIf: formData =>
                          !sponsorMailingAddressHasState(formData),
                      },
                    },
                  },
                ),
              },
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  veteran: {
                    type: 'object',
                    properties: {
                      address: address.schema(fullSchemaPreNeed),
                    },
                  },
                },
              },
            },
          },
        },
        preparer: {
          path: 'preparer',
          uiSchema: {
            application: {
              applicant: {
                applicantRelationshipToClaimant: {
                  'ui:title': 'Who is filling out this application?',
                  'ui:widget': PreparerRadioWidget,
                  'ui:options': {
                    updateSchema: formData => {
                      const nameData = get(
                        'application.claimant.name',
                        formData,
                      );
                      const applicantName = nameData
                        ? formatName(nameData)
                        : null;

                      return {
                        enumNames: [
                          applicantName || 'Myself',
                          'Someone else, such as a preparer',
                        ],
                      };
                    },
                  },
                },
              },
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  applicant: {
                    type: 'object',
                    required: ['applicantRelationshipToClaimant'],
                    properties: {
                      applicantRelationshipToClaimant:
                        applicant.properties.applicantRelationshipToClaimant,
                    },
                  },
                },
              },
            },
          },
        },
        preparerDetails: {
          title: 'Preparer details',
          path: 'preparer-details',
          depends: formData => isAuthorizedAgent(formData),
          uiSchema: {
            'ui:title': PreparerDetailsTitle,
            'ui:description': PreparerDescription,
            application: {
              applicant: {
                name: {
                  first: {
                    'ui:title': "Preparer's first name",
                    'ui:required': isAuthorizedAgent,
                  },
                  middle: {
                    'ui:options': {
                      hideIf: () => true,
                    },
                  },
                  last: {
                    'ui:title': "Preparer's last name",
                    'ui:required': isAuthorizedAgent,
                  },
                  suffix: {
                    'ui:options': {
                      hideIf: () => true,
                    },
                  },
                },
              },
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  applicant: {
                    type: 'object',
                    properties: {
                      name: applicant.properties.name,
                    },
                  },
                },
              },
            },
          },
        },
        preparerContactDetails: {
          title: 'Preparer contact details',
          path: 'preparer-contact-details',
          depends: formData => isAuthorizedAgent(formData),
          uiSchema: {
            application: {
              applicant: {
                'view:applicantInfo': {
                  mailingAddress: merge(
                    {},
                    address.uiSchema("Preparer's mailing address"),
                    {
                      country: { 'ui:required': isAuthorizedAgent },
                      street: {
                        'ui:title': 'Street address',
                        'ui:required': isAuthorizedAgent,
                      },
                      street2: {
                        'ui:title': 'Street address line 2',
                      },
                      city: { 'ui:required': isAuthorizedAgent },
                      state: {
                        'ui:title': preparerMailingAddressStateTitleWrapper,
                        'ui:required': isAuthorizedAgent,
                        'ui:options': {
                          hideIf: formData =>
                            !preparerAddressHasState(formData),
                        },
                      },
                      postalCode: { 'ui:required': isAuthorizedAgent },
                    },
                  ),
                },
                'view:contactInfo': {
                  'ui:title': ContactDetailsTitle,
                  applicantPhoneNumber: merge(
                    {},
                    preparerPhoneUI('Phone number'),
                    {
                      'ui:required': isAuthorizedAgent,
                    },
                  ),
                },
              },
            },
          },
          schema: {
            type: 'object',
            properties: {
              application: {
                type: 'object',
                properties: {
                  applicant: {
                    type: 'object',
                    properties: {
                      'view:applicantInfo': {
                        type: 'object',
                        properties: {
                          mailingAddress: address.schema(fullSchemaPreNeed),
                        },
                      },
                      'view:contactInfo': {
                        type: 'object',
                        properties: {
                          applicantPhoneNumber:
                            applicant.properties.applicantPhoneNumber,
                        },
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
    },
  },
};

export default formConfig;