-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(feat) O3-3211: Ward App - display metrics for admission status and b…
…ed occupancy (#1213) * feat-metrics * update metrics * correct test * refactor useAdmission * fix e2e tests * (refactor) Refactor registration form cancel modal to match conventions (#1294) This PR refactors the registration form's cancel modal to match new modal naming and registration conventions. Modals are now registered in the routes registry file under the `modals`. The naming convention has also changed - modals now use the `*.modal.tsx` suffix. I've also amended the modal to use Carbon's ModalBody, ModalHeader, and ModalFooter components instead of using divs with custom classes. Finally, I've amended the modal title and content to align with other confirmation modals in O3. * (feat) 03-3404: follow-up -ensure the dateAppointmentScheduled <= appointmentDate (#1295) * correct yarn.lock --------- Co-authored-by: Dennis Kigen <kigen.work@gmail.com> Co-authored-by: Lucy Jemutai <130601439+lucyjemutai@users.noreply.github.com>
- Loading branch information
1 parent
04fde53
commit b17c19e
Showing
21 changed files
with
519 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { mockBedType } from './wards.mock'; | ||
|
||
export const mockWardBeds = [ | ||
{ | ||
id: 1, | ||
uuid: '0000-bed1', | ||
bedNumber: 'bed1', | ||
bedType: mockBedType, | ||
row: 1, | ||
column: 2, | ||
status: 'OCCUPIED' as const, | ||
}, | ||
{ | ||
id: 2, | ||
uuid: '0000-bed2', | ||
bedNumber: 'bed2', | ||
bedType: mockBedType, | ||
row: 1, | ||
column: 2, | ||
status: 'AVAILABLE' as const, | ||
}, | ||
{ | ||
id: 1, | ||
uuid: '0000-bed3', | ||
bedNumber: 'bed3', | ||
bedType: mockBedType, | ||
row: 1, | ||
column: 3, | ||
status: 'AVAILABLE' as const, | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { useMemo } from 'react'; | ||
import { createAndGetWardPatientGrouping, getInpatientAdmissionsUuidMap } from '../ward-view/ward-view.resource'; | ||
import { useAdmissionLocation } from './useAdmissionLocation'; | ||
import { useInpatientAdmission } from './useInpatientAdmission'; | ||
|
||
export function useWardPatientGrouping() { | ||
const admissionLocationResponse = useAdmissionLocation(); | ||
const inpatientAdmissionResponse = useInpatientAdmission(); | ||
|
||
const { inpatientAdmissions } = inpatientAdmissionResponse; | ||
const { admissionLocation } = admissionLocationResponse; | ||
const inpatientAdmissionsByPatientUuid = useMemo(() => { | ||
return getInpatientAdmissionsUuidMap(inpatientAdmissions); | ||
}, [inpatientAdmissions]); | ||
|
||
const { | ||
wardAdmittedPatientsWithBed, | ||
wardUnadmittedPatientsWithBed, | ||
wardPatientPendingCount, | ||
bedLayouts, | ||
wardUnassignedPatientsList, | ||
} = useMemo(() => { | ||
return createAndGetWardPatientGrouping(inpatientAdmissions, admissionLocation, inpatientAdmissionsByPatientUuid); | ||
}, [inpatientAdmissionsByPatientUuid, admissionLocation, inpatientAdmissions]); | ||
|
||
return { | ||
wardAdmittedPatientsWithBed, | ||
wardUnadmittedPatientsWithBed, | ||
wardUnassignedPatientsList, | ||
wardPatientPendingCount, | ||
admissionLocationResponse, | ||
inpatientAdmissionResponse, | ||
bedLayouts, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
packages/esm-ward-app/src/ward-view-header/ward-metric.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import styles from './ward-metric.scss'; | ||
import { SkeletonPlaceholder } from '@carbon/react'; | ||
|
||
interface WardMetricProps { | ||
metricName: string; | ||
metricValue: string; | ||
isLoading: boolean; | ||
} | ||
const WardMetric: React.FC<WardMetricProps> = ({ metricName, metricValue, isLoading }) => { | ||
return ( | ||
<div className={styles.metric}> | ||
<span className={styles.metricName}>{metricName}</span> | ||
{isLoading ? ( | ||
<SkeletonPlaceholder className={styles.skeleton} /> | ||
) : ( | ||
<span className={styles.metricValue}>{metricValue}</span> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default WardMetric; |
25 changes: 25 additions & 0 deletions
25
packages/esm-ward-app/src/ward-view-header/ward-metric.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
@use '@carbon/styles/scss/spacing'; | ||
@use '@carbon/type'; | ||
@import '~@openmrs/esm-styleguide/src/vars'; | ||
|
||
.metric { | ||
margin-left: spacing.$spacing-05; | ||
display: flex; | ||
align-items: end; | ||
gap: 5px; | ||
} | ||
|
||
.metricName { | ||
@include type.type-style('helper-text-01'); | ||
color: $color-gray-70; | ||
} | ||
|
||
.metricValue { | ||
@include type.type-style('heading-03'); | ||
line-height: revert; | ||
} | ||
|
||
.skeleton { | ||
height: 15px; | ||
width: 15px; | ||
} |
60 changes: 60 additions & 0 deletions
60
packages/esm-ward-app/src/ward-view-header/ward-metrics.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React from 'react'; | ||
import styles from './ward-metrics.scss'; | ||
import { useBeds } from '../hooks/useBeds'; | ||
import { showNotification, useAppContext, useFeatureFlag } from '@openmrs/esm-framework'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { getWardMetrics } from '../ward-view/ward-view.resource'; | ||
import WardMetric from './ward-metric.component'; | ||
import type { WardPatientGroupDetails } from '../types'; | ||
import useWardLocation from '../hooks/useWardLocation'; | ||
|
||
const wardMetrics = [ | ||
{ name: 'Patients', key: 'patients' }, | ||
{ name: 'Free beds', key: 'freeBeds' }, | ||
{ name: 'Capacity', key: 'capacity' }, | ||
]; | ||
|
||
const WardMetrics = () => { | ||
const { location } = useWardLocation(); | ||
const { beds, isLoading, error } = useBeds({ locationUuid: location.uuid }); | ||
const { t } = useTranslation(); | ||
const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module'); | ||
const wardPatientGroup = useAppContext<WardPatientGroupDetails>('ward-patients-group'); | ||
|
||
if (error) { | ||
showNotification({ | ||
kind: 'error', | ||
title: t('errorLoadingBedDetails', 'Error Loading Bed Details'), | ||
description: error.message, | ||
}); | ||
} | ||
const wardMetricValues = getWardMetrics(beds); | ||
return ( | ||
<div className={styles.metricsContainer}> | ||
{isBedManagementModuleInstalled ? ( | ||
wardMetrics.map((wardMetric) => { | ||
return ( | ||
<WardMetric | ||
metricName={wardMetric.name} | ||
metricValue={wardMetricValues[wardMetric.key]} | ||
isLoading={!!isLoading} | ||
key={wardMetric.key} | ||
/> | ||
); | ||
}) | ||
) : ( | ||
<WardMetric metricName={'Patients'} metricValue={'--'} isLoading={false} key={'patients'} /> | ||
)} | ||
{isBedManagementModuleInstalled && ( | ||
<WardMetric | ||
metricName="Pending out" | ||
metricValue={error ? '--' : wardPatientGroup?.wardPatientPendingCount.toString() ?? '--'} | ||
isLoading={!wardPatientGroup} | ||
key="pending" | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default WardMetrics; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@use '@carbon/styles/scss/spacing'; | ||
@import '~@openmrs/esm-styleguide/src/vars'; | ||
|
||
.metricsContainer { | ||
display: flex; | ||
align-items: end; | ||
margin-left: auto; | ||
} |
77 changes: 77 additions & 0 deletions
77
packages/esm-ward-app/src/ward-view-header/ward-metrics.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React from 'react'; | ||
import WardMetrics from './ward-metrics.component'; | ||
import { renderWithSwr } from '../../../../tools/test-utils'; | ||
import { useBeds } from '../hooks/useBeds'; | ||
import { mockWardBeds } from '../../../../__mocks__/wardBeds.mock'; | ||
import { getWardMetrics } from '../ward-view/ward-view.resource'; | ||
import { useAdmissionLocation } from '../hooks/useAdmissionLocation'; | ||
import { mockAdmissionLocation, mockInpatientAdmissions } from '__mocks__'; | ||
import { useInpatientAdmission } from '../hooks/useInpatientAdmission'; | ||
import useWardLocation from '../hooks/useWardLocation'; | ||
import { screen } from '@testing-library/react'; | ||
|
||
jest.mock('react-router-dom', () => ({ | ||
...jest.requireActual('react-router-dom'), | ||
useParams: jest.fn().mockReturnValue({}), | ||
})); | ||
|
||
jest.mock('../hooks/useWardLocation', () => | ||
jest.fn().mockReturnValue({ | ||
location: { uuid: 'abcd', display: 'mock location' }, | ||
isLoadingLocation: false, | ||
errorFetchingLocation: null, | ||
invalidLocation: false, | ||
}), | ||
); | ||
|
||
const mockUseWardLocation = jest.mocked(useWardLocation); | ||
|
||
jest.mock('../hooks/useBeds', () => ({ | ||
useBeds: jest.fn(), | ||
})); | ||
|
||
jest.mock('../hooks/useAdmissionLocation', () => ({ | ||
useAdmissionLocation: jest.fn(), | ||
})); | ||
jest.mock('../hooks/useInpatientAdmission', () => ({ | ||
useInpatientAdmission: jest.fn(), | ||
})); | ||
|
||
jest.mocked(useBeds).mockReturnValue({ | ||
error: undefined, | ||
mutate: jest.fn(), | ||
isValidating: false, | ||
isLoading: false, | ||
beds: mockWardBeds, | ||
}); | ||
|
||
jest.mocked(useAdmissionLocation).mockReturnValue({ | ||
error: undefined, | ||
mutate: jest.fn(), | ||
isValidating: false, | ||
isLoading: false, | ||
admissionLocation: mockAdmissionLocation, | ||
}); | ||
jest.mocked(useInpatientAdmission).mockReturnValue({ | ||
error: undefined, | ||
mutate: jest.fn(), | ||
isValidating: false, | ||
isLoading: false, | ||
inpatientAdmissions: mockInpatientAdmissions, | ||
}); | ||
|
||
describe('Ward Metrics', () => { | ||
it('Should display metrics of in the ward ', () => { | ||
mockUseWardLocation.mockReturnValueOnce({ | ||
location: null, | ||
isLoadingLocation: false, | ||
errorFetchingLocation: null, | ||
invalidLocation: true, | ||
}); | ||
const bedMetrics = getWardMetrics(mockWardBeds); | ||
renderWithSwr(<WardMetrics />); | ||
for (let [key, value] of Object.entries(bedMetrics)) { | ||
expect(screen.getByText(value)).toBeInTheDocument(); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,4 @@ | |
margin: layout.$spacing-05 0; | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
} |
Oops, something went wrong.