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 };
+};