From cb86c63fc9d2e2d11ca1f424cb3d375fb35652c4 Mon Sep 17 00:00:00 2001 From: Lucy Jemutai <130601439+lucyjemutai@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:34:52 +0300 Subject: [PATCH] OHRI-2318: Infant's name to display on the Mother banner (#1929) * Infant's name to display on the Mother banner * change display of childern names * faillling test and remove redundant code --- .../banner-tags/.patient-status-tag.test.tsx | 114 +++++++++++------- .../patient-status-tag.component.tsx | 22 +++- .../banner-tags/usePatientFamilyNames.ts | 60 +++++++++ 3 files changed, 154 insertions(+), 42 deletions(-) create mode 100644 packages/esm-commons-lib/src/components/banner-tags/usePatientFamilyNames.ts diff --git a/packages/esm-commons-lib/src/components/banner-tags/.patient-status-tag.test.tsx b/packages/esm-commons-lib/src/components/banner-tags/.patient-status-tag.test.tsx index b371a66b2..af6c214ad 100644 --- a/packages/esm-commons-lib/src/components/banner-tags/.patient-status-tag.test.tsx +++ b/packages/esm-commons-lib/src/components/banner-tags/.patient-status-tag.test.tsx @@ -1,91 +1,123 @@ import React from 'react'; -import { render, act, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import { PatientStatusBannerTag } from './patient-status-tag.component'; import { usePatientHivStatus } from './patientHivStatus'; +import { usePatientFamilyNames } from './usePatientFamilyNames'; -jest.mock('./patientHivStatus'); +jest.mock('./patientHivStatus', () => ({ + usePatientHivStatus: jest.fn(), +})); -const mockusePatientHivStatus = usePatientHivStatus as jest.Mock; +jest.mock('./usePatientFamilyNames', () => ({ + usePatientFamilyNames: jest.fn(), +})); describe('PatientStatusBannerTag', () => { + const hivPositiveSampleUuid = '138571AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; + beforeEach(() => { jest.clearAllMocks(); }); - const hivPositiveSampleUuid = '138571AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; - - it('renders red tag when patient is HIV positive', async () => { - mockusePatientHivStatus.mockReturnValue({ - hivStatus: 'positive', - isLoading: false, + it('should not render anything while loading', () => { + (usePatientHivStatus as jest.Mock).mockReturnValue({ + hivStatus: null, + isLoading: true, isError: false, }); - await act(async () => { - render(); + (usePatientFamilyNames as jest.Mock).mockReturnValue({ + childrenNames: [], + motherName: null, + patientAge: null, + patientGender: null, + isLoading: true, + isError: false, }); - expect(screen.getByText(/HIV Positive/i)).toBeInTheDocument(); + const { container } = render(); + + expect(container.firstChild).toBeNull(); }); - it('renders green tag when patient is HIV negative', async () => { - mockusePatientHivStatus.mockReturnValue({ - hivStatus: 'negative', + it('should display the correct tag for HIV positive status', () => { + (usePatientHivStatus as jest.Mock).mockReturnValue({ + hivStatus: 'positive', isLoading: false, isError: false, }); - await act(async () => { - render(); + (usePatientFamilyNames as jest.Mock).mockReturnValue({ + childrenNames: [], + motherName: null, + patientAge: null, + patientGender: null, + isLoading: false, + isError: false, }); - expect(screen.getByText(/HIV Negative/i)).toBeInTheDocument(); + render(); + expect(screen.getByText('HIV Positive')).toBeInTheDocument(); }); - it('does not render any tag when patient HIV status is not positive or negative', async () => { - mockusePatientHivStatus.mockReturnValue({ - hivStatus: 'other', + it('should display the correct tag for HIV negative status', () => { + (usePatientHivStatus as jest.Mock).mockReturnValue({ + hivStatus: 'negative', isLoading: false, isError: false, }); - await act(async () => { - render(); + (usePatientFamilyNames as jest.Mock).mockReturnValue({ + childrenNames: [], + motherName: null, + patientAge: null, + patientGender: null, + isLoading: false, + isError: false, }); - expect(screen.queryByText(/HIV Positive/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/HIV Negative/i)).not.toBeInTheDocument(); + render(); + expect(screen.getByText('HIV Negative')).toBeInTheDocument(); }); - it('shows loading state initially', async () => { - mockusePatientHivStatus.mockReturnValue({ - hivStatus: null, - isLoading: true, + it('should display mother’s name on the Infant banner', () => { + (usePatientHivStatus as jest.Mock).mockReturnValue({ + hivStatus: 'negative', + isLoading: false, isError: false, }); - await act(async () => { - render(); + (usePatientFamilyNames as jest.Mock).mockReturnValue({ + childrenNames: [], + motherName: 'Jane Doe', + patientAge: 10, + patientGender: 'M', + isLoading: false, + isError: false, }); - expect(screen.queryByText(/HIV Positive/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/HIV Negative/i)).not.toBeInTheDocument(); + render(); + expect(screen.getByText('Mother: Jane Doe')).toBeInTheDocument(); }); - it('handles error state', async () => { - mockusePatientHivStatus.mockReturnValue({ + it('should show an error message when there is an error fetching data', () => { + (usePatientHivStatus as jest.Mock).mockReturnValue({ hivStatus: null, isLoading: false, - isError: true, + isError: false, }); - await act(async () => { - render(); + (usePatientFamilyNames as jest.Mock).mockReturnValue({ + childrenNames: [], + motherName: null, + patientAge: null, + patientGender: null, + isLoading: false, + isError: true, }); - expect(screen.queryByText(/HIV Positive/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/HIV Negative/i)).not.toBeInTheDocument(); - // Optionally check for an error message if your component shows one + render(); + expect(screen.getByText('Error fetching family information')).toBeInTheDocument(); }); }); diff --git a/packages/esm-commons-lib/src/components/banner-tags/patient-status-tag.component.tsx b/packages/esm-commons-lib/src/components/banner-tags/patient-status-tag.component.tsx index 1ef075df7..049c04451 100644 --- a/packages/esm-commons-lib/src/components/banner-tags/patient-status-tag.component.tsx +++ b/packages/esm-commons-lib/src/components/banner-tags/patient-status-tag.component.tsx @@ -1,16 +1,36 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Tag } from '@carbon/react'; import { useTranslation } from 'react-i18next'; import { usePatientHivStatus } from './patientHivStatus'; +import { usePatientFamilyNames } from './usePatientFamilyNames'; export function PatientStatusBannerTag({ patientUuid }) { const { t } = useTranslation(); const { hivStatus } = usePatientHivStatus(patientUuid); + const { childrenNames, motherName, patientAge, patientGender, isLoading, isError } = + usePatientFamilyNames(patientUuid); + + if (isLoading) { + return null; + } + + if (isError) { + return
Error fetching family information
; + } return ( <> + {/* HIV Status Display */} {hivStatus === 'positive' && {t('hivPositive', 'HIV Positive')}} {hivStatus === 'negative' && {t('hivNegative', 'HIV Negative')}} + + {/* Mother Name Display (if patient is under 10) */} + {patientAge !== null && patientAge <= 14 && motherName && Mother: {motherName}} + + {/* Children Names Display (if patient is female and over 10) */} + {patientAge !== null && patientAge > 14 && patientGender === 'F' && childrenNames.length > 0 && ( + Children: {childrenNames.join(' || ')} + )} ); } diff --git a/packages/esm-commons-lib/src/components/banner-tags/usePatientFamilyNames.ts b/packages/esm-commons-lib/src/components/banner-tags/usePatientFamilyNames.ts new file mode 100644 index 000000000..dcd04e330 --- /dev/null +++ b/packages/esm-commons-lib/src/components/banner-tags/usePatientFamilyNames.ts @@ -0,0 +1,60 @@ +import { useState, useEffect, useCallback } from 'react'; +import { fetchPatientRelationships } from '@ohri/openmrs-esm-ohri-commons-lib'; + +export const usePatientFamilyNames = (patientUuid: string) => { + const [childrenNames, setChildrenNames] = useState([]); + const [motherName, setMotherName] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [isError, setIsError] = useState(false); + const [patientAge, setPatientAge] = useState(null); + const [patientGender, setPatientGender] = useState(null); + + const fetchFamilyData = useCallback(async () => { + try { + // Fetch patient demographics (age and gender) + const response = await fetch(`/openmrs/ws/rest/v1/patient/${patientUuid}?v=full`); + const patient = await response.json(); + setPatientAge(patient.person.age); + setPatientGender(patient.person.gender); + + // Fetch relationships + const relationships = await fetchPatientRelationships(patientUuid); + + if (!relationships || !Array.isArray(relationships)) { + console.warn('No valid relationships data:', relationships); + setChildrenNames([]); + setMotherName(null); + setIsLoading(false); + return; + } + + const childRelationships = relationships + .filter((relationship) => relationship.relationshipType?.displayBIsToA === 'Child') + .map((relationship) => relationship.personB?.display); + + setChildrenNames(childRelationships); + + const motherRelationship = relationships.find( + (relationship) => + relationship.relationshipType?.displayAIsToB === 'Mother' || + relationship.relationshipType?.displayBIsToA === 'Child', + ); + + setMotherName(motherRelationship?.personA?.display || 'Mother not found'); + + setIsLoading(false); + } catch (error) { + console.error('Error fetching family names:', error); + setIsError(true); + setIsLoading(false); + } + }, [patientUuid]); + + useEffect(() => { + if (patientUuid) { + fetchFamilyData(); + } + }, [fetchFamilyData, patientUuid]); + + return { childrenNames, motherName, patientAge, patientGender, isLoading, isError }; +};