-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(applicant): add more logic to disable/enable save and close button #2918
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,42 @@ | ||
import { Application } from 'benefit-shared/types/application'; | ||
import { FormikErrors, FormikTouched } from 'formik'; | ||
|
||
export const getTouchedAndInvalidFields = ( | ||
type FlattenedObject = Record<string, string>; | ||
|
||
function flattenObject( | ||
obj: FlattenedObject, | ||
parentKey = '', | ||
result: FlattenedObject = {} | ||
): FlattenedObject { | ||
const appendResult = result; | ||
Object.keys(obj).forEach((key) => { | ||
const newKey = `${parentKey}${parentKey ? '.' : ''}${key}`; | ||
if ( | ||
typeof obj[key] === 'object' && | ||
obj[key] !== null && | ||
!Array.isArray(obj[key]) | ||
) { | ||
flattenObject(obj[key] as unknown as FlattenedObject, newKey, result); | ||
} else { | ||
appendResult[newKey] = obj[key]; | ||
} | ||
}); | ||
return result; | ||
} | ||
|
||
/** | ||
* Used to enable / disable "save and close" button. | ||
* Flatten Formik's error and touched fields to compare touched substring against error fields. | ||
* Error fields are more verbose than touched fields, including min, max etc. validation data | ||
* for the whole nested data set, for example, company or employee. Touch fields only consist | ||
* of single fields that are touched. Thus substring is used to match touched fields against error fields. | ||
* */ | ||
export const findIntersectionOfTouchedAndErroredFields = ( | ||
touched: FormikTouched<Partial<Application>>, | ||
errors: FormikErrors<Partial<Application>> | ||
): string[] => | ||
Object.keys(touched).filter((field) => Object.keys(errors).includes(field)); | ||
Object.keys(flattenObject(touched as FlattenedObject)).filter((field) => | ||
Object.keys(flattenObject(errors as FlattenedObject)).some((errorField) => | ||
errorField.includes(field) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the above suggestion, these could just be passed as is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, and |
||
) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation is sound but the typing is iffy, yeah. The input is already assigned to FlattenedObject – assumed to be an object with only string values – which doesn't make sense since the whole point of the function is to flatten nested objects onto one level.
Here's how I would type this. The effective FormikTouched and FormikErrors types already are the same shape as the SimpleObject type given, which means the casts in the next function can also be removed altogether.
In our use case, where we only care about the object-ness of each leaf and the keys of the output, we could even define SimpleObjectNode as
SimpleObject | unknown
and I believe it would still work.