@kenyaemr/esm-adr-app 5.4.2-pre.2448 → 5.4.2-pre.2453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +18 -23
- package/dist/197.js +1 -1
- package/dist/216.js +1 -1
- package/dist/216.js.map +1 -1
- package/dist/294.js +1 -1
- package/dist/300.js +1 -1
- package/dist/490.js +1 -1
- package/dist/490.js.map +1 -1
- package/dist/696.js +1 -0
- package/dist/696.js.map +1 -0
- package/dist/796.js +2 -0
- package/dist/796.js.map +1 -0
- package/dist/902.js +1 -0
- package/dist/902.js.map +1 -0
- package/dist/kenyaemr-esm-adr-app.js +1 -1
- package/dist/kenyaemr-esm-adr-app.js.buildmanifest.json +61 -34
- package/dist/kenyaemr-esm-adr-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/components/adr-patient-summary/patient-summary.component.tsx +59 -0
- package/src/components/adr-patient-summary/patient-summary.scss +22 -0
- package/src/components/dashboard/dashboard-view.component.tsx +8 -2
- package/src/components/dashboard/home-dashboard.component.tsx +15 -3
- package/src/components/encounters/adr-encounter.component.tsx +63 -58
- package/src/components/encounters/encounter.resource.tsx +38 -1
- package/src/components/encounters/encounter.scss +12 -0
- package/src/components/encounters/patient-encounter.component.tsx +54 -0
- package/src/components/patient-search/patient-search.component.tsx +30 -0
- package/src/components/patient-search/patient-search.scss +5 -0
- package/src/components/patient-search/useInitialize.ts +24 -0
- package/src/components/summary/summary.component.tsx +30 -34
- package/src/components/summary/summary.scss +1 -4
- package/src/config-schema.ts +19 -1
- package/src/root.component.tsx +3 -2
- package/translations/am.json +6 -4
- package/translations/en.json +6 -4
- package/translations/sw.json +6 -4
- package/dist/715.js +0 -1
- package/dist/715.js.map +0 -1
- package/dist/797.js +0 -2
- package/dist/797.js.map +0 -1
- /package/dist/{797.js.LICENSE.txt → 796.js.LICENSE.txt} +0 -0
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"adrAssessmentApp","route":"adr-assessment"}],"workspaces":[{"name":"patient-adr-workspace","title":"ADR Assessment Review","component":"patientAdrWorkspace","type":"workspace","canMaximize":true,"canHide":true,"width":"extra-wide"}],"extensions":[{"name":"adr-assessment-side-nav","slot":"adr-assessment-side-nav-slot","component":"adrAssessmentSideNav"},{"name":"adr-assessment-search-dashboard-db-link","slot":"adr-assessment-page-dashboard-slot","component":"overviewDashboardLink","meta":{"name":"adr-assessment-overview","title":"Overview","slot":"adr-assessment-overview-dashboard-slot"}},{"name":"adr-assessment-summary","component":"adrAssessmentSummary","slot":"adr-assessment-overview-dashboard-slot"}],"version":"5.4.2-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"adrAssessmentApp","route":"adr-assessment"}],"workspaces":[{"name":"patient-adr-workspace","title":"ADR Assessment Review","component":"patientAdrWorkspace","type":"workspace","canMaximize":true,"canHide":true,"width":"extra-wide"}],"extensions":[{"name":"adr-assessment-side-nav","slot":"adr-assessment-side-nav-slot","component":"adrAssessmentSideNav"},{"name":"adr-assessment-search-dashboard-db-link","slot":"adr-assessment-page-dashboard-slot","component":"overviewDashboardLink","meta":{"name":"adr-assessment-overview","title":"Overview","slot":"adr-assessment-overview-dashboard-slot"}},{"name":"adr-assessment-summary","component":"adrAssessmentSummary","slot":"adr-assessment-overview-dashboard-slot"}],"version":"5.4.2-pre.2453"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import styles from './patient-summary.scss';
|
|
3
|
+
import {
|
|
4
|
+
ErrorState,
|
|
5
|
+
ExtensionSlot,
|
|
6
|
+
fetchCurrentPatient,
|
|
7
|
+
useLayoutType,
|
|
8
|
+
WorkspaceContainer,
|
|
9
|
+
} from '@openmrs/esm-framework';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
import { useParams } from 'react-router-dom';
|
|
12
|
+
import { InlineLoading } from '@carbon/react';
|
|
13
|
+
import { useInitialize } from '../patient-search/useInitialize';
|
|
14
|
+
import PatientEncounter from '../encounters/patient-encounter.component';
|
|
15
|
+
import useSWR from 'swr';
|
|
16
|
+
|
|
17
|
+
const AdrPatientSummary: React.FC = () => {
|
|
18
|
+
const layout = useLayoutType();
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
const isTablet = layout === 'tablet';
|
|
21
|
+
const { patientUuid } = useParams<{ patientUuid: string }>();
|
|
22
|
+
const {
|
|
23
|
+
data: patient,
|
|
24
|
+
isLoading,
|
|
25
|
+
error,
|
|
26
|
+
} = useSWR(patientUuid ? ['patient', patientUuid] : null, () => fetchCurrentPatient(patientUuid!, {}));
|
|
27
|
+
|
|
28
|
+
const state = useMemo(() => ({ patient, patientUuid }), [patient, patientUuid]);
|
|
29
|
+
|
|
30
|
+
useInitialize(patientUuid, state);
|
|
31
|
+
|
|
32
|
+
if (isLoading) {
|
|
33
|
+
return (
|
|
34
|
+
<div className={styles.loadingContainer}>
|
|
35
|
+
<InlineLoading description={t('loading', 'Loading...')} />
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (error) {
|
|
40
|
+
return <ErrorState error={error} headerTitle={t('error', 'Error')} />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={isTablet ? styles.tabletHeading : styles.desktopHeading}>
|
|
45
|
+
{patient && patientUuid && <ExtensionSlot name="patient-header-slot" state={{ patient, patientUuid }} />}
|
|
46
|
+
<div className={styles.patientEncounterContainer}>
|
|
47
|
+
<PatientEncounter patientUuid={patientUuid} />
|
|
48
|
+
</div>
|
|
49
|
+
<WorkspaceContainer
|
|
50
|
+
showSiderailAndBottomNav
|
|
51
|
+
key="adr-assessment"
|
|
52
|
+
contextKey={`adr-assessment/overview/${patientUuid}`}
|
|
53
|
+
additionalWorkspaceProps={state}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default AdrPatientSummary;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
|
|
3
|
+
.desktopHeading {
|
|
4
|
+
padding-left: 16rem;
|
|
5
|
+
margin-right: 3rem;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.loadingContainer {
|
|
9
|
+
display: flex;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
align-items: center;
|
|
12
|
+
height: 100vh;
|
|
13
|
+
width: 100vw;
|
|
14
|
+
|
|
15
|
+
:global(.cds--inline-loading) {
|
|
16
|
+
width: unset;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.patientEncounterContainer {
|
|
21
|
+
margin: layout.$spacing-05;
|
|
22
|
+
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ExtensionSlot,
|
|
4
|
+
PageHeader,
|
|
5
|
+
AppointmentsPictogram,
|
|
6
|
+
PageHeaderContent,
|
|
7
|
+
PharmacyPictogram,
|
|
8
|
+
} from '@openmrs/esm-framework';
|
|
3
9
|
import { useTranslation } from 'react-i18next';
|
|
4
10
|
import styles from './dashboard-view.scss';
|
|
5
11
|
const DashboardView: React.FC<{ dashboardSlot: string; title: string }> = ({ dashboardSlot, title }) => {
|
|
@@ -7,7 +13,7 @@ const DashboardView: React.FC<{ dashboardSlot: string; title: string }> = ({ das
|
|
|
7
13
|
return (
|
|
8
14
|
<>
|
|
9
15
|
<PageHeader className={styles.pageHeader}>
|
|
10
|
-
<PageHeaderContent title={t('adrAssessment', 'ADR Assessment')} illustration={<
|
|
16
|
+
<PageHeaderContent title={t('adrAssessment', 'ADR Assessment')} illustration={<PharmacyPictogram />} />
|
|
11
17
|
</PageHeader>
|
|
12
18
|
<ExtensionSlot name={dashboardSlot} state={{ dashboardTitle: title }} />
|
|
13
19
|
</>
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ExtensionSlot,
|
|
5
|
+
WorkspaceContainer,
|
|
6
|
+
isDesktop,
|
|
7
|
+
navigate,
|
|
8
|
+
useExtensionStore,
|
|
9
|
+
useLayoutType,
|
|
10
|
+
} from '@openmrs/esm-framework';
|
|
4
11
|
import DashboardView from './dashboard-view.component';
|
|
5
12
|
import styles from './home-dashboard.scss';
|
|
6
13
|
import { DashboardConfig } from '../../types';
|
|
@@ -16,6 +23,12 @@ export default function Dashboard() {
|
|
|
16
23
|
const dashboards = ungroupedDashboards as Array<DashboardConfig>;
|
|
17
24
|
const activeDashboard = dashboards.find((dashboard) => dashboard.name === params?.dashboard) || dashboards[0];
|
|
18
25
|
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (params?.dashboard === undefined) {
|
|
28
|
+
navigate({ to: `${window.spaBase}/adr-assessment/overview` });
|
|
29
|
+
}
|
|
30
|
+
}, [params?.dashboard]);
|
|
31
|
+
|
|
19
32
|
return (
|
|
20
33
|
<>
|
|
21
34
|
<div className={styles.homePageWrapper}>
|
|
@@ -23,7 +36,6 @@ export default function Dashboard() {
|
|
|
23
36
|
{isDesktop(layout) && <ExtensionSlot name="adr-assessment-side-nav-slot" key={layout} />}
|
|
24
37
|
<DashboardView title={activeDashboard?.name} dashboardSlot={activeDashboard?.slot} />
|
|
25
38
|
</section>
|
|
26
|
-
<WorkspaceContainer overlay contextKey="adr-assessment" />
|
|
27
39
|
</div>
|
|
28
40
|
</>
|
|
29
41
|
);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
Button,
|
|
4
3
|
DataTable,
|
|
4
|
+
Layer,
|
|
5
|
+
OverflowMenu,
|
|
6
|
+
OverflowMenuItem,
|
|
5
7
|
Pagination,
|
|
6
8
|
Table,
|
|
7
9
|
TableBody,
|
|
@@ -17,7 +19,6 @@ import {
|
|
|
17
19
|
import styles from './encounter.scss';
|
|
18
20
|
import { useTranslation } from 'react-i18next';
|
|
19
21
|
import {
|
|
20
|
-
ActionMenuButton,
|
|
21
22
|
formatDatetime,
|
|
22
23
|
isDesktop,
|
|
23
24
|
launchWorkspace,
|
|
@@ -44,7 +45,6 @@ const AdrEncounter: React.FC<adrEncounterProps> = ({ encounters }) => {
|
|
|
44
45
|
{ header: 'Visit type', key: 'visitTypeName' },
|
|
45
46
|
{ header: 'Form name', key: 'formName' },
|
|
46
47
|
{ header: 'Provider', key: 'provider' },
|
|
47
|
-
{ header: 'Actions', key: 'action' },
|
|
48
48
|
];
|
|
49
49
|
const sortedEncounters = encounters.sort((a, b) => {
|
|
50
50
|
const dateA = new Date(a.encounterDatetime || 0).getTime();
|
|
@@ -67,11 +67,6 @@ const AdrEncounter: React.FC<adrEncounterProps> = ({ encounters }) => {
|
|
|
67
67
|
formName: encounter?.formName,
|
|
68
68
|
id: encounter?.encounterUuid,
|
|
69
69
|
provider: encounter?.provider || '--',
|
|
70
|
-
action: (
|
|
71
|
-
<Button kind="tertiary" renderIcon={ReviewIcon} onClick={() => handler(encounter)}>
|
|
72
|
-
{t('review', 'Review')}
|
|
73
|
-
</Button>
|
|
74
|
-
),
|
|
75
70
|
}));
|
|
76
71
|
if (encounters.length === 0) {
|
|
77
72
|
return (
|
|
@@ -86,58 +81,68 @@ const AdrEncounter: React.FC<adrEncounterProps> = ({ encounters }) => {
|
|
|
86
81
|
|
|
87
82
|
return (
|
|
88
83
|
<div className={styles.encounterContainer}>
|
|
89
|
-
<
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
</TableRow>
|
|
123
|
-
</TableHead>
|
|
124
|
-
<TableBody>
|
|
125
|
-
{rows.map((row) => (
|
|
126
|
-
<TableRow
|
|
127
|
-
key={row.id}
|
|
128
|
-
{...getRowProps({
|
|
129
|
-
row,
|
|
130
|
-
})}>
|
|
131
|
-
{row.cells.map((cell) => (
|
|
132
|
-
<TableCell key={cell.id}>{cell.value}</TableCell>
|
|
84
|
+
<Layer>
|
|
85
|
+
<DataTable size={responsiveSize} rows={tableRows} headers={headers} useZebraStyles={false}>
|
|
86
|
+
{({
|
|
87
|
+
rows,
|
|
88
|
+
headers,
|
|
89
|
+
getHeaderProps,
|
|
90
|
+
getRowProps,
|
|
91
|
+
getTableProps,
|
|
92
|
+
getToolbarProps,
|
|
93
|
+
onInputChange,
|
|
94
|
+
getTableContainerProps,
|
|
95
|
+
}) => (
|
|
96
|
+
<TableContainer
|
|
97
|
+
className={styles.encounterTable}
|
|
98
|
+
title={t('adrAssessmentEncounters', 'ADR Assessment Encounters')}
|
|
99
|
+
description={t('summaryOfAdrAssessmentEncounters', 'Summary of ADR assessment encounters')}
|
|
100
|
+
{...getTableContainerProps()}>
|
|
101
|
+
<TableToolbar {...getToolbarProps()} aria-label="data table toolbar">
|
|
102
|
+
<TableToolbarContent>
|
|
103
|
+
<TableToolbarSearch persistent onChange={onInputChange} />
|
|
104
|
+
</TableToolbarContent>
|
|
105
|
+
</TableToolbar>
|
|
106
|
+
<Table {...getTableProps()} aria-label={t('encounters', 'Encounters')}>
|
|
107
|
+
<TableHead>
|
|
108
|
+
<TableRow>
|
|
109
|
+
{headers.map((header) => (
|
|
110
|
+
<TableHeader
|
|
111
|
+
key={header.key}
|
|
112
|
+
{...getHeaderProps({
|
|
113
|
+
header,
|
|
114
|
+
})}>
|
|
115
|
+
{header.header}
|
|
116
|
+
</TableHeader>
|
|
133
117
|
))}
|
|
118
|
+
<TableHeader aria-label={t('actions', 'Actions')} />
|
|
134
119
|
</TableRow>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
120
|
+
</TableHead>
|
|
121
|
+
<TableBody>
|
|
122
|
+
{rows.map((row, index) => (
|
|
123
|
+
<TableRow
|
|
124
|
+
key={row.id}
|
|
125
|
+
{...getRowProps({
|
|
126
|
+
row,
|
|
127
|
+
})}>
|
|
128
|
+
{row.cells.map((cell) => (
|
|
129
|
+
<TableCell key={cell.id}>{cell.value}</TableCell>
|
|
130
|
+
))}
|
|
131
|
+
<TableCell className="cds--table-column-menu">
|
|
132
|
+
<OverflowMenu size="sm" flipped>
|
|
133
|
+
<OverflowMenuItem onClick={() => handler(encounters[index])}>
|
|
134
|
+
{t('review', 'Review')}
|
|
135
|
+
</OverflowMenuItem>
|
|
136
|
+
</OverflowMenu>
|
|
137
|
+
</TableCell>
|
|
138
|
+
</TableRow>
|
|
139
|
+
))}
|
|
140
|
+
</TableBody>
|
|
141
|
+
</Table>
|
|
142
|
+
</TableContainer>
|
|
143
|
+
)}
|
|
144
|
+
</DataTable>
|
|
145
|
+
</Layer>
|
|
141
146
|
{paginated && (
|
|
142
147
|
<Pagination
|
|
143
148
|
forwardText="Next page"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
1
|
import useSWR from 'swr';
|
|
2
|
+
import { openmrsFetch, restBaseUrl, useConfig, useOpenmrsPagination, type Encounter } from '@openmrs/esm-framework';
|
|
3
|
+
|
|
3
4
|
import { MappedAdrEncounter } from '../../types';
|
|
5
|
+
import { type ADRConfigObject } from '../../config-schema';
|
|
4
6
|
|
|
5
7
|
export const useAdrAssessmentEncounter = (fromDate: string, toDate?: string) => {
|
|
6
8
|
const url = `${restBaseUrl}/kenyaemr/adrencounter?fromdate=${fromDate}&todate=${toDate}`;
|
|
@@ -11,3 +13,38 @@ export const useAdrAssessmentEncounter = (fromDate: string, toDate?: string) =>
|
|
|
11
13
|
error,
|
|
12
14
|
};
|
|
13
15
|
};
|
|
16
|
+
|
|
17
|
+
export const usePatientAdrAssessmentEncounter = (patientUuid: string) => {
|
|
18
|
+
const { adrAssessmentEncounterTypeUuid } = useConfig<ADRConfigObject>();
|
|
19
|
+
const url = `${restBaseUrl}/encounter?patient=${patientUuid}&encounterType=${adrAssessmentEncounterTypeUuid}&v=full`;
|
|
20
|
+
const pageSize = 10;
|
|
21
|
+
const { data, error, isLoading, paginated, currentPage, goTo, totalCount, currentPageSize, mutate } =
|
|
22
|
+
useOpenmrsPagination<Encounter>(url, pageSize);
|
|
23
|
+
|
|
24
|
+
const mappedEncounters: Array<MappedAdrEncounter> = data?.map((encounter) => ({
|
|
25
|
+
encounterUuid: encounter.uuid,
|
|
26
|
+
encounterTypeUuid: encounter.encounterType?.uuid,
|
|
27
|
+
patientUuid: encounter.patient?.uuid,
|
|
28
|
+
patientName: encounter.patient?.display,
|
|
29
|
+
encounterType: encounter.encounterType?.name,
|
|
30
|
+
encounterDatetime: encounter.encounterDatetime,
|
|
31
|
+
visitTypeName: encounter.visit?.visitType?.display,
|
|
32
|
+
formName: encounter.form?.display,
|
|
33
|
+
location: encounter.location?.display,
|
|
34
|
+
provider: encounter.encounterProviders?.map((provider) => provider.provider?.display).join(', '),
|
|
35
|
+
formUuid: encounter.form?.uuid,
|
|
36
|
+
visitUuid: encounter.visit?.uuid,
|
|
37
|
+
visitTypeUuid: encounter.visit?.visitType?.uuid,
|
|
38
|
+
}));
|
|
39
|
+
return {
|
|
40
|
+
encounters: mappedEncounters ?? [],
|
|
41
|
+
isLoading,
|
|
42
|
+
error,
|
|
43
|
+
paginated,
|
|
44
|
+
currentPage,
|
|
45
|
+
goTo,
|
|
46
|
+
totalCount,
|
|
47
|
+
currentPageSize,
|
|
48
|
+
mutate,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { mutate } from 'swr';
|
|
3
|
+
import { InlineLoading } from '@carbon/react';
|
|
4
|
+
import { EmptyState, useLaunchWorkspaceRequiringVisit } from '@openmrs/esm-patient-common-lib';
|
|
5
|
+
import { useConfig } from '@openmrs/esm-framework';
|
|
6
|
+
|
|
7
|
+
import { usePatientAdrAssessmentEncounter } from './encounter.resource';
|
|
8
|
+
import AdrEncounter from './adr-encounter.component';
|
|
9
|
+
import { type ADRConfigObject } from '../../config-schema';
|
|
10
|
+
import styles from './encounter.scss';
|
|
11
|
+
|
|
12
|
+
type PatientEncounterProps = {
|
|
13
|
+
patientUuid: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const PatientEncounter: React.FC<PatientEncounterProps> = ({ patientUuid }) => {
|
|
17
|
+
const { adrAssessmentFormUuid } = useConfig<ADRConfigObject>();
|
|
18
|
+
const { encounters, isLoading } = usePatientAdrAssessmentEncounter(patientUuid);
|
|
19
|
+
const launchWorkspaceRequiringVisit = useLaunchWorkspaceRequiringVisit('patient-form-entry-workspace');
|
|
20
|
+
|
|
21
|
+
const launchAdrAssessmentWorkspace = (encounterUuid: string = '') => {
|
|
22
|
+
launchWorkspaceRequiringVisit({
|
|
23
|
+
formInfo: {
|
|
24
|
+
formUuid: adrAssessmentFormUuid,
|
|
25
|
+
encounterUuid: encounterUuid,
|
|
26
|
+
},
|
|
27
|
+
mutateForm: () => {
|
|
28
|
+
mutate((key) => typeof key === 'string' && key.startsWith(`/ws/rest/v1/encounter`), undefined, {
|
|
29
|
+
revalidate: true,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (isLoading) {
|
|
36
|
+
return (
|
|
37
|
+
<div className={styles.loadingContainer}>
|
|
38
|
+
<InlineLoading description="Loading..." />
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (encounters.length === 0) {
|
|
44
|
+
return (
|
|
45
|
+
<div className={styles.emptyContainer}>
|
|
46
|
+
<EmptyState displayText="ADR Encounter" headerTitle="ADR Encounter" launchForm={launchAdrAssessmentWorkspace} />
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return <AdrEncounter encounters={encounters} />;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default PatientEncounter;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from './patient-search.scss';
|
|
3
|
+
import { ExtensionSlot, navigate } from '@openmrs/esm-framework';
|
|
4
|
+
import { launchPatientChartWithWorkspaceOpen } from '@openmrs/esm-patient-common-lib';
|
|
5
|
+
import { Layer } from '@carbon/react';
|
|
6
|
+
|
|
7
|
+
const PatientSearch: React.FC = () => {
|
|
8
|
+
const selectPatient = (patientUuid: string) => {
|
|
9
|
+
navigate({ to: `${window.spaBase}/adr-assessment/overview/${patientUuid}` });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className={styles.patientSearchContainer}>
|
|
14
|
+
<Layer>
|
|
15
|
+
<ExtensionSlot
|
|
16
|
+
className={styles.patientSearchBar}
|
|
17
|
+
name="patient-search-bar-slot"
|
|
18
|
+
state={{
|
|
19
|
+
selectPatientAction: selectPatient,
|
|
20
|
+
buttonProps: {
|
|
21
|
+
kind: 'secondary',
|
|
22
|
+
},
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
</Layer>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default PatientSearch;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { setCurrentVisit } from '@openmrs/esm-framework';
|
|
3
|
+
import { getPatientChartStore } from '@openmrs/esm-patient-common-lib';
|
|
4
|
+
|
|
5
|
+
type PatientState = {
|
|
6
|
+
patient: any;
|
|
7
|
+
patientUuid?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const useInitialize = (patientUuid: string | undefined, state: PatientState) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
setCurrentVisit(patientUuid, null);
|
|
13
|
+
return () => {
|
|
14
|
+
setCurrentVisit(null, null);
|
|
15
|
+
};
|
|
16
|
+
}, [patientUuid]);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
getPatientChartStore().setState({ ...state });
|
|
20
|
+
return () => {
|
|
21
|
+
getPatientChartStore().setState({});
|
|
22
|
+
};
|
|
23
|
+
}, [state]);
|
|
24
|
+
};
|
|
@@ -5,7 +5,20 @@ import styles from './summary.scss';
|
|
|
5
5
|
import AdrEncounter from '../encounters/adr-encounter.component';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { useAdrAssessmentEncounter } from '../encounters/encounter.resource';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Button,
|
|
10
|
+
Checkbox,
|
|
11
|
+
DataTableSkeleton,
|
|
12
|
+
Layer,
|
|
13
|
+
Tab,
|
|
14
|
+
TabList,
|
|
15
|
+
TabPanel,
|
|
16
|
+
TabPanels,
|
|
17
|
+
Tabs,
|
|
18
|
+
TextInput,
|
|
19
|
+
} from '@carbon/react';
|
|
20
|
+
import { CloudMonitoring, Activity, IbmWatsonDiscovery, Settings, Search } from '@carbon/react/icons';
|
|
21
|
+
import PatientSearch from '../patient-search/patient-search.component';
|
|
9
22
|
|
|
10
23
|
type SummaryProps = {};
|
|
11
24
|
|
|
@@ -45,39 +58,22 @@ const Summary: React.FC<SummaryProps> = () => {
|
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
return (
|
|
48
|
-
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
placeholder="mm/dd/yyyy"
|
|
65
|
-
labelText={t('endDate', 'End date')}
|
|
66
|
-
size="md"
|
|
67
|
-
/>
|
|
68
|
-
</DatePicker>
|
|
69
|
-
</div>
|
|
70
|
-
<div className={styles.summaryContainer}>
|
|
71
|
-
<div className={styles.summaryCard}>
|
|
72
|
-
<h4>{t('adrAssessment', 'ADR Assessment')}</h4>
|
|
73
|
-
<div>
|
|
74
|
-
<h6>{t('totalAdrAssessment', 'Total ADR assessment')}</h6>
|
|
75
|
-
<p>{counts.assessment}</p>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
<AdrEncounter encounters={encounters} />
|
|
80
|
-
</>
|
|
61
|
+
<div className={styles.summaryContainer}>
|
|
62
|
+
<Tabs>
|
|
63
|
+
<TabList contained>
|
|
64
|
+
<Tab renderIcon={Search}>{t('search', 'Search')}</Tab>
|
|
65
|
+
<Tab renderIcon={CloudMonitoring}>{t('adrEncounters', 'ADR Encounters')}</Tab>
|
|
66
|
+
</TabList>
|
|
67
|
+
<TabPanels>
|
|
68
|
+
<TabPanel>
|
|
69
|
+
<PatientSearch />
|
|
70
|
+
</TabPanel>
|
|
71
|
+
<TabPanel>
|
|
72
|
+
<AdrEncounter encounters={encounters} />
|
|
73
|
+
</TabPanel>
|
|
74
|
+
</TabPanels>
|
|
75
|
+
</Tabs>
|
|
76
|
+
</div>
|
|
81
77
|
);
|
|
82
78
|
};
|
|
83
79
|
|
package/src/config-schema.ts
CHANGED
|
@@ -1 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { Type } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
3
|
+
export interface ADRConfigObject {
|
|
4
|
+
adrAssessmentEncounterTypeUuid: string;
|
|
5
|
+
adrAssessmentFormUuid: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const configSchema = {
|
|
9
|
+
adrAssessmentEncounterTypeUuid: {
|
|
10
|
+
_type: Type.String,
|
|
11
|
+
_description: 'UUID for ADR Assessment encounter type',
|
|
12
|
+
_default: '7a185fe4-c56f-4195-b682-d3f5afa9d9c2 ',
|
|
13
|
+
},
|
|
14
|
+
adrAssessmentFormUuid: {
|
|
15
|
+
_type: Type.String,
|
|
16
|
+
_description: 'UUID for ADR Assessment form',
|
|
17
|
+
_default: '461e1b45-b3f2-4899-b3e9-d3b110b6ed9c',
|
|
18
|
+
},
|
|
19
|
+
};
|
package/src/root.component.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
2
|
import { Routes, BrowserRouter, Route } from 'react-router-dom';
|
|
3
|
-
import { setLeftNav, unsetLeftNav
|
|
3
|
+
import { setLeftNav, unsetLeftNav } from '@openmrs/esm-framework';
|
|
4
4
|
import Dashboard from './components/dashboard/home-dashboard.component';
|
|
5
|
+
import AdrPatientSummary from './components/adr-patient-summary/patient-summary.component';
|
|
5
6
|
|
|
6
7
|
const AdrAssessmentApp = () => {
|
|
7
8
|
const spaBasePath = `${window.spaBase}/adr-assessment`;
|
|
@@ -17,8 +18,8 @@ const AdrAssessmentApp = () => {
|
|
|
17
18
|
<Routes>
|
|
18
19
|
<Route path="/adr-assessment" element={<Dashboard />} />
|
|
19
20
|
<Route path="/adr-assessment/:dashboard/*" element={<Dashboard />} />
|
|
21
|
+
<Route path="/adr-assessment/:dashboard/:patientUuid" element={<AdrPatientSummary />} />
|
|
20
22
|
</Routes>
|
|
21
|
-
<WorkspaceContainer key="adr-assessment" contextKey="adr-assessment"></WorkspaceContainer>
|
|
22
23
|
</BrowserRouter>
|
|
23
24
|
</main>
|
|
24
25
|
);
|
package/translations/am.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
+
"actions": "Actions",
|
|
2
3
|
"adrAssessment": "የኤዲአር ግምገማ",
|
|
3
4
|
"adrAssessmentEncounters": "የኤዲአር ግምገማ ግኝቶች",
|
|
5
|
+
"adrEncounters": "ADR Encounters",
|
|
4
6
|
"encounters": "ግኝቶች",
|
|
5
|
-
"
|
|
7
|
+
"error": "Error",
|
|
8
|
+
"loading": "Loading...",
|
|
6
9
|
"noAdrEncountersFound": "ምንም የኤዲአር ግኝቶች አልተገኙም",
|
|
7
10
|
"noEncountersFoundTitle": "ምንም ግኝቶች አልተገኙም",
|
|
8
11
|
"review": "ይገምግሙ",
|
|
9
|
-
"
|
|
10
|
-
"summaryOfAdrAssessmentEncounters": "የኤዲአር ግምገማ ግኝቶች ማጠቃለያ"
|
|
11
|
-
"totalAdrAssessment": "ጠቅላላ የኤዲአር ግምገማ"
|
|
12
|
+
"search": "Search",
|
|
13
|
+
"summaryOfAdrAssessmentEncounters": "የኤዲአር ግምገማ ግኝቶች ማጠቃለያ"
|
|
12
14
|
}
|