@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2128 → 5.4.2-pre.2131

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.
Files changed (31) hide show
  1. package/.turbo/turbo-build.log +75 -88
  2. package/dist/574.js +1 -1
  3. package/dist/{551.js → 825.js} +1 -1
  4. package/dist/825.js.map +1 -0
  5. package/dist/kenyaemr-esm-patient-clinical-view-app.js +1 -1
  6. package/dist/kenyaemr-esm-patient-clinical-view-app.js.buildmanifest.json +32 -32
  7. package/dist/main.js +1 -1
  8. package/dist/main.js.map +1 -1
  9. package/dist/routes.json +1 -1
  10. package/package.json +1 -1
  11. package/src/config-schema.ts +21 -5
  12. package/src/contact-list/contact-list.component.tsx +3 -1
  13. package/src/contact-list/contact-list.resource.tsx +15 -13
  14. package/src/contact-list/contact-list.workspace.tsx +10 -249
  15. package/src/contact-list/contact-tracing-history.component.tsx +1 -1
  16. package/src/family-partner-history/family-history.component.tsx +40 -9
  17. package/src/family-partner-history/family-relationship.workspace.tsx +10 -4
  18. package/src/family-partner-history/relationships.resource.tsx +24 -98
  19. package/src/hooks/useContacts.ts +1 -1
  20. package/src/hooks/usePersonAttributes.ts +15 -0
  21. package/src/index.ts +0 -4
  22. package/src/relationships/forms/baseline-info-form-section.component.tsx +315 -0
  23. package/src/relationships/forms/patient-search-create-form.tsx +38 -23
  24. package/src/relationships/relationship.resources.ts +15 -5
  25. package/src/relationships/tabs/relationships-tabs-component.tsx +0 -5
  26. package/src/routes.json +0 -14
  27. package/translations/en.json +13 -3
  28. package/dist/551.js.map +0 -1
  29. package/src/other-relationships/other-relationships.component.tsx +0 -229
  30. package/src/other-relationships/other-relationships.scss +0 -125
  31. package/src/other-relationships/other-relationships.workspace.tsx +0 -155
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"clinical-view-section","component":"clinicalViewPatientDashboard","slot":"patient-chart-dashboard-slot"},{"name":"family-history","slot":"patient-chart-family-history-slot","component":"familyHistory","order":0,"online":true,"offline":false},{"name":"other-relationships","slot":"patient-chart-family-history-slot","component":"otherRelationships","order":0,"online":true,"offline":false},{"name":"relationships-link","component":"relationshipsLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationships-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationships","slot":"patient-chart-relationships-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"contact-list-form","component":"contactListForm"},{"name":"maternal-and-child-health-dashboard-group-link","slot":"clinical-view-section","component":"maternalAndChildHealthSideNavGroup"},{"name":"antenatal-care-dashboard-link","component":"antenatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-antenatal-care-dashboard-slot","path":"antenatal-care-dashboard","layoutMode":"anchored"}},{"name":"antenatal-care-dashboard","slot":"patient-chart-antenatal-care-dashboard-slot","component":"antenatalCare"},{"name":"postnatal-care-dashboard-link","component":"postnatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-postnatal-care-dashboard-slot","path":"postnatal-care-dashboard","layoutMode":"anchored"}},{"name":"postnatal-care-dashboard","slot":"patient-chart-postnatal-care-dashboard-slot","component":"postnatalCare"},{"name":"labour-and-delivery-dashboard-link","component":"labourAndDeliveryLink","slot":"maternal-and-child-health-slot","meta":{"fullWidth":true,"slot":"patient-chart-labour-and-delivery-dashboard-slot","path":"labour-and-delivery-dashboard","layoutMode":"anchored"}},{"name":"labour-and-delivery-dashboard","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"labourAndDelivery","meta":{"fullWidth":true}},{"name":"hiv-care-and-treatment-dashboard-group-link","slot":"special-clinics-slot","component":"hivCareAndTreatMentSideNavGroup"},{"name":"genericNavLinks","slot":"special-clinics-slot","component":"genericNavLinks","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinic-dashboard-slot","path":"special-clinics-dashboard","layoutMode":"anchored"}},{"name":"patient-chart-special-clinic-dashboard-slot","slot":"patient-chart-special-clinic-dashboard-slot","component":"genericDashboard"},{"name":"hts-dashboard-link","component":"htsDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hts-dashboard-slot","path":"hts-dashboard","layoutMode":"anchored"}},{"name":"hts-clinical-view","slot":"patient-chart-hts-dashboard-slot","component":"htsClinicalView","order":2,"online":true,"offline":false},{"name":"defaulter-tracing-dashboard-link","component":"defaulterTracingLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-defaulter-tracing-dashboard-slot","path":"defaulter-tracing-dashboard","layoutMode":"anchored"}},{"name":"defaulter-tracing-dashboard","slot":"patient-chart-defaulter-tracing-dashboard-slot","component":"defaulterTracing","order":3,"online":true,"offline":false},{"name":"special-clinics-dashboard-group-link","slot":"clinical-view-section","component":"specialClinicsSideNavGroup"},{"name":"clinical-encounter-link","component":"inPatientClinicalEncounterLink","slot":"clinical-view-section","order":40,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter","slot":"patient-chart-clinical-encounter-slot","component":"inPatientClinicalEncounter","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"in-patient-dashboard-link","component":"inPatientChartLink","slot":"patient-chart-dashboard-slot","order":7,"meta":{"slot":"patient-chart-in-patient-dashboard-slot","path":"in-patient","layoutMode":"anchored","columns":1,"columnSpan":1}},{"name":"in-patient-dashboard","slot":"patient-chart-in-patient-dashboard-slot","component":"inPatientChartDashboard","meta":{"fullWidth":false}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"deceased-panel-dashboard-link","component":"deceasedPanelDashboardLink","slot":"patient-chart-dashboard-slot","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-deceased-panel-slot","path":"deceased-panel","layoutMode":"anchored"}},{"name":"deceased-details-tabs","slot":"patient-chart-deceased-panel-slot","component":"deceasedDetailsTabs","order":0,"online":true,"offline":false},{"name":"parto-graph-chart","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"partograph","meta":{"fullWidth":true}}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"relationship-update-form","component":"relationshipUpdateForm","title":"Relationship Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.2128"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"clinical-view-section","component":"clinicalViewPatientDashboard","slot":"patient-chart-dashboard-slot"},{"name":"family-history","slot":"patient-chart-family-history-slot","component":"familyHistory","order":0,"online":true,"offline":false},{"name":"relationships-link","component":"relationshipsLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationships-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationships","slot":"patient-chart-relationships-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"contact-list-form","component":"contactListForm"},{"name":"maternal-and-child-health-dashboard-group-link","slot":"clinical-view-section","component":"maternalAndChildHealthSideNavGroup"},{"name":"antenatal-care-dashboard-link","component":"antenatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-antenatal-care-dashboard-slot","path":"antenatal-care-dashboard","layoutMode":"anchored"}},{"name":"antenatal-care-dashboard","slot":"patient-chart-antenatal-care-dashboard-slot","component":"antenatalCare"},{"name":"postnatal-care-dashboard-link","component":"postnatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-postnatal-care-dashboard-slot","path":"postnatal-care-dashboard","layoutMode":"anchored"}},{"name":"postnatal-care-dashboard","slot":"patient-chart-postnatal-care-dashboard-slot","component":"postnatalCare"},{"name":"labour-and-delivery-dashboard-link","component":"labourAndDeliveryLink","slot":"maternal-and-child-health-slot","meta":{"fullWidth":true,"slot":"patient-chart-labour-and-delivery-dashboard-slot","path":"labour-and-delivery-dashboard","layoutMode":"anchored"}},{"name":"labour-and-delivery-dashboard","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"labourAndDelivery","meta":{"fullWidth":true}},{"name":"hiv-care-and-treatment-dashboard-group-link","slot":"special-clinics-slot","component":"hivCareAndTreatMentSideNavGroup"},{"name":"genericNavLinks","slot":"special-clinics-slot","component":"genericNavLinks","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinic-dashboard-slot","path":"special-clinics-dashboard","layoutMode":"anchored"}},{"name":"patient-chart-special-clinic-dashboard-slot","slot":"patient-chart-special-clinic-dashboard-slot","component":"genericDashboard"},{"name":"hts-dashboard-link","component":"htsDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hts-dashboard-slot","path":"hts-dashboard","layoutMode":"anchored"}},{"name":"hts-clinical-view","slot":"patient-chart-hts-dashboard-slot","component":"htsClinicalView","order":2,"online":true,"offline":false},{"name":"defaulter-tracing-dashboard-link","component":"defaulterTracingLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-defaulter-tracing-dashboard-slot","path":"defaulter-tracing-dashboard","layoutMode":"anchored"}},{"name":"defaulter-tracing-dashboard","slot":"patient-chart-defaulter-tracing-dashboard-slot","component":"defaulterTracing","order":3,"online":true,"offline":false},{"name":"special-clinics-dashboard-group-link","slot":"clinical-view-section","component":"specialClinicsSideNavGroup"},{"name":"clinical-encounter-link","component":"inPatientClinicalEncounterLink","slot":"clinical-view-section","order":40,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter","slot":"patient-chart-clinical-encounter-slot","component":"inPatientClinicalEncounter","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"in-patient-dashboard-link","component":"inPatientChartLink","slot":"patient-chart-dashboard-slot","order":7,"meta":{"slot":"patient-chart-in-patient-dashboard-slot","path":"in-patient","layoutMode":"anchored","columns":1,"columnSpan":1}},{"name":"in-patient-dashboard","slot":"patient-chart-in-patient-dashboard-slot","component":"inPatientChartDashboard","meta":{"fullWidth":false}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"deceased-panel-dashboard-link","component":"deceasedPanelDashboardLink","slot":"patient-chart-dashboard-slot","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-deceased-panel-slot","path":"deceased-panel","layoutMode":"anchored"}},{"name":"deceased-details-tabs","slot":"patient-chart-deceased-panel-slot","component":"deceasedDetailsTabs","order":0,"online":true,"offline":false},{"name":"parto-graph-chart","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"partograph","meta":{"fullWidth":true}}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"relationship-update-form","component":"relationshipUpdateForm","title":"Relationship Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.2131"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-patient-clinical-view-app",
3
- "version": "5.4.2-pre.2128",
3
+ "version": "5.4.2-pre.2131",
4
4
  "description": "Patient clinical view microfrontend for the OpenMRS SPA",
5
5
  "browser": "dist/kenyaemr-esm-patient-clinical-view-app.js",
6
6
  "main": "src/index.ts",
@@ -2,6 +2,11 @@ import { Type } from '@openmrs/esm-framework';
2
2
  import _default from 'react-hook-form/dist/logic/appendErrors';
3
3
 
4
4
  export const configSchema = {
5
+ requireMaritalStatusOnAgeGreaterThanOrEqualTo: {
6
+ _type: Type.Number,
7
+ _description: 'Age in years',
8
+ _default: 10,
9
+ },
5
10
  encounterTypes: {
6
11
  _type: Type.Object,
7
12
  _description: 'List of encounter type UUIDs',
@@ -200,12 +205,12 @@ export const configSchema = {
200
205
  {
201
206
  uuid: '5f115f62-68b7-11e3-94ee-6bef9086de92',
202
207
  display: 'Guardian/Dependant',
203
- category: ['other'],
208
+ category: ['family'],
204
209
  },
205
210
  {
206
211
  uuid: 'd6895098-5d8d-11e3-94ee-b35a4132a5e3',
207
212
  display: 'Spouse/Spouse',
208
- category: ['sexual', 'pns', 'family'],
213
+ category: ['sexual', 'family'],
209
214
  },
210
215
  {
211
216
  uuid: '007b765f-6725-4ae9-afee-9966302bace4',
@@ -215,7 +220,17 @@ export const configSchema = {
215
220
  {
216
221
  uuid: '2ac0d501-eadc-4624-b982-563c70035d46',
217
222
  display: 'Co-wife/Co-wife',
218
- category: ['pns'],
223
+ category: ['family'],
224
+ },
225
+ {
226
+ uuid: 'a8058424-5ddf-4ce2-a5ee-6e08d01b5960',
227
+ display: 'Care-giver/Care-giver',
228
+ category: ['family'],
229
+ },
230
+ {
231
+ uuid: '3667e52f-8653-40e1-b227-a7278d474020',
232
+ display: 'Primary caregiver/Primary caregiver',
233
+ category: ['family'],
219
234
  },
220
235
  {
221
236
  uuid: '58da0d1e-9c89-42e9-9412-275cef1e0429',
@@ -225,7 +240,7 @@ export const configSchema = {
225
240
  {
226
241
  uuid: '76edc1fe-c5ce-4608-b326-c8ecd1020a73',
227
242
  display: 'SNS/SNS',
228
- category: ['other'],
243
+ category: ['pns'],
229
244
  },
230
245
  ],
231
246
  },
@@ -282,6 +297,7 @@ export const configSchema = {
282
297
  };
283
298
 
284
299
  export interface ConfigObject {
300
+ requireMaritalStatusOnAgeGreaterThanOrEqualTo: number;
285
301
  peerEducatorRelationship: string;
286
302
  morgueVisitTypeUuid: string;
287
303
  morgueDischargeEncounterUuid: string;
@@ -339,7 +355,7 @@ export interface ConfigObject {
339
355
  relationshipTypesList: Array<{
340
356
  uuid: string;
341
357
  display: string;
342
- category: Array<'sexual' | 'pns' | 'family' | 'other'>;
358
+ category: Array<'sexual' | 'pns' | 'family'>;
343
359
  }>;
344
360
  }
345
361
 
@@ -46,7 +46,7 @@ interface ContactListProps {
46
46
  const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
47
47
  const { t } = useTranslation();
48
48
  const [pageSize, setPageSize] = useState(10);
49
- const headerTitle = t('contactList', 'Contact list');
49
+ const headerTitle = t('pnsContactList', 'PNS Contact list');
50
50
  const layout = useLayoutType();
51
51
  const size = layout === 'tablet' ? 'lg' : 'md';
52
52
  const { contacts, error, isLoading } = useContacts(patientUuid);
@@ -117,6 +117,8 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
117
117
  const handleLaunchContactTracingForm = (contactUuid: string) => {
118
118
  launchWorkspace('kenyaemr-cusom-form-entry-workspace', {
119
119
  formUuid: htsClientTracingFormUuid,
120
+ workspaceTitle: t('contactTracingForm', 'Contact tracing form'),
121
+
120
122
  patientUuid: contactUuid,
121
123
  encounterUuid: '',
122
124
  mutateForm: () => {
@@ -2,22 +2,11 @@ import { Session } from '@openmrs/esm-framework';
2
2
  import omit from 'lodash/omit';
3
3
  import { z } from 'zod';
4
4
  import { ConfigObject } from '../config-schema';
5
- import { relationshipFormSchema, saveRelationship } from '../relationships/relationship.resources';
6
- import { Enrollment, HTSEncounter } from '../types';
5
+ import { BOOLEAN_YES, relationshipFormSchema, saveRelationship } from '../relationships/relationship.resources';
6
+ import { Enrollment, HTSEncounter, Person } from '../types';
7
7
  import { replaceAll } from '../utils/expression-helper';
8
- export const BOOLEAN_YES = '1065';
9
- export const BOOLEAN_NO = '1066';
10
8
 
11
9
  export const ContactListFormSchema = relationshipFormSchema
12
- .extend({
13
- physicalAssault: z.enum([BOOLEAN_YES, BOOLEAN_NO]).optional(),
14
- threatened: z.enum([BOOLEAN_YES, BOOLEAN_NO]).optional(),
15
- sexualAssault: z.enum([BOOLEAN_YES, BOOLEAN_NO]).optional(),
16
- livingWithClient: z.string().optional(),
17
- baselineStatus: z.string().optional(),
18
- preferedPNSAproach: z.string().optional(),
19
- ipvOutCome: z.enum(['True', 'False']).optional(),
20
- })
21
10
  .refine(
22
11
  (data) => {
23
12
  return !(data.mode === 'search' && !data.personB);
@@ -67,6 +56,7 @@ export const saveContact = async (
67
56
  data: z.infer<typeof ContactListFormSchema>,
68
57
  config: ConfigObject,
69
58
  session: Session,
59
+ personAttributes: Person['attributes'] = [],
70
60
  ) => {
71
61
  const { baselineStatus, ipvOutCome, preferedPNSAproach, livingWithClient } = data;
72
62
 
@@ -90,6 +80,9 @@ export const saveContact = async (
90
80
  {
91
81
  attributeType: config.contactPersonAttributesUuid.baselineHIVStatus,
92
82
  value: replaceAll(baselineStatus, 'A', ''),
83
+ attribute: personAttributes.find(
84
+ (a) => a.attributeType.uuid === config.contactPersonAttributesUuid.baselineHIVStatus,
85
+ )?.uuid,
93
86
  },
94
87
  ]
95
88
  : []),
@@ -108,6 +101,9 @@ export const saveContact = async (
108
101
  {
109
102
  attributeType: config.contactPersonAttributesUuid.preferedPnsAproach,
110
103
  value: replaceAll(preferedPNSAproach, 'A', ''),
104
+ attribute: personAttributes.find(
105
+ (a) => a.attributeType.uuid === config.contactPersonAttributesUuid.preferedPnsAproach,
106
+ )?.uuid,
111
107
  },
112
108
  ]
113
109
  : []),
@@ -117,6 +113,9 @@ export const saveContact = async (
117
113
  {
118
114
  attributeType: config.contactPersonAttributesUuid.livingWithContact,
119
115
  value: replaceAll(livingWithClient, 'A', ''),
116
+ attribute: personAttributes.find(
117
+ (a) => a.attributeType.uuid === config.contactPersonAttributesUuid.livingWithContact,
118
+ )?.uuid,
120
119
  },
121
120
  ]
122
121
  : []),
@@ -125,6 +124,9 @@ export const saveContact = async (
125
124
  {
126
125
  attributeType: config.contactPersonAttributesUuid.contactIPVOutcome,
127
126
  value: ipvOutCome,
127
+ attribute: personAttributes.find(
128
+ (a) => a.attributeType.uuid === config.contactPersonAttributesUuid.contactIPVOutcome,
129
+ )?.uuid,
128
130
  },
129
131
  ]
130
132
  : []),
@@ -1,15 +1,4 @@
1
- import {
2
- Button,
3
- ButtonSet,
4
- Column,
5
- DatePicker,
6
- DatePickerInput,
7
- Dropdown,
8
- Form,
9
- RadioButton,
10
- RadioButtonGroup,
11
- Stack,
12
- } from '@carbon/react';
1
+ import { Button, ButtonSet, Column, DatePicker, DatePickerInput, Dropdown, Form, Stack } from '@carbon/react';
13
2
  import { zodResolver } from '@hookform/resolvers/zod';
14
3
  import { DefaultWorkspaceProps, useConfig, useSession } from '@openmrs/esm-framework';
15
4
  import React, { useEffect, useMemo } from 'react';
@@ -18,21 +7,11 @@ import { useTranslation } from 'react-i18next';
18
7
  import { z } from 'zod';
19
8
  import { ConfigObject } from '../config-schema';
20
9
  import { useMappedRelationshipTypes } from '../family-partner-history/relationships.resource';
10
+ import usePersonAttributes from '../hooks/usePersonAttributes';
11
+ import RelationshipBaselineInfoFormSection from '../relationships/forms/baseline-info-form-section.component';
21
12
  import PatientSearchCreate from '../relationships/forms/patient-search-create-form';
22
- import {
23
- LIVING_WITH_PATIENT_CONCEPT_UUID,
24
- PARTNER_HIV_STATUS_CONCEPT_UUID,
25
- PNS_APROACH_CONCEPT_UUID,
26
- } from '../relationships/relationships-constants';
27
- import { contactListConceptMap } from './contact-list-concept-map';
28
13
  import styles from './contact-list-form.scss';
29
- import {
30
- BOOLEAN_NO,
31
- BOOLEAN_YES,
32
- contactIPVOutcomeOptions,
33
- ContactListFormSchema,
34
- saveContact,
35
- } from './contact-list.resource';
14
+ import { ContactListFormSchema, saveContact } from './contact-list.resource';
36
15
  interface ContactListFormProps extends DefaultWorkspaceProps {
37
16
  patientUuid: string;
38
17
  props: any;
@@ -40,12 +19,7 @@ interface ContactListFormProps extends DefaultWorkspaceProps {
40
19
 
41
20
  type ContactListFormType = z.infer<typeof ContactListFormSchema>;
42
21
 
43
- const ContactListForm: React.FC<ContactListFormProps> = ({
44
- closeWorkspace,
45
- closeWorkspaceWithSavedChanges,
46
- promptBeforeClosing,
47
- patientUuid,
48
- }) => {
22
+ const ContactListForm: React.FC<ContactListFormProps> = ({ closeWorkspace, patientUuid }) => {
49
23
  const form = useForm<ContactListFormType>({
50
24
  mode: 'all',
51
25
  defaultValues: {
@@ -56,6 +30,8 @@ const ContactListForm: React.FC<ContactListFormProps> = ({
56
30
  });
57
31
  const { t } = useTranslation();
58
32
  const session = useSession();
33
+ const personUuid = form.watch('personB');
34
+ const { attributes } = usePersonAttributes(personUuid);
59
35
 
60
36
  const config = useConfig<ConfigObject>();
61
37
  const { data } = useMappedRelationshipTypes();
@@ -72,67 +48,11 @@ const ContactListForm: React.FC<ContactListFormProps> = ({
72
48
 
73
49
  const onSubmit = async (values: ContactListFormType) => {
74
50
  try {
75
- await saveContact(values, config, session);
51
+ await saveContact(values, config, session, attributes);
76
52
  closeWorkspace();
77
53
  } catch (error) {}
78
54
  };
79
55
 
80
- const hivStatus = useMemo(
81
- () =>
82
- Object.entries(contactListConceptMap[PARTNER_HIV_STATUS_CONCEPT_UUID].answers).map(([uuid, display]) => ({
83
- label: display,
84
- value: uuid,
85
- })),
86
- [],
87
- );
88
-
89
- const pnsAproach = useMemo(
90
- () =>
91
- Object.entries(contactListConceptMap[PNS_APROACH_CONCEPT_UUID].answers).map(([uuid, display]) => ({
92
- label: display,
93
- value: uuid,
94
- })),
95
- [],
96
- );
97
-
98
- const contactLivingWithPatient = useMemo(
99
- () =>
100
- Object.entries(contactListConceptMap[LIVING_WITH_PATIENT_CONCEPT_UUID].answers).map(([uuid, display]) => ({
101
- label: display,
102
- value: uuid,
103
- })),
104
- [],
105
- );
106
-
107
- const observableRelationship = form.watch('relationshipType');
108
- const observablePhysicalAssault = form.watch('physicalAssault');
109
- const observableThreatened = form.watch('threatened');
110
- const observableSexualAssault = form.watch('sexualAssault');
111
- const observableMode = form.watch('mode');
112
- const showIPVRelatedFields =
113
- pnsRelationships.findIndex((r) => r.uuid === observableRelationship && r.category.some((c) => c === 'sexual')) !==
114
- -1;
115
-
116
- useEffect(() => {
117
- if ([observablePhysicalAssault, observableThreatened, observableSexualAssault].includes(BOOLEAN_YES)) {
118
- form.setValue('ipvOutCome', 'True');
119
- } else if (
120
- [observablePhysicalAssault, observableThreatened, observableSexualAssault].every((v) => v === BOOLEAN_NO)
121
- ) {
122
- form.setValue('ipvOutCome', 'False');
123
- }
124
- if (!showIPVRelatedFields) {
125
- form.setValue('ipvOutCome', undefined);
126
- }
127
- }, [
128
- observablePhysicalAssault,
129
- observableThreatened,
130
- observableSexualAssault,
131
- observableRelationship,
132
- form,
133
- showIPVRelatedFields,
134
- ]);
135
-
136
56
  return (
137
57
  <FormProvider {...form}>
138
58
  <Form onSubmit={form.handleSubmit(onSubmit)} className={styles.form}>
@@ -212,167 +132,8 @@ const ContactListForm: React.FC<ContactListFormProps> = ({
212
132
  )}
213
133
  />
214
134
  </Column>
215
- {observableMode === 'create' && (
216
- <>
217
- <Column>
218
- <Controller
219
- control={form.control}
220
- name="livingWithClient"
221
- render={({ field, fieldState: { error } }) => (
222
- <Dropdown
223
- ref={field.ref}
224
- invalid={error?.message}
225
- invalidText={error?.message}
226
- id="livingWithClient"
227
- titleText={t('livingWithClient', 'Living with client')}
228
- onChange={(e) => {
229
- field.onChange(e.selectedItem);
230
- }}
231
- initialSelectedItem={field.value}
232
- label="Select"
233
- items={contactLivingWithPatient.map((r) => r.value)}
234
- itemToString={(item) => contactLivingWithPatient.find((r) => r.value === item)?.label ?? ''}
235
- />
236
- )}
237
- />
238
- </Column>
239
- {showIPVRelatedFields && (
240
- <>
241
- <span className={styles.sectionHeader}>{t('ipvQuestions', 'IPV Questions')}</span>
242
- <Column>
243
- <Controller
244
- control={form.control}
245
- name="physicalAssault"
246
- render={({ field, fieldState: { error } }) => (
247
- <RadioButtonGroup
248
- id="physicalAssault"
249
- legendText={t(
250
- 'physicalAssault',
251
- '1. Has he/she ever hit, kicked, slapped, or otherwise physically hurt you?',
252
- )}
253
- {...field}
254
- invalid={error?.message}
255
- invalidText={error?.message}
256
- className={styles.billingItem}>
257
- <RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="physicalAssault_yes" />
258
- <RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="physicalAssault_no" />
259
- </RadioButtonGroup>
260
- )}
261
- />
262
- </Column>
263
- <Column>
264
- <Controller
265
- control={form.control}
266
- name="threatened"
267
- render={({ field, fieldState: { error } }) => (
268
- <RadioButtonGroup
269
- id="threatened"
270
- legendText={t('threatened', '2. Has he/she ever threatened to hurt you?')}
271
- {...field}
272
- invalid={error?.message}
273
- invalidText={error?.message}
274
- className={styles.billingItem}>
275
- <RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="threatened_yes" />
276
- <RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="threatened_no" />
277
- </RadioButtonGroup>
278
- )}
279
- />
280
- </Column>
281
- <Column>
282
- <Controller
283
- control={form.control}
284
- name="sexualAssault"
285
- render={({ field, fieldState: { error } }) => (
286
- <RadioButtonGroup
287
- id="sexualAssault"
288
- legendText={t(
289
- 'sexualAssault',
290
- '3.Has he/she ever forced you to do something sexually that made you feel uncomfortable?',
291
- )}
292
- {...field}
293
- invalid={error?.message}
294
- invalidText={error?.message}
295
- className={styles.billingItem}>
296
- <RadioButton labelText={t('yes', 'Yes')} value={BOOLEAN_YES} id="sexualAssault_yes" />
297
- <RadioButton labelText={t('no', 'No')} value={BOOLEAN_NO} id="sexualAssault_no" />
298
- </RadioButtonGroup>
299
- )}
300
- />
301
- </Column>
302
- <span className={styles.sectionHeader}>{t('ipvOutcome', 'IPV Outcome')}</span>
303
- <Column>
304
- <Controller
305
- control={form.control}
306
- name="ipvOutCome"
307
- render={({ field, fieldState: { error } }) => (
308
- <Dropdown
309
- ref={field.ref}
310
- invalid={error?.message}
311
- invalidText={error?.message}
312
- id="ipvOutCome"
313
- titleText={t('ipvOutCome', 'IPV Outcome')}
314
- onChange={(e) => {
315
- field.onChange(e.selectedItem);
316
- }}
317
- selectedItem={field.value}
318
- label="Choose option"
319
- items={contactIPVOutcomeOptions.map((r) => r.value)}
320
- itemToString={(item) => {
321
- return contactIPVOutcomeOptions.find((r) => r.value === item)?.label ?? '';
322
- }}
323
- />
324
- )}
325
- />
326
- </Column>
327
- </>
328
- )}
329
- <span className={styles.sectionHeader}>{t('baselineInformation', 'Baseline Information')}</span>
330
- <Column>
331
- <Controller
332
- control={form.control}
333
- name="baselineStatus"
334
- render={({ field, fieldState: { error } }) => (
335
- <Dropdown
336
- ref={field.ref}
337
- invalid={error?.message}
338
- invalidText={error?.message}
339
- id="baselineStatus"
340
- titleText={t('baselineStatus', 'HIV Status')}
341
- onChange={(e) => {
342
- field.onChange(e.selectedItem);
343
- }}
344
- initialSelectedItem={field.value}
345
- label="Select HIV Status"
346
- items={hivStatus.map((r) => r.value)}
347
- itemToString={(item) => hivStatus.find((r) => r.value === item)?.label ?? ''}
348
- />
349
- )}
350
- />
351
- </Column>
352
- <Column>
353
- <Controller
354
- control={form.control}
355
- name="preferedPNSAproach"
356
- render={({ field, fieldState: { error } }) => (
357
- <Dropdown
358
- ref={field.ref}
359
- invalid={error?.message}
360
- invalidText={error?.message}
361
- id="preferedPNSAproach"
362
- titleText={t('preferedPNSAproach', 'Prefered PNS Aproach')}
363
- onChange={(e) => {
364
- field.onChange(e.selectedItem);
365
- }}
366
- initialSelectedItem={field.value}
367
- label="Select Aproach"
368
- items={pnsAproach.map((r) => r.value)}
369
- itemToString={(item) => pnsAproach.find((r) => r.value === item)?.label ?? ''}
370
- />
371
- )}
372
- />
373
- </Column>
374
- </>
375
- )}
135
+
136
+ <RelationshipBaselineInfoFormSection />
376
137
  </Stack>
377
138
 
378
139
  <ButtonSet className={styles.buttonSet}>
@@ -35,7 +35,7 @@ const ContactTracingHistory: React.FC<ContactTracingHistoryProps> = ({ patientUu
35
35
 
36
36
  const handleLaunchContactTracingForm = (encounterUuid: string) => {
37
37
  launchWorkspace('kenyaemr-cusom-form-entry-workspace', {
38
- workspaceTitle: 'Contact tracing form',
38
+ workspaceTitle: t('contactTracingForm', 'Contact tracing form'),
39
39
  formUuid: htsClientTracingFormUuid,
40
40
  patientUuid,
41
41
  encounterUuid,
@@ -30,6 +30,7 @@ import ConceptObservations from './concept-obs.component';
30
30
  import type { ConfigObject } from '../config-schema';
31
31
  import styles from './family-history.scss';
32
32
  import { deleteRelationship } from '../relationships/relationship.resources';
33
+ import HIVStatus from '../contact-list/hiv-status.component';
33
34
 
34
35
  interface FamilyHistoryProps {
35
36
  patientUuid: string;
@@ -42,18 +43,15 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
42
43
  const layout = useLayoutType();
43
44
  const [pageSize, setPageSize] = useState(10);
44
45
  const { relationships, error, isLoading, isValidating } = usePatientRelationships(patientUuid);
45
- const familyRelationshipTypes = useMemo(
46
- () => config.relationshipTypesList.filter((rl) => rl.category.some((c) => c === 'family')),
47
- [config],
48
- );
49
- const familyRelationshipTypeUUIDs = new Set(familyRelationshipTypes.map((type) => type.uuid));
50
- const familyRelationships = relationships.filter((r) => familyRelationshipTypeUUIDs.has(r.relationshipTypeUUID));
51
-
52
46
  const headerTitle = t('familyContacts', 'Family contacts');
53
- const { results, totalPages, currentPage, goTo } = usePagination(familyRelationships, pageSize);
47
+ const { results, totalPages, currentPage, goTo } = usePagination(relationships, pageSize);
54
48
  const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, results.length);
55
49
 
56
50
  const headers = [
51
+ {
52
+ header: t('listingDate', 'Listing date'),
53
+ key: 'startDate',
54
+ },
57
55
  {
58
56
  header: t('name', 'Name'),
59
57
  key: 'name',
@@ -66,6 +64,10 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
66
64
  header: t('age', 'Age'),
67
65
  key: 'age',
68
66
  },
67
+ {
68
+ header: t('sex', 'Sex'),
69
+ key: 'sex',
70
+ },
69
71
  {
70
72
  header: t('alive', 'Alive'),
71
73
  key: 'alive',
@@ -78,6 +80,26 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
78
80
  header: t('chronicDisease', 'Chronic Disease'),
79
81
  key: 'chronicDisease',
80
82
  },
83
+ {
84
+ header: t('hivStatus', 'HIV Status'),
85
+ key: 'hivStatus',
86
+ },
87
+ {
88
+ header: t('baselineHivStatus', 'Baseline HIV Status'),
89
+ key: 'baseLineivStatus',
90
+ },
91
+ {
92
+ header: t('livingWithClient', 'Living with client'),
93
+ key: 'livingWithClient',
94
+ },
95
+ {
96
+ header: t('pnsAproach', 'PNS Aproach'),
97
+ key: 'pnsAproach',
98
+ },
99
+ {
100
+ header: t('ipvOutcome', 'IPV Outcome'),
101
+ key: 'ipvOutcome',
102
+ },
81
103
  { header: t('actions', 'Actions'), key: 'actions' },
82
104
  ];
83
105
 
@@ -99,6 +121,7 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
99
121
 
100
122
  return {
101
123
  id: `${relation.uuid}`,
124
+ startDate: relation.startDate ?? '--',
102
125
  name: (
103
126
  <ConfigurableLink
104
127
  style={{ textDecoration: 'none' }}
@@ -108,12 +131,20 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
108
131
  ),
109
132
  relation: relation?.relationshipType,
110
133
  age: relation?.relativeAge ?? '--',
134
+ sex: relation.gender,
135
+
111
136
  alive: relation?.dead ? t('dead', 'Dead') : t('alive', 'Alive'),
112
137
  causeOfDeath: (
113
138
  <ConceptObservations patientUuid={patientUuid} conceptUuid={concepts.probableCauseOfDeathConceptUuid} />
114
139
  ),
115
140
  patientUuid: relation,
116
141
  chronicDisease: <ConceptObservations patientUuid={patientUuid} conceptUuid={concepts.problemListConceptUuid} />,
142
+ hivStatus: <HIVStatus relativeUuid={relation.relativeUuid} />,
143
+ baseLineivStatus: relation.baselineHIVStatus ?? '--',
144
+ livingWithClient: relation.livingWithClient ?? '--',
145
+ pnsAproach: relation.pnsAproach ?? '--',
146
+ ipvOutcome: relation.ipvOutcome ?? '--',
147
+
117
148
  actions: (
118
149
  <>
119
150
  <Button
@@ -154,7 +185,7 @@ const FamilyHistory: React.FC<FamilyHistoryProps> = ({ patientUuid }) => {
154
185
  return <ErrorState headerTitle={headerTitle} error={error} />;
155
186
  }
156
187
 
157
- if (familyRelationships.length === 0) {
188
+ if (relationships.length === 0) {
158
189
  return (
159
190
  <Layer>
160
191
  <Tile className={styles.tile}>