From 52857e0942950d57f29b597fb7f610cdd1e37cde Mon Sep 17 00:00:00 2001 From: Brooklyn Welsh Date: Wed, 14 Aug 2024 17:03:37 -0400 Subject: [PATCH 1/7] All fields for customer contact forms and orders forms on the customer side of the app now show red "required" warnings for every empty field as soon as the page is loaded. --- .../Customer/ContactInfoForm/index.jsx | 8 ++++- .../EditContactInfoForm.jsx | 29 ++++++++++++----- .../EditOrdersForm/EditOrdersForm.jsx | 26 +++++++++++++-- .../EditOrdersForm/EditOrdersForm.test.jsx | 18 +++++++++++ .../OrdersInfoForm/OrdersInfoForm.jsx | 30 ++++++++++++++--- .../OrdersInfoForm/OrdersInfoForm.test.jsx | 2 +- .../CustomerAltContactInfoFields/index.jsx | 11 ++++--- .../form/CustomerContactInfoFields/index.jsx | 9 ++++-- src/styles/form.module.scss | 4 +++ src/utils/validation.js | 32 +++++++++---------- 10 files changed, 130 insertions(+), 39 deletions(-) diff --git a/src/components/Customer/ContactInfoForm/index.jsx b/src/components/Customer/ContactInfoForm/index.jsx index ffe6d9ca538..efd3c9cc549 100644 --- a/src/components/Customer/ContactInfoForm/index.jsx +++ b/src/components/Customer/ContactInfoForm/index.jsx @@ -11,7 +11,13 @@ import { contactInfoSchema } from 'utils/validation'; const ContactInfoForm = ({ initialValues, onSubmit, onBack }) => { return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return (
diff --git a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx index 4ffc3b0c0e5..140f7de3ba5 100644 --- a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx +++ b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx @@ -11,7 +11,12 @@ import SectionWrapper from 'components/Customer/SectionWrapper'; import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigation'; import { Form } from 'components/form/Form'; import formStyles from 'styles/form.module.scss'; -import { backupContactInfoSchema, contactInfoSchema, requiredAddressSchema } from 'utils/validation'; +import { + backupContactInfoSchema, + contactInfoSchema, + requiredAddressSchema, + preferredContactMethodValidation, +} from 'utils/validation'; import { ResidentialAddressShape } from 'types/address'; import { CustomerContactInfoFields } from 'components/form/CustomerContactInfoFields'; import { BackupContactInfoFields } from 'components/form/BackupContactInfoFields'; @@ -22,17 +27,25 @@ export const backupAddressName = 'backup_mailing_address'; export const backupContactName = 'backup_contact'; const EditContactInfoForm = ({ initialValues, onSubmit, onCancel }) => { - const validationSchema = Yup.object().shape({ - ...contactInfoSchema.fields, - [residentialAddressName]: requiredAddressSchema.required(), - [backupAddressName]: requiredAddressSchema.required(), - [backupContactName]: backupContactInfoSchema.required(), - }); + const validationSchema = Yup.object() + .shape({ + ...contactInfoSchema.fields, + [residentialAddressName]: requiredAddressSchema.required(), + [backupAddressName]: requiredAddressSchema.required(), + [backupContactName]: backupContactInfoSchema.required(), + }) + .test('contactMethodRequired', 'Please select a preferred method of contact.', preferredContactMethodValidation); const sectionStyles = classnames(formStyles.formSection, editContactInfoFormStyle.formSection); return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return ( diff --git a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx index 66637d24125..21a151366e8 100644 --- a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx +++ b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx @@ -66,11 +66,26 @@ const EditOrdersForm = ({ const payGradeOptions = dropdownInputOptions(ORDERS_PAY_GRADE_OPTIONS); + let originMeta; + let newDutyMeta = ''; + return ( - + {({ isValid, isSubmitting, handleSubmit, values }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); + if (!values.origin_duty_location) originMeta = 'Required'; + else originMeta = null; + + if (!values.new_duty_location) newDutyMeta = 'Required'; + else newDutyMeta = null; + return ( @@ -130,6 +145,7 @@ const EditOrdersForm = ({ name="origin_duty_location" id="origin_duty_location" required + metaOverride={originMeta} /> {isRetirementOrSeparation ? ( @@ -161,10 +177,16 @@ const EditOrdersForm = ({ displayAddress={false} hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." placeholder="Enter a city or ZIP" + metaOverride={newDutyMeta} /> ) : ( - + )} diff --git a/src/components/Customer/EditOrdersForm/EditOrdersForm.test.jsx b/src/components/Customer/EditOrdersForm/EditOrdersForm.test.jsx index d9d3cb5f4ef..08f03e5f3c1 100644 --- a/src/components/Customer/EditOrdersForm/EditOrdersForm.test.jsx +++ b/src/components/Customer/EditOrdersForm/EditOrdersForm.test.jsx @@ -159,6 +159,24 @@ const initialValues = { issue_date: '2020-11-08', report_by_date: '2020-11-26', has_dependents: 'No', + origin_duty_location: { + address: { + city: 'Des Moines', + country: 'US', + id: 'a4b30b99-4e82-48a6-b736-01662b499d6a', + postalCode: '50309', + state: 'IA', + streetAddress1: '987 Other Avenue', + streetAddress2: 'P.O. Box 1234', + streetAddress3: 'c/o Another Person', + }, + address_id: 'a4b30b99-4e82-48a6-b736-01662b499d6a', + affiliation: 'AIR_FORCE', + created_at: '2020-10-19T17:01:16.114Z', + id: 'f9299768-16d2-4a13-ae39-7087a58b1f62', + name: 'Yuma AFB', + updated_at: '2020-10-19T17:01:16.114Z', + }, new_duty_location: { address: { city: 'Des Moines', diff --git a/src/components/Customer/OrdersInfoForm/OrdersInfoForm.jsx b/src/components/Customer/OrdersInfoForm/OrdersInfoForm.jsx index 499761fd256..1ded9eaf938 100644 --- a/src/components/Customer/OrdersInfoForm/OrdersInfoForm.jsx +++ b/src/components/Customer/OrdersInfoForm/OrdersInfoForm.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Formik, Field } from 'formik'; import * as Yup from 'yup'; -import { Radio, FormGroup, Label, Link as USWDSLink } from '@trussworks/react-uswds'; +import { Radio, FormGroup, Label, Link as USWDSLink, ErrorMessage } from '@trussworks/react-uswds'; import styles from './OrdersInfoForm.module.scss'; @@ -18,6 +18,8 @@ import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigat import Callout from 'components/Callout'; import { formatLabelReportByDate, dropdownInputOptions } from 'utils/formatters'; +let originMeta; +let newDutyMeta = ''; const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) => { const payGradeOptions = dropdownInputOptions(ORDERS_PAY_GRADE_OPTIONS); @@ -38,10 +40,22 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) }); return ( - - {({ isValid, isSubmitting, handleSubmit, values }) => { + + {({ isValid, isSubmitting, handleSubmit, values, errors }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); + if (!values.origin_duty_location) originMeta = 'Required'; + else originMeta = null; + + if (!values.new_duty_location) newDutyMeta = 'Required'; + else newDutyMeta = null; + return (

Tell us about your move orders

@@ -64,6 +78,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) + {errors.has_dependents ? {errors.has_dependents} : null}
{isRetirementOrSeparation ? ( @@ -121,11 +137,17 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) label="HOR, PLEAD or HOS" displayAddress={false} hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." + metaOverride={newDutyMeta} placeholder="Enter a city or ZIP" /> ) : ( - + )} diff --git a/src/components/Customer/OrdersInfoForm/OrdersInfoForm.test.jsx b/src/components/Customer/OrdersInfoForm/OrdersInfoForm.test.jsx index 49b7ab3ccfc..045609b86fe 100644 --- a/src/components/Customer/OrdersInfoForm/OrdersInfoForm.test.jsx +++ b/src/components/Customer/OrdersInfoForm/OrdersInfoForm.test.jsx @@ -227,7 +227,7 @@ describe('OrdersInfoForm component', () => { await userEvent.click(submitBtn); await waitFor(() => { - expect(getAllByText('Required').length).toBe(4); + expect(getAllByText('Required').length).toBe(5); }); expect(testProps.onSubmit).not.toHaveBeenCalled(); }); diff --git a/src/components/form/CustomerAltContactInfoFields/index.jsx b/src/components/form/CustomerAltContactInfoFields/index.jsx index ddf6baf522c..a407574a785 100644 --- a/src/components/form/CustomerAltContactInfoFields/index.jsx +++ b/src/components/form/CustomerAltContactInfoFields/index.jsx @@ -1,14 +1,18 @@ import React, { useRef } from 'react'; import { func, node, string } from 'prop-types'; import { v4 as uuidv4 } from 'uuid'; -import { Label, Fieldset } from '@trussworks/react-uswds'; +import { Label, Fieldset, ErrorMessage } from '@trussworks/react-uswds'; +import { useFormikContext } from 'formik'; +import classnames from 'classnames'; +import formStyles from 'styles/form.module.scss'; import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; import { CheckboxField } from 'components/form/fields'; export const CustomerAltContactInfoFields = ({ legend, className, render }) => { const CustomerAltContactInfoFieldsUUID = useRef(uuidv4()); + const { errors } = useFormikContext(); return (
@@ -64,14 +68,13 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => {
-
+ {errors.preferredContactMethod ? {errors.preferredContactMethod} : null} +
-
-
{ const CustomerContactInfoFieldsUUID = useRef(uuidv4()); + const { errors } = useFormikContext(); + return (
{render( @@ -48,7 +52,8 @@ export const CustomerContactInfoFields = ({ legend, className, render }) => { required /> -
+ {errors.preferredContactMethod ? {errors.preferredContactMethod} : null} +
div{ + margin-top: 0; +} + .formActions { @include u-margin-top(3); @include u-margin-bottom(6); diff --git a/src/utils/validation.js b/src/utils/validation.js index e453b81fd99..64f0cd1c3bd 100644 --- a/src/utils/validation.js +++ b/src/utils/validation.js @@ -103,25 +103,23 @@ export const emailSchema = Yup.string().matches( 'Must be a valid email address', ); -const validatePreferredContactMethod = (value, testContext) => { - return testContext.parent.phone_is_preferred || testContext.parent.email_is_preferred; +export const preferredContactMethodValidation = (value) => { + return ( + value?.phone_is_preferred || + value?.email_is_preferred || + new Yup.ValidationError('Please select a preferred method of contact.', null, 'preferredContactMethod') + ); }; -export const contactInfoSchema = Yup.object().shape({ - telephone: phoneSchema.required('Required'), - secondary_telephone: phoneSchema, - personal_email: emailSchema.required('Required'), - phone_is_preferred: Yup.bool().test( - 'contactMethodRequired', - 'Please select a preferred method of contact.', - validatePreferredContactMethod, - ), - email_is_preferred: Yup.bool().test( - 'contactMethodRequired', - 'Please select a preferred method of contact.', - validatePreferredContactMethod, - ), -}); +export const contactInfoSchema = Yup.object() + .shape({ + telephone: phoneSchema.required('Required'), + secondary_telephone: phoneSchema, + personal_email: emailSchema.required('Required'), + phone_is_preferred: Yup.bool(), + email_is_preferred: Yup.bool(), + }) + .test('contactMethodRequired', 'Please select a preferred method of contact.', preferredContactMethodValidation); export const backupContactInfoSchema = Yup.object().shape({ name: Yup.string().required('Required'), From e949c3ac729a647fc7ec71404a3096c2b6f975c2 Mon Sep 17 00:00:00 2001 From: Brooklyn Welsh Date: Tue, 20 Aug 2024 16:18:42 -0400 Subject: [PATCH 2/7] Re-do of required/optional fields for updated AC, optional text removed, required fields marked with grey text, flashes to red if user exits without entering data. --- .../Customer/ContactInfoForm/index.jsx | 8 +---- .../EditContactInfoForm.jsx | 29 +++++-------------- .../EditOrdersForm/EditOrdersForm.jsx | 15 +++++----- .../MtoShipmentForm/MtoShipmentForm.jsx | 12 ++++---- src/components/Customer/NameForm/NameForm.jsx | 4 +-- .../OrdersInfoForm/OrdersInfoForm.jsx | 24 +++++++-------- .../DateAndLocationForm.jsx | 10 +++++-- .../PPM/Closeout/AboutForm/AboutForm.jsx | 1 + .../PPM/Closeout/ExpenseForm/ExpenseForm.jsx | 4 +-- .../ServiceInfoForm/ServiceInfoForm.jsx | 4 +-- .../LocationSearchBox/LocationSearchBox.jsx | 3 ++ .../form/AddressFields/AddressFields.jsx | 5 ++-- .../ContactInfoFields/ContactInfoFields.jsx | 21 ++++++++++---- .../CustomerAltContactInfoFields/index.jsx | 14 ++++----- .../form/CustomerContactInfoFields/index.jsx | 11 ++++--- src/components/form/RequiredTag.jsx | 10 +++++++ src/components/form/RequiredTag.module.scss | 6 ++++ .../form/fields/DatePickerInput.jsx | 2 ++ src/components/form/fields/DropdownInput.jsx | 15 ++++++++-- .../form/fields/DutyLocationInput.jsx | 21 ++++++++++++-- .../MaskedTextField/MaskedTextField.jsx | 4 +-- .../form/fields/TextField/TextField.jsx | 4 +-- .../CustomerOnboarding/CreateCustomerForm.jsx | 18 ++++++------ 23 files changed, 146 insertions(+), 99 deletions(-) create mode 100644 src/components/form/RequiredTag.jsx create mode 100644 src/components/form/RequiredTag.module.scss diff --git a/src/components/Customer/ContactInfoForm/index.jsx b/src/components/Customer/ContactInfoForm/index.jsx index efd3c9cc549..ffe6d9ca538 100644 --- a/src/components/Customer/ContactInfoForm/index.jsx +++ b/src/components/Customer/ContactInfoForm/index.jsx @@ -11,13 +11,7 @@ import { contactInfoSchema } from 'utils/validation'; const ContactInfoForm = ({ initialValues, onSubmit, onBack }) => { return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return ( diff --git a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx index 140f7de3ba5..4ffc3b0c0e5 100644 --- a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx +++ b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx @@ -11,12 +11,7 @@ import SectionWrapper from 'components/Customer/SectionWrapper'; import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigation'; import { Form } from 'components/form/Form'; import formStyles from 'styles/form.module.scss'; -import { - backupContactInfoSchema, - contactInfoSchema, - requiredAddressSchema, - preferredContactMethodValidation, -} from 'utils/validation'; +import { backupContactInfoSchema, contactInfoSchema, requiredAddressSchema } from 'utils/validation'; import { ResidentialAddressShape } from 'types/address'; import { CustomerContactInfoFields } from 'components/form/CustomerContactInfoFields'; import { BackupContactInfoFields } from 'components/form/BackupContactInfoFields'; @@ -27,25 +22,17 @@ export const backupAddressName = 'backup_mailing_address'; export const backupContactName = 'backup_contact'; const EditContactInfoForm = ({ initialValues, onSubmit, onCancel }) => { - const validationSchema = Yup.object() - .shape({ - ...contactInfoSchema.fields, - [residentialAddressName]: requiredAddressSchema.required(), - [backupAddressName]: requiredAddressSchema.required(), - [backupContactName]: backupContactInfoSchema.required(), - }) - .test('contactMethodRequired', 'Please select a preferred method of contact.', preferredContactMethodValidation); + const validationSchema = Yup.object().shape({ + ...contactInfoSchema.fields, + [residentialAddressName]: requiredAddressSchema.required(), + [backupAddressName]: requiredAddressSchema.required(), + [backupContactName]: backupContactInfoSchema.required(), + }); const sectionStyles = classnames(formStyles.formSection, editContactInfoFormStyle.formSection); return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return ( diff --git a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx index 21a151366e8..70e3cf27ac5 100644 --- a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx +++ b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx @@ -70,14 +70,8 @@ const EditOrdersForm = ({ let newDutyMeta = ''; return ( - - {({ isValid, isSubmitting, handleSubmit, values }) => { + + {({ isValid, isSubmitting, handleSubmit, values, touched }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); if (!values.origin_duty_location) originMeta = 'Required'; @@ -146,6 +140,7 @@ const EditOrdersForm = ({ id="origin_duty_location" required metaOverride={originMeta} + touched={touched} /> {isRetirementOrSeparation ? ( @@ -178,6 +173,8 @@ const EditOrdersForm = ({ hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." placeholder="Enter a city or ZIP" metaOverride={newDutyMeta} + touched={touched} + required /> ) : ( @@ -186,6 +183,8 @@ const EditOrdersForm = ({ label="New duty location" displayAddress={false} metaOverride={newDutyMeta} + touched={touched} + required /> )} diff --git a/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx b/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx index ab68d8d1221..668c97ca549 100644 --- a/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx +++ b/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx @@ -182,8 +182,6 @@ class MtoShipmentForm extends Component { const initialValues = formatMtoShipmentForDisplay(isCreatePage ? {} : mtoShipment); - const optionalLabel = Optional; - return (
@@ -359,8 +358,9 @@ class MtoShipmentForm extends Component { /> Releasing agent {optionalLabel}
} + legend={
Releasing agent
} render={(fields) => ( <>

Who can let the movers pick up your personal property if you are not there?

@@ -384,6 +384,7 @@ class MtoShipmentForm extends Component { label="Preferred delivery date" id="requestedDeliveryDate" validate={validateDate} + required /> @@ -518,8 +519,9 @@ class MtoShipmentForm extends Component { Receiving agent {optionalLabel}
} + legend={
Receiving agent
} render={(fields) => ( <>

Who can take delivery for you if the movers arrive and you are not there?

@@ -546,7 +548,7 @@ class MtoShipmentForm extends Component { )} -
Remarks {optionalLabel}
}> +
Remarks}> diff --git a/src/components/Customer/NameForm/NameForm.jsx b/src/components/Customer/NameForm/NameForm.jsx index 2cd11fbece9..ff76274447f 100644 --- a/src/components/Customer/NameForm/NameForm.jsx +++ b/src/components/Customer/NameForm/NameForm.jsx @@ -25,9 +25,9 @@ const NameForm = ({ initialValues, onSubmit, onBack }) => {

Name

- + - +
- {({ isValid, isSubmitting, handleSubmit, values, errors }) => { + + {({ isValid, isSubmitting, handleSubmit, values, touched }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); - if (!values.origin_duty_location) originMeta = 'Required'; + if (!values.origin_duty_location && touched.origin_duty_location) originMeta = 'Required'; else originMeta = null; - if (!values.new_duty_location) newDutyMeta = 'Required'; + if (!values.new_duty_location && touched.new_duty_location) newDutyMeta = 'Required'; else newDutyMeta = null; return ( @@ -78,7 +73,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) - {errors.has_dependents ? {errors.has_dependents} : null} +
{isRetirementOrSeparation ? ( @@ -139,6 +135,8 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." metaOverride={newDutyMeta} placeholder="Enter a city or ZIP" + touched={touched} + required /> ) : ( @@ -146,7 +144,9 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) name="new_duty_location" label="New duty location" displayAddress={false} + touched={touched} metaOverride={newDutyMeta} + required /> )} diff --git a/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx b/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx index df5efa41a6e..25dadbebcaa 100644 --- a/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx +++ b/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx @@ -138,7 +138,7 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb validateOnMount validateOnChange > - {({ isValid, isSubmitting, handleSubmit, setValues, values }) => { + {({ isValid, isSubmitting, handleSubmit, setValues, values, touched }) => { const handleUseCurrentResidenceChange = (e) => { const { checked } = e.target; if (checked) { @@ -404,6 +404,8 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb placeholder="Start typing a closeout office..." searchLocations={searchTransportationOffices} metaOverride={meta} + touched={touched} + required /> If you have more than one PPM for this move, your closeout office will be the same for all your @@ -456,7 +458,11 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb

Departure date

- + Enter the first day you expect to move things. It's OK if the actual date is different. We will ask for your actual departure date when you document and complete your PPM. diff --git a/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx b/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx index b6973cdf4e1..ba0af0c77cc 100644 --- a/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx +++ b/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx @@ -91,6 +91,7 @@ const AboutForm = ({ mtoShipment, onBack, onSubmit }) => { className={classnames(styles.actualMoveDate, 'usa-input')} name="actualMoveDate" label="When did you leave your origin?" + required /> If it took you more than one day to move out, use the first day.

Locations

diff --git a/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx b/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx index 4b784ade515..275ee9be5f5 100644 --- a/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx +++ b/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx @@ -228,8 +228,8 @@ const ExpenseForm = ({ {values.expenseType === 'STORAGE' && (

Dates

- - + +

Days in storage:{' '} {values.sitStartDate && values.sitEndDate && !errors.sitStartDate && !errors.sitEndDate diff --git a/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx b/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx index 588b5a5ea47..abe93daa91f 100644 --- a/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx +++ b/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx @@ -75,7 +75,7 @@ const ServiceInfoForm = ({ initialValues, onSubmit, onCancel }) => { - + @@ -84,7 +84,7 @@ const ServiceInfoForm = ({ initialValues, onSubmit, onCancel }) => { - + diff --git a/src/components/LocationSearchBox/LocationSearchBox.jsx b/src/components/LocationSearchBox/LocationSearchBox.jsx index c4d0133533c..6663c511732 100644 --- a/src/components/LocationSearchBox/LocationSearchBox.jsx +++ b/src/components/LocationSearchBox/LocationSearchBox.jsx @@ -9,6 +9,7 @@ import { debounce } from 'lodash'; import styles from './LocationSearchBox.module.scss'; import { SearchDutyLocations, ShowAddress } from './api'; +import { RequiredTag } from 'components/form/RequiredTag'; import Hint from 'components/Hint'; import { DutyLocationShape } from 'types'; @@ -87,6 +88,7 @@ export const LocationSearchBoxComponent = ({ hint, placeholder, isDisabled, + required, }) => { const { value, onChange, name: inputName } = input; @@ -187,6 +189,7 @@ export const LocationSearchBoxComponent = ({ + {required && }

{hint && {hint}}
diff --git a/src/components/form/AddressFields/AddressFields.jsx b/src/components/form/AddressFields/AddressFields.jsx index 0d26aad4dcc..ade70e1031f 100644 --- a/src/components/form/AddressFields/AddressFields.jsx +++ b/src/components/form/AddressFields/AddressFields.jsx @@ -75,14 +75,14 @@ export const AddressFields = ({ />
diff --git a/src/components/form/ContactInfoFields/ContactInfoFields.jsx b/src/components/form/ContactInfoFields/ContactInfoFields.jsx index e4d1f26c9b0..a28abe33f21 100644 --- a/src/components/form/ContactInfoFields/ContactInfoFields.jsx +++ b/src/components/form/ContactInfoFields/ContactInfoFields.jsx @@ -6,15 +6,24 @@ import { Fieldset } from '@trussworks/react-uswds'; import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; -export const ContactInfoFields = ({ legend, className, name, render }) => { +export const ContactInfoFields = ({ legend, className, name, render, optional }) => { const contactInfoFieldsUUID = uuidv4(); - return (
{render( <> - - + + { type="tel" minimum="12" mask="000{-}000{-}0000" - required + optional={optional} /> - + , )}
diff --git a/src/components/form/CustomerAltContactInfoFields/index.jsx b/src/components/form/CustomerAltContactInfoFields/index.jsx index a407574a785..ad60965a2dd 100644 --- a/src/components/form/CustomerAltContactInfoFields/index.jsx +++ b/src/components/form/CustomerAltContactInfoFields/index.jsx @@ -1,10 +1,11 @@ import React, { useRef } from 'react'; import { func, node, string } from 'prop-types'; import { v4 as uuidv4 } from 'uuid'; -import { Label, Fieldset, ErrorMessage } from '@trussworks/react-uswds'; -import { useFormikContext } from 'formik'; +import { Label, Fieldset } from '@trussworks/react-uswds'; import classnames from 'classnames'; +import RequiredTag from '../RequiredTag'; + import formStyles from 'styles/form.module.scss'; import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; @@ -12,7 +13,6 @@ import { CheckboxField } from 'components/form/fields'; export const CustomerAltContactInfoFields = ({ legend, className, render }) => { const CustomerAltContactInfoFieldsUUID = useRef(uuidv4()); - const { errors } = useFormikContext(); return (
@@ -23,13 +23,13 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => {
- +
- +
@@ -52,7 +52,7 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => { type="tel" minimum="12" mask="000{-}000{-}0000" - labelHint="Optional" + optional />
@@ -68,7 +68,7 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => {
- {errors.preferredContactMethod ? {errors.preferredContactMethod} : null} +
{ const CustomerContactInfoFieldsUUID = useRef(uuidv4()); - const { errors } = useFormikContext(); - return (
{render( @@ -36,7 +35,7 @@ export const CustomerContactInfoFields = ({ legend, className, render }) => {
{ required /> - {errors.preferredContactMethod ? {errors.preferredContactMethod} : null} +
{ + // eslint-disable-next-line react/jsx-props-no-spreading + return
Required
; +}; + +export default RequiredTag; diff --git a/src/components/form/RequiredTag.module.scss b/src/components/form/RequiredTag.module.scss new file mode 100644 index 00000000000..6c898f56f23 --- /dev/null +++ b/src/components/form/RequiredTag.module.scss @@ -0,0 +1,6 @@ +@import 'shared/styles/colors'; +.RequiredTag { + font-size: 13px; + color: $base; + font-weight: normal; +} diff --git a/src/components/form/fields/DatePickerInput.jsx b/src/components/form/fields/DatePickerInput.jsx index ad918ce0010..a8a9845c340 100644 --- a/src/components/form/fields/DatePickerInput.jsx +++ b/src/components/form/fields/DatePickerInput.jsx @@ -6,6 +6,7 @@ import { v4 as uuidv4 } from 'uuid'; import styles from './DatePickerInput.module.scss'; +import { RequiredTag } from 'components/form/RequiredTag'; import { ErrorMessage } from 'components/form/ErrorMessage'; import SingleDatePicker from 'shared/JsonSchemaForm/SingleDatePicker'; import { datePickerFormat, formatDate } from 'shared/dates'; @@ -40,6 +41,7 @@ export const DatePickerInput = (props) => { {label} {showOptional &&
Optional
} + {required && }
{hint && {hint}} {meta.error} diff --git a/src/components/form/fields/DropdownInput.jsx b/src/components/form/fields/DropdownInput.jsx index 453cd130655..87818d0735d 100644 --- a/src/components/form/fields/DropdownInput.jsx +++ b/src/components/form/fields/DropdownInput.jsx @@ -4,13 +4,24 @@ import { v4 as uuidv4 } from 'uuid'; import { useField } from 'formik'; import { Dropdown, FormGroup, Label } from '@trussworks/react-uswds'; +import { RequiredTag } from 'components/form/RequiredTag'; import { ErrorMessage } from 'components/form/ErrorMessage'; // import { OptionalTag } from 'components/form/OptionalTag'; import { DropdownArrayOf } from 'types/form'; import './DropdownInput.module.scss'; export const DropdownInput = (props) => { - const { id, name, label, options, showDropdownPlaceholderText, isDisabled, disableErrorLabel, ...inputProps } = props; + const { + id, + name, + label, + options, + showDropdownPlaceholderText, + isDisabled, + disableErrorLabel, + required, + ...inputProps + } = props; const [field, meta] = useField(props); const hasError = disableErrorLabel ? false : meta.touched && !!meta.error; @@ -23,7 +34,7 @@ export const DropdownInput = (props) => { - {/* {optional && } */} + {required && }
{meta.error} {/* eslint-disable-next-line react/jsx-props-no-spreading */} diff --git a/src/components/form/fields/DutyLocationInput.jsx b/src/components/form/fields/DutyLocationInput.jsx index 8f5e571a18d..d6802644ab4 100644 --- a/src/components/form/fields/DutyLocationInput.jsx +++ b/src/components/form/fields/DutyLocationInput.jsx @@ -7,7 +7,18 @@ import './DropdownInput.module.scss'; // TODO: refactor component when we can to make it more user friendly with Formik export const DutyLocationInput = (props) => { - const { label, name, displayAddress, hint, placeholder, isDisabled, searchLocations, metaOverride } = props; + const { + label, + name, + displayAddress, + hint, + placeholder, + isDisabled, + searchLocations, + metaOverride, + touched, + required, + } = props; const [field, meta, helpers] = useField(props); let errorString = ''; @@ -17,13 +28,18 @@ export const DutyLocationInput = (props) => { errorString = meta.value?.name ? meta.error?.name || meta.error : ''; } + const handleChange = (value) => { + touched[name] = true; + helpers.setValue(value); + }; + return ( { placeholder={placeholder} isDisabled={isDisabled} searchLocations={searchLocations} + required={required} /> ); }; diff --git a/src/components/form/fields/MaskedTextField/MaskedTextField.jsx b/src/components/form/fields/MaskedTextField/MaskedTextField.jsx index 57f84e2d860..daddcf9fbdd 100644 --- a/src/components/form/fields/MaskedTextField/MaskedTextField.jsx +++ b/src/components/form/fields/MaskedTextField/MaskedTextField.jsx @@ -8,10 +8,10 @@ import { FormGroup, Label } from '@trussworks/react-uswds'; import styles from './MaskedTextField.module.scss'; -import { OptionalTag } from 'components/form/OptionalTag'; import { ErrorMessage } from 'components/form/index'; import Hint from 'components/Hint'; import { isNullUndefinedOrWhitespace } from 'shared/utils'; +import RequiredTag from 'components/form/RequiredTag'; const MaskedTextField = ({ containerClassName, @@ -68,7 +68,7 @@ const MaskedTextField = ({ {description}
)} - {optional && } + {optional || }
{showError && ( diff --git a/src/components/form/fields/TextField/TextField.jsx b/src/components/form/fields/TextField/TextField.jsx index d7e96143720..577f9c8bff5 100644 --- a/src/components/form/fields/TextField/TextField.jsx +++ b/src/components/form/fields/TextField/TextField.jsx @@ -4,7 +4,7 @@ import classnames from 'classnames'; import { useField } from 'formik'; import { FormGroup, Label, TextInput, Textarea, ErrorMessage } from '@trussworks/react-uswds'; -import { OptionalTag } from 'components/form/OptionalTag'; +import { RequiredTag } from 'components/form/RequiredTag'; import Hint from 'components/Hint'; /** @@ -50,7 +50,7 @@ const TextField = ({ - {optional && } + {optional || } {showError && ( diff --git a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx index b8a6ed6a6fa..21aa186b364 100644 --- a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx +++ b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx @@ -262,7 +262,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { label="DoD ID number" name="edipi" id="edipi" - labelHint="Optional" + optional maxLength="10" isDisabled={isSafetyMove} /> @@ -272,7 +272,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { name="emplid" id="emplid" maxLength="7" - labelHint="Optional" + optional inputMode="numeric" pattern="[0-9]{7}" isDisabled={isSafetyMove} @@ -282,9 +282,9 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => {

Customer Name

- + - +

Contact Info

@@ -299,7 +299,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { /> { /> { /> Date: Wed, 28 Aug 2024 10:57:04 -0400 Subject: [PATCH 3/7] Revert "Re-do of required/optional fields for updated AC, optional text removed, required fields marked with grey text, flashes to red if user exits without entering data." This reverts commit e949c3ac729a647fc7ec71404a3096c2b6f975c2. --- .../Customer/ContactInfoForm/index.jsx | 8 ++++- .../EditContactInfoForm.jsx | 29 ++++++++++++++----- .../EditOrdersForm/EditOrdersForm.jsx | 15 +++++----- .../MtoShipmentForm/MtoShipmentForm.jsx | 12 ++++---- src/components/Customer/NameForm/NameForm.jsx | 4 +-- .../OrdersInfoForm/OrdersInfoForm.jsx | 24 +++++++-------- .../DateAndLocationForm.jsx | 10 ++----- .../PPM/Closeout/AboutForm/AboutForm.jsx | 1 - .../PPM/Closeout/ExpenseForm/ExpenseForm.jsx | 4 +-- .../ServiceInfoForm/ServiceInfoForm.jsx | 4 +-- .../LocationSearchBox/LocationSearchBox.jsx | 3 -- .../form/AddressFields/AddressFields.jsx | 5 ++-- .../ContactInfoFields/ContactInfoFields.jsx | 21 ++++---------- .../CustomerAltContactInfoFields/index.jsx | 14 ++++----- .../form/CustomerContactInfoFields/index.jsx | 11 +++---- src/components/form/RequiredTag.jsx | 10 ------- src/components/form/RequiredTag.module.scss | 6 ---- .../form/fields/DatePickerInput.jsx | 2 -- src/components/form/fields/DropdownInput.jsx | 15 ++-------- .../form/fields/DutyLocationInput.jsx | 21 ++------------ .../MaskedTextField/MaskedTextField.jsx | 4 +-- .../form/fields/TextField/TextField.jsx | 4 +-- .../CustomerOnboarding/CreateCustomerForm.jsx | 18 ++++++------ 23 files changed, 99 insertions(+), 146 deletions(-) delete mode 100644 src/components/form/RequiredTag.jsx delete mode 100644 src/components/form/RequiredTag.module.scss diff --git a/src/components/Customer/ContactInfoForm/index.jsx b/src/components/Customer/ContactInfoForm/index.jsx index ffe6d9ca538..efd3c9cc549 100644 --- a/src/components/Customer/ContactInfoForm/index.jsx +++ b/src/components/Customer/ContactInfoForm/index.jsx @@ -11,7 +11,13 @@ import { contactInfoSchema } from 'utils/validation'; const ContactInfoForm = ({ initialValues, onSubmit, onBack }) => { return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return ( diff --git a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx index 4ffc3b0c0e5..140f7de3ba5 100644 --- a/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx +++ b/src/components/Customer/EditContactInfoForm/EditContactInfoForm.jsx @@ -11,7 +11,12 @@ import SectionWrapper from 'components/Customer/SectionWrapper'; import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigation'; import { Form } from 'components/form/Form'; import formStyles from 'styles/form.module.scss'; -import { backupContactInfoSchema, contactInfoSchema, requiredAddressSchema } from 'utils/validation'; +import { + backupContactInfoSchema, + contactInfoSchema, + requiredAddressSchema, + preferredContactMethodValidation, +} from 'utils/validation'; import { ResidentialAddressShape } from 'types/address'; import { CustomerContactInfoFields } from 'components/form/CustomerContactInfoFields'; import { BackupContactInfoFields } from 'components/form/BackupContactInfoFields'; @@ -22,17 +27,25 @@ export const backupAddressName = 'backup_mailing_address'; export const backupContactName = 'backup_contact'; const EditContactInfoForm = ({ initialValues, onSubmit, onCancel }) => { - const validationSchema = Yup.object().shape({ - ...contactInfoSchema.fields, - [residentialAddressName]: requiredAddressSchema.required(), - [backupAddressName]: requiredAddressSchema.required(), - [backupContactName]: backupContactInfoSchema.required(), - }); + const validationSchema = Yup.object() + .shape({ + ...contactInfoSchema.fields, + [residentialAddressName]: requiredAddressSchema.required(), + [backupAddressName]: requiredAddressSchema.required(), + [backupContactName]: backupContactInfoSchema.required(), + }) + .test('contactMethodRequired', 'Please select a preferred method of contact.', preferredContactMethodValidation); const sectionStyles = classnames(formStyles.formSection, editContactInfoFormStyle.formSection); return ( - + {({ isValid, isSubmitting, handleSubmit }) => { return ( diff --git a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx index 70e3cf27ac5..21a151366e8 100644 --- a/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx +++ b/src/components/Customer/EditOrdersForm/EditOrdersForm.jsx @@ -70,8 +70,14 @@ const EditOrdersForm = ({ let newDutyMeta = ''; return ( - - {({ isValid, isSubmitting, handleSubmit, values, touched }) => { + + {({ isValid, isSubmitting, handleSubmit, values }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); if (!values.origin_duty_location) originMeta = 'Required'; @@ -140,7 +146,6 @@ const EditOrdersForm = ({ id="origin_duty_location" required metaOverride={originMeta} - touched={touched} /> {isRetirementOrSeparation ? ( @@ -173,8 +178,6 @@ const EditOrdersForm = ({ hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." placeholder="Enter a city or ZIP" metaOverride={newDutyMeta} - touched={touched} - required /> ) : ( @@ -183,8 +186,6 @@ const EditOrdersForm = ({ label="New duty location" displayAddress={false} metaOverride={newDutyMeta} - touched={touched} - required /> )} diff --git a/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx b/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx index 668c97ca549..ab68d8d1221 100644 --- a/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx +++ b/src/components/Customer/MtoShipmentForm/MtoShipmentForm.jsx @@ -182,6 +182,8 @@ class MtoShipmentForm extends Component { const initialValues = formatMtoShipmentForDisplay(isCreatePage ? {} : mtoShipment); + const optionalLabel = Optional; + return (
@@ -358,9 +359,8 @@ class MtoShipmentForm extends Component { /> Releasing agent} + legend={
Releasing agent {optionalLabel}
} render={(fields) => ( <>

Who can let the movers pick up your personal property if you are not there?

@@ -384,7 +384,6 @@ class MtoShipmentForm extends Component { label="Preferred delivery date" id="requestedDeliveryDate" validate={validateDate} - required /> @@ -519,9 +518,8 @@ class MtoShipmentForm extends Component { Receiving agent} + legend={
Receiving agent {optionalLabel}
} render={(fields) => ( <>

Who can take delivery for you if the movers arrive and you are not there?

@@ -548,7 +546,7 @@ class MtoShipmentForm extends Component { )} -
Remarks}> +
Remarks {optionalLabel}}> diff --git a/src/components/Customer/NameForm/NameForm.jsx b/src/components/Customer/NameForm/NameForm.jsx index ff76274447f..2cd11fbece9 100644 --- a/src/components/Customer/NameForm/NameForm.jsx +++ b/src/components/Customer/NameForm/NameForm.jsx @@ -25,9 +25,9 @@ const NameForm = ({ initialValues, onSubmit, onBack }) => {

Name

- + - +
- {({ isValid, isSubmitting, handleSubmit, values, touched }) => { + + {({ isValid, isSubmitting, handleSubmit, values, errors }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type); - if (!values.origin_duty_location && touched.origin_duty_location) originMeta = 'Required'; + if (!values.origin_duty_location) originMeta = 'Required'; else originMeta = null; - if (!values.new_duty_location && touched.new_duty_location) newDutyMeta = 'Required'; + if (!values.new_duty_location) newDutyMeta = 'Required'; else newDutyMeta = null; return ( @@ -73,7 +78,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) - + {errors.has_dependents ? {errors.has_dependents} : null}
{isRetirementOrSeparation ? ( @@ -135,8 +139,6 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) hint="Enter the option closest to your destination. Your move counselor will identify if there might be a cost to you." metaOverride={newDutyMeta} placeholder="Enter a city or ZIP" - touched={touched} - required /> ) : ( @@ -144,9 +146,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack }) name="new_duty_location" label="New duty location" displayAddress={false} - touched={touched} metaOverride={newDutyMeta} - required /> )} diff --git a/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx b/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx index 25dadbebcaa..df5efa41a6e 100644 --- a/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx +++ b/src/components/Customer/PPM/Booking/DateAndLocationForm/DateAndLocationForm.jsx @@ -138,7 +138,7 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb validateOnMount validateOnChange > - {({ isValid, isSubmitting, handleSubmit, setValues, values, touched }) => { + {({ isValid, isSubmitting, handleSubmit, setValues, values }) => { const handleUseCurrentResidenceChange = (e) => { const { checked } = e.target; if (checked) { @@ -404,8 +404,6 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb placeholder="Start typing a closeout office..." searchLocations={searchTransportationOffices} metaOverride={meta} - touched={touched} - required /> If you have more than one PPM for this move, your closeout office will be the same for all your @@ -458,11 +456,7 @@ const DateAndLocationForm = ({ mtoShipment, destinationDutyLocation, serviceMemb

Departure date

- + Enter the first day you expect to move things. It's OK if the actual date is different. We will ask for your actual departure date when you document and complete your PPM. diff --git a/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx b/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx index ba0af0c77cc..b6973cdf4e1 100644 --- a/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx +++ b/src/components/Customer/PPM/Closeout/AboutForm/AboutForm.jsx @@ -91,7 +91,6 @@ const AboutForm = ({ mtoShipment, onBack, onSubmit }) => { className={classnames(styles.actualMoveDate, 'usa-input')} name="actualMoveDate" label="When did you leave your origin?" - required /> If it took you more than one day to move out, use the first day.

Locations

diff --git a/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx b/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx index 275ee9be5f5..4b784ade515 100644 --- a/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx +++ b/src/components/Customer/PPM/Closeout/ExpenseForm/ExpenseForm.jsx @@ -228,8 +228,8 @@ const ExpenseForm = ({ {values.expenseType === 'STORAGE' && (

Dates

- - + +

Days in storage:{' '} {values.sitStartDate && values.sitEndDate && !errors.sitStartDate && !errors.sitEndDate diff --git a/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx b/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx index abe93daa91f..588b5a5ea47 100644 --- a/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx +++ b/src/components/Customer/ServiceInfoForm/ServiceInfoForm.jsx @@ -75,7 +75,7 @@ const ServiceInfoForm = ({ initialValues, onSubmit, onCancel }) => { - + @@ -84,7 +84,7 @@ const ServiceInfoForm = ({ initialValues, onSubmit, onCancel }) => { - + diff --git a/src/components/LocationSearchBox/LocationSearchBox.jsx b/src/components/LocationSearchBox/LocationSearchBox.jsx index 6663c511732..c4d0133533c 100644 --- a/src/components/LocationSearchBox/LocationSearchBox.jsx +++ b/src/components/LocationSearchBox/LocationSearchBox.jsx @@ -9,7 +9,6 @@ import { debounce } from 'lodash'; import styles from './LocationSearchBox.module.scss'; import { SearchDutyLocations, ShowAddress } from './api'; -import { RequiredTag } from 'components/form/RequiredTag'; import Hint from 'components/Hint'; import { DutyLocationShape } from 'types'; @@ -88,7 +87,6 @@ export const LocationSearchBoxComponent = ({ hint, placeholder, isDisabled, - required, }) => { const { value, onChange, name: inputName } = input; @@ -189,7 +187,6 @@ export const LocationSearchBoxComponent = ({ - {required && }

{hint && {hint}}
diff --git a/src/components/form/AddressFields/AddressFields.jsx b/src/components/form/AddressFields/AddressFields.jsx index ade70e1031f..0d26aad4dcc 100644 --- a/src/components/form/AddressFields/AddressFields.jsx +++ b/src/components/form/AddressFields/AddressFields.jsx @@ -75,14 +75,14 @@ export const AddressFields = ({ />
diff --git a/src/components/form/ContactInfoFields/ContactInfoFields.jsx b/src/components/form/ContactInfoFields/ContactInfoFields.jsx index a28abe33f21..e4d1f26c9b0 100644 --- a/src/components/form/ContactInfoFields/ContactInfoFields.jsx +++ b/src/components/form/ContactInfoFields/ContactInfoFields.jsx @@ -6,24 +6,15 @@ import { Fieldset } from '@trussworks/react-uswds'; import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; -export const ContactInfoFields = ({ legend, className, name, render, optional }) => { +export const ContactInfoFields = ({ legend, className, name, render }) => { const contactInfoFieldsUUID = uuidv4(); + return (
{render( <> - - + + - + , )}
diff --git a/src/components/form/CustomerAltContactInfoFields/index.jsx b/src/components/form/CustomerAltContactInfoFields/index.jsx index ad60965a2dd..a407574a785 100644 --- a/src/components/form/CustomerAltContactInfoFields/index.jsx +++ b/src/components/form/CustomerAltContactInfoFields/index.jsx @@ -1,11 +1,10 @@ import React, { useRef } from 'react'; import { func, node, string } from 'prop-types'; import { v4 as uuidv4 } from 'uuid'; -import { Label, Fieldset } from '@trussworks/react-uswds'; +import { Label, Fieldset, ErrorMessage } from '@trussworks/react-uswds'; +import { useFormikContext } from 'formik'; import classnames from 'classnames'; -import RequiredTag from '../RequiredTag'; - import formStyles from 'styles/form.module.scss'; import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; @@ -13,6 +12,7 @@ import { CheckboxField } from 'components/form/fields'; export const CustomerAltContactInfoFields = ({ legend, className, render }) => { const CustomerAltContactInfoFieldsUUID = useRef(uuidv4()); + const { errors } = useFormikContext(); return (
@@ -23,13 +23,13 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => {
- +
- +
@@ -52,7 +52,7 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => { type="tel" minimum="12" mask="000{-}000{-}0000" - optional + labelHint="Optional" />
@@ -68,7 +68,7 @@ export const CustomerAltContactInfoFields = ({ legend, className, render }) => {
- + {errors.preferredContactMethod ? {errors.preferredContactMethod} : null}
{ const CustomerContactInfoFieldsUUID = useRef(uuidv4()); + const { errors } = useFormikContext(); + return (
{render( @@ -35,7 +36,7 @@ export const CustomerContactInfoFields = ({ legend, className, render }) => {
{ required /> - + {errors.preferredContactMethod ? {errors.preferredContactMethod} : null}
{ - // eslint-disable-next-line react/jsx-props-no-spreading - return
Required
; -}; - -export default RequiredTag; diff --git a/src/components/form/RequiredTag.module.scss b/src/components/form/RequiredTag.module.scss deleted file mode 100644 index 6c898f56f23..00000000000 --- a/src/components/form/RequiredTag.module.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import 'shared/styles/colors'; -.RequiredTag { - font-size: 13px; - color: $base; - font-weight: normal; -} diff --git a/src/components/form/fields/DatePickerInput.jsx b/src/components/form/fields/DatePickerInput.jsx index a8a9845c340..ad918ce0010 100644 --- a/src/components/form/fields/DatePickerInput.jsx +++ b/src/components/form/fields/DatePickerInput.jsx @@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid'; import styles from './DatePickerInput.module.scss'; -import { RequiredTag } from 'components/form/RequiredTag'; import { ErrorMessage } from 'components/form/ErrorMessage'; import SingleDatePicker from 'shared/JsonSchemaForm/SingleDatePicker'; import { datePickerFormat, formatDate } from 'shared/dates'; @@ -41,7 +40,6 @@ export const DatePickerInput = (props) => { {label} {showOptional &&
Optional
} - {required && }
{hint && {hint}} {meta.error} diff --git a/src/components/form/fields/DropdownInput.jsx b/src/components/form/fields/DropdownInput.jsx index 87818d0735d..453cd130655 100644 --- a/src/components/form/fields/DropdownInput.jsx +++ b/src/components/form/fields/DropdownInput.jsx @@ -4,24 +4,13 @@ import { v4 as uuidv4 } from 'uuid'; import { useField } from 'formik'; import { Dropdown, FormGroup, Label } from '@trussworks/react-uswds'; -import { RequiredTag } from 'components/form/RequiredTag'; import { ErrorMessage } from 'components/form/ErrorMessage'; // import { OptionalTag } from 'components/form/OptionalTag'; import { DropdownArrayOf } from 'types/form'; import './DropdownInput.module.scss'; export const DropdownInput = (props) => { - const { - id, - name, - label, - options, - showDropdownPlaceholderText, - isDisabled, - disableErrorLabel, - required, - ...inputProps - } = props; + const { id, name, label, options, showDropdownPlaceholderText, isDisabled, disableErrorLabel, ...inputProps } = props; const [field, meta] = useField(props); const hasError = disableErrorLabel ? false : meta.touched && !!meta.error; @@ -34,7 +23,7 @@ export const DropdownInput = (props) => { - {required && } + {/* {optional && } */}
{meta.error} {/* eslint-disable-next-line react/jsx-props-no-spreading */} diff --git a/src/components/form/fields/DutyLocationInput.jsx b/src/components/form/fields/DutyLocationInput.jsx index d6802644ab4..8f5e571a18d 100644 --- a/src/components/form/fields/DutyLocationInput.jsx +++ b/src/components/form/fields/DutyLocationInput.jsx @@ -7,18 +7,7 @@ import './DropdownInput.module.scss'; // TODO: refactor component when we can to make it more user friendly with Formik export const DutyLocationInput = (props) => { - const { - label, - name, - displayAddress, - hint, - placeholder, - isDisabled, - searchLocations, - metaOverride, - touched, - required, - } = props; + const { label, name, displayAddress, hint, placeholder, isDisabled, searchLocations, metaOverride } = props; const [field, meta, helpers] = useField(props); let errorString = ''; @@ -28,18 +17,13 @@ export const DutyLocationInput = (props) => { errorString = meta.value?.name ? meta.error?.name || meta.error : ''; } - const handleChange = (value) => { - touched[name] = true; - helpers.setValue(value); - }; - return ( { placeholder={placeholder} isDisabled={isDisabled} searchLocations={searchLocations} - required={required} /> ); }; diff --git a/src/components/form/fields/MaskedTextField/MaskedTextField.jsx b/src/components/form/fields/MaskedTextField/MaskedTextField.jsx index daddcf9fbdd..57f84e2d860 100644 --- a/src/components/form/fields/MaskedTextField/MaskedTextField.jsx +++ b/src/components/form/fields/MaskedTextField/MaskedTextField.jsx @@ -8,10 +8,10 @@ import { FormGroup, Label } from '@trussworks/react-uswds'; import styles from './MaskedTextField.module.scss'; +import { OptionalTag } from 'components/form/OptionalTag'; import { ErrorMessage } from 'components/form/index'; import Hint from 'components/Hint'; import { isNullUndefinedOrWhitespace } from 'shared/utils'; -import RequiredTag from 'components/form/RequiredTag'; const MaskedTextField = ({ containerClassName, @@ -68,7 +68,7 @@ const MaskedTextField = ({ {description}
)} - {optional || } + {optional && }
{showError && ( diff --git a/src/components/form/fields/TextField/TextField.jsx b/src/components/form/fields/TextField/TextField.jsx index 577f9c8bff5..d7e96143720 100644 --- a/src/components/form/fields/TextField/TextField.jsx +++ b/src/components/form/fields/TextField/TextField.jsx @@ -4,7 +4,7 @@ import classnames from 'classnames'; import { useField } from 'formik'; import { FormGroup, Label, TextInput, Textarea, ErrorMessage } from '@trussworks/react-uswds'; -import { RequiredTag } from 'components/form/RequiredTag'; +import { OptionalTag } from 'components/form/OptionalTag'; import Hint from 'components/Hint'; /** @@ -50,7 +50,7 @@ const TextField = ({ - {optional || } + {optional && } {showError && ( diff --git a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx index 21aa186b364..b8a6ed6a6fa 100644 --- a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx +++ b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx @@ -262,7 +262,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { label="DoD ID number" name="edipi" id="edipi" - optional + labelHint="Optional" maxLength="10" isDisabled={isSafetyMove} /> @@ -272,7 +272,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { name="emplid" id="emplid" maxLength="7" - optional + labelHint="Optional" inputMode="numeric" pattern="[0-9]{7}" isDisabled={isSafetyMove} @@ -282,9 +282,9 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => {

Customer Name

- + - +

Contact Info

@@ -299,7 +299,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage }) => { /> { /> { /> Date: Thu, 29 Aug 2024 12:29:06 -0400 Subject: [PATCH 4/7] Reverted previous changes, added required hint and removed optional hint where needed on customer side --- .../BackupAddressForm/BackupAddressForm.jsx | 1 + .../BackupContactForm.stories.jsx | 8 +++- .../Customer/BackupContactForm/index.jsx | 2 +- .../BoatShipmentForm/BoatShipmentForm.jsx | 19 ++++---- .../BoatShipmentForm.module.scss | 2 +- .../Customer/ContactInfoForm/index.jsx | 10 +--- .../Customer/DodInfoForm/DodInfoForm.jsx | 3 ++ .../EditContactInfoForm.jsx | 8 ++-- .../EditOrdersForm/EditOrdersForm.jsx | 36 ++++++++------ .../MtoShipmentForm/MtoShipmentForm.jsx | 26 ++++++---- src/components/Customer/NameForm/NameForm.jsx | 8 ++-- .../OrdersInfoForm/OrdersInfoForm.jsx | 48 ++++++++++++------- .../PPM/Booking/Advance/AdvanceForm.jsx | 1 + .../DateAndLocationForm.jsx | 23 +++++++-- .../EstimatedWeightsProGearForm.jsx | 5 ++ .../PPM/Closeout/AboutForm/AboutForm.jsx | 6 ++- src/components/Customer/PPM/PPM.module.scss | 21 +++++++- .../ResidentialAddressForm.jsx | 1 + .../LocationSearchBox/LocationSearchBox.jsx | 4 +- .../form/AddressFields/AddressFields.jsx | 10 +++- .../form/BackupContactInfoFields/index.jsx | 12 ++++- .../CustomerContactInfoFields.stories.jsx | 2 +- .../form/CustomerContactInfoFields/index.jsx | 14 +++--- src/components/form/RequiredTag.jsx | 10 ++++ src/components/form/RequiredTag.module.scss | 6 +++ .../form/fields/DatePickerInput.jsx | 4 +- src/components/form/fields/DropdownInput.jsx | 5 +- .../form/fields/DutyLocationInput.jsx | 11 ++++- 28 files changed, 206 insertions(+), 100 deletions(-) create mode 100644 src/components/form/RequiredTag.jsx create mode 100644 src/components/form/RequiredTag.module.scss diff --git a/src/components/Customer/BackupAddressForm/BackupAddressForm.jsx b/src/components/Customer/BackupAddressForm/BackupAddressForm.jsx index e745afa9b2d..be56f6a059f 100644 --- a/src/components/Customer/BackupAddressForm/BackupAddressForm.jsx +++ b/src/components/Customer/BackupAddressForm/BackupAddressForm.jsx @@ -36,6 +36,7 @@ const BackupAddressForm = ({ formFieldsName, initialValues, onSubmit, onBack }) diff --git a/src/components/Customer/BackupContactForm/BackupContactForm.stories.jsx b/src/components/Customer/BackupContactForm/BackupContactForm.stories.jsx index 8ff7a0b13b3..60a1e96b6e0 100644 --- a/src/components/Customer/BackupContactForm/BackupContactForm.stories.jsx +++ b/src/components/Customer/BackupContactForm/BackupContactForm.stories.jsx @@ -18,7 +18,12 @@ const emptyInitialValues = { }; export const DefaultState = (argTypes) => ( - + ); export const WithInitialValues = (argTypes) => ( @@ -30,5 +35,6 @@ export const WithInitialValues = (argTypes) => ( }} onSubmit={argTypes.onSubmit} onBack={argTypes.onBack} + labelHint="Required" /> ); diff --git a/src/components/Customer/BackupContactForm/index.jsx b/src/components/Customer/BackupContactForm/index.jsx index bb6978d156b..e24bdf8d73e 100644 --- a/src/components/Customer/BackupContactForm/index.jsx +++ b/src/components/Customer/BackupContactForm/index.jsx @@ -27,7 +27,7 @@ const BackupContactForm = ({ initialValues, onSubmit, onBack }) => {

- +
diff --git a/src/components/Customer/BoatShipment/BoatShipmentForm/BoatShipmentForm.jsx b/src/components/Customer/BoatShipment/BoatShipmentForm/BoatShipmentForm.jsx index 71231b68f6f..4c43be5cbf7 100644 --- a/src/components/Customer/BoatShipment/BoatShipmentForm/BoatShipmentForm.jsx +++ b/src/components/Customer/BoatShipment/BoatShipmentForm/BoatShipmentForm.jsx @@ -7,6 +7,7 @@ import classnames from 'classnames'; import styles from './BoatShipmentForm.module.scss'; +import RequiredTag from 'components/form/RequiredTag'; import SectionWrapper from 'components/Customer/SectionWrapper'; import Hint from 'components/Hint'; import Fieldset from 'shared/Fieldset'; @@ -125,6 +126,7 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => { name="year" label="Year" id="year" + labelHint="Required" maxLength={4} mask={Number} scale={0} @@ -143,8 +145,8 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => {
- - + +
@@ -158,6 +160,7 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => {
Length + Required
@@ -195,6 +198,7 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => {
Width + Required
@@ -232,6 +236,7 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => {
Height + Required
@@ -272,6 +277,7 @@ const BoatShipmentForm = ({ mtoShipment, onBack, onSubmit }) => {

Trailer Status

Does the boat have a trailer? + { {values.hasTrailer === 'true' && (
Is the trailer roadworthy? + {
-
- Remarks Optional -
- } - > +
Remarks
}>
@@ -283,6 +282,7 @@ class MtoShipmentForm extends Component { ( <>

What address are the movers picking up from?

@@ -323,7 +323,9 @@ class MtoShipmentForm extends Component { />
- {hasSecondaryPickup === 'yes' && } + {hasSecondaryPickup === 'yes' && ( + + )} {isTertiaryAddressEnabled && hasSecondaryPickup === 'yes' && (
@@ -358,7 +360,7 @@ class MtoShipmentForm extends Component { hasSecondaryPickup === 'yes' && ( <>

Third pickup location

- + )} @@ -367,7 +369,7 @@ class MtoShipmentForm extends Component { Releasing agent {optionalLabel}
} + legend={
Releasing agent
} render={(fields) => ( <>

Who can let the movers pick up your personal property if you are not there?

@@ -391,13 +393,16 @@ class MtoShipmentForm extends Component { label="Preferred delivery date" id="requestedDeliveryDate" validate={validateDate} + hint="Required" />
{!isNTSR && ( -

Do you know your delivery address yet?

+
( <> {fields} @@ -456,7 +462,7 @@ class MtoShipmentForm extends Component {
{hasSecondaryDelivery === 'yes' && ( - + )} {isTertiaryAddressEnabled && hasSecondaryDelivery === 'yes' && (
@@ -492,7 +498,7 @@ class MtoShipmentForm extends Component { hasSecondaryDelivery === 'yes' && ( <>

Third delivery location

- + )} @@ -526,7 +532,7 @@ class MtoShipmentForm extends Component { Receiving agent {optionalLabel}
} + legend={
Receiving agent
} render={(fields) => ( <>

Who can take delivery for you if the movers arrive and you are not there?

@@ -554,7 +560,7 @@ class MtoShipmentForm extends Component { {!isBoat && ( -
Remarks {optionalLabel}}> +
Remarks}>