Skip to content

Commit

Permalink
feat: get veteran info showing and using platform code in mock form app
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwhitlock1 committed Jan 4, 2025
1 parent 72e462c commit b5d6495
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { taskCompletePagePattern2 } from 'applications/_mock-form-ae-design-patt
// page level imports
import IntroductionPage from '../IntroductionPage';
import profileContactInfo from './profileContactInfo';
import veteranInfo from './veteranInfo';
import { veteranInformation } from './veteranInfo';

const formConfig = {
rootUrl: manifest.rootUrl,
Expand Down Expand Up @@ -62,8 +62,8 @@ const formConfig = {
veteranInformation: {
title: 'Veteran information',
path: 'veteran-details',
uiSchema: veteranInfo.uiSchema,
schema: veteranInfo.schema,
uiSchema: veteranInformation.uiSchema,
schema: veteranInformation.schema,
},
...profileContactInfo({
contactInfoPageKey: 'confirmContactInfo3',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import VeteranInformation from '../VeteranInformation';
import React from 'react';
import { PersonalInformation } from '~/platform/forms-system/src/js/components/PersonalInformation/PersonalInformation';

const veteranInformation = {
export const veteranInformation = {
uiSchema: {
'ui:description': VeteranInformation,
'ui:description': props => (
<PersonalInformation
config={{
showSSN: true,
showVAFileNumber: false,
showDateOfBirth: true,
showGender: false,
showName: true,
errorMessage: 'Required information is missing.',
}}
dataAdapter={{
ssnPath: 'veteranSocialSecurityNumber',
}}
{...props}
/>
),
'ui:options': {
hideOnReview: true,
},
Expand All @@ -12,5 +28,3 @@ const veteranInformation = {
properties: {},
},
};

export default veteranInformation;
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { format, isValid } from 'date-fns';

import { CONTACTS } from '@department-of-veterans-affairs/component-library/contacts';

import { genderLabels } from '~/platform/static-data/labels';
import { selectProfile } from '~/platform/user/selectors';

import { formatNumberForScreenReader } from '../../utilities/ui/mask-string';
import {
hasRequiredData,
parseDateToDateObj,
FORMAT_YMD_DATE_FNS_CONCAT,
FORMAT_READABLE_DATE_FNS,
} from './utils';
import { adaptFormData } from './adapter';

/**
* @typedef {Object} FieldConfig - Field configuration object for PersonalInformation component
* @property {boolean} [showSSN] - Whether to show SSN field
Expand All @@ -13,3 +32,148 @@
* @property {string} [ssnPath] - Path to SSN in form data
* @property {string} [vaFileNumberPath] - Path to VA file number in form data
*/

export const PersonalInformation = ({
formData,
config = {},
dataAdapter = {},
}) => {
const profile = useSelector(selectProfile);
const adaptedData = adaptFormData(formData, dataAdapter);
const { ssnLastFour, vaFileLastFour } = adaptedData;
const { dob, gender, userFullName = {} } = profile;
const { first, middle, last, suffix } = userFullName;

const shouldShowErrorOrNull = !hasRequiredData(
{ ...adaptedData, ...profile },
config,
);

if (shouldShowErrorOrNull) {
return config.errorMessage ? (
<div className="usa-alert usa-alert-warning">
<div className="usa-alert-body">{config.errorMessage}</div>
</div>
) : null;
}

const dobDateObj = parseDateToDateObj(
dob || null,
FORMAT_YMD_DATE_FNS_CONCAT,
);

// console.log({
// shouldShowErrorOrNull,
// ssnLastFour,
// vaFileLastFour,
// dob,
// gender,
// formData,
// dobDateObj,
// });

return (
<>
<h3 className="vads-u-margin-y--2">
Confirm the personal information we have on file for you.
</h3>
<div className="blue-bar-block">
{config.showName &&
(first || last) && (
<strong
className="name dd-privacy-hidden"
data-dd-action-name="Veteran's name"
>
{`${first || ''} ${middle || ''} ${last || ''}`}
{suffix ? `, ${suffix}` : null}
</strong>
)}

{config.showSSN &&
ssnLastFour && (
<p className="ssn">
Social Security number:{' '}
<span
className="dd-privacy-mask"
data-dd-action-name="Veteran's SSN"
>
{formatNumberForScreenReader(ssnLastFour)}
</span>
</p>
)}

{config.showVAFileNumber &&
vaFileLastFour && (
<p className="vafn">
VA file number:{' '}
<span
className="dd-privacy-mask"
data-dd-action-name="Veteran's VA file number"
>
{formatNumberForScreenReader(vaFileLastFour)}
</span>
</p>
)}

{config.showDateOfBirth &&
isValid(dobDateObj) && (
<p>
Date of birth:{' '}
<span
className="dob dd-privacy-mask"
data-dd-action-name="Veteran's date of birth"
>
{format(dobDateObj, FORMAT_READABLE_DATE_FNS)}
</span>
</p>
)}

{config.showGender &&
gender && (
<p>
Gender:{' '}
<span
className="gender dd-privacy-hidden"
data-dd-action-name="Veteran's gender"
>
{genderLabels?.[gender] || ''}
</span>
</p>
)}
</div>

<br role="presentation" />

<p>
<strong>Note:</strong> If you need to update your personal information,
you can call us at <va-telephone contact={CONTACTS.VA_BENEFITS} />.
We’re here Monday through Friday, 8:00 a.m. to 9:00 p.m.{' '}
<dfn>
<abbr title="Eastern Time">ET</abbr>
</dfn>
.
</p>
</>
);
};

PersonalInformation.propTypes = {
config: PropTypes.shape({
showSSN: PropTypes.bool,
showVAFileNumber: PropTypes.bool,
showDateOfBirth: PropTypes.bool,
showGender: PropTypes.bool,
showName: PropTypes.bool,
errorMessage: PropTypes.string,
}),
dataAdapter: PropTypes.shape({
ssnPath: PropTypes.string,
vaFileNumberPath: PropTypes.string,
}),
formData: PropTypes.shape({
veteran: PropTypes.shape({
ssnLastFour: PropTypes.string,
vaFileLastFour: PropTypes.string,
}),
}),
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import PersonalInformation from './PersonalInformation';
import { PersonalInformation } from './PersonalInformation';

// Example usage in a form as a veteranInformation page
export const veteranInformation = {
Expand All @@ -15,7 +15,6 @@ export const veteranInformation = {
}}
dataAdapter={{
ssnPath: 'formData.veteran.ssn',
// other mappings
}}
{...props}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { isValid, parse, parseISO } from 'date-fns';
import { get, every } from 'lodash';

/**
* Checks if required data is present based on config
* @param {Object} data - The data to check
* @param {Object} config - The field configuration
* @returns {boolean} Whether all required data is present
*/
export const hasRequiredData = (data, config) => {
const checks = {
showName: get(data, 'userFullName.first') || get(data, 'userFullName.last'),
showSSN: !config.showSSN || get(data, 'ssnLastFour'),
showVAFileNumber: !config.showVAFileNumber || get(data, 'vaFileLastFour'),
showDateOfBirth: !config.showDateOfBirth || get(data, 'dob'),
showGender: !config.showGender || get(data, 'gender'),
};

return every(checks);
};

/**
* parseDateToDateObj from ISO8601 or JS number date (not unix time)
* @param {string, number, Date} date - date to format
* @returns {dateObj|null} date object
*/
export const parseDateToDateObj = (date, template) => {
let newDate = date;
if (typeof date === 'string') {
if (date.includes('T')) {
newDate = parseISO((date || '').split('T')[0]);
} else if (template) {
newDate = parse(date, template, new Date());
}
} else if (date instanceof Date && isValid(date)) {
// Remove timezone offset - the only time we pass in a date object is for
// unit tests (see https://stackoverflow.com/a/67599505)
newDate.setMinutes(newDate.getMinutes() + newDate.getTimezoneOffset());
}
return isValid(newDate) ? newDate : null;
};
export const FORMAT_YMD_DATE_FNS_CONCAT = 'yyyyMMdd';
export const FORMAT_YMD_DATE_FNS = 'yyyy-MM-dd';
export const FORMAT_COMPACT_DATE_FNS = 'MMM d, yyyy';
export const FORMAT_READABLE_DATE_FNS = 'MMMM d, yyyy';

0 comments on commit b5d6495

Please sign in to comment.