@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2202 → 5.4.2-pre.2223
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 +26 -489
- package/dist/144.js +2 -0
- package/dist/144.js.map +1 -0
- package/dist/300.js +1 -0
- package/dist/317.js +1 -0
- package/dist/317.js.map +1 -0
- package/dist/{807.js → 335.js} +1 -1
- package/dist/349.js +2 -0
- package/dist/349.js.map +1 -0
- package/dist/359.js +2 -0
- package/dist/359.js.LICENSE.txt +29 -0
- package/dist/359.js.map +1 -0
- package/dist/41.js +2 -0
- package/dist/41.js.map +1 -0
- package/dist/474.js +2 -0
- package/dist/474.js.map +1 -0
- package/dist/479.js +2 -0
- package/dist/479.js.LICENSE.txt +9 -0
- package/dist/479.js.map +1 -0
- package/dist/537.js +1 -0
- package/dist/537.js.map +1 -0
- package/dist/{319.js → 55.js} +1 -1
- package/dist/60.js +1 -0
- package/dist/60.js.map +1 -0
- package/dist/746.js +2 -0
- package/dist/{164.js.LICENSE.txt → 746.js.LICENSE.txt} +0 -10
- package/dist/746.js.map +1 -0
- package/dist/907.js +1 -0
- package/dist/907.js.map +1 -0
- package/dist/913.js +2 -0
- package/dist/{591.js.map → 913.js.map} +1 -1
- package/dist/{757.js → 99.js} +1 -1
- package/dist/kenyaemr-esm-patient-clinical-view-app.js +1 -1
- package/dist/kenyaemr-esm-patient-clinical-view-app.js.buildmanifest.json +219 -117
- package/dist/kenyaemr-esm-patient-clinical-view-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 +4 -1
- package/src/autosuggest/autosuggest.component.tsx +3 -3
- package/src/autosuggest/autosuggest.scss +1 -1
- package/src/autosuggest/patient-search-info.component.tsx +1 -1
- package/src/case-management/encounters/case-encounter-header.scss +1 -1
- package/src/case-management/encounters/case-encounter-overview.component.tsx +11 -8
- package/src/case-management/header/case-management-header.scss +1 -1
- package/src/case-management/metrics/case-management-header.scss +1 -1
- package/src/case-management/table/case-management-list.scss +1 -1
- package/src/case-management/tabs/case-management-tabs.component.tsx +2 -2
- package/src/case-management/tabs/case-management-tabs.scss +1 -1
- package/src/case-management/workspace/case-management.scss +1 -1
- package/src/case-management/workspace/patient-info.scss +1 -1
- package/src/clinical-encounter/clinical-enc.component.tsx +4 -4
- package/src/clinical-encounter/dashboard/in-patient.scss +1 -1
- package/src/clinical-encounter/summary/in-patient-medical-summary/in-patient-medical-summary.component.tsx +1 -1
- package/src/clinical-encounter/summary/maternal-summary/maternal-summary.component.tsx +4 -4
- package/src/clinical-encounter/summary/neonatal summary/neonatal-summary.component.tsx +4 -4
- package/src/clinical-encounter/summary/out-patient-summary/out-patient-summary.scss +1 -1
- package/src/clinical-encounter/summary/out-patient-summary/patient-medical-history.component.tsx +2 -2
- package/src/clinical-encounter/summary/out-patient-summary/patient-social-history.component.tsx +5 -5
- package/src/clinical-encounter/summary/surgical summary/surgical-summary.component.tsx +4 -5
- package/src/contact-list/contact-actions.component.tsx +4 -5
- package/src/contact-list/contact-list-concept-map.ts +1 -0
- package/src/contact-list/contact-list.component.tsx +2 -2
- package/src/contact-list/contact-list.scss +1 -1
- package/src/contact-list/contact-list.workspace.tsx +28 -13
- package/src/contact-list/contact-tracing-history.component.tsx +3 -3
- package/src/contact-list/forms/contact-list-update.workspace.tsx +22 -267
- package/src/deceased-panel/mortuary-summary/mortuary-summary.component.tsx +2 -10
- package/src/deceased-panel/mortuary-summary/mortuary-summary.scss +1 -1
- package/src/deceased-panel/panels/autopsy.component.tsx +11 -4
- package/src/declarations.d.ts +0 -13
- package/src/family-partner-history/family-history.component.tsx +2 -2
- package/src/family-partner-history/family-history.scss +1 -1
- package/src/family-partner-history/family-relationship.scss +1 -1
- package/src/family-partner-history/family-relationship.workspace.tsx +27 -12
- package/src/hooks/useContacts.ts +1 -0
- package/src/in-patient/in-patient-table/in-patient-table.component.tsx +4 -4
- package/src/in-patient/in-patient.component.tsx +3 -8
- package/src/maternal-and-child-health/maternal-health-component.scss +4 -3
- package/src/maternal-and-child-health/partography/labour-delivery.scss +7 -5
- package/src/maternal-and-child-health/partography/partograph-chart.scss +1 -1
- package/src/maternal-and-child-health/partography/partograph.component.tsx +5 -11
- package/src/peer-calendar/forms/peer-form.workspace.tsx +11 -11
- package/src/peer-calendar/header/reporting-period-input.component.tsx +3 -1
- package/src/peer-calendar/metrics/peer-calendar-metrics.component.tsx +2 -3
- package/src/peer-calendar/table/generic-data-table.scss +1 -1
- package/src/peer-calendar/table/generic-data-table.tsx +2 -1
- package/src/peer-calendar/table/peer-calendar-table-filter.component.tsx +6 -3
- package/src/relationships/forms/baseline-info-form-section.component.tsx +46 -31
- package/src/relationships/forms/form.scss +1 -1
- package/src/relationships/forms/patient-search-create-form.tsx +25 -20
- package/src/relationships/modals/birthdate-calculator.modal.tsx +3 -2
- package/src/relationships/relationship.resources.ts +18 -2
- package/src/relationships/tabs/relationships-tabs-component.tsx +2 -2
- package/src/relationships/tabs/relationships-tabs.scss +1 -1
- package/src/root.scss +1 -2
- package/src/specialized-clinics/generic-nav-links/generic-dashboard.component.tsx +3 -3
- package/src/specialized-clinics/hiv-care-and-treatment-services/defaulter-tracing/defaulter-tracing.component.tsx +5 -5
- package/src/specialized-clinics/hiv-care-and-treatment-services/defaulter-tracing/defaulter-tracing.test.tsx +2 -8
- package/src/specialized-clinics/hiv-care-and-treatment-services/hiv-testing-services/hiv-testing-component.scss +4 -3
- package/src/specialized-clinics/hiv-care-and-treatment-services/hiv-testing-services/views/hiv-testing/hiv-testing-services.component.tsx +3 -8
- package/src/ui/data-table/o-table.component.tsx +2 -2
- package/src/ui/data-table/o-table.scss +1 -1
- package/src/ui/encounter-list/encounter-list.scss +5 -3
- package/translations/en.json +1 -0
- package/dist/130.js +0 -2
- package/dist/130.js.LICENSE.txt +0 -7
- package/dist/130.js.map +0 -1
- package/dist/164.js +0 -2
- package/dist/164.js.map +0 -1
- package/dist/316.js +0 -2
- package/dist/316.js.map +0 -1
- package/dist/40.js +0 -1
- package/dist/40.js.map +0 -1
- package/dist/574.js +0 -1
- package/dist/589.js +0 -1
- package/dist/589.js.map +0 -1
- package/dist/591.js +0 -2
- package/dist/685.js +0 -2
- package/dist/685.js.map +0 -1
- package/dist/700.js +0 -2
- package/dist/700.js.map +0 -1
- package/dist/784.js +0 -2
- package/dist/784.js.map +0 -1
- /package/dist/{316.js.LICENSE.txt → 144.js.LICENSE.txt} +0 -0
- /package/dist/{700.js.LICENSE.txt → 349.js.LICENSE.txt} +0 -0
- /package/dist/{784.js.LICENSE.txt → 41.js.LICENSE.txt} +0 -0
- /package/dist/{685.js.LICENSE.txt → 474.js.LICENSE.txt} +0 -0
- /package/dist/{591.js.LICENSE.txt → 913.js.LICENSE.txt} +0 -0
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { ComboButton, MenuItem, DataTableSkeleton } from '@carbon/react';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
EmptyState,
|
|
7
|
-
launchPatientWorkspace,
|
|
8
|
-
useVisitOrOfflineVisit,
|
|
9
|
-
} from '@openmrs/esm-patient-common-lib';
|
|
10
|
-
import { useConfig, useVisit, evaluateAsBoolean } from '@openmrs/esm-framework';
|
|
4
|
+
import { CardHeader, EmptyState, useVisitOrOfflineVisit } from '@openmrs/esm-patient-common-lib';
|
|
5
|
+
import { useConfig, useVisit, evaluateAsBoolean, launchWorkspace } from '@openmrs/esm-framework';
|
|
11
6
|
import dayjs from 'dayjs';
|
|
12
7
|
import { BedManagementConfig } from '../config-schema';
|
|
13
8
|
import { usePatientEncounters } from './in-patient.resource';
|
|
@@ -41,7 +36,7 @@ const InPatient: React.FC<InPatientProps> = ({ patientUuid, patient }) => {
|
|
|
41
36
|
});
|
|
42
37
|
|
|
43
38
|
const handleLaunchForm = (form: { label: string; uuid: string }) => {
|
|
44
|
-
|
|
39
|
+
launchWorkspace('patient-form-entry-workspace', {
|
|
45
40
|
workspaceTitle: form.label,
|
|
46
41
|
mutateForm: () => mutate(),
|
|
47
42
|
formInfo: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
@use '@carbon/styles/scss/spacing';
|
|
2
|
-
@
|
|
2
|
+
@use '@carbon/colors';
|
|
3
|
+
@use '~@openmrs/esm-styleguide/src/vars' as *;
|
|
3
4
|
|
|
4
5
|
.widgetContainer {
|
|
5
|
-
background-color:
|
|
6
|
+
background-color: colors.$white;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
.widgetHeaderContainer {
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
.widgetCard {
|
|
55
|
-
background-color:
|
|
56
|
+
background-color: colors.$white;
|
|
56
57
|
border: 1px solid $ui-03;
|
|
57
58
|
position: relative;
|
|
58
59
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
@use '@carbon/styles/scss/spacing';
|
|
2
2
|
@use '@carbon/styles/scss/type';
|
|
3
|
-
@
|
|
3
|
+
@use '@carbon/colors';
|
|
4
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
5
|
+
@use '../../root.scss';
|
|
4
6
|
|
|
5
7
|
.widgetContainer {
|
|
6
|
-
background-color:
|
|
8
|
+
background-color: colors.$white;
|
|
7
9
|
border: 1px solid #e0e0e0;
|
|
8
10
|
margin-bottom: 1rem;
|
|
9
11
|
}
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
.widgetCard {
|
|
51
|
-
background-color:
|
|
53
|
+
background-color: colors.$white;
|
|
52
54
|
border: 1px solid $ui-03;
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -82,11 +84,11 @@
|
|
|
82
84
|
|
|
83
85
|
&:global(.cds--btn--tertiary:focus) {
|
|
84
86
|
background-color: $interactive-01;
|
|
85
|
-
color:
|
|
87
|
+
color: colors.$white;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
&:global(.cds--btn--tertiary:hover) {
|
|
89
|
-
color:
|
|
91
|
+
color: colors.$white;
|
|
90
92
|
background-color: $interactive-01;
|
|
91
93
|
}
|
|
92
94
|
|
|
@@ -15,14 +15,8 @@ import {
|
|
|
15
15
|
Button,
|
|
16
16
|
} from '@carbon/react';
|
|
17
17
|
import { Add, ChartLineSmooth } from '@carbon/react/icons';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
ErrorState,
|
|
21
|
-
CardHeader,
|
|
22
|
-
launchPatientWorkspace,
|
|
23
|
-
EmptyState,
|
|
24
|
-
} from '@openmrs/esm-patient-common-lib';
|
|
25
|
-
import { formatDate, isDesktop, parseDate, useLayoutType } from '@openmrs/esm-framework';
|
|
18
|
+
import { EmptyDataIllustration, ErrorState, CardHeader, EmptyState } from '@openmrs/esm-patient-common-lib';
|
|
19
|
+
import { formatDate, isDesktop, launchWorkspace, parseDate, useLayoutType } from '@openmrs/esm-framework';
|
|
26
20
|
import styles from './labour-delivery.scss';
|
|
27
21
|
import { usePartograph } from '../../hooks/usePartograph';
|
|
28
22
|
import dayjs from 'dayjs';
|
|
@@ -108,7 +102,7 @@ const Partograph: React.FC<PartographyProps> = ({ patientUuid }) => {
|
|
|
108
102
|
}) ?? [];
|
|
109
103
|
|
|
110
104
|
const handleAddHistory = () => {
|
|
111
|
-
|
|
105
|
+
launchWorkspace('patient-form-entry-workspace', {
|
|
112
106
|
workspaceTitle: headerTitle,
|
|
113
107
|
mutateForm: () => {
|
|
114
108
|
mutate();
|
|
@@ -204,9 +198,9 @@ const Partograph: React.FC<PartographyProps> = ({ patientUuid }) => {
|
|
|
204
198
|
<TableHeader
|
|
205
199
|
{...getHeaderProps({
|
|
206
200
|
header,
|
|
207
|
-
isSortable:
|
|
201
|
+
isSortable: true,
|
|
208
202
|
})}>
|
|
209
|
-
{header.header
|
|
203
|
+
{header.header}
|
|
210
204
|
</TableHeader>
|
|
211
205
|
))}
|
|
212
206
|
</TableRow>
|
|
@@ -80,7 +80,7 @@ const PeerForm: React.FC<PeerFormProps> = ({ closeWorkspace }) => {
|
|
|
80
80
|
render={({ field }) => (
|
|
81
81
|
<Dropdown
|
|
82
82
|
ref={field.ref}
|
|
83
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
83
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
84
84
|
invalidText={form.formState.errors[field.name]?.message}
|
|
85
85
|
id="relationship"
|
|
86
86
|
titleText={t('relationshipType', 'RelationshipbType')}
|
|
@@ -105,7 +105,7 @@ const PeerForm: React.FC<PeerFormProps> = ({ closeWorkspace }) => {
|
|
|
105
105
|
render={({ field }) => (
|
|
106
106
|
<Dropdown
|
|
107
107
|
ref={field.ref}
|
|
108
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
108
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
109
109
|
invalidText={form.formState.errors[field.name]?.message}
|
|
110
110
|
id="peerEducator"
|
|
111
111
|
titleText={t('peerEducator', 'Peer Educator')}
|
|
@@ -132,16 +132,16 @@ const PeerForm: React.FC<PeerFormProps> = ({ closeWorkspace }) => {
|
|
|
132
132
|
value={field.value}
|
|
133
133
|
onChange={field.onChange}
|
|
134
134
|
dateFormat="d/m/Y"
|
|
135
|
-
id="startDate"
|
|
136
135
|
datePickerType="single"
|
|
137
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
136
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
138
137
|
invalidText={form.formState.errors[field.name]?.message}>
|
|
139
138
|
<DatePickerInput
|
|
140
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
139
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
141
140
|
invalidText={form.formState.errors[field.name]?.message}
|
|
142
141
|
placeholder="mm/dd/yyyy"
|
|
143
142
|
labelText={t('startDate', 'Start Date')}
|
|
144
|
-
size=
|
|
143
|
+
size="lg"
|
|
144
|
+
id="startDate"
|
|
145
145
|
/>
|
|
146
146
|
</DatePicker>
|
|
147
147
|
)}
|
|
@@ -156,16 +156,16 @@ const PeerForm: React.FC<PeerFormProps> = ({ closeWorkspace }) => {
|
|
|
156
156
|
value={field.value}
|
|
157
157
|
onChange={field.onChange}
|
|
158
158
|
dateFormat="d/m/Y"
|
|
159
|
-
id="endDate"
|
|
160
159
|
datePickerType="single"
|
|
161
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
160
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
162
161
|
invalidText={form.formState.errors[field.name]?.message}>
|
|
163
162
|
<DatePickerInput
|
|
164
|
-
invalid={form.formState.errors[field.name]?.message}
|
|
163
|
+
invalid={!!form.formState.errors[field.name]?.message}
|
|
165
164
|
invalidText={form.formState.errors[field.name]?.message}
|
|
166
165
|
placeholder="mm/dd/yyyy"
|
|
167
166
|
labelText={t('endDate', 'End Date')}
|
|
168
|
-
size="
|
|
167
|
+
size="lg"
|
|
168
|
+
id="endDate"
|
|
169
169
|
/>
|
|
170
170
|
</DatePicker>
|
|
171
171
|
)}
|
|
@@ -173,7 +173,7 @@ const PeerForm: React.FC<PeerFormProps> = ({ closeWorkspace }) => {
|
|
|
173
173
|
</Column>
|
|
174
174
|
</Stack>
|
|
175
175
|
<ButtonSet className={styles.buttonSet}>
|
|
176
|
-
<Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
|
|
176
|
+
<Button className={styles.button} kind="secondary" onClick={() => closeWorkspace()}>
|
|
177
177
|
{t('discard', 'Discard')}
|
|
178
178
|
</Button>
|
|
179
179
|
<Button className={styles.button} kind="primary" type="submit" disabled={form.formState.isSubmitting}>
|
|
@@ -22,6 +22,7 @@ const ReportingPeriodInput: React.FC<ReportingPeriodInputProps> = ({
|
|
|
22
22
|
<Column className={styles.reportingPeriodInput}>Select Period:</Column>
|
|
23
23
|
<Column className={styles.reportingPeriodInput}>
|
|
24
24
|
<Dropdown
|
|
25
|
+
titleText={t('reportingMonth', 'Reporting month')}
|
|
25
26
|
type="inline"
|
|
26
27
|
id="reportingMonth"
|
|
27
28
|
autoAlign={true}
|
|
@@ -36,6 +37,7 @@ const ReportingPeriodInput: React.FC<ReportingPeriodInputProps> = ({
|
|
|
36
37
|
</Column>
|
|
37
38
|
<Column className={styles.reportingPeriodInput}>
|
|
38
39
|
<Dropdown
|
|
40
|
+
titleText={t('reportingYear', 'Reporting year')}
|
|
39
41
|
type="inline"
|
|
40
42
|
autoAlign={true}
|
|
41
43
|
id="reportingYear"
|
|
@@ -45,7 +47,7 @@ const ReportingPeriodInput: React.FC<ReportingPeriodInputProps> = ({
|
|
|
45
47
|
initialSelectedItem={reportigPeriod?.year}
|
|
46
48
|
label={t('reportingYear', 'Year')}
|
|
47
49
|
items={years.map((r) => r)}
|
|
48
|
-
itemToString={(item) => years.find((r) => r === item) ?? ''}
|
|
50
|
+
itemToString={(item) => years.find((r) => r === item).toString() ?? ''}
|
|
49
51
|
/>
|
|
50
52
|
</Column>
|
|
51
53
|
</div>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Button, Layer, Row, SkeletonPlaceholder } from '@carbon/react';
|
|
2
2
|
import { Add } from '@carbon/react/icons';
|
|
3
|
-
import { useSession } from '@openmrs/esm-framework';
|
|
4
|
-
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
3
|
+
import { launchWorkspace, useSession } from '@openmrs/esm-framework';
|
|
5
4
|
import React from 'react';
|
|
6
5
|
import { useTranslation } from 'react-i18next';
|
|
7
6
|
import type { Peer, ReportingPeriod } from '../../types';
|
|
@@ -31,7 +30,7 @@ const PeerCalendarMetricsHeader: React.FC<PeerCalendarMetricsHeaderProps> = ({
|
|
|
31
30
|
|
|
32
31
|
const { t } = useTranslation();
|
|
33
32
|
const handleAddPeer = () => {
|
|
34
|
-
|
|
33
|
+
launchWorkspace('peers-form', {});
|
|
35
34
|
};
|
|
36
35
|
|
|
37
36
|
if (isLoading) {
|
|
@@ -19,6 +19,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
19
19
|
|
|
20
20
|
type GenericDataTableProps = {
|
|
21
21
|
headers: Array<{ key: string; header: string }>;
|
|
22
|
+
// TODO : Map row to correct carbon data-table row type
|
|
22
23
|
rows: Array<Record<string, any>>;
|
|
23
24
|
title: string;
|
|
24
25
|
renderActionComponent?: () => ReactNode;
|
|
@@ -31,7 +32,7 @@ const GenericDataTable: React.FC<GenericDataTableProps> = ({ headers, rows, titl
|
|
|
31
32
|
return (
|
|
32
33
|
<div className={styles.widgetContainer}>
|
|
33
34
|
<CardHeader title={title}>{renderActionComponent?.()}</CardHeader>
|
|
34
|
-
<DataTable useZebraStyles size="sm" rows={rows} headers={headers}>
|
|
35
|
+
<DataTable useZebraStyles size="sm" rows={rows as any} headers={headers}>
|
|
35
36
|
{({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => (
|
|
36
37
|
<Table {...getTableProps()}>
|
|
37
38
|
<TableHead>
|
|
@@ -2,9 +2,11 @@ import { Dropdown } from '@carbon/react';
|
|
|
2
2
|
import React, { useMemo, useState } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
|
|
5
|
+
type FilterStatus = 'completed' | 'pending' | 'all';
|
|
6
|
+
|
|
5
7
|
type PeerCalendarTableFilterProps = {
|
|
6
8
|
filterStatus?: 'completed' | 'pending' | 'all';
|
|
7
|
-
onUpdateFilterStatus: (status:
|
|
9
|
+
onUpdateFilterStatus: (status: FilterStatus) => void;
|
|
8
10
|
};
|
|
9
11
|
|
|
10
12
|
const PeerCalendarTableFilter: React.FC<PeerCalendarTableFilterProps> = ({
|
|
@@ -13,13 +15,14 @@ const PeerCalendarTableFilter: React.FC<PeerCalendarTableFilterProps> = ({
|
|
|
13
15
|
}) => {
|
|
14
16
|
const { t } = useTranslation();
|
|
15
17
|
const statuses = useMemo(() => ['completed', 'pending', 'all'], []);
|
|
16
|
-
const [_state,
|
|
18
|
+
const [_state, setSate] = useState<'completed' | 'pending' | 'all'>('completed');
|
|
17
19
|
return (
|
|
18
20
|
<div style={{ width: '200px' }}>
|
|
19
21
|
<Dropdown
|
|
22
|
+
titleText={t('filterByStatue', 'Filter by status')}
|
|
20
23
|
id="filterByStatus"
|
|
21
24
|
onChange={(e) => {
|
|
22
|
-
onUpdateFilterStatus(e.selectedItem);
|
|
25
|
+
onUpdateFilterStatus(e.selectedItem as FilterStatus);
|
|
23
26
|
}}
|
|
24
27
|
selectedItem={filterStatus}
|
|
25
28
|
label={t('filterByStatus', 'Filter by status')}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Column, Dropdown, RadioButton, RadioButtonGroup, SelectSkeleton } from '@carbon/react';
|
|
2
2
|
import { useConfig } from '@openmrs/esm-framework';
|
|
3
|
-
import React, { useEffect, useMemo } from 'react';
|
|
3
|
+
import React, { FC, useEffect, useMemo } from 'react';
|
|
4
4
|
import { Controller, useFormContext } from 'react-hook-form';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { z } from 'zod';
|
|
@@ -11,45 +11,40 @@ import {
|
|
|
11
11
|
getHivStatusBasedOnEnrollmentAndHTSEncounters,
|
|
12
12
|
} from '../../contact-list/contact-list.resource';
|
|
13
13
|
import usePersonAttributes from '../../hooks/usePersonAttributes';
|
|
14
|
-
import
|
|
14
|
+
import useRelativeHivEnrollment from '../../hooks/useRelativeHivEnrollment';
|
|
15
|
+
import useRelativeHTSEncounter from '../../hooks/useRelativeHTSEncounter';
|
|
16
|
+
import {
|
|
17
|
+
BOOLEAN_NO,
|
|
18
|
+
BOOLEAN_YES,
|
|
19
|
+
HIV_EXPOSED_INFANT,
|
|
20
|
+
INFANT_AGE_THRESHOLD_IN_MONTHS,
|
|
21
|
+
relationshipFormSchema,
|
|
22
|
+
} from '../relationship.resources';
|
|
15
23
|
import {
|
|
16
24
|
LIVING_WITH_PATIENT_CONCEPT_UUID,
|
|
17
25
|
PARTNER_HIV_STATUS_CONCEPT_UUID,
|
|
18
26
|
PNS_APROACH_CONCEPT_UUID,
|
|
19
27
|
} from '../relationships-constants';
|
|
20
28
|
import styles from './form.scss';
|
|
21
|
-
import useRelativeHivEnrollment from '../../hooks/useRelativeHivEnrollment';
|
|
22
|
-
import useRelativeHTSEncounter from '../../hooks/useRelativeHTSEncounter';
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
type RelationshipBaselineInfoFormSectionProps = {
|
|
31
|
+
patientAgeMonths?: number;
|
|
32
|
+
patientUuid?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const RelationshipBaselineInfoFormSection: FC<RelationshipBaselineInfoFormSectionProps> = ({
|
|
36
|
+
patientAgeMonths = null,
|
|
37
|
+
patientUuid,
|
|
38
|
+
}) => {
|
|
25
39
|
const form = useFormContext<z.infer<typeof relationshipFormSchema>>();
|
|
26
|
-
const {
|
|
27
|
-
|
|
28
|
-
isLoading: enrollmentLoading,
|
|
29
|
-
error: enrollmentError,
|
|
30
|
-
} = useRelativeHivEnrollment(form.watch('personB'));
|
|
31
|
-
const {
|
|
32
|
-
encounters,
|
|
33
|
-
isLoading: encounterLoading,
|
|
34
|
-
error: encounterError,
|
|
35
|
-
} = useRelativeHTSEncounter(form.watch('personB'));
|
|
40
|
+
const { enrollment, isLoading: enrollmentLoading, error: enrollmentError } = useRelativeHivEnrollment(patientUuid);
|
|
41
|
+
const { encounters, isLoading: encounterLoading, error: encounterError } = useRelativeHTSEncounter(patientUuid);
|
|
36
42
|
const hivStatusPersonB = getHivStatusBasedOnEnrollmentAndHTSEncounters(encounters, enrollment);
|
|
37
43
|
|
|
38
44
|
const { t } = useTranslation();
|
|
39
|
-
const personUuid = form.watch('personB');
|
|
40
45
|
const config = useConfig<ConfigObject>();
|
|
41
46
|
const { setValue } = form;
|
|
42
|
-
const { attributes, isLoading } = usePersonAttributes(
|
|
43
|
-
|
|
44
|
-
const hivStatus = useMemo(
|
|
45
|
-
() =>
|
|
46
|
-
Object.entries(contactListConceptMap[PARTNER_HIV_STATUS_CONCEPT_UUID].answers).map(([uuid, display]) => ({
|
|
47
|
-
label: display,
|
|
48
|
-
value: uuid,
|
|
49
|
-
})),
|
|
50
|
-
[],
|
|
51
|
-
);
|
|
52
|
-
|
|
47
|
+
const { attributes, isLoading } = usePersonAttributes(patientUuid);
|
|
53
48
|
const pnsAproach = useMemo(
|
|
54
49
|
() =>
|
|
55
50
|
Object.entries(contactListConceptMap[PNS_APROACH_CONCEPT_UUID].answers).map(([uuid, display]) => ({
|
|
@@ -77,6 +72,26 @@ const RelationshipBaselineInfoFormSection = () => {
|
|
|
77
72
|
(r) => r.uuid === observableRelationship && r.category.some((c) => c === 'sexual'),
|
|
78
73
|
) !== -1;
|
|
79
74
|
|
|
75
|
+
const hivStatus = useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
Object.entries(contactListConceptMap[PARTNER_HIV_STATUS_CONCEPT_UUID].answers).reduce((prev, [uuid, display]) => {
|
|
78
|
+
if (
|
|
79
|
+
display === HIV_EXPOSED_INFANT &&
|
|
80
|
+
(patientAgeMonths === null || patientAgeMonths > INFANT_AGE_THRESHOLD_IN_MONTHS)
|
|
81
|
+
) {
|
|
82
|
+
return prev;
|
|
83
|
+
}
|
|
84
|
+
return [
|
|
85
|
+
...prev,
|
|
86
|
+
{
|
|
87
|
+
label: display,
|
|
88
|
+
value: uuid,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}, []),
|
|
92
|
+
[patientAgeMonths],
|
|
93
|
+
);
|
|
94
|
+
|
|
80
95
|
useEffect(() => {
|
|
81
96
|
if ([observablePhysicalAssault, observableThreatened, observableSexualAssault].includes(BOOLEAN_YES)) {
|
|
82
97
|
form.setValue('ipvOutCome', 'True');
|
|
@@ -196,7 +211,7 @@ const RelationshipBaselineInfoFormSection = () => {
|
|
|
196
211
|
'1. Has he/she ever hit, kicked, slapped, or otherwise physically hurt you?',
|
|
197
212
|
)}
|
|
198
213
|
{...field}
|
|
199
|
-
invalid={error?.message}
|
|
214
|
+
invalid={!!error?.message}
|
|
200
215
|
invalidText={error?.message}
|
|
201
216
|
className={styles.billingItem}>
|
|
202
217
|
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="physicalAssault_yes" />
|
|
@@ -214,7 +229,7 @@ const RelationshipBaselineInfoFormSection = () => {
|
|
|
214
229
|
id="threatened"
|
|
215
230
|
legendText={t('threatened', '2. Has he/she ever threatened to hurt you?')}
|
|
216
231
|
{...field}
|
|
217
|
-
invalid={error?.message}
|
|
232
|
+
invalid={!!error?.message}
|
|
218
233
|
invalidText={error?.message}
|
|
219
234
|
className={styles.billingItem}>
|
|
220
235
|
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="threatened_yes" />
|
|
@@ -235,7 +250,7 @@ const RelationshipBaselineInfoFormSection = () => {
|
|
|
235
250
|
'3.Has he/she ever forced you to do something sexually that made you feel uncomfortable?',
|
|
236
251
|
)}
|
|
237
252
|
{...field}
|
|
238
|
-
invalid={error?.message}
|
|
253
|
+
invalid={!!error?.message}
|
|
239
254
|
invalidText={error?.message}
|
|
240
255
|
className={styles.billingItem}>
|
|
241
256
|
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="sexualAssault_yes" />
|
|
@@ -256,7 +271,7 @@ const RelationshipBaselineInfoFormSection = () => {
|
|
|
256
271
|
) : (
|
|
257
272
|
<Dropdown
|
|
258
273
|
ref={field.ref}
|
|
259
|
-
invalid={error?.message}
|
|
274
|
+
invalid={!!error?.message}
|
|
260
275
|
invalidText={error?.message}
|
|
261
276
|
id="ipvOutCome"
|
|
262
277
|
titleText={t('ipvOutCome', 'IPV Outcome')}
|
|
@@ -74,6 +74,7 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
74
74
|
name="mode"
|
|
75
75
|
render={({ field }) => (
|
|
76
76
|
<ContentSwitcher
|
|
77
|
+
size="md"
|
|
77
78
|
selectedIndex={field.value == 'search' ? 0 : 1}
|
|
78
79
|
onChange={(value) => {
|
|
79
80
|
let { index, name, text } = value;
|
|
@@ -128,7 +129,8 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
128
129
|
name="personBInfo.givenName"
|
|
129
130
|
render={({ field, fieldState: { error } }) => (
|
|
130
131
|
<TextInput
|
|
131
|
-
|
|
132
|
+
id={field.name}
|
|
133
|
+
invalid={!!error?.message}
|
|
132
134
|
invalidText={error?.message}
|
|
133
135
|
{...field}
|
|
134
136
|
placeholder="First name"
|
|
@@ -143,7 +145,8 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
143
145
|
name="personBInfo.middleName"
|
|
144
146
|
render={({ field, fieldState: { error } }) => (
|
|
145
147
|
<TextInput
|
|
146
|
-
|
|
148
|
+
id={field.name}
|
|
149
|
+
invalid={!!error?.message}
|
|
147
150
|
invalidText={error?.message}
|
|
148
151
|
{...field}
|
|
149
152
|
placeholder="Middle name"
|
|
@@ -158,7 +161,8 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
158
161
|
name="personBInfo.familyName"
|
|
159
162
|
render={({ field, fieldState: { error } }) => (
|
|
160
163
|
<TextInput
|
|
161
|
-
|
|
164
|
+
id={field.name}
|
|
165
|
+
invalid={!!error?.message}
|
|
162
166
|
invalidText={error?.message}
|
|
163
167
|
{...field}
|
|
164
168
|
placeholder="Last name"
|
|
@@ -172,17 +176,15 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
172
176
|
control={form.control}
|
|
173
177
|
name="personBInfo.gender"
|
|
174
178
|
render={({ field, fieldState: { error } }) => (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
</RadioButtonGroup>
|
|
185
|
-
</>
|
|
179
|
+
<RadioButtonGroup
|
|
180
|
+
name="personBInfo.gender"
|
|
181
|
+
legendText={t('sex', 'Sex')}
|
|
182
|
+
{...field}
|
|
183
|
+
invalid={!!error?.message}
|
|
184
|
+
invalidText={error?.message}>
|
|
185
|
+
<RadioButton labelText={t('male', 'Male')} value="M" id="M" />
|
|
186
|
+
<RadioButton labelText={t('female', 'Female')} value="F" id="F" />
|
|
187
|
+
</RadioButtonGroup>
|
|
186
188
|
)}
|
|
187
189
|
/>
|
|
188
190
|
</Column>
|
|
@@ -194,15 +196,16 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
194
196
|
<DatePicker
|
|
195
197
|
datePickerType="single"
|
|
196
198
|
{...field}
|
|
197
|
-
invalid={error?.message}
|
|
199
|
+
invalid={!!error?.message}
|
|
198
200
|
invalidText={error?.message}
|
|
199
201
|
className={styles.datePickerInput}>
|
|
200
202
|
<DatePickerInput
|
|
201
|
-
|
|
203
|
+
id={field.name}
|
|
204
|
+
invalid={!!error?.message}
|
|
202
205
|
invalidText={error?.message}
|
|
203
206
|
placeholder="mm/dd/yyyy"
|
|
204
207
|
labelText={t('dateOfBirth', 'Date of birth')}
|
|
205
|
-
size="
|
|
208
|
+
size="lg"
|
|
206
209
|
/>
|
|
207
210
|
</DatePicker>
|
|
208
211
|
)}
|
|
@@ -219,7 +222,7 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
219
222
|
render={({ field, fieldState: { error } }) => (
|
|
220
223
|
<Dropdown
|
|
221
224
|
ref={field.ref}
|
|
222
|
-
invalid={error?.message}
|
|
225
|
+
invalid={!!error?.message}
|
|
223
226
|
invalidText={error?.message}
|
|
224
227
|
id="maritalStatus"
|
|
225
228
|
titleText={t('maritalStatus', 'Marital status')}
|
|
@@ -242,7 +245,8 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
242
245
|
name="personBInfo.address"
|
|
243
246
|
render={({ field, fieldState: { error } }) => (
|
|
244
247
|
<TextInput
|
|
245
|
-
|
|
248
|
+
id={field.name}
|
|
249
|
+
invalid={!!error?.message}
|
|
246
250
|
invalidText={error?.message}
|
|
247
251
|
{...field}
|
|
248
252
|
placeholder="Physical Address/Landmark"
|
|
@@ -258,7 +262,8 @@ const PatientSearchCreate: React.FC<PatientSearchCreateProps> = () => {
|
|
|
258
262
|
render={({ field, fieldState: { error } }) => (
|
|
259
263
|
<TextInput
|
|
260
264
|
{...field}
|
|
261
|
-
|
|
265
|
+
id={field.name}
|
|
266
|
+
invalid={!!error?.message}
|
|
262
267
|
invalidText={error?.message}
|
|
263
268
|
placeholder="Phone number"
|
|
264
269
|
labelText={t('phoneNumber', 'Phone number')}
|
|
@@ -46,12 +46,13 @@ const BirthDateCalculator = ({ onClose, props: { date, onBirthDateChange } }) =>
|
|
|
46
46
|
<Column>
|
|
47
47
|
<Layer>
|
|
48
48
|
<TextInput
|
|
49
|
+
id="age"
|
|
49
50
|
placeholder="age"
|
|
50
51
|
labelText={t('age', 'Age')}
|
|
51
52
|
type="number"
|
|
52
53
|
min={5}
|
|
53
54
|
value={formState.age}
|
|
54
|
-
onChange={(e) => setFormState({ ...formState, age: e.target.value })}
|
|
55
|
+
onChange={(e) => setFormState({ ...formState, age: parseInt(e.target.value) })}
|
|
55
56
|
/>
|
|
56
57
|
</Layer>
|
|
57
58
|
</Column>
|
|
@@ -61,7 +62,7 @@ const BirthDateCalculator = ({ onClose, props: { date, onBirthDateChange } }) =>
|
|
|
61
62
|
datePickerType="single"
|
|
62
63
|
value={formState.fromDate}
|
|
63
64
|
onChange={([date]) => setFormState({ ...formState, fromDate: date })}>
|
|
64
|
-
<DatePickerInput placeholder="mm/dd/yyyy" labelText={t('onDate', 'On Date')} size="
|
|
65
|
+
<DatePickerInput id="onDate" placeholder="mm/dd/yyyy" labelText={t('onDate', 'On Date')} size="lg" />
|
|
65
66
|
</DatePicker>
|
|
66
67
|
</Layer>
|
|
67
68
|
</Column>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { openmrsFetch, restBaseUrl, Session, showModal, showSnackbar } from '@openmrs/esm-framework';
|
|
2
|
-
import { mutate } from 'swr';
|
|
1
|
+
import { FetchResponse, openmrsFetch, restBaseUrl, Session, showModal, showSnackbar } from '@openmrs/esm-framework';
|
|
2
|
+
import useSWR, { mutate } from 'swr';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { Patient } from '../types';
|
|
5
5
|
import { ConfigObject } from '../config-schema';
|
|
@@ -7,6 +7,8 @@ import omit from 'lodash/omit';
|
|
|
7
7
|
|
|
8
8
|
export const BOOLEAN_YES = '1065';
|
|
9
9
|
export const BOOLEAN_NO = '1066';
|
|
10
|
+
export const HIV_EXPOSED_INFANT = 'HIV exposed infant';
|
|
11
|
+
export const INFANT_AGE_THRESHOLD_IN_MONTHS = 24;
|
|
10
12
|
|
|
11
13
|
export const relationshipUpdateFormSchema = z
|
|
12
14
|
.object({
|
|
@@ -230,3 +232,17 @@ export const saveRelationship = async (
|
|
|
230
232
|
throw error;
|
|
231
233
|
}
|
|
232
234
|
};
|
|
235
|
+
|
|
236
|
+
export const usePatientBirthdate = (patientUuid?: string) => {
|
|
237
|
+
const customRep = 'custom:(person:(birthdate))';
|
|
238
|
+
const url = `${restBaseUrl}/patient/${patientUuid}?v=${customRep}`;
|
|
239
|
+
const { data, error, isLoading } = useSWR<FetchResponse<{ person: { birthdate: string } }>>(
|
|
240
|
+
patientUuid ? url : null,
|
|
241
|
+
openmrsFetch,
|
|
242
|
+
);
|
|
243
|
+
return {
|
|
244
|
+
isLoading,
|
|
245
|
+
error,
|
|
246
|
+
birthdate: data?.data?.person?.birthdate,
|
|
247
|
+
};
|
|
248
|
+
};
|
|
@@ -12,8 +12,8 @@ interface RelationshipsTabProps {
|
|
|
12
12
|
export const RelationshipsTab: React.FC<RelationshipsTabProps> = ({ patientUuid }) => {
|
|
13
13
|
const { t } = useTranslation();
|
|
14
14
|
return (
|
|
15
|
-
<main>
|
|
16
|
-
<Tabs
|
|
15
|
+
<main className={styles.relationshipTabs}>
|
|
16
|
+
<Tabs>
|
|
17
17
|
<TabList className={styles.relationshipTablist} aria-label="List tabs" contained>
|
|
18
18
|
<Tab className={styles.relationshipTab}>{t('family', 'Family')}</Tab>
|
|
19
19
|
<Tab className={styles.relationshipTab}>{t('pnsContacts', 'PNS Contacts')}</Tab>
|
package/src/root.scss
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
@use '@carbon/styles/scss/spacing';
|
|
2
2
|
@use '@carbon/styles/scss/type';
|
|
3
|
-
@
|
|
3
|
+
@use '~@openmrs/esm-styleguide/src/vars' as *;
|
|
4
4
|
|
|
5
5
|
$ui-01: #f4f4f4;
|
|
6
6
|
$ui-02: #ffffff;
|
|
7
7
|
$ui-03: #e0e0e0;
|
|
8
8
|
$ui-05: #161616;
|
|
9
|
-
$ui-background: #ffffff;
|
|
10
9
|
$color-gray-70: #525252;
|
|
11
10
|
$color-blue-60-2: #0f62fe;
|
|
12
11
|
$color-yellow-50: #feecae;
|