diff --git a/components/elements/index.js b/components/elements/index.js index 76031fe3..3134fee3 100644 --- a/components/elements/index.js +++ b/components/elements/index.js @@ -29,6 +29,37 @@ import { RenderFileUpload } from "./fields/renderFileUpload"; export { RenderSubFields } from "./fields/renderSubFields"; export { FieldArrayForm } from "./fields/fieldArrayForm"; +const getValidationMessages = (t) => ({ + requiredMessage: t("newappeal:is-required-label"), + emojiNotAllowedMessage: t("newappeal:emojis-not-allowed-label"), + invalidPostcodeMessage: t("newappeal:invalid-postcode-label") +}); + +const hasParentFieldValue = ({ parentField, form, formProps }) => + parentField != false && + !_.isEmpty(formProps[form]) && + _.has(formProps[form].values, parentField); + +const isVisibleByEquality = ({ + parentField, + form, + formProps, + parentFieldShowOnValue +}) => + (hasParentFieldValue({ parentField, form, formProps }) && + formProps[form].values[parentField]) == parentFieldShowOnValue; + +const isVisibleByInclusion = ({ + parentField, + form, + formProps, + parentFieldShowOnValue +}) => + hasParentFieldValue({ parentField, form, formProps }) && + parentFieldShowOnValue.indexOf( + formProps[form].values[parentField].toString() + ) > -1; + export function Textfield(props) { const { name, @@ -128,19 +159,22 @@ export function Textfield(props) { ); } else { - var showIfHasParentShowValue = - (parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - formProps[form].values[parentField]) == parentFieldShowOnValue; + var showIfHasParentShowValue = isVisibleByEquality({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); // console.log(parentField, showIfHasParentShowValue); // console.log(parentField, formProps, form); //console.log("validation props:", validation); - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { + requiredMessage, + emojiNotAllowedMessage, + invalidPostcodeMessage + } = getValidationMessages(t); return (
{parentField != false ? ( @@ -222,13 +256,12 @@ export function MultiLinefield(props) { return errors; }; - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; @@ -237,9 +270,8 @@ export function MultiLinefield(props) { let { t } = useTranslation(); const translatedLabel = FieldsTranslations(props.label); - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); return ( <> {parentField != false ? ( @@ -335,22 +367,20 @@ export function RichMultiLinefield(props) { const required = (value) => value ? undefined : t("newappeal:is-required-label"); - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; //console.log(showIfHasParentShowValue, formProps[form].values[parentField]); let { t } = useTranslation(); - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); return ( <> {parentField != false ? ( @@ -445,15 +475,15 @@ export function DateFieldPicker(props) { let dateEnd = props.dateEnd; let { t } = useTranslation(); const required = (value) => (value ? undefined : "Required"); - var showIfHasParentShowValue = - (parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - formProps[form].values[parentField]) == parentFieldShowOnValue; + var showIfHasParentShowValue = isVisibleByEquality({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); // a and b are javascript Date objects function dateDiffInDays(a, b) { @@ -621,13 +651,12 @@ export function YesNofield(props) { const yesNo = router.locale == "cy" ? ["Ydw", "Na"] : ["Yes", "No"]; const required = (value) => (value ? undefined : "Required"); - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; @@ -697,20 +726,18 @@ export function Radiofield(props) { .split(","); //parentFieldShowOnValue - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); return ( <> {parentField != false ? ( @@ -849,21 +876,19 @@ export function NumericField(props) { : undefined; //parentFieldShowOnValue - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; //console.log("parentField:", parentField, showIfHasParentShowValue); - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); return ( <> {parentField != false ? ( @@ -968,13 +993,12 @@ export function DecimalField(props) { : undefined; //parentFieldShowOnValue - var showIfHasParentShowValue = - parentField != false && - !_.isEmpty(formProps[form]) && - _.has(formProps[form].values, parentField) && - parentFieldShowOnValue.indexOf( - formProps[form].values[parentField].toString() - ) > -1; + var showIfHasParentShowValue = isVisibleByInclusion({ + parentField, + form, + formProps, + parentFieldShowOnValue + }); (showIfHasParentShowValue == parentField) != false && showIfHasParentShowValue; @@ -999,9 +1023,8 @@ export function DecimalField(props) { return undefined; }; - const requiredMessage = t("newappeal:is-required-label"); - const emojiNotAllowedMessage = t("newappeal:emojis-not-allowed-label"); - const invalidPostcodeMessage = t("newappeal:invalid-postcode-label"); + const { requiredMessage, emojiNotAllowedMessage, invalidPostcodeMessage } = + getValidationMessages(t); return ( <> {parentField != false ? ( diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md index b3d55e9f..d0f4f422 100644 --- a/memory-bank/change-log.md +++ b/memory-bank/change-log.md @@ -3555,3 +3555,33 @@ Validation: Follow-ups: - Continue Phase 2 with bounded renderer/module extractions from `components/elements/index.js` (one cohesive bundle per commit). + +--- + +### CL-100: 22500 `components/elements/index.js` helper normalization (validation messages + visibility checks) + +date: 2026-04-07 +author: Cline +scope: `components/elements/index.js` +type: change +rationale: Apply the requested next bounded refactor slice by consolidating repeated validation message setup and parent-field visibility logic into shared local helpers. +impact: No intended behavior change; EN/CY and accessibility behavior preserved while reducing repeated logic and future drift risk. +status: completed + +Summary: + +- Added `getValidationMessages(t)` helper for repeated `required/emoji/postcode` message retrieval. +- Added visibility helpers: + - `hasParentFieldValue(...)` + - `isVisibleByEquality(...)` + - `isVisibleByInclusion(...)` +- Replaced repeated inline visibility and validation-message setup across field wrappers with helper usage (Textfield, MultiLinefield, RichMultiLinefield, DateFieldPicker, YesNofield, Radiofield, NumericField, DecimalField). +- Kept existing field render paths, conditions, and validation calls intact. + +Validation: + +- `npx eslint components/elements/index.js` -> pass + +Follow-ups: + +- Continue bounded no-behavior-change slices by removing dead locals/comments and extracting one additional low-risk field wrapper at a time.