diff --git a/packages/esm-patient-orders-app/src/lab-results/result-form-field.component.tsx b/packages/esm-patient-orders-app/src/lab-results/lab-results-form-field.component.tsx similarity index 56% rename from packages/esm-patient-orders-app/src/lab-results/result-form-field.component.tsx rename to packages/esm-patient-orders-app/src/lab-results/lab-results-form-field.component.tsx index 38c968decf..52f6dbb0e6 100644 --- a/packages/esm-patient-orders-app/src/lab-results/result-form-field.component.tsx +++ b/packages/esm-patient-orders-app/src/lab-results/lab-results-form-field.component.tsx @@ -1,29 +1,29 @@ import React from 'react'; -import { TextInput, Select, SelectItem } from '@carbon/react'; +import { NumberInput, Select, SelectItem, TextInput } from '@carbon/react'; import { useTranslation } from 'react-i18next'; -import { Controller } from 'react-hook-form'; +import { type Control, Controller } from 'react-hook-form'; import { type LabOrderConcept } from './lab-results.resource'; import styles from './lab-results-form.scss'; interface ResultFormFieldProps { - defaultValue: any; concept: LabOrderConcept; - control: any; - register: any; - errors?: any; + control: Control; + defaultValue: any; } -const ResultFormField: React.FC = ({ defaultValue, register, concept, control, errors }) => { +const ResultFormField: React.FC = ({ concept, control, defaultValue }) => { const { t } = useTranslation(); - const isTextOrNumeric = (concept) => concept.datatype?.display === 'Text' || concept.datatype?.display === 'Numeric'; - const isCoded = (concept) => concept.datatype?.display === 'Coded'; - const isPanel = (concept) => concept.setMembers?.length > 0; + + const isCoded = (concept: LabOrderConcept) => concept.datatype?.display === 'Coded'; + const isNumeric = (concept: LabOrderConcept) => concept.datatype?.display === 'Numeric'; + const isPanel = (concept: LabOrderConcept) => concept.setMembers?.length > 0; + const isText = (concept: LabOrderConcept) => concept.datatype?.display === 'Text'; const printValueRange = (concept: LabOrderConcept) => { if (concept?.datatype?.display === 'Numeric') { const maxVal = Math.max(concept?.hiAbsolute, concept?.hiCritical, concept?.hiNormal); const minVal = Math.min(concept?.lowAbsolute, concept?.lowCritical, concept?.lowNormal); - return `(${minVal ?? 0} - ${maxVal > 0 ? maxVal : '--'} ${concept?.units ?? ''})`; + return ` (${minVal ?? 0} - ${maxVal > 0 ? maxVal : '--'} ${concept?.units ?? ''})`; } return ''; }; @@ -36,25 +36,38 @@ const ResultFormField: React.FC = ({ defaultValue, registe return ( <> - {Object.keys(errors).length > 0 &&
All fields are required
} - {isTextOrNumeric(concept) && ( + {isText(concept) && ( ( + )} + /> + )} + + {isNumeric(concept) && ( + ( + field.onChange(event.target.value)} + value={field.value || ''} /> )} /> @@ -64,18 +77,14 @@ const ResultFormField: React.FC = ({ defaultValue, registe ( @@ -144,9 +160,9 @@ const ResultFormField: React.FC = ({ defaultValue, registe )} /> - ); - } - })} + )} + + ))} ); }; diff --git a/packages/esm-patient-orders-app/src/lab-results/lab-results-form.component.tsx b/packages/esm-patient-orders-app/src/lab-results/lab-results-form.component.tsx index 599e1c51fb..4632389dd0 100644 --- a/packages/esm-patient-orders-app/src/lab-results/lab-results-form.component.tsx +++ b/packages/esm-patient-orders-app/src/lab-results/lab-results-form.component.tsx @@ -1,22 +1,22 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useForm } from 'react-hook-form'; -import { restBaseUrl, showSnackbar, useAbortController, useLayoutType } from '@openmrs/esm-framework'; -import { Button, ButtonSet, Form, InlineLoading, Stack } from '@carbon/react'; +import { mutate } from 'swr'; +import { Button, ButtonSet, Form, InlineLoading, InlineNotification, Stack } from '@carbon/react'; import { type DefaultPatientWorkspaceProps, type Order } from '@openmrs/esm-patient-common-lib'; +import { restBaseUrl, showSnackbar, useAbortController, useLayoutType } from '@openmrs/esm-framework'; import { useOrderConceptByUuid, updateOrderResult, useLabEncounter, useObservation } from './lab-results.resource'; -import ResultFormField from './result-form-field.component'; +import ResultFormField from './lab-results-form-field.component'; import styles from './lab-results-form.scss'; -import { mutate } from 'swr'; export interface LabResultsFormProps extends DefaultPatientWorkspaceProps { order: Order; } const LabResultsForm: React.FC = ({ - order, closeWorkspace, closeWorkspaceWithSavedChanges, + order, promptBeforeClosing, }) => { const { t } = useTranslation(); @@ -24,17 +24,17 @@ const LabResultsForm: React.FC = ({ const isTablet = useLayoutType() === 'tablet'; const [obsUuid, setObsUuid] = useState(''); const [isEditing, setIsEditing] = useState(false); - const [isSubmitting, setIsSubmitting] = useState(false); const [initialValues, setInitialValues] = useState(null); const [isLoadingInitialValues, setIsLoadingInitialValues] = useState(false); const { concept, isLoading: isLoadingConcepts } = useOrderConceptByUuid(order.concept.uuid); const { encounter, isLoading: isLoadingEncounter, mutate: mutateLabOrders } = useLabEncounter(order.encounter.uuid); const { data, isLoading: isLoadingObs, error: isErrorObs } = useObservation(obsUuid); + const [showEmptyFormErrorNotification, setShowEmptyFormErrorNotification] = useState(false); const { control, register, - formState: { errors, isDirty }, + formState: { errors, isDirty, isSubmitting }, getValues, handleSubmit, } = useForm<{ testResult: any }>({ @@ -82,11 +82,18 @@ const LabResultsForm: React.FC = ({ ); } - const saveLabResults = (data, e) => { - setIsSubmitting(true); - e.preventDefault(); - // assign result to test order - const documentedValues = getValues(); + const saveLabResults = () => { + const formValues = getValues(); + + const isEmptyForm = Object.values(formValues).every( + (value) => value === '' || value === null || value === undefined, + ); + + if (isEmptyForm) { + setShowEmptyFormErrorNotification(true); + return; + } + let obsValue = []; if (concept.set && concept.setMembers.length > 0) { @@ -160,7 +167,6 @@ const LabResultsForm: React.FC = ({ abortController, ).then( () => { - setIsSubmitting(false); closeWorkspaceWithSavedChanges(); mutateLabOrders(); mutate( @@ -177,7 +183,6 @@ const LabResultsForm: React.FC = ({ }); }, (err) => { - setIsSubmitting(false); showSnackbar({ title: t('errorSavingLabResults', 'Error saving lab results'), kind: 'error', @@ -185,6 +190,8 @@ const LabResultsForm: React.FC = ({ }); }, ); + + setShowEmptyFormErrorNotification(false); }; return ( @@ -192,22 +199,23 @@ const LabResultsForm: React.FC = ({
{concept.setMembers.length > 0 &&

{concept.display}

} {concept && ( - + {!isLoadingInitialValues ? ( - + ) : ( )} )} + {showEmptyFormErrorNotification && ( + + )}
-