src/applications/fry-dea/config/form.js
import React from 'react';
import { createSelector } from 'reselect';
import fullSchema5490 from 'vets-json-schema/dist/22-5490-schema.json';
import commonDefinitions from 'vets-json-schema/dist/definitions.json';
import { vagovprod, VAGOVSTAGING } from 'site/constants/buckets';
import * as address from 'platform/forms/definitions/address';
import FormFooter from 'platform/forms/components/FormFooter';
import bankAccountUI from 'platform/forms/definitions/bankAccount';
// import createNonRequiredFullName from 'platform/forms/definitions/nonRequiredFullName';
import currentOrPastDateUI from 'platform/forms-system/src/js/definitions/currentOrPastDate';
// import dateRangeUi from 'platform/forms-system/src/js/definitions/dateRange';
// import dateUI from 'platform/forms-system/src/js/definitions/date';
import emailUI from 'platform/forms-system/src/js/definitions/email';
import environment from 'platform/utilities/environment';
import fullNameUI from 'platform/forms-system/src/js/definitions/fullName';
// import fullNameUi from 'platform/forms/definitions/fullName';
// import monthYearUI from 'platform/forms-system/src/js/definitions/monthYear';
// import * as personId from 'platform/forms/definitions/personId';
// import phoneUI from 'platform/forms-system/src/js/definitions/phone';
import { VA_FORM_IDS } from 'platform/forms/constants';
// import {
// validateMonthYear,
// validateFutureDateIfExpectedGrad,
// } from 'platform/forms-system/src/js/validation';
import manifest from '../manifest.json';
import {
AdditionalConsiderationTemplate,
addWhitespaceOnlyError,
applicantIsChildOfVeteran,
applicantIsSpouseOfVeteran,
isAlphaNumeric,
isOnlyWhitespace,
prefillTransformer,
} from '../helpers';
import IntroductionPage from '../containers/IntroductionPage';
import ConfirmationPage from '../containers/ConfirmationPage';
import {
// ELIGIBILITY,
formFields,
RELATIONSHIP,
VETERAN_NOT_LISTED_VALUE,
} from '../constants';
import GetFormHelp from '../components/GetFormHelp';
import GoToYourProfileLink from '../components/GoToYourProfileLink';
import RelatedVeterans from '../components/RelatedVeterans';
import { phoneSchema, phoneUISchema } from '../schema';
import EmailViewField from '../components/EmailViewField';
import {
isValidPhoneField,
validateEmail,
validateReMarriageDate,
} from '../validation';
import EmailReviewField from '../components/EmailReviewField';
import YesNoReviewField from '../components/YesNoReviewField';
import MailingAddressViewField from '../components/MailingAddressViewField';
import VeteransRadioGroup from '../components/VeteransRadioGroup';
import SelectedVeteranReviewPage from '../components/SelectedVeteranReviewPage';
import FryDeaEligibilityCards from '../components/FryDeaEligibilityCards';
import PreSubmitInfo from '../components/PreSubmitInfo';
const { date, fullName } = fullSchema5490.definitions;
const { /* fullName, date, dateRange, usaPhone, */ email } = commonDefinitions;
const contactMethods = ['Email', 'Home Phone', 'Mobile Phone', 'Mail'];
const checkImageSrc = environment.isStaging()
? `${VAGOVSTAGING}/img/check-sample.png`
: `${vagovprod}/img/check-sample.png`;
// const BENEFITS = [ELIGIBILITY.FRY, ELIGIBILITY.DEA];
function isValidName(str) {
return str && /^[A-Za-z][A-Za-z ']*$/.test(str);
}
function isValidLastName(str) {
return str && /^[A-Za-z][A-Za-z '-]*$/.test(str);
}
const formConfig = {
rootUrl: manifest.rootUrl,
urlPrefix: '/',
submitUrl: '/v0/api',
trackingPrefix: 'fry-dea-',
introduction: IntroductionPage,
confirmation: ConfirmationPage,
formId: VA_FORM_IDS.FORM_22_5490E,
saveInProgress: {
// messages: {
// inProgress: 'Your education benefits application (22-5490) is in progress.',
// expired: 'Your saved education benefits application (22-5490) has expired. If you want to apply for education benefits, please start a new application.',
// saved: 'Your education benefits application has been saved.',
// },
},
version: 0,
prefillEnabled: true,
prefillTransformer,
savedFormMessages: {
notFound: 'Please start over to apply for education benefits.',
noAuth:
'Please sign in again to continue your application for education benefits.',
},
title: 'Apply for education benefits as an eligible dependent',
subTitle:
"Equal to VA Form 22-5490 (Dependents' Application for VA Education Benefits)",
footerContent: FormFooter,
getHelp: GetFormHelp,
defaultDefinitions: {
fullName,
date,
},
preSubmitInfo: PreSubmitInfo,
chapters: {
applicantInformationChapter: {
title: 'Your information',
pages: {
applicantInformation: {
title: 'Your information',
path: 'applicant/information',
subTitle: 'Your information',
instructions:
'This is the personal information we have on file for you.',
uiSchema: {
'view:subHeadings': {
'ui:description': (
<>
<h3>Review your personal information</h3>
<p>
This is the personal information we have on file for you. If
you notice any errors, please correct them now. Any updates
you make will change the information for your education
benefits only.
</p>
<p>
<strong>Note:</strong> If you want to update your personal
information for other VA benefits, you can do that from your
profile.
</p>
<p className="vads-u-margin-bottom--3">
<GoToYourProfileLink />
</p>
</>
),
},
[formFields.userFullName]: {
...fullNameUI,
first: {
...fullNameUI.first,
'ui:title': 'Your first name',
'ui:validations': [
(errors, field) => {
if (!isValidName(field)) {
if (field.length === 0) {
errors.addError('Please enter your first name');
} else if (field[0] === ' ' || field[0] === "'") {
errors.addError(
'First character must be a letter with no leading space.',
);
} else {
errors.addError(
'Please enter a valid entry. Acceptable entries are letters, spaces and apostrophes.',
);
}
}
},
],
},
last: {
...fullNameUI.last,
'ui:title': 'Your last name',
'ui:validations': [
(errors, field) => {
if (!isValidLastName(field)) {
if (field.length === 0) {
errors.addError('Please enter your last name');
} else if (
field[0] === ' ' ||
field[0] === "'" ||
field[0] === '-'
) {
errors.addError(
'First character must be a letter with no leading space.',
);
} else {
errors.addError(
'Please enter a valid entry. Acceptable entries are letters, spaces, dashes and apostrophes.',
);
}
}
},
],
},
middle: {
...fullNameUI.middle,
'ui:title': 'Your middle name',
'ui:validations': [
(errors, field) => {
if (!isValidName(field)) {
if (field.length === 0) {
errors.addError('Please enter your middle name');
} else if (field[0] === ' ' || field[0] === "'") {
errors.addError(
'First character must be a letter with no leading space.',
);
} else {
errors.addError(
'Please enter a valid entry. Acceptable entries are letters, spaces and apostrophes.',
);
}
}
},
],
},
},
[formFields.dateOfBirth]: {
...currentOrPastDateUI('Your date of birth'),
},
},
schema: {
type: 'object',
required: [formFields.dateOfBirth],
properties: {
'view:subHeadings': {
type: 'object',
properties: {},
},
[formFields.userFullName]: {
...fullName,
properties: {
...fullName.properties,
middle: {
...fullName.properties.middle,
maxLength: 30,
},
},
},
[formFields.dateOfBirth]: date,
'view:dateOfBirthUnder18Alert': {
type: 'object',
properties: {},
},
},
},
},
},
},
veteranServiceMember: {
title: 'Veteran and service member information',
pages: {
selectVeteran: {
title: 'Veteran and service member information',
path: 'choose-veteran-or-service-member',
CustomPageReview: SelectedVeteranReviewPage,
depends: formData => formData.veterans?.length > 1,
uiSchema: {
'view:selectedVeteranSubHeadings': {
'ui:description': (
<>
<h3>Choose your Veteran or service member</h3>
<p>
Based on Department of Defense records, these are the
Veterans and service members we have on file related to you,
as well as the associated education benefits you may be
eligible for.
</p>
<RelatedVeterans />
</>
),
},
[formFields.selectedVeteran]: {
'ui:title':
'Which Veteran or service member’s benefits would you like to use?',
'ui:widget': VeteransRadioGroup,
'ui:errorMessages': {
required: 'Please select a Veteran or service member',
},
},
},
schema: {
type: 'object',
required: [formFields.selectedVeteran],
properties: {
'view:selectedVeteranSubHeadings': {
type: 'object',
properties: {},
},
[formFields.selectedVeteran]: {
type: 'string',
},
},
},
},
veteranInformation: {
title: 'Enter Veteran or service member information',
path: 'veteran-service-member/information',
depends: formData =>
!formData.veterans?.length ||
formData[formFields.selectedVeteran] === VETERAN_NOT_LISTED_VALUE,
uiSchema: {
'view:veteranInformationHeading': {
'ui:description': (
<h3>Enter Veteran or service member information</h3>
),
},
'view:noVeteranWarning': {
'ui:description': (
<va-alert
close-btn-aria-label="Close notification"
status="warning"
visible
>
<h3 slot="headline">
We do not have any Veteran or service member information on
file
</h3>
<p>
If you think this is incorrect, you may still continue this
application and enter their information manually.
</p>
</va-alert>
),
'ui:options': {
hideIf: formData => formData.veterans?.length,
},
},
'view:veteranNotOnFileWarning': {
'ui:description': (
<va-alert
close-btn-aria-label="Close notification"
status="info"
visible
>
<h3 slot="headline">
Your selected Veteran or service member is not on file
</h3>
<p>
You may still continue this application and enter their
information manually.
</p>
</va-alert>
),
'ui:options': {
hideIf: formData => !formData.veterans?.length,
},
},
[formFields.relationshipToVeteran]: {
'ui:title':
'What’s your relationship to the Veteran or service member whose benefits you’d like to use?',
'ui:widget': 'radio',
'ui:errorMessages': {
required: 'Please select a relationship',
},
},
'view:veteranFullNameHeading': {
'ui:description': <h4>Veteran or service member information</h4>,
},
[formFields.veteranFullName]: {
...fullNameUI,
first: {
...fullNameUI.first,
'ui:validations': [
(errors, field) =>
addWhitespaceOnlyError(
field,
errors,
'Please enter a first name',
),
],
},
last: {
...fullNameUI.last,
'ui:validations': [
(errors, field) =>
addWhitespaceOnlyError(
field,
errors,
'Please enter a last name',
),
],
},
},
[formFields.veteranDateOfBirth]: {
...currentOrPastDateUI('Date of birth'),
},
},
schema: {
type: 'object',
required: [
formFields.relationshipToVeteran,
formFields.veteranDateOfBirth,
],
properties: {
'view:veteranInformationHeading': {
type: 'object',
properties: {},
},
'view:noVeteranWarning': {
type: 'object',
properties: {},
},
'view:veteranNotOnFileWarning': {
type: 'object',
properties: {},
},
[formFields.relationshipToVeteran]: {
type: 'string',
enum: [RELATIONSHIP.SPOUSE, RELATIONSHIP.CHILD],
},
'view:veteranFullNameHeading': {
type: 'object',
properties: {},
},
[formFields.veteranFullName]: {
...fullName,
required: ['first', 'last'],
properties: {
...fullName.properties,
middle: {
...fullName.properties.middle,
maxLength: 30,
},
},
},
[formFields.veteranDateOfBirth]: date,
},
},
},
},
},
benefitSelection: {
title: 'Benefit selection',
pages: {
benefitSelection: {
title: 'Benefit Selection',
path: 'benefit-selection',
// depends: formData =>
// formData.veterans?.length &&
// formData[formFields.selectedVeteran] !== VETERAN_NOT_LISTED_VALUE,
uiSchema: {
'view:benefitSelectionHeaderInfo': {
'ui:description': (
<>
<h3>Choose the benefit you’d like to apply for</h3>
<p>
We estimated your benefit eligibility based on your chosen
Veteran or service member’s service history. This isn’t an
eligibility determination. An official determination won’t
be made until you complete and submit this application.
</p>
<p>
<strong>Note:</strong> If you are eligible for both the Fry
Scholarship and Survivors’ and Dependents’ Educational
Assistance benefits, you’ll need to choose which one to use.
Once you make this choice, you can’t switch to the other
program.
</p>
<FryDeaEligibilityCards />
<va-additional-info trigger="Which benefit should I choose?">
<p>
For each benefit, you should consider the amount you can
receive, how payments are made, and when they expire.
</p>
</va-additional-info>
</>
),
},
[formFields.benefitSelection]: {
'ui:title': (
<>
<span className="fry-dea-labels_label--main vads-u-padding-left--1">
Which education benefit would you like to apply for?
</span>
<span className="fry-dea-labels_label--secondary fry-dea-input-message fry-dea-review-view-hidden vads-u-background-color--primary-alt-lightest vads-u-padding--1 vads-u-margin-top--1">
<span className="vads-u-margin-right--1">
<va-icon icon="info" size={3} />
</span>{' '}
<span className="sr-only">information</span> If you’re the
child of a veteran or service member who died in the line of
duty before August 1, 2011 you can use both Fry Scholarship
and DEA and get up to 81 months of benefits. You’ll need to
apply separately and use one program at a time.
</span>
</>
),
'ui:errorMessages': {
required: 'Please select an education benefit',
},
'ui:widget': 'radio',
'ui:options': {
labels: {
fry: 'Fry Scholarship (Chapter 33)',
dea:
'Survivors’ and Dependents’ Educational Assistance (DEA, Chapter 35)',
},
widgetProps: {
fry: { 'data-info': 'fry' },
dea: { 'data-info': 'dea' },
},
// Only added to the radio when it is selected
// a11y requirement: aria-describedby ID’s *must* exist on the page; and we
// conditionally add content based on the selection
selectedProps: {
fry: { 'aria-describedby': 'fry' },
dea: { 'aria-describedby': 'dea' },
},
// updateSchema: (() => {
// const filterBenefits = createSelector(
// state => state,
// formData => {
// const veteran = formData?.veterans?.find(
// v => v.id === formData[formFields.selectedVeteran],
// );
// return {
// enum: BENEFITS.filter(
// benefit =>
// (benefit === ELIGIBILITY.FRY &&
// veteran?.fryEligibility) ||
// (benefit === ELIGIBILITY.DEA &&
// veteran?.deaEligibility),
// ),
// };
// },
// );
// return (form, state) => filterBenefits(form, state);
// })(),
},
},
},
schema: {
type: 'object',
required: [formFields.benefitSelection],
properties: {
'view:benefitSelectionHeaderInfo': {
type: 'object',
properties: {},
},
[formFields.benefitSelection]: {
type: 'string',
enum: [
'Fry Scholarship (Chapter 33)',
'Survivors’ and Dependents’ Educational Assistance (DEA, Chapter 35)',
],
},
},
},
},
},
},
additionalConsideration: {
title: 'Additional considerations',
pages: {
verifyHighSchool: {
title: 'High school education',
path: 'child/high-school-education',
depends: formData => applicantIsChildOfVeteran(formData),
uiSchema: {
'view:highSchoolDiplomaHeadings': {
'ui:description': <h3>High school education</h3>,
},
[formFields.highSchoolDiploma]: {
'ui:title':
'Did you earn a high school diploma or an equivalency certificate?',
'ui:widget': 'radio',
},
},
schema: {
type: 'object',
required: [formFields.highSchoolDiploma],
properties: {
'view:highSchoolDiplomaHeadings': {
type: 'object',
properties: {},
},
[formFields.highSchoolDiploma]: {
type: 'string',
enum: ['Yes', 'No'],
},
},
},
},
highSchool: {
title: 'Date received',
path: 'veteran-service-member/high-school-education',
depends: formData =>
applicantIsChildOfVeteran(formData) &&
formData[formFields.highSchoolDiploma] === 'Yes',
uiSchema: {
'view:highSchoolDiplomaDateHeading': {
'ui:description': <h3>Date received</h3>,
},
[formFields.highSchoolDiplomaDate]: {
...currentOrPastDateUI(
'What date did you receive your high school diploma or equivalency certificate?',
),
},
},
schema: {
type: 'object',
required: [formFields.highSchoolDiplomaDate],
properties: {
'view:highSchoolDiplomaDateHeading': {
type: 'object',
properties: {},
},
[formFields.highSchoolDiplomaDate]: date,
},
},
},
marriageDate: {
...AdditionalConsiderationTemplate(
'Marriage date',
'additional/consideration/marriage/date',
formFields.additionalConsiderations.marriageDate,
{
...currentOrPastDateUI(
'When did you get married to your chosen Veteran or service member?',
),
},
{ ...date },
),
depends: formData => applicantIsSpouseOfVeteran(formData),
},
marriageInformation: {
...AdditionalConsiderationTemplate(
'Marriage information',
'additional/consideration/marriage/information',
formFields.additionalConsiderations.marriageInformation,
{
'ui:title':
'What’s the status of your marriage with your chosen Veteran or service member?',
'ui:widget': 'radio',
},
{
type: 'string',
enum: [
'Married',
'Divorced (or a divorce is in progress)',
'Marriage was annulled (or annulment is in progress)',
'Widowed',
],
},
),
depends: formData => applicantIsSpouseOfVeteran(formData),
},
marriageInformationDivorced: {
...AdditionalConsiderationTemplate(
'Remarriage',
'additional/consideration/remarriage/information/divorced',
formFields.additionalConsiderations.remarriage,
{
'ui:title': 'Have you been remarried?',
'ui:widget': 'yesNo',
},
{
type: 'boolean',
},
),
depends: formData =>
applicantIsSpouseOfVeteran(formData) &&
formData[
formFields.additionalConsiderations.marriageInformation
] === 'Divorced (or a divorce is in progress)',
},
marriageInformationAnnulled: {
...AdditionalConsiderationTemplate(
'Remarriage',
'additional/consideration/remarriage/information/annulment',
formFields.additionalConsiderations.remarriage,
{
'ui:title': 'Have you been remarried since your annulment?',
'ui:widget': 'yesNo',
},
{
type: 'boolean',
},
),
depends: formData =>
applicantIsSpouseOfVeteran(formData) &&
formData[
formFields.additionalConsiderations.marriageInformation
] === 'Marriage was annulled (or annulment is in progress)',
},
marriageInformationWidowed: {
...AdditionalConsiderationTemplate(
'Remarriage',
'additional/consideration/remarriage/information/widowed',
formFields.additionalConsiderations.remarriage,
{
'ui:title': 'Have you been remarried since being widowed?',
'ui:widget': 'yesNo',
},
{
type: 'boolean',
},
),
depends: formData =>
applicantIsSpouseOfVeteran(formData) &&
formData[
formFields.additionalConsiderations.marriageInformation
] === 'Widowed',
},
remarriageDate: {
...AdditionalConsiderationTemplate(
'Remarriage date',
'additional/consideration/remarriage/date',
formFields.additionalConsiderations.remarriageDate,
{
...currentOrPastDateUI('When did you get remarried?'),
'ui:validations': [validateReMarriageDate],
},
{
...date,
},
),
depends: formData =>
applicantIsSpouseOfVeteran(formData) &&
formData[
formFields.additionalConsiderations.marriageInformation
] !== 'Married' &&
formData[formFields.additionalConsiderations.remarriage],
},
outstandingFelony: {
...AdditionalConsiderationTemplate(
'Outstanding felony',
'new/additional/consideration/felony/status',
formFields.additionalConsiderations.outstandingFelony,
{
'ui:title':
'Do you or your chosen Veteran or service member have an outstanding felony or warrant?',
'ui:widget': 'yesNo',
},
{
type: 'boolean',
},
),
},
},
},
contactInformationChapter: {
title: 'Contact information',
pages: {
phoneEmail: {
title: 'Phone numbers and email address',
path: 'contact-information/email-phone',
uiSchema: {
'view:subHeadings': {
'ui:description': (
<>
<h3>Review your phone numbers and email address</h3>
<div className="meb-list-label">
<strong>We’ll use this information to:</strong>
</div>
<ul>
<li>
Contact you if we have questions about your application
</li>
<li>Tell you important information about your benefits</li>
</ul>
<p>
This is the contact information we have on file for you. If
you notice any errors, please correct them now. Any updates
you make will change the information for your education
benefits only.
</p>
<p>
<strong>Note:</strong> If you want to update your contact
information for other VA benefits, you can do that from your
profile.
</p>
<p>
<GoToYourProfileLink />
</p>
</>
),
},
[formFields.viewPhoneNumbers]: {
'ui:description': (
<>
<h4 className="form-review-panel-page-header vads-u-font-size--h5 fry-dea-review-page-only">
Phone numbers and email addresss
</h4>
<p className="fry-dea-review-page-only">
If you’d like to update your phone numbers and email
address, please edit the form fields below.
</p>
</>
),
[formFields.mobilePhoneNumber]: phoneUISchema('mobile'),
[formFields.phoneNumber]: phoneUISchema('home'),
},
[formFields.email]: {
'ui:options': {
hideLabelText: true,
showFieldLabel: false,
viewComponent: EmailViewField,
},
[formFields.email]: {
...emailUI('Email address'),
'ui:validations': [validateEmail],
'ui:reviewField': EmailReviewField,
},
[formFields.confirmEmail]: {
...emailUI('Confirm email address'),
'ui:options': {
...emailUI()['ui:options'],
hideOnReview: true,
},
},
'ui:validations': [
(errors, field) => {
if (
field[formFields.email] !== field[formFields.confirmEmail]
) {
errors[formFields.confirmEmail].addError(
'Sorry, your emails must match',
);
}
},
],
},
},
schema: {
type: 'object',
properties: {
'view:subHeadings': {
type: 'object',
properties: {},
},
[formFields.viewPhoneNumbers]: {
type: 'object',
properties: {
[formFields.mobilePhoneNumber]: phoneSchema(),
[formFields.phoneNumber]: phoneSchema(),
},
},
[formFields.email]: {
type: 'object',
required: [formFields.email, formFields.confirmEmail],
properties: {
[formFields.email]: email,
[formFields.confirmEmail]: email,
},
},
},
},
},
mailingAddress: {
title: 'Mailing address',
path: 'contact-information/mailing-address',
uiSchema: {
'view:subHeadings': {
'ui:description': (
<>
<h3>Review your mailing address</h3>
<p>
We’ll send any important information about your application
to this address.
</p>
<p>
This is the mailing address we have on file for you. If you
notice any errors, please correct them now. Any updates you
make will change the information for your education benefits
only.
</p>
<p>
<strong>Note:</strong> If you want to update your personal
information for other VA benefits, you can do that from your
profile.
</p>
<p className="vads-u-margin-bottom--4">
<GoToYourProfileLink />
</p>
</>
),
},
[formFields.viewMailingAddress]: {
'ui:description': (
<>
<h4 className="form-review-panel-page-header vads-u-font-size--h5 fry-dea-review-page-only">
Mailing address
</h4>
<p className="fry-dea-review-page-only">
If you’d like to update your mailing address, please edit
the form fields below.
</p>
</>
),
livesOnMilitaryBase: {
'ui:title': (
<span id="LiveOnMilitaryBaseTooltip">
I live on a United States military base outside of the
country
</span>
),
'ui:reviewField': YesNoReviewField,
},
livesOnMilitaryBaseInfo: {
'ui:description': (
<va-additional-info
trigger="Learn more about military base addresses"
class="vads-u-margin-top--4"
>
<p>
U.S. military bases are considered a domestic address and
a part of the United States.
</p>
</va-additional-info>
),
},
[formFields.address]: {
...address.uiSchema(''),
street: {
'ui:title': 'Street address',
'ui:errorMessages': {
required: 'Please enter your full street address',
},
'ui:validations': [
(errors, field) => {
if (isOnlyWhitespace(field)) {
errors.addError(
'Please enter your full street address',
);
}
},
],
},
city: {
'ui:title': 'City',
'ui:errorMessages': {
required: 'Please enter a valid city',
},
'ui:validations': [
(errors, field) => {
if (isOnlyWhitespace(field)) {
errors.addError('Please enter a valid city');
}
},
],
},
state: {
'ui:title': 'State/Province/Region',
'ui:errorMessages': {
required: 'State is required',
},
},
postalCode: {
'ui:title': 'Postal Code (5-digit)',
'ui:errorMessages': {
required: 'Zip code must be 5 digits',
},
},
},
'ui:options': {
hideLabelText: true,
showFieldLabel: false,
viewComponent: MailingAddressViewField,
},
},
},
schema: {
type: 'object',
properties: {
'view:subHeadings': {
type: 'object',
properties: {},
},
'view:mailingAddress': {
type: 'object',
properties: {
livesOnMilitaryBase: {
type: 'boolean',
},
livesOnMilitaryBaseInfo: {
type: 'object',
properties: {},
},
[formFields.address]: {
...address.schema(fullSchema5490, true),
},
},
},
},
},
},
contactPreferences: {
title: 'Contact preferences',
path: 'contact-information/contact-preferences',
uiSchema: {
'view:contactMethodIntro': {
'ui:description': (
<>
<h3 className="fry-dea-form-page-only">
Choose your contact method for follow-up questions
</h3>
</>
),
},
[formFields.contactMethod]: {
'ui:title':
'How should we contact you if we have questions about your application?',
'ui:widget': 'radio',
'ui:errorMessages': {
required: 'Please select at least one way we can contact you.',
},
'ui:options': {
updateSchema: (() => {
const filterContactMethods = createSelector(
form =>
form[formFields.viewPhoneNumbers][
formFields.mobilePhoneNumber
]?.phone,
form =>
form[formFields.viewPhoneNumbers][formFields.phoneNumber]
?.phone,
(mobilePhoneNumber, homePhoneNumber) => {
const invalidContactMethods = [];
if (!mobilePhoneNumber) {
invalidContactMethods.push('Mobile Phone');
}
if (!homePhoneNumber) {
invalidContactMethods.push('Home Phone');
}
return {
enum: contactMethods.filter(
method => !invalidContactMethods.includes(method),
),
};
},
);
return form => filterContactMethods(form);
})(),
},
},
'view:receiveTextMessages': {
'ui:description': (
<>
<div className="fry-dea-form-page-only">
<h3>Choose how you want to get notifications</h3>
<p>
We recommend that you opt in to text message notifications
about your benefits. These include notifications that
prompt you to verify your enrollment so you’ll receive
your education payments. This is an easy way to verify
your monthly enrollment.
</p>
<va-alert status="info">
<>
If you choose to get text message notifications from
VA’s GI Bill program, message and data rates may apply.
Two messages per month. At this time, we can only send
text messages to U.S. mobile phone numbers. Text STOP to
opt out or HELP for help.{' '}
<a
href="https://benefits.va.gov/gibill/isaksonroe/verification_of_enrollment.asp"
rel="noopener noreferrer"
target="_blank"
>
View Terms and Conditions and Privacy Policy.
</a>
</>
</va-alert>
</div>
</>
),
[formFields.receiveTextMessages]: {
'ui:title':
'Would you like to receive text message notifications on your education benefits?',
'ui:widget': 'radio',
'ui:validations': [
(errors, field, formData) => {
const isYes = field?.slice(0, 4).includes('Yes');
if (!isYes) {
return;
}
const { phone, isInternational } = formData[
formFields.viewPhoneNumbers
][formFields.mobilePhoneNumber];
if (!phone) {
errors.addError(
'You can’t select that response because we don’t have a mobile phone number on file for you.',
);
} else if (isInternational) {
errors.addError(
'You can’t select that response because you have an international mobile phone number',
);
}
},
],
'ui:options': {
widgetProps: {
Yes: { 'data-info': 'yes' },
No: { 'data-info': 'no' },
},
selectedProps: {
Yes: { 'aria-describedby': 'yes' },
No: { 'aria-describedby': 'no' },
},
},
},
},
'view:noMobilePhoneAlert': {
'ui:description': (
<va-alert status="warning">
<>
You can’t choose to get text message notifications because
we don’t have a mobile phone number on file for you.
</>
</va-alert>
),
'ui:options': {
hideIf: formData =>
(formData[formFields.viewReceiveTextMessages][
formFields.receiveTextMessages
] &&
!formData[formFields.viewReceiveTextMessages][
formFields.receiveTextMessages
]
.slice(0, 4)
.includes('Yes')) ||
isValidPhoneField(
formData[formFields.viewPhoneNumbers][
formFields.mobilePhoneNumber
],
),
},
},
'view:internationalTextMessageAlert': {
'ui:description': (
<va-alert status="warning">
<>
You can’t choose to get text notifications because you have
an international mobile phone number. At this time, we can
send text messages about your education benefits only to
U.S. mobile phone numbers.
</>
</va-alert>
),
'ui:options': {
hideIf: formData =>
(formData[formFields.viewReceiveTextMessages][
formFields.receiveTextMessages
] &&
!formData[formFields.viewReceiveTextMessages][
formFields.receiveTextMessages
]
.slice(0, 4)
.includes('Yes')) ||
!isValidPhoneField(
formData[formFields.viewPhoneNumbers][
formFields.mobilePhoneNumber
],
) ||
!formData[formFields.viewPhoneNumbers][
formFields.mobilePhoneNumber
]?.isInternational,
},
},
},
schema: {
type: 'object',
properties: {
'view:contactMethodIntro': {
type: 'object',
properties: {},
},
[formFields.contactMethod]: {
type: 'string',
enum: contactMethods,
},
[formFields.viewReceiveTextMessages]: {
type: 'object',
required: [formFields.receiveTextMessages],
properties: {
[formFields.receiveTextMessages]: {
type: 'string',
enum: [
'Yes, send me text message notifications',
'No, just send me email notifications',
],
},
},
},
'view:noMobilePhoneAlert': {
type: 'object',
properties: {},
},
'view:internationalTextMessageAlert': {
type: 'object',
properties: {},
},
},
required: [formFields.contactMethod],
},
},
},
},
bankAccountInfoChapter: {
title: 'Direct deposit',
pages: {
directDeposit: {
path: 'direct-deposit',
title: 'Direct deposit',
uiSchema: {
'ui:description': (
<>
<h3>Enter your direct deposit information</h3>
<p className="vads-u-margin-bottom--4">
<strong>Note</strong>: VA makes payments only through direct
deposit, also called electronic funds transfer (EFT).
</p>
</>
),
[formFields.bankAccount]: {
...bankAccountUI,
'ui:order': ['accountType', 'accountNumber', 'routingNumber'],
accountType: {
...bankAccountUI.accountType,
'ui:errorMessages': {
required: 'Please select an account type',
},
},
accountNumber: {
...bankAccountUI.accountNumber,
'ui:validations': [
(errors, field) => {
if (!isAlphaNumeric(field)) {
errors.addError('Please enter a valid account number');
}
},
],
},
},
'view:directDepositLearnMore': {
'ui:description': (
<va-additional-info trigger="Where can I find these numbers?">
<img
key="check-image-src"
src={checkImageSrc}
alt="Example of a check showing where the account and routing numbers are"
/>
<p>
The bank routing number is the first 9 digits on the bottom
left corner of a printed check. Your account number is the
second set of numbers on the bottom of a printed check, just
to the right of the bank routing number.
</p>
</va-additional-info>
),
},
},
schema: {
type: 'object',
properties: {
[formFields.bankAccount]: {
type: 'object',
required: ['accountType', 'routingNumber', 'accountNumber'],
properties: {
accountType: {
type: 'string',
enum: ['checking', 'savings'],
},
routingNumber: {
type: 'string',
pattern: '^\\d{9}$',
},
accountNumber: {
type: 'string',
},
},
},
'view:directDepositLearnMore': {
type: 'object',
properties: {},
},
},
},
},
},
},
},
};
export default formConfig;