diff --git a/i18n/en.pot b/i18n/en.pot index b1a2483c15..2a3f2311c9 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -1414,13 +1414,6 @@ msgstr "{{ linkableStageLabel }} has no linkable events" msgid "Ambiguous relationships, contact system administrator" msgstr "Ambiguous relationships, contact system administrator" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." - msgid "Enter details now" msgstr "Enter details now" diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index 2da2338fe6..07832fe83f 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -47,7 +47,6 @@ const getEventDetailsByLinkMode = ({ }), ); } - return ({ linkedEvent: { ...baseEventDetails, @@ -56,23 +55,34 @@ const getEventDetailsByLinkMode = ({ }, linkedEventId: baseEventDetails.event, }); - } else if (linkMode === RelatedStageModes.ENTER_DATA) { + } + + if (linkMode === RelatedStageModes.ENTER_DATA) { + const { orgUnit: linkedEventOrgUnit } = relatedStageDataValues; + if (!linkedEventOrgUnit) { + throw new Error( + errorCreator('Missing required data for creating related stage event')({ + linkedEventOrgUnit, + }), + ); + } return ({ linkedEvent: { ...baseEventDetails, scheduledAt: convertFn(clientRequestEvent.scheduledAt, dataElementTypes.DATE), - orgUnit: clientRequestEvent.orgUnit, + orgUnit: convertFn(linkedEventOrgUnit, dataElementTypes.ORGANISATION_UNIT), }, linkedEventId: baseEventDetails.event, }); - } else if (linkMode === RelatedStageModes.LINK_EXISTING_RESPONSE) { + } + + if (linkMode === RelatedStageModes.LINK_EXISTING_RESPONSE) { const { linkedEventId } = relatedStageDataValues; return { linkedEvent: null, linkedEventId, }; } - log.error(errorCreator(`Referral mode ${linkMode} is not supported`)()); return { linkedEvent: null, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js new file mode 100644 index 0000000000..47ff354bed --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js @@ -0,0 +1,114 @@ +// @flow +import React from 'react'; +import i18n from '@dhis2/d2-i18n'; +import type { ComponentType } from 'react'; +import { withStyles } from '@material-ui/core'; +import { colors, spacers, spacersNum, IconInfo16 } from '@dhis2/ui'; +import { OrgUnitSelectorForRelatedStages } from '../FormComponents'; +import type { ErrorMessagesForRelatedStages } from '../RelatedStagesActions'; +import type { RelatedStageDataValueStates } from '../WidgetRelatedStages.types'; + +const styles = { + wrapper: { + padding: `${spacers.dp16} 0`, + maxWidth: '55.75rem', + }, + fieldWrapper: { + display: 'flex', + flexWrap: 'wrap', + alignItems: 'start', + justifyContent: 'space-between', + padding: `${spacers.dp8} ${spacers.dp16}`, + }, + fieldLabel: { + color: colors.grey900, + paddingTop: spacersNum.dp12, + paddingRight: spacersNum.dp16, + flexBasis: '200px', + }, + fieldContent: { + flexBasis: '150px', + flexGrow: 1, + }, + alternateColor: { + backgroundColor: colors.grey100, + }, + infoBox: { + margin: '8px 8px', + display: 'flex', + fontSize: '14px', + gap: '5px', + background: colors.grey100, + padding: '12px 8px', + border: `1px solid ${colors.grey600}`, + }, +}; + +type Props = { + linkableStageLabel: string, + relatedStagesDataValues: RelatedStageDataValueStates, + setRelatedStagesDataValues: (() => Object) => void, + currentStageLabel: string, + saveAttempted: boolean, + errorMessages: ErrorMessagesForRelatedStages, + ...CssClasses +} + +export const EnterDataInOrgUnitPlain = ({ + linkableStageLabel, + relatedStagesDataValues, + setRelatedStagesDataValues, + saveAttempted, + errorMessages, + currentStageLabel, + classes, +}: Props) => { + const onSelectOrgUnit = (e: { id: string, displayName: string, path: string }) => { + const orgUnit = { + id: e.id, + name: e.displayName, + path: e.path, + }; + + setRelatedStagesDataValues(prevValues => ({ + ...prevValues, + orgUnit, + })); + }; + + const onDeselectOrgUnit = () => { + setRelatedStagesDataValues(prevValues => ({ + ...prevValues, + orgUnit: null, + })); + }; + + return ( +
+
+ +
+
+ + {i18n.t( + relatedStagesDataValues?.orgUnit?.name + ? 'Enter {{linkableStageLabel}} details for {{orgUnitLabel}} in the next step after completing this {{currentStageLabel}}.' + : 'Select organisation unit and enter {{linkableStageLabel}} details in the next step after completing this {{currentStageLabel}}.', + { + linkableStageLabel, + currentStageLabel, + orgUnitLabel: relatedStagesDataValues?.orgUnit?.name, + }, + )} +
+
+ ); +}; + +export const EnterDataInOrgUnit: ComponentType<$Diff> = withStyles(styles)(EnterDataInOrgUnitPlain); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js new file mode 100644 index 0000000000..0d5a3fe03e --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js @@ -0,0 +1,2 @@ +// @flow +export { EnterDataInOrgUnit } from './EnterData.component'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js index 47f623af6e..a53c05eb3f 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js @@ -68,5 +68,4 @@ export const LinkToExistingPlain = ({ ); }; -export const LinkToExisting = - withStyles(styles)(LinkToExistingPlain); +export const LinkToExisting = withStyles(styles)(LinkToExistingPlain); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js index 4266eaf52a..38bbb6e24b 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js @@ -1,7 +1,7 @@ // @flow import React, { type ComponentType, useMemo } from 'react'; import i18n from '@dhis2/d2-i18n'; -import { Button, colors, IconInfo16, Radio, spacers, spacersNum } from '@dhis2/ui'; +import { Button, colors, Radio, spacers, spacersNum } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; import { ConditionalTooltip } from 'capture-core/components/Tooltips/ConditionalTooltip'; import { actions as RelatedStagesActionTypes, mainOptionTranslatedTexts, relatedStageStatus } from '../constants'; @@ -11,6 +11,7 @@ import { ScheduleInOrgUnit } from '../ScheduleInOrgUnit'; import { useProgramStageInfo } from '../../../metaDataMemoryStores/programCollection/helpers'; import type { Props } from './RelatedStagesActions.types'; import { LinkToExisting } from '../LinkToExisting'; +import { EnterDataInOrgUnit } from '../EnterDataInOrgUnit/EnterData.component'; const styles = () => ({ wrapper: { @@ -37,15 +38,6 @@ const styles = () => ({ clearSelections: { padding: spacers.dp8, }, - infoBox: { - margin: '8px 8px', - display: 'flex', - fontSize: '14px', - gap: '5px', - background: colors.grey100, - padding: '12px 8px', - border: `1px solid ${colors.grey600}`, - }, }); export const RelatedStagesActionsPlain = ({ @@ -171,16 +163,14 @@ export const RelatedStagesActionsPlain = ({ )} {selectedAction === RelatedStagesActionTypes.ENTER_DATA && ( -
- - {i18n.t( - 'Enter {{linkableStageLabel}} details in the next step after completing this {{currentStageLabel}}.', - { - linkableStageLabel: programStage.stageForm.name, - currentStageLabel, - }, - )} -
+ )} {selectedAction === RelatedStagesActionTypes.LINK_EXISTING_RESPONSE && ( diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.container.js b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.component.js similarity index 100% rename from src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.container.js rename to src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.component.js diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js index 2e1a21bf88..c547d9d70d 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js @@ -1,2 +1,2 @@ // @flow -export { ScheduleInOrgUnit } from './ScheduleInOrgUnit.container'; +export { ScheduleInOrgUnit } from './ScheduleInOrgUnit.component'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js index 07ad6a17a8..b02e1f5ae5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js @@ -44,6 +44,23 @@ const scheduleInOrgUnit = (props) => { return scheduledAtIsValid && orgUnitIsValid; }; +const enterData = (props) => { + const { orgUnit, setErrorMessages } = props ?? {}; + const orgUnitIsValid = isValidOrgUnit(orgUnit); + + if (!orgUnitIsValid) { + setErrorMessages({ + orgUnit: i18n.t('Please provide a valid organisation unit'), + }); + } else { + setErrorMessages({ + orgUnit: null, + }); + } + + return orgUnitIsValid; +}; + const linkToExistingResponse = (props) => { const { linkedEventId, setErrorMessages } = props ?? {}; const linkedEventIdIsValid = !!linkedEventId; @@ -64,7 +81,7 @@ const linkToExistingResponse = (props) => { export const ValidationFunctionsByLinkMode: { [key: string]: (props: ?Props) => boolean } = { [RelatedStageModes.SCHEDULE_IN_ORG]: props => scheduleInOrgUnit(props), - [RelatedStageModes.ENTER_DATA]: () => true, + [RelatedStageModes.ENTER_DATA]: props => enterData(props), [RelatedStageModes.LINK_EXISTING_RESPONSE]: props => linkToExistingResponse(props), };