@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
|
@@ -94,7 +94,7 @@ const ContactTracingHistory: React.FC<ContactTracingHistoryProps> = ({ patientUu
|
|
|
94
94
|
/>
|
|
95
95
|
),
|
|
96
96
|
})),
|
|
97
|
-
[results],
|
|
97
|
+
[results, t],
|
|
98
98
|
);
|
|
99
99
|
|
|
100
100
|
if (contactTracesHistory.length === 0) {
|
|
@@ -121,9 +121,9 @@ const ContactTracingHistory: React.FC<ContactTracingHistoryProps> = ({ patientUu
|
|
|
121
121
|
<TableHeader
|
|
122
122
|
{...getHeaderProps({
|
|
123
123
|
header,
|
|
124
|
-
isSortable:
|
|
124
|
+
isSortable: true,
|
|
125
125
|
})}>
|
|
126
|
-
{header.header
|
|
126
|
+
{header.header}
|
|
127
127
|
</TableHeader>
|
|
128
128
|
))}
|
|
129
129
|
</TableRow>
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
RadioButton,
|
|
14
14
|
} from '@carbon/react';
|
|
15
15
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
16
|
-
import { DefaultWorkspaceProps, restBaseUrl, showSnackbar, useConfig } from '@openmrs/esm-framework';
|
|
16
|
+
import { DefaultWorkspaceProps, parseDate, restBaseUrl, showSnackbar, useConfig } from '@openmrs/esm-framework';
|
|
17
17
|
import React, { useEffect, useMemo } from 'react';
|
|
18
18
|
import { Controller, FormProvider, useForm } from 'react-hook-form';
|
|
19
19
|
import { useTranslation } from 'react-i18next';
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
relationshipFormSchema,
|
|
31
31
|
relationshipUpdateFormSchema,
|
|
32
32
|
updateRelationship,
|
|
33
|
+
usePatientBirthdate,
|
|
33
34
|
} from '../../relationships/relationship.resources';
|
|
34
35
|
import { type Contact } from '../../types';
|
|
35
36
|
import { ConfigObject } from '../../config-schema';
|
|
@@ -39,6 +40,8 @@ import {
|
|
|
39
40
|
PARTNER_HIV_STATUS_CONCEPT_UUID,
|
|
40
41
|
PNS_APROACH_CONCEPT_UUID,
|
|
41
42
|
} from '../../relationships/relationships-constants';
|
|
43
|
+
import dayjs from 'dayjs';
|
|
44
|
+
import RelationshipBaselineInfoFormSection from '../../relationships/forms/baseline-info-form-section.component';
|
|
42
45
|
|
|
43
46
|
interface ContactListUpdateFormProps extends DefaultWorkspaceProps {
|
|
44
47
|
relation: Contact;
|
|
@@ -56,15 +59,6 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
56
59
|
|
|
57
60
|
const { t } = useTranslation();
|
|
58
61
|
|
|
59
|
-
const hivStatus = useMemo(
|
|
60
|
-
() =>
|
|
61
|
-
Object.entries(contactListConceptMap[PARTNER_HIV_STATUS_CONCEPT_UUID].answers).map(([uuid, display]) => ({
|
|
62
|
-
label: display,
|
|
63
|
-
value: uuid,
|
|
64
|
-
})),
|
|
65
|
-
[],
|
|
66
|
-
);
|
|
67
|
-
|
|
68
62
|
const pnsAproach = useMemo(
|
|
69
63
|
() =>
|
|
70
64
|
Object.entries(contactListConceptMap[PNS_APROACH_CONCEPT_UUID].answers).map(([uuid, display]) => ({
|
|
@@ -84,32 +78,19 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
84
78
|
);
|
|
85
79
|
|
|
86
80
|
const form = useForm<ContactListUpdateFormType>({
|
|
87
|
-
defaultValues: {
|
|
88
|
-
endDate: undefined,
|
|
89
|
-
startDate: undefined,
|
|
90
|
-
relationshipType: undefined,
|
|
91
|
-
baselineStatus: undefined,
|
|
92
|
-
preferedPNSAproach: undefined,
|
|
93
|
-
livingWithClient: undefined,
|
|
94
|
-
ipvOutCome: undefined,
|
|
95
|
-
physicalAssault: undefined,
|
|
96
|
-
threatened: undefined,
|
|
97
|
-
sexualAssault: undefined,
|
|
98
|
-
},
|
|
81
|
+
defaultValues: {},
|
|
99
82
|
resolver: zodResolver(relationshipUpdateFormSchema),
|
|
100
83
|
});
|
|
101
84
|
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
85
|
+
const { isLoading: isPatientloading, birthdate } = usePatientBirthdate(relationship?.personB?.uuid);
|
|
86
|
+
|
|
87
|
+
const patientAgeMonths = useMemo(() => {
|
|
88
|
+
let birthDate = birthdate ? parseDate(birthdate) : null;
|
|
89
|
+
if (birthDate) {
|
|
90
|
+
return dayjs().diff(birthDate, 'month');
|
|
106
91
|
}
|
|
107
|
-
return
|
|
108
|
-
|
|
109
|
-
(r) => r.uuid === observableRelationship && r.category.some((c) => c === 'sexual'),
|
|
110
|
-
) !== -1
|
|
111
|
-
);
|
|
112
|
-
}, [observableRelationship, config.relationshipTypesList]);
|
|
92
|
+
return null;
|
|
93
|
+
}, [birthdate]);
|
|
113
94
|
|
|
114
95
|
useEffect(() => {
|
|
115
96
|
if (relationship && relationshipTypes.length > 0) {
|
|
@@ -126,55 +107,7 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
126
107
|
}, [relationship, relationshipTypes, form]);
|
|
127
108
|
|
|
128
109
|
useEffect(() => {
|
|
129
|
-
if (relation
|
|
130
|
-
if (relation.baselineHIVStatus) {
|
|
131
|
-
const hivStatusValue = hivStatus.find(
|
|
132
|
-
(status) =>
|
|
133
|
-
typeof status.label === 'string' &&
|
|
134
|
-
status.label.toLowerCase().includes(relation.baselineHIVStatus.toLowerCase()),
|
|
135
|
-
)?.value;
|
|
136
|
-
if (hivStatusValue) {
|
|
137
|
-
form.setValue('baselineStatus', hivStatusValue);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (relation.pnsAproach) {
|
|
142
|
-
const pnsValue = pnsAproach.find((approach) =>
|
|
143
|
-
(approach.label as string).toLowerCase().includes((relation.pnsAproach as string).toLowerCase()),
|
|
144
|
-
)?.value;
|
|
145
|
-
if (pnsValue) {
|
|
146
|
-
form.setValue('preferedPNSAproach', pnsValue);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (relation.livingWithClient) {
|
|
151
|
-
const livingValue = contactLivingWithPatient.find((living) => {
|
|
152
|
-
const relationLiving = (relation.livingWithClient as string).toLowerCase();
|
|
153
|
-
const livingLabel = (living.label as string).toLowerCase();
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
livingLabel === relationLiving ||
|
|
157
|
-
livingLabel.includes(relationLiving) ||
|
|
158
|
-
relationLiving.includes(livingLabel)
|
|
159
|
-
);
|
|
160
|
-
})?.value;
|
|
161
|
-
|
|
162
|
-
if (livingValue) {
|
|
163
|
-
form.setValue('livingWithClient', livingValue);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (relation.ipvOutcome) {
|
|
168
|
-
const ipvValue = contactIPVOutcomeOptions.find(
|
|
169
|
-
(outcome) =>
|
|
170
|
-
outcome.value === relation.ipvOutcome ||
|
|
171
|
-
outcome.label.toLowerCase().includes(relation.ipvOutcome.toLowerCase()),
|
|
172
|
-
)?.value;
|
|
173
|
-
if (ipvValue) {
|
|
174
|
-
form.setValue('ipvOutCome', ipvValue as any);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
110
|
+
if (relation) {
|
|
178
111
|
if (relation.startDate) {
|
|
179
112
|
try {
|
|
180
113
|
const startDate = new Date(relation.startDate);
|
|
@@ -203,24 +136,7 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
203
136
|
}
|
|
204
137
|
}
|
|
205
138
|
}
|
|
206
|
-
}, [relation,
|
|
207
|
-
|
|
208
|
-
const observablePhysicalAssault = form.watch('physicalAssault');
|
|
209
|
-
const observableThreatened = form.watch('threatened');
|
|
210
|
-
const observableSexualAssault = form.watch('sexualAssault');
|
|
211
|
-
|
|
212
|
-
useEffect(() => {
|
|
213
|
-
if ([observablePhysicalAssault, observableThreatened, observableSexualAssault].includes(BOOLEAN_YES)) {
|
|
214
|
-
form.setValue('ipvOutCome', 'True');
|
|
215
|
-
} else if (
|
|
216
|
-
[observablePhysicalAssault, observableThreatened, observableSexualAssault].every((v) => v === BOOLEAN_NO)
|
|
217
|
-
) {
|
|
218
|
-
form.setValue('ipvOutCome', 'False');
|
|
219
|
-
}
|
|
220
|
-
if (!showIPVRelatedFields) {
|
|
221
|
-
form.setValue('ipvOutCome', undefined);
|
|
222
|
-
}
|
|
223
|
-
}, [observablePhysicalAssault, observableThreatened, observableSexualAssault, showIPVRelatedFields, form]);
|
|
139
|
+
}, [relation, relationshipTypes, form]);
|
|
224
140
|
|
|
225
141
|
const onSubmit = async (values: ContactListUpdateFormType) => {
|
|
226
142
|
try {
|
|
@@ -304,7 +220,6 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
304
220
|
<DatePicker
|
|
305
221
|
className={styles.datePickerInput}
|
|
306
222
|
dateFormat="d/m/Y"
|
|
307
|
-
id="startDate"
|
|
308
223
|
datePickerType="single"
|
|
309
224
|
{...field}
|
|
310
225
|
ref={undefined}
|
|
@@ -312,12 +227,11 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
312
227
|
invalidText={error?.message}>
|
|
313
228
|
<DatePickerInput
|
|
314
229
|
id={`startdate-input`}
|
|
315
|
-
name="startdate-input"
|
|
316
230
|
invalid={!!error?.message}
|
|
317
231
|
invalidText={error?.message}
|
|
318
232
|
placeholder="mm/dd/yyyy"
|
|
319
233
|
labelText={t('startDate', 'Start Date')}
|
|
320
|
-
size="
|
|
234
|
+
size="lg"
|
|
321
235
|
/>
|
|
322
236
|
</DatePicker>
|
|
323
237
|
)}
|
|
@@ -332,7 +246,6 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
332
246
|
<DatePicker
|
|
333
247
|
className={styles.datePickerInput}
|
|
334
248
|
dateFormat="d/m/Y"
|
|
335
|
-
id="endDate"
|
|
336
249
|
datePickerType="single"
|
|
337
250
|
{...field}
|
|
338
251
|
ref={undefined}
|
|
@@ -340,12 +253,11 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
340
253
|
invalidText={error?.message}>
|
|
341
254
|
<DatePickerInput
|
|
342
255
|
id="enddate-input"
|
|
343
|
-
name="enddate-input"
|
|
344
256
|
invalid={!!error?.message}
|
|
345
257
|
invalidText={error?.message}
|
|
346
258
|
placeholder="mm/dd/yyyy"
|
|
347
259
|
labelText={t('endDate', 'End Date')}
|
|
348
|
-
size="
|
|
260
|
+
size="lg"
|
|
349
261
|
/>
|
|
350
262
|
</DatePicker>
|
|
351
263
|
)}
|
|
@@ -369,173 +281,16 @@ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWork
|
|
|
369
281
|
selectedItem={field.value}
|
|
370
282
|
label="Select Relationship"
|
|
371
283
|
items={relationshipTypes.map((r) => r.uuid)}
|
|
372
|
-
itemToString={(item) => relationshipTypes.find((r) => r.uuid === item)?.displayBIsToA
|
|
284
|
+
itemToString={(item) => relationshipTypes.find((r) => r.uuid === item)?.displayBIsToA.toString()}
|
|
373
285
|
/>
|
|
374
286
|
)}
|
|
375
287
|
/>
|
|
376
288
|
</Column>
|
|
377
289
|
|
|
378
|
-
<
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
render={({ field, fieldState: { error } }) => (
|
|
383
|
-
<Dropdown
|
|
384
|
-
ref={field.ref}
|
|
385
|
-
invalid={!!error?.message}
|
|
386
|
-
invalidText={error?.message}
|
|
387
|
-
id="livingWithClient"
|
|
388
|
-
titleText={t('livingWithClient', 'Living with client')}
|
|
389
|
-
onChange={(e: { selectedItem: string }) => {
|
|
390
|
-
field.onChange(e.selectedItem);
|
|
391
|
-
}}
|
|
392
|
-
selectedItem={field.value}
|
|
393
|
-
label="Select"
|
|
394
|
-
items={contactLivingWithPatient.map((r) => r.value)}
|
|
395
|
-
itemToString={(item: string) => contactLivingWithPatient.find((r) => r.value === item)?.label ?? ''}
|
|
396
|
-
/>
|
|
397
|
-
)}
|
|
398
|
-
/>
|
|
399
|
-
</Column>
|
|
400
|
-
|
|
401
|
-
{showIPVRelatedFields && (
|
|
402
|
-
<>
|
|
403
|
-
<span className={styles.sectionHeader}>{t('ipvQuestions', 'IPV Questions')}</span>
|
|
404
|
-
<Column>
|
|
405
|
-
<Controller
|
|
406
|
-
control={form.control}
|
|
407
|
-
name="physicalAssault"
|
|
408
|
-
render={({ field, fieldState: { error } }) => (
|
|
409
|
-
<RadioButtonGroup
|
|
410
|
-
id="physicalAssault"
|
|
411
|
-
legendText={t(
|
|
412
|
-
'physicalAssault',
|
|
413
|
-
'1. Has he/she ever hit, kicked, slapped, or otherwise physically hurt you?',
|
|
414
|
-
)}
|
|
415
|
-
{...field}
|
|
416
|
-
invalid={!!error?.message}
|
|
417
|
-
invalidText={error?.message}
|
|
418
|
-
className={styles.billingItem}>
|
|
419
|
-
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="physicalAssault_yes" />
|
|
420
|
-
<RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="physicalAssault_no" />
|
|
421
|
-
</RadioButtonGroup>
|
|
422
|
-
)}
|
|
423
|
-
/>
|
|
424
|
-
</Column>
|
|
425
|
-
<Column>
|
|
426
|
-
<Controller
|
|
427
|
-
control={form.control}
|
|
428
|
-
name="threatened"
|
|
429
|
-
render={({ field, fieldState: { error } }) => (
|
|
430
|
-
<RadioButtonGroup
|
|
431
|
-
id="threatened"
|
|
432
|
-
legendText={t('threatened', '2. Has he/she ever threatened to hurt you?')}
|
|
433
|
-
{...field}
|
|
434
|
-
invalid={!!error?.message}
|
|
435
|
-
invalidText={error?.message}
|
|
436
|
-
className={styles.billingItem}>
|
|
437
|
-
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="threatened_yes" />
|
|
438
|
-
<RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="threatened_no" />
|
|
439
|
-
</RadioButtonGroup>
|
|
440
|
-
)}
|
|
441
|
-
/>
|
|
442
|
-
</Column>
|
|
443
|
-
<Column>
|
|
444
|
-
<Controller
|
|
445
|
-
control={form.control}
|
|
446
|
-
name="sexualAssault"
|
|
447
|
-
render={({ field, fieldState: { error } }) => (
|
|
448
|
-
<RadioButtonGroup
|
|
449
|
-
id="sexualAssault"
|
|
450
|
-
legendText={t(
|
|
451
|
-
'sexualAssault',
|
|
452
|
-
'3.Has he/she ever forced you to do something sexually that made you feel uncomfortable?',
|
|
453
|
-
)}
|
|
454
|
-
{...field}
|
|
455
|
-
invalid={!!error?.message}
|
|
456
|
-
invalidText={error?.message}
|
|
457
|
-
className={styles.billingItem}>
|
|
458
|
-
<RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="sexualAssault_yes" />
|
|
459
|
-
<RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="sexualAssault_no" />
|
|
460
|
-
</RadioButtonGroup>
|
|
461
|
-
)}
|
|
462
|
-
/>
|
|
463
|
-
</Column>
|
|
464
|
-
<span className={styles.sectionHeader}>{t('ipvOutcome', 'IPV Outcome')}</span>
|
|
465
|
-
<Column>
|
|
466
|
-
<Controller
|
|
467
|
-
control={form.control}
|
|
468
|
-
name="ipvOutCome"
|
|
469
|
-
render={({ field, fieldState: { error } }) => (
|
|
470
|
-
<Dropdown
|
|
471
|
-
ref={field.ref}
|
|
472
|
-
invalid={!!error?.message}
|
|
473
|
-
invalidText={error?.message}
|
|
474
|
-
id="ipvOutCome"
|
|
475
|
-
titleText={t('ipvOutCome', 'IPV Outcome')}
|
|
476
|
-
onChange={(e) => {
|
|
477
|
-
field.onChange(e.selectedItem);
|
|
478
|
-
}}
|
|
479
|
-
selectedItem={field.value}
|
|
480
|
-
label="Choose option"
|
|
481
|
-
items={contactIPVOutcomeOptions.map((r) => r.value)}
|
|
482
|
-
itemToString={(item) => {
|
|
483
|
-
return contactIPVOutcomeOptions.find((r) => r.value === item)?.label ?? '';
|
|
484
|
-
}}
|
|
485
|
-
/>
|
|
486
|
-
)}
|
|
487
|
-
/>
|
|
488
|
-
</Column>
|
|
489
|
-
</>
|
|
490
|
-
)}
|
|
491
|
-
|
|
492
|
-
<span className={styles.sectionHeader}>{t('baselineInformation', 'Baseline Information')}</span>
|
|
493
|
-
<Column>
|
|
494
|
-
<Controller
|
|
495
|
-
control={form.control}
|
|
496
|
-
name="baselineStatus"
|
|
497
|
-
render={({ field, fieldState: { error } }) => (
|
|
498
|
-
<Dropdown
|
|
499
|
-
ref={field.ref}
|
|
500
|
-
invalid={!!error?.message}
|
|
501
|
-
invalidText={error?.message}
|
|
502
|
-
id="baselineStatus"
|
|
503
|
-
titleText={t('baselineStatus', 'HIV Status')}
|
|
504
|
-
onChange={(e: { selectedItem: string }) => {
|
|
505
|
-
field.onChange(e.selectedItem);
|
|
506
|
-
}}
|
|
507
|
-
selectedItem={field.value}
|
|
508
|
-
label="Select HIV Status"
|
|
509
|
-
items={hivStatus.map((r) => r.value)}
|
|
510
|
-
itemToString={(item: string) => hivStatus.find((r) => r.value === item)?.label ?? ''}
|
|
511
|
-
/>
|
|
512
|
-
)}
|
|
513
|
-
/>
|
|
514
|
-
</Column>
|
|
515
|
-
|
|
516
|
-
<Column>
|
|
517
|
-
<Controller
|
|
518
|
-
control={form.control}
|
|
519
|
-
name="preferedPNSAproach"
|
|
520
|
-
render={({ field, fieldState: { error } }) => (
|
|
521
|
-
<Dropdown
|
|
522
|
-
ref={field.ref}
|
|
523
|
-
invalid={!!error?.message}
|
|
524
|
-
invalidText={error?.message}
|
|
525
|
-
id="preferedPNSAproach"
|
|
526
|
-
titleText={t('preferedPNSAproach', 'Preferred PNS Approach')}
|
|
527
|
-
onChange={(e: { selectedItem: string }) => {
|
|
528
|
-
field.onChange(e.selectedItem);
|
|
529
|
-
}}
|
|
530
|
-
selectedItem={field.value}
|
|
531
|
-
className={styles.preferredPnsApproach}
|
|
532
|
-
label="Select Approach"
|
|
533
|
-
items={pnsAproach.map((r) => r.value)}
|
|
534
|
-
itemToString={(item: string) => pnsAproach.find((r) => r.value === item)?.label ?? ''}
|
|
535
|
-
/>
|
|
536
|
-
)}
|
|
537
|
-
/>
|
|
538
|
-
</Column>
|
|
290
|
+
<RelationshipBaselineInfoFormSection
|
|
291
|
+
patientAgeMonths={patientAgeMonths}
|
|
292
|
+
patientUuid={relationship?.personB?.uuid}
|
|
293
|
+
/>
|
|
539
294
|
</Stack>
|
|
540
295
|
|
|
541
296
|
<ButtonSet className={styles.buttonSet}>
|
|
@@ -19,18 +19,10 @@ const MortuarySummary: React.FC = () => {
|
|
|
19
19
|
const patientUuid = getPatientUuidFromStore();
|
|
20
20
|
const { person, isLoading } = usePerson(patientUuid);
|
|
21
21
|
const { activeVisit, isLoading: isActiveLoading } = useActiveMorgueVisit(patientUuid);
|
|
22
|
-
const startDate = activeVisit?.startDatetime;
|
|
23
|
-
const compartment = activeVisit?.encounters[0]?.location?.display;
|
|
24
22
|
|
|
25
23
|
if (isLoading || isActiveLoading) {
|
|
26
24
|
return (
|
|
27
|
-
<InlineLoading
|
|
28
|
-
status="active"
|
|
29
|
-
iconDescription="Loading"
|
|
30
|
-
Suggested
|
|
31
|
-
change
|
|
32
|
-
description={t('loadData', 'Loading summary data...')}
|
|
33
|
-
/>
|
|
25
|
+
<InlineLoading status="active" iconDescription="Loading" description={t('loadData', 'Loading summary data...')} />
|
|
34
26
|
);
|
|
35
27
|
}
|
|
36
28
|
|
|
@@ -38,7 +30,7 @@ const MortuarySummary: React.FC = () => {
|
|
|
38
30
|
<div className={styles.summaryContainer}>
|
|
39
31
|
<p className={styles.morgueLabel}>{''}</p>
|
|
40
32
|
<ExtensionSlot name="deceased-banner-info-slot" state={{ patientUuid }} />
|
|
41
|
-
<Tabs
|
|
33
|
+
<Tabs>
|
|
42
34
|
<TabList aria-label="morgue summary tabs" className={styles.tablist}>
|
|
43
35
|
<Tab className={styles.tab} id="billing-tab">
|
|
44
36
|
{t('billingHistory', 'Billing history')}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
formatDate,
|
|
5
|
+
isDesktop,
|
|
6
|
+
launchWorkspace,
|
|
7
|
+
parseDate,
|
|
8
|
+
useConfig,
|
|
9
|
+
useLayoutType,
|
|
10
|
+
usePagination,
|
|
11
|
+
} from '@openmrs/esm-framework';
|
|
4
12
|
import {
|
|
5
13
|
CardHeader,
|
|
6
14
|
EmptyState,
|
|
7
15
|
ErrorState,
|
|
8
16
|
getPatientUuidFromStore,
|
|
9
|
-
launchPatientWorkspace,
|
|
10
17
|
usePaginationInfo,
|
|
11
18
|
} from '@openmrs/esm-patient-common-lib';
|
|
12
19
|
import {
|
|
@@ -50,7 +57,7 @@ const AutopsyView: React.FC = () => {
|
|
|
50
57
|
const { pageSizes } = usePaginationInfo(pageSize, encounters?.length, currentPage, results?.length);
|
|
51
58
|
|
|
52
59
|
const handleLaunchAutopsyForm = (encounterUUID = '') => {
|
|
53
|
-
|
|
60
|
+
launchWorkspace('patient-form-entry-workspace', {
|
|
54
61
|
workspaceTitle: t('autopsyReport', 'Autopsy report'),
|
|
55
62
|
mutateForm: () => mutate(),
|
|
56
63
|
formInfo: {
|
|
@@ -110,7 +117,7 @@ const AutopsyView: React.FC = () => {
|
|
|
110
117
|
formName: encounter?.form?.name,
|
|
111
118
|
mortician: encounter?.encounterProviders[0]?.provider?.name,
|
|
112
119
|
action: (
|
|
113
|
-
<OverflowMenu aria-label="overflow-menu" flipped=
|
|
120
|
+
<OverflowMenu aria-label="overflow-menu" flipped={false}>
|
|
114
121
|
<OverflowMenuItem onClick={() => handleLaunchAutopsyForm(encounter.uuid)} itemText={t('edit', 'Edit')} />
|
|
115
122
|
</OverflowMenu>
|
|
116
123
|
),
|
package/src/declarations.d.ts
CHANGED
|
@@ -1,15 +1,2 @@
|
|
|
1
1
|
declare module '*.css';
|
|
2
2
|
declare module '*.scss';
|
|
3
|
-
declare module '@carbon/react';
|
|
4
|
-
declare module 'react-aria' {
|
|
5
|
-
export const I18nProvider: (...args: any) => JSX.Element;
|
|
6
|
-
export { DateValue } from '@react-types/datepicker';
|
|
7
|
-
export const mergeProps: any;
|
|
8
|
-
export const useLocale: any;
|
|
9
|
-
export const useDateField: any;
|
|
10
|
-
export const useDatePicker: any;
|
|
11
|
-
export const useDateSegment: any;
|
|
12
|
-
export const useFocusRing: any;
|
|
13
|
-
export const useHover: any;
|
|
14
|
-
export const useObjectRef: any;
|
|
15
|
-
}
|
|
@@ -221,9 +221,9 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
|
|
|
221
221
|
<TableHeader
|
|
222
222
|
{...getHeaderProps({
|
|
223
223
|
header,
|
|
224
|
-
isSortable:
|
|
224
|
+
isSortable: true,
|
|
225
225
|
})}>
|
|
226
|
-
{header.header
|
|
226
|
+
{header.header}
|
|
227
227
|
</TableHeader>
|
|
228
228
|
))}
|
|
229
229
|
</TableRow>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Button, ButtonSet, Column, ComboBox, DatePicker, DatePickerInput, Form, Stack } from '@carbon/react';
|
|
2
2
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
3
|
-
import { useConfig, useSession } from '@openmrs/esm-framework';
|
|
3
|
+
import { parseDate, useConfig, useSession } from '@openmrs/esm-framework';
|
|
4
4
|
import React, { useMemo } from 'react';
|
|
5
5
|
import { Controller, FormProvider, SubmitHandler, useForm } from 'react-hook-form';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -10,10 +10,11 @@ import { saveContact } from '../contact-list/contact-list.resource';
|
|
|
10
10
|
import usePersonAttributes from '../hooks/usePersonAttributes';
|
|
11
11
|
import RelationshipBaselineInfoFormSection from '../relationships/forms/baseline-info-form-section.component';
|
|
12
12
|
import PatientSearchCreate from '../relationships/forms/patient-search-create-form';
|
|
13
|
-
import { relationshipFormSchema } from '../relationships/relationship.resources';
|
|
13
|
+
import { relationshipFormSchema, usePatientBirthdate } from '../relationships/relationship.resources';
|
|
14
14
|
import { uppercaseText } from '../utils/expression-helper';
|
|
15
15
|
import styles from './family-relationship.scss';
|
|
16
16
|
import { useMappedRelationshipTypes } from './relationships.resource';
|
|
17
|
+
import dayjs from 'dayjs';
|
|
17
18
|
|
|
18
19
|
const schema = relationshipFormSchema
|
|
19
20
|
.refine(
|
|
@@ -62,7 +63,21 @@ const FamilyRelationshipForm: React.FC<RelationshipFormProps> = ({ closeWorkspac
|
|
|
62
63
|
});
|
|
63
64
|
const personUuid = form.watch('personB');
|
|
64
65
|
const { attributes } = usePersonAttributes(personUuid);
|
|
65
|
-
|
|
66
|
+
const { isLoading: isPatientloading, birthdate } = usePatientBirthdate(personUuid);
|
|
67
|
+
const mode = form.watch('mode');
|
|
68
|
+
const dobCreateMode = form.watch('personBInfo.birthdate');
|
|
69
|
+
const patientAgeMonths = useMemo(() => {
|
|
70
|
+
let birthDate: Date | null = null;
|
|
71
|
+
if (mode === 'create') {
|
|
72
|
+
birthDate = dobCreateMode;
|
|
73
|
+
} else {
|
|
74
|
+
birthDate = birthdate ? parseDate(birthdate) : null;
|
|
75
|
+
}
|
|
76
|
+
if (birthDate) {
|
|
77
|
+
return dayjs().diff(birthDate, 'month');
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}, [mode, dobCreateMode, birthdate]);
|
|
66
81
|
const { control, handleSubmit } = form;
|
|
67
82
|
|
|
68
83
|
const onSubmit: SubmitHandler<FormData> = async (data) => {
|
|
@@ -105,18 +120,18 @@ const FamilyRelationshipForm: React.FC<RelationshipFormProps> = ({ closeWorkspac
|
|
|
105
120
|
<DatePicker
|
|
106
121
|
className={styles.datePickerInput}
|
|
107
122
|
dateFormat="d/m/Y"
|
|
108
|
-
id="startDate"
|
|
109
123
|
datePickerType="single"
|
|
110
124
|
{...field}
|
|
111
125
|
ref={undefined}
|
|
112
|
-
invalid={error?.message}
|
|
126
|
+
invalid={!!error?.message}
|
|
113
127
|
invalidText={error?.message}>
|
|
114
128
|
<DatePickerInput
|
|
115
|
-
invalid={error?.message}
|
|
129
|
+
invalid={!!error?.message}
|
|
116
130
|
invalidText={error?.message}
|
|
117
131
|
placeholder="mm/dd/yyyy"
|
|
118
132
|
labelText={t('startDate', 'Start Date')}
|
|
119
|
-
size="
|
|
133
|
+
size="lg"
|
|
134
|
+
id="startDate"
|
|
120
135
|
/>
|
|
121
136
|
</DatePicker>
|
|
122
137
|
)}
|
|
@@ -130,24 +145,24 @@ const FamilyRelationshipForm: React.FC<RelationshipFormProps> = ({ closeWorkspac
|
|
|
130
145
|
<DatePicker
|
|
131
146
|
className={styles.datePickerInput}
|
|
132
147
|
dateFormat="d/m/Y"
|
|
133
|
-
id="endDate"
|
|
134
148
|
datePickerType="single"
|
|
135
149
|
{...field}
|
|
136
150
|
ref={undefined}
|
|
137
|
-
invalid={error?.message}
|
|
151
|
+
invalid={!!error?.message}
|
|
138
152
|
invalidText={error?.message}>
|
|
139
153
|
<DatePickerInput
|
|
140
|
-
invalid={error?.message}
|
|
154
|
+
invalid={!!error?.message}
|
|
141
155
|
invalidText={error?.message}
|
|
142
156
|
placeholder="mm/dd/yyyy"
|
|
143
157
|
labelText={t('endDate', 'End Date')}
|
|
144
|
-
size="
|
|
158
|
+
size="lg"
|
|
159
|
+
id="endDate"
|
|
145
160
|
/>
|
|
146
161
|
</DatePicker>
|
|
147
162
|
)}
|
|
148
163
|
/>
|
|
149
164
|
</Column>
|
|
150
|
-
<RelationshipBaselineInfoFormSection />
|
|
165
|
+
<RelationshipBaselineInfoFormSection patientUuid={personUuid} patientAgeMonths={patientAgeMonths} />
|
|
151
166
|
</Stack>
|
|
152
167
|
|
|
153
168
|
<ButtonSet className={styles.buttonSet}>
|
package/src/hooks/useContacts.ts
CHANGED
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
import { Edit } from '@carbon/react/icons';
|
|
17
17
|
import { Encounter } from '../encounter-observations/visit.resource';
|
|
18
18
|
import { useTranslation } from 'react-i18next';
|
|
19
|
-
import { formatDatetime, usePagination, Visit } from '@openmrs/esm-framework';
|
|
19
|
+
import { formatDatetime, launchWorkspace, usePagination, Visit } from '@openmrs/esm-framework';
|
|
20
20
|
import EncounterObservations from '../encounter-observations';
|
|
21
|
-
import { EmptyState,
|
|
21
|
+
import { EmptyState, PatientChartPagination } from '@openmrs/esm-patient-common-lib';
|
|
22
22
|
import styles from './in-patient-table.scss';
|
|
23
23
|
import { mutate } from 'swr';
|
|
24
24
|
|
|
@@ -51,7 +51,7 @@ const InPatientTable: React.FC<InPatientTableProps> = ({ tableRows }) => {
|
|
|
51
51
|
}, [results]);
|
|
52
52
|
|
|
53
53
|
const onEncounterEdit = (encounter: Encounter) => {
|
|
54
|
-
|
|
54
|
+
launchWorkspace('patient-form-entry-workspace', {
|
|
55
55
|
workspaceTitle: encounter.form.display,
|
|
56
56
|
mutateForm: () => {
|
|
57
57
|
mutate((key) => typeof key === 'string' && key.startsWith(`/ws/rest/v1/encounter`), undefined, {
|
|
@@ -74,7 +74,7 @@ const InPatientTable: React.FC<InPatientTableProps> = ({ tableRows }) => {
|
|
|
74
74
|
|
|
75
75
|
return (
|
|
76
76
|
<>
|
|
77
|
-
<DataTable
|
|
77
|
+
<DataTable size="sm" useZebraStyles rows={paginatedRows} headers={headers}>
|
|
78
78
|
{({
|
|
79
79
|
rows,
|
|
80
80
|
headers,
|