@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2188 → 5.4.2-pre.2191

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.
@@ -0,0 +1,554 @@
1
+ import {
2
+ Button,
3
+ ButtonSet,
4
+ Column,
5
+ DatePicker,
6
+ DatePickerInput,
7
+ Dropdown,
8
+ Form,
9
+ InlineLoading,
10
+ Stack,
11
+ Tile,
12
+ RadioButtonGroup,
13
+ RadioButton,
14
+ } from '@carbon/react';
15
+ import { zodResolver } from '@hookform/resolvers/zod';
16
+ import { DefaultWorkspaceProps, restBaseUrl, showSnackbar, useConfig } from '@openmrs/esm-framework';
17
+ import React, { useEffect, useMemo } from 'react';
18
+ import { Controller, FormProvider, useForm } from 'react-hook-form';
19
+ import { useTranslation } from 'react-i18next';
20
+ import { mutate } from 'swr';
21
+ import { z } from 'zod';
22
+ import useRelationship from '../../hooks/useRelationship';
23
+ import useRelationshipTypes from '../../hooks/useRelationshipTypes';
24
+ import styles from './contact-list-update.scss';
25
+ import PatientInfo from '../../case-management/workspace/patient-info.component';
26
+ import usePerson, { contactIPVOutcomeOptions, updateContactAttributes } from '../../contact-list/contact-list.resource';
27
+ import {
28
+ BOOLEAN_NO,
29
+ BOOLEAN_YES,
30
+ relationshipFormSchema,
31
+ relationshipUpdateFormSchema,
32
+ updateRelationship,
33
+ } from '../../relationships/relationship.resources';
34
+ import { type Contact } from '../../types';
35
+ import { ConfigObject } from '../../config-schema';
36
+ import { contactListConceptMap } from '../../contact-list/contact-list-concept-map';
37
+ import {
38
+ LIVING_WITH_PATIENT_CONCEPT_UUID,
39
+ PARTNER_HIV_STATUS_CONCEPT_UUID,
40
+ PNS_APROACH_CONCEPT_UUID,
41
+ } from '../../relationships/relationships-constants';
42
+
43
+ interface ContactListUpdateFormProps extends DefaultWorkspaceProps {
44
+ relation: Contact;
45
+ closeWorkspace: () => void;
46
+ patientUuid: string;
47
+ }
48
+
49
+ type ContactListUpdateFormType = z.infer<typeof relationshipFormSchema>;
50
+
51
+ const ContactListUpdateForm: React.FC<ContactListUpdateFormProps> = ({ closeWorkspace, relation, patientUuid }) => {
52
+ const { error, isLoading, relationship } = useRelationship(relation?.uuid);
53
+ const { isLoading: typesLoading, error: typesError, relationshipTypes } = useRelationshipTypes();
54
+ const { person } = usePerson(relationship?.personB?.uuid);
55
+ const config = useConfig<ConfigObject>();
56
+
57
+ const { t } = useTranslation();
58
+
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
+ const pnsAproach = useMemo(
69
+ () =>
70
+ Object.entries(contactListConceptMap[PNS_APROACH_CONCEPT_UUID].answers).map(([uuid, display]) => ({
71
+ label: display,
72
+ value: uuid,
73
+ })),
74
+ [],
75
+ );
76
+
77
+ const contactLivingWithPatient = useMemo(
78
+ () =>
79
+ Object.entries(contactListConceptMap[LIVING_WITH_PATIENT_CONCEPT_UUID].answers).map(([uuid, display]) => ({
80
+ label: display,
81
+ value: uuid,
82
+ })),
83
+ [],
84
+ );
85
+
86
+ 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
+ },
99
+ resolver: zodResolver(relationshipUpdateFormSchema),
100
+ });
101
+
102
+ const observableRelationship = form.watch('relationshipType');
103
+ const showIPVRelatedFields = useMemo(() => {
104
+ if (!observableRelationship || !config.relationshipTypesList) {
105
+ return false;
106
+ }
107
+ return (
108
+ config.relationshipTypesList.findIndex(
109
+ (r) => r.uuid === observableRelationship && r.category.some((c) => c === 'sexual'),
110
+ ) !== -1
111
+ );
112
+ }, [observableRelationship, config.relationshipTypesList]);
113
+
114
+ useEffect(() => {
115
+ if (relationship && relationshipTypes.length > 0) {
116
+ if (relationship.endDate) {
117
+ form.setValue('endDate', new Date(relationship.endDate));
118
+ }
119
+ if (relationship.startDate) {
120
+ form.setValue('startDate', new Date(relationship.startDate));
121
+ }
122
+ if (relationship.relationshipType) {
123
+ form.setValue('relationshipType', relationship.relationshipType.uuid);
124
+ }
125
+ }
126
+ }, [relationship, relationshipTypes, form]);
127
+
128
+ useEffect(() => {
129
+ if (relation && hivStatus.length > 0 && pnsAproach.length > 0 && contactLivingWithPatient.length > 0) {
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
+
178
+ if (relation.startDate) {
179
+ try {
180
+ const startDate = new Date(relation.startDate);
181
+ form.setValue('startDate', startDate);
182
+ } catch (e) {
183
+ console.warn('Invalid start date format:', relation.startDate);
184
+ }
185
+ }
186
+
187
+ if (relation.endDate) {
188
+ try {
189
+ const endDate = new Date(relation.endDate);
190
+ form.setValue('endDate', endDate);
191
+ } catch (e) {
192
+ console.warn('Invalid end date format:', relation.endDate);
193
+ }
194
+ }
195
+
196
+ if (relation.relationshipType && relationshipTypes.length > 0) {
197
+ const relType = relationshipTypes.find(
198
+ (type) =>
199
+ type.displayBIsToA === relation.relationshipType || type.displayAIsToB === relation.relationshipType,
200
+ );
201
+ if (relType) {
202
+ form.setValue('relationshipType', relType.uuid);
203
+ }
204
+ }
205
+ }
206
+ }, [relation, hivStatus, pnsAproach, contactLivingWithPatient, relationshipTypes, form]);
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]);
224
+
225
+ const onSubmit = async (values: ContactListUpdateFormType) => {
226
+ try {
227
+ const data = form.getValues();
228
+
229
+ await updateRelationship(relationship.uuid, values);
230
+
231
+ await updateContactAttributes(
232
+ person?.uuid,
233
+ {
234
+ baselineStatus: data?.baselineStatus,
235
+ preferedPNSAproach: data?.preferedPNSAproach,
236
+ livingWithClient: data?.livingWithClient,
237
+ ipvOutCome: data?.ipvOutCome,
238
+ },
239
+ config,
240
+ person?.attributes?.map((attr) => ({
241
+ uuid: attr.uuid,
242
+ display: attr.display ?? '',
243
+ value: attr.value,
244
+ attributeType: {
245
+ uuid: attr.attributeType.uuid,
246
+ display: attr.attributeType.display ?? '',
247
+ },
248
+ })),
249
+ );
250
+
251
+ showSnackbar({
252
+ title: 'Success',
253
+ kind: 'success',
254
+ subtitle: t('relationshipUpdated', ' Relationship updated successfully'),
255
+ });
256
+
257
+ mutate((key) => {
258
+ return typeof key === 'string' && key.startsWith(`${restBaseUrl}/relationship`);
259
+ });
260
+
261
+ closeWorkspace();
262
+ } catch (error) {
263
+ showSnackbar({
264
+ title: 'Error',
265
+ subtitle: 'Failure updating relationship! ' + JSON.stringify(error),
266
+ kind: 'error',
267
+ });
268
+ }
269
+ };
270
+
271
+ if (isLoading || typesLoading) {
272
+ return (
273
+ <div className={styles.loading}>
274
+ <InlineLoading status="active" iconDescription="Loading" description="Loading form..." />
275
+ </div>
276
+ );
277
+ }
278
+
279
+ if (error || typesError) {
280
+ return (
281
+ <div className={styles.error}>
282
+ <Tile id="error">
283
+ <strong>Error:</strong>
284
+ <p>{error?.message ?? typesError?.message ?? t('errorLoadingForm', 'Failed to load form')}</p>
285
+ </Tile>
286
+ </div>
287
+ );
288
+ }
289
+
290
+ return (
291
+ <FormProvider {...form}>
292
+ <Form onSubmit={form.handleSubmit(onSubmit)}>
293
+ <Stack gap={4} className={styles.grid}>
294
+ <Column>
295
+ <PatientInfo patientUuid={relationship?.personB?.uuid || relation?.relativeUuid} />
296
+ </Column>
297
+
298
+ <span className={styles.sectionHeader}>{t('relationship', 'Relationship')}</span>
299
+ <Column>
300
+ <Controller
301
+ control={form.control}
302
+ name="startDate"
303
+ render={({ field, fieldState: { error } }) => (
304
+ <DatePicker
305
+ className={styles.datePickerInput}
306
+ dateFormat="d/m/Y"
307
+ id="startDate"
308
+ datePickerType="single"
309
+ {...field}
310
+ ref={undefined}
311
+ invalid={!!error?.message}
312
+ invalidText={error?.message}>
313
+ <DatePickerInput
314
+ id={`startdate-input`}
315
+ name="startdate-input"
316
+ invalid={!!error?.message}
317
+ invalidText={error?.message}
318
+ placeholder="mm/dd/yyyy"
319
+ labelText={t('startDate', 'Start Date')}
320
+ size="xl"
321
+ />
322
+ </DatePicker>
323
+ )}
324
+ />
325
+ </Column>
326
+
327
+ <Column>
328
+ <Controller
329
+ control={form.control}
330
+ name="endDate"
331
+ render={({ field, fieldState: { error } }) => (
332
+ <DatePicker
333
+ className={styles.datePickerInput}
334
+ dateFormat="d/m/Y"
335
+ id="endDate"
336
+ datePickerType="single"
337
+ {...field}
338
+ ref={undefined}
339
+ invalid={!!error?.message}
340
+ invalidText={error?.message}>
341
+ <DatePickerInput
342
+ id="enddate-input"
343
+ name="enddate-input"
344
+ invalid={!!error?.message}
345
+ invalidText={error?.message}
346
+ placeholder="mm/dd/yyyy"
347
+ labelText={t('endDate', 'End Date')}
348
+ size="xl"
349
+ />
350
+ </DatePicker>
351
+ )}
352
+ />
353
+ </Column>
354
+
355
+ <Column>
356
+ <Controller
357
+ control={form.control}
358
+ name="relationshipType"
359
+ render={({ field, fieldState: { error } }) => (
360
+ <Dropdown
361
+ ref={field.ref}
362
+ invalid={!!error?.message}
363
+ invalidText={error?.message}
364
+ id="relationshipToPatient"
365
+ titleText={t('relationToPatient', 'Relation to patient')}
366
+ onChange={(e) => {
367
+ field.onChange(e.selectedItem);
368
+ }}
369
+ selectedItem={field.value}
370
+ label="Select Relationship"
371
+ items={relationshipTypes.map((r) => r.uuid)}
372
+ itemToString={(item) => relationshipTypes.find((r) => r.uuid === item)?.displayBIsToA ?? ''}
373
+ />
374
+ )}
375
+ />
376
+ </Column>
377
+
378
+ <Column>
379
+ <Controller
380
+ control={form.control}
381
+ name="livingWithClient"
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>
539
+ </Stack>
540
+
541
+ <ButtonSet className={styles.buttonSet}>
542
+ <Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
543
+ {t('discard', 'Discard')}
544
+ </Button>
545
+ <Button className={styles.button} kind="primary" type="submit" disabled={form.formState.isSubmitting}>
546
+ {t('submit', 'Submit')}
547
+ </Button>
548
+ </ButtonSet>
549
+ </Form>
550
+ </FormProvider>
551
+ );
552
+ };
553
+
554
+ export default ContactListUpdateForm;
@@ -1,4 +1,4 @@
1
- import React, { useMemo, useState } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import {
4
4
  DataTable,
@@ -14,8 +14,10 @@ import {
14
14
  TableRow,
15
15
  Tile,
16
16
  Button,
17
+ OverflowMenu,
18
+ OverflowMenuItem,
17
19
  } from '@carbon/react';
18
- import { Add, Edit, TrashCan } from '@carbon/react/icons';
20
+ import { Add } from '@carbon/react/icons';
19
21
  import { EmptyDataIllustration, ErrorState, CardHeader, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
20
22
  import {
21
23
  ConfigurableLink,
@@ -31,6 +33,8 @@ import type { ConfigObject } from '../config-schema';
31
33
  import styles from './family-history.scss';
32
34
  import { deleteRelationship } from '../relationships/relationship.resources';
33
35
  import HIVStatus from '../contact-list/hiv-status.component';
36
+ import { type Contact } from '../types';
37
+ import { extractNameString, uppercaseText } from '../utils/expression-helper';
34
38
 
35
39
  interface FamilyHistoryProps {
36
40
  patientUuid: string;
@@ -42,6 +46,7 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
42
46
  const { concepts } = config;
43
47
  const layout = useLayoutType();
44
48
  const [pageSize, setPageSize] = useState(10);
49
+ const size = layout === 'tablet' ? 'lg' : 'md';
45
50
  const { relationships, error, isLoading, isValidating } = usePatientRelationships(patientUuid);
46
51
  const headerTitle = t('familyContacts', 'Family contacts');
47
52
  const { results, totalPages, currentPage, goTo } = usePagination(relationships, pageSize);
@@ -109,9 +114,11 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
109
114
  patientUuid,
110
115
  });
111
116
  };
112
- const handleEditRelationship = (relationShipUuid: string) => {
113
- launchWorkspace('relationship-update-form', {
114
- relationShipUuid,
117
+ const handleEditRelationship = (relation: Contact) => {
118
+ launchWorkspace('contact-list-update-form', {
119
+ relation,
120
+ workspaceTitle: t('editContactList', 'Edit contact list'),
121
+ patientUuid,
115
122
  });
116
123
  };
117
124
 
@@ -126,7 +133,7 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
126
133
  <ConfigurableLink
127
134
  style={{ textDecoration: 'none' }}
128
135
  to={window.getOpenmrsSpaBase() + `patient/${relation.relativeUuid}/chart/Patient Summary`}>
129
- {relation.name}
136
+ {extractNameString(uppercaseText(relation.name))}
130
137
  </ConfigurableLink>
131
138
  ),
132
139
  relation: relation?.relationshipType,
@@ -147,20 +154,10 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
147
154
 
148
155
  actions: (
149
156
  <>
150
- <Button
151
- renderIcon={Edit}
152
- hasIconOnly
153
- kind="ghost"
154
- iconDescription="Edit"
155
- onClick={() => handleEditRelationship(relation.uuid)}
156
- />
157
- <Button
158
- renderIcon={TrashCan}
159
- hasIconOnly
160
- kind="ghost"
161
- iconDescription="Delete"
162
- onClick={() => deleteRelationship(relation.uuid)}
163
- />
157
+ <OverflowMenu size={size} flipped>
158
+ <OverflowMenuItem itemText={t('edit', 'Edit')} onClick={() => handleEditRelationship(relation)} />
159
+ <OverflowMenuItem itemText={t('delete', 'Delete')} onClick={() => deleteRelationship(relation.uuid)} />
160
+ </OverflowMenu>
164
161
  </>
165
162
  ),
166
163
  };
package/src/index.ts CHANGED
@@ -49,12 +49,12 @@ import { inPatientMeta } from './in-patient/in-patient.meta';
49
49
  import PeerCalendar from './peer-calendar/peer-calendar.component';
50
50
  import PeerForm from './peer-calendar/forms/peer-form.workspace';
51
51
  import FormEntryWorkspace from './peer-calendar/forms/form-entry.workspace';
52
- import RelationshipUpdateForm from './relationships/forms/relationships-update-form.workspace';
53
52
  import DeleteRelationshipConfirmDialog from './relationships/modals/delete-relationship-dialog.modal';
54
53
  import DeceasedDetailsView from './deceased-panel/tabs/tabs.component';
55
54
  import DeceasedPanelDashboardLink from './deceased-panel/dashboard-link/dashboard-link.component';
56
55
  import EndRelationshipWorkspace from './case-management/workspace/case-management-workspace.component';
57
56
  import Partograph from './maternal-and-child-health/partography/partograph.component';
57
+ import ContactListUpdateForm from './contact-list/forms/contact-list-update.workspace';
58
58
 
59
59
  const moduleName = '@kenyaemr/esm-patient-clinical-view-app';
60
60
 
@@ -101,7 +101,6 @@ export const otherRelationshipsLink = getSyncLifecycle(createDashboardLink(other
101
101
  // Relationships links for Family History and the corresponding view in the patient chart
102
102
  export const relationshipsLink = getSyncLifecycle(createDashboardLink(relationshipsDashboardMeta), options);
103
103
  export const relationships = getSyncLifecycle(Relationships, options);
104
- export const relationshipUpdateForm = getSyncLifecycle(RelationshipUpdateForm, options);
105
104
  export const relationshipDeleteConfirmialog = getSyncLifecycle(DeleteRelationshipConfirmDialog, options);
106
105
 
107
106
  // Contacts
@@ -109,6 +108,7 @@ export const contactList = getSyncLifecycle(ContactList, options);
109
108
  export const contactListLink = getSyncLifecycle(createDashboardLink(contactListDashboardMeta), options);
110
109
  export const contactListForm = getSyncLifecycle(ContactListForm, options);
111
110
  export const birthDateCalculator = getSyncLifecycle(BirthDateCalculator, options);
111
+ export const contactListUpdateForm = getSyncLifecycle(ContactListUpdateForm, options);
112
112
 
113
113
  // Peer Clendar
114
114
  export const peerCalendar = getSyncLifecycle(PeerCalendar, options);