diff --git a/src/core_modules/capture-core/components/D2Form/field/configs/ageField/getAgeFieldConfig.js b/src/core_modules/capture-core/components/D2Form/field/configs/ageField/getAgeFieldConfig.js index 4c55b92527..f4db2f3c30 100644 --- a/src/core_modules/capture-core/components/D2Form/field/configs/ageField/getAgeFieldConfig.js +++ b/src/core_modules/capture-core/components/D2Form/field/configs/ageField/getAgeFieldConfig.js @@ -1,13 +1,15 @@ // @flow +import moment from 'moment'; import { orientations } from '../../../../FormFields/New'; import { createFieldConfig, createProps } from '../base/configBaseDefaultForm'; import { AgeFieldForForm } from '../../Components'; -import { type DataElement } from '../../../../../metaData'; +import { convertDateObjectToDateFormatString } from '../../../../../../capture-core/utils/converters/date'; +import { type DateDataElement } from '../../../../../metaData'; import type { QuerySingleResource } from '../../../../../utils/api/api.types'; const getCalendarAnchorPosition = (formHorizontal: ?boolean) => (formHorizontal ? 'center' : 'left'); -export const getAgeFieldConfig = (metaData: DataElement, options: Object, querySingleResource: QuerySingleResource) => { +export const getAgeFieldConfig = (metaData: DateDataElement, options: Object, querySingleResource: QuerySingleResource) => { const props = createProps({ formHorizontal: options.formHorizontal, fieldLabelMediaBasedClass: options.fieldLabelMediaBasedClass, @@ -15,6 +17,7 @@ export const getAgeFieldConfig = (metaData: DataElement, options: Object, queryS shrinkDisabled: options.formHorizontal, dateCalendarWidth: options.formHorizontal ? 250 : 350, datePopupAnchorPosition: getCalendarAnchorPosition(options.formHorizontal), + calendarMax: !metaData.allowFutureDate ? convertDateObjectToDateFormatString(moment()) : undefined, }, options, metaData); return createFieldConfig({ diff --git a/src/core_modules/capture-core/components/D2Form/field/defaultFormFieldGetter.js b/src/core_modules/capture-core/components/D2Form/field/defaultFormFieldGetter.js index 01466c57d9..52d0d21ad4 100644 --- a/src/core_modules/capture-core/components/D2Form/field/defaultFormFieldGetter.js +++ b/src/core_modules/capture-core/components/D2Form/field/defaultFormFieldGetter.js @@ -67,7 +67,8 @@ const fieldForTypes: FieldForTypes = { [dataElementTypes.TIME_RANGE]: getTextRangeFieldConfig, [dataElementTypes.PERCENTAGE]: getTextFieldConfig, [dataElementTypes.URL]: getTextFieldConfig, - [dataElementTypes.AGE]: getAgeFieldConfig, + [dataElementTypes.AGE]: (metaData: any, options: Object, querySingleResource: QuerySingleResource) => + getAgeFieldConfig(metaData, options, querySingleResource), [dataElementTypes.ORGANISATION_UNIT]: getOrgUnitFieldConfig, [dataElementTypes.COORDINATE]: getCoordinateFieldConfig, [dataElementTypes.POLYGON]: getPolygonFieldConfig, diff --git a/src/core_modules/capture-core/utils/validation/getValidators.js b/src/core_modules/capture-core/utils/validation/getValidators.js index 7f65ac02c1..1def1a9ef7 100644 --- a/src/core_modules/capture-core/utils/validation/getValidators.js +++ b/src/core_modules/capture-core/utils/validation/getValidators.js @@ -18,6 +18,7 @@ import { } from 'capture-core-utils/validators/form'; import { isValidAge, + isValidNonFutureAge, isValidDate, isValidNonFutureDate, isValidDateTime, @@ -153,6 +154,11 @@ const validatorsForTypes = { validator: isValidAge, message: errorMessages.AGE, type: validatorTypes.TYPE_BASE, + }, + { + validator: isValidNonFutureAge, + type: validatorTypes.TYPE_EXTENDED, + message: errorMessages.DATE_FUTURE_NOT_ALLOWED, }], [dataElementTypes.PHONE_NUMBER]: [{ validator: isValidPhoneNumber, diff --git a/src/core_modules/capture-core/utils/validation/validators/form/ageValidator.js b/src/core_modules/capture-core/utils/validation/validators/form/ageValidator.js index 3986f22ebb..f5b73ef412 100644 --- a/src/core_modules/capture-core/utils/validation/validators/form/ageValidator.js +++ b/src/core_modules/capture-core/utils/validation/validators/form/ageValidator.js @@ -62,13 +62,21 @@ export function isValidAge(value: Object, internalComponentError?: ?{error: ?str return false; } - const numberResult = validateNumbers( + if (internalComponentError && internalComponentError?.errorCode === 'INVALID_DATE_MORE_THAN_MAX') { + return { valid: true, errorMessage: null }; + } + + const dateValidation = value.date + ? validateDate(value.date, internalComponentError) + : { valid: true, errorMessage: null }; + + if (!dateValidation.valid) { + return dateValidation; + } + + return validateNumbers( value.years, value.months, value.days, ); - - if (!numberResult.valid) return numberResult; - - return validateDate(value.date, internalComponentError); } diff --git a/src/core_modules/capture-core/utils/validation/validators/form/index.js b/src/core_modules/capture-core/utils/validation/validators/form/index.js index 5390b8853c..e8fe0457a9 100644 --- a/src/core_modules/capture-core/utils/validation/validators/form/index.js +++ b/src/core_modules/capture-core/utils/validation/validators/form/index.js @@ -7,3 +7,4 @@ export { getDateRangeValidator } from './getDateRangeValidator'; export { getDateTimeRangeValidator } from './getDateTimeRangeValidator'; export { getNumberRangeValidator } from './getNumberRangeValidator'; export { getTimeRangeValidator } from './getTimeRangeValidator'; +export { isValidNonFutureAge } from './isValidNonFutureAge'; diff --git a/src/core_modules/capture-core/utils/validation/validators/form/isValidNonFutureAge.js b/src/core_modules/capture-core/utils/validation/validators/form/isValidNonFutureAge.js new file mode 100644 index 0000000000..3c183c5d31 --- /dev/null +++ b/src/core_modules/capture-core/utils/validation/validators/form/isValidNonFutureAge.js @@ -0,0 +1,21 @@ +// @flow +import i18n from '@dhis2/d2-i18n'; + +const CUSTOM_VALIDATION_MESSAGES = { + INVALID_DATE_MORE_THAN_MAX: i18n.t('A date in the future is not allowed'), +}; + +export const isValidNonFutureAge = (value: string, internalComponentError?: ?{error: ?string, errorCode: ?string}) => { + if (!value) { + return true; + } + + if (internalComponentError && internalComponentError?.errorCode === 'INVALID_DATE_MORE_THAN_MAX') { + return { + valid: false, + errorMessage: { date: CUSTOM_VALIDATION_MESSAGES.INVALID_DATE_MORE_THAN_MAX }, + }; + } + + return true; +}; diff --git a/src/core_modules/capture-ui/AgeField/ageField.module.css b/src/core_modules/capture-ui/AgeField/ageField.module.css index ffd6907cf9..69bf287b30 100644 --- a/src/core_modules/capture-ui/AgeField/ageField.module.css +++ b/src/core_modules/capture-ui/AgeField/ageField.module.css @@ -18,6 +18,7 @@ } .ageDateInputContainerHorizontal { + width: 150px; } .ageClearHorizontal {