diff --git a/.eslintrc b/.eslintrc index c64a3f879..1f5070e58 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,14 +1,38 @@ { + "env": { + "node": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint" - ], - "extends": ["ts-react-important-stuff", "plugin:prettier/recommended"], + "plugins": ["@typescript-eslint", "react-hooks", "prettier"], "rules": { + "react-hooks/exhaustive-deps": "warn", + "react-hooks/rules-of-hooks": "error", + // Disabling these rules for now just to keep the diff small. I'll enable them in a future PR that fixes lint issues. + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/ban-types": "off", + // Use `import type` instead of `import` for type imports https://typescript-eslint.io/blog/consistent-type-imports-and-exports-why-and-how + "@typescript-eslint/consistent-type-imports": [ + "error", + { + "fixStyle": "inline-type-imports" + } + ], + "prefer-const": "off", + "no-console": ["error", { "allow": ["warn", "error"] }], + "no-unsafe-optional-chaining": "off", + "no-explicit-any": "off", + "no-extra-boolean-cast": "off", + "no-prototype-builtins": "off", + "no-useless-escape": "off", "no-restricted-imports": [ "error", { "paths": [ + // These two rules ensure that we're importing lodash and lodash-es correctly. Not doing so can bloat our bundle size significantly. { "name": "lodash", "message": "Import specific methods from `lodash`. e.g. `import map from 'lodash/map'`" @@ -18,6 +42,7 @@ "importNames": ["default"], "message": "Import specific methods from `lodash-es`. e.g. `import { map } from 'lodash-es'`" }, + // These two rules ensure that we're importing Carbon components and icons from the correct packages (after v10). May be removed in the future. { "name": "carbon-components-react", "message": "Import from `@carbon/react` directly. e.g. `import { Toggle } from '@carbon/react'`" @@ -28,6 +53,12 @@ } ] } + ], + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } ] } } diff --git a/.husky/pre-commit b/.husky/pre-commit index 79dc913b5..73c92693d 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -6,3 +6,6 @@ set -e # die on error # yarn prettier // commented because it causes alot of unncecessary changes that are not related to the commit # yarn turbo run extract-translations // commented because it creates new translations files that are not related to the commit # yarn pretty-quick --staged + +npx lint-staged + diff --git a/.husky/pre-push b/.husky/pre-push index 5b79a6ef8..3c1a21a7f 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1,8 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" +#not sure if its needed for Mac, but its needed for Windows +exec < /dev/tty + set -e # die on error +yarn verify diff --git a/package.json b/package.json index 86f5b7195..502f203aa 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,10 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.8.1" }, + "lint-staged": { + "packages/**/src/**/*.{ts,tsx}": "eslint --cache --fix --max-warnings 0", + "*.{css,scss,ts,tsx}": "prettier --write --list-different" + }, "resolutions": { "@types/react": "^18.0.14", "@types/react-dom": "^18.0.5" diff --git a/packages/esm-commons-lib/src/components/card-summary/summary-card.component.tsx b/packages/esm-commons-lib/src/components/card-summary/summary-card.component.tsx index 737b1db4f..aabb2c4ca 100644 --- a/packages/esm-commons-lib/src/components/card-summary/summary-card.component.tsx +++ b/packages/esm-commons-lib/src/components/card-summary/summary-card.component.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import styles from '../../styleguide/tiles.scss'; import { SkeletonText, Tile, Column } from '@carbon/react'; import { LazyCell } from '../lazy-cell/lazy-cell.component'; -import { OpenmrsEncounter } from '@openmrs/openmrs-form-engine-lib'; +import { type OpenmrsEncounter } from '@openmrs/openmrs-form-engine-lib'; import { fetchLatestEncountersOfTypes } from './helpers'; export interface SummaryCardProps { diff --git a/packages/esm-commons-lib/src/components/cohort-patient-list/cohort-patient-list.component.tsx b/packages/esm-commons-lib/src/components/cohort-patient-list/cohort-patient-list.component.tsx index 0a407051b..9463be21e 100644 --- a/packages/esm-commons-lib/src/components/cohort-patient-list/cohort-patient-list.component.tsx +++ b/packages/esm-commons-lib/src/components/cohort-patient-list/cohort-patient-list.component.tsx @@ -13,7 +13,7 @@ import { basePath } from '../../constants'; import styles from './cohort-patient-list.scss'; import { useTranslation } from 'react-i18next'; import { useFormsJson } from '../../hooks/useFormsJson'; -import { columns, consolidatatePatientMeta, filterPatientsByName, PatientListColumn } from './helpers'; +import { columns, consolidatatePatientMeta, filterPatientsByName, type PatientListColumn } from './helpers'; interface CohortPatientListProps { cohortId: string; @@ -172,6 +172,8 @@ export const CohortPatientList: React.FC = ({ launchableForm, addPatientToListOptions, t, + viewTptPatientProgramSummary, + viewPatientProgramSummary, ]); useEffect(() => { @@ -190,7 +192,7 @@ export const CohortPatientList: React.FC = ({ ); } setPatientsCount(allPatients.length); - }, [hasLoadedPatients]); + }, [allPatients, associatedEncounterType, hasLoadedPatients]); useEffect(() => { const fetchHivResults = excludeColumns ? !excludeColumns.includes('hivResult') : true; @@ -289,7 +291,6 @@ export const CohortPatientList: React.FC = ({ autoFocus: true, }; }, [ - loadedExtraEncounters, searchTerm, filteredResults, paginatedPatients, @@ -303,7 +304,7 @@ export const CohortPatientList: React.FC = ({ useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); useEffect(() => { if (allPatients.length && extraAssociatedEncounterTypes && !loadedExtraEncounters) { diff --git a/packages/esm-commons-lib/src/components/cohort-patient-list/helpers.tsx b/packages/esm-commons-lib/src/components/cohort-patient-list/helpers.tsx index a97c98a7c..2986aab6b 100644 --- a/packages/esm-commons-lib/src/components/cohort-patient-list/helpers.tsx +++ b/packages/esm-commons-lib/src/components/cohort-patient-list/helpers.tsx @@ -54,7 +54,7 @@ export const LaunchableFormMenuItem = ({ } else { setIsLoading(false); } - }, []); + }, [continueEncounterActionText, encounterType, encounterUuid, launchableForm.editLatestEncounter, patientUuid]); return ( <> @@ -95,7 +95,7 @@ export const ViewSummaryMenuItem = ({ patientUuid, ViewSummary, encounterType }) } else { setIsLoading(false); } - }, []); + }, [ViewSummary.editLatestEncounter, encounterType, encounterUuid, patientUuid, viewSummaryActionText]); return ( <> diff --git a/packages/esm-commons-lib/src/components/encounter-list/encounter-list.component.tsx b/packages/esm-commons-lib/src/components/encounter-list/encounter-list.component.tsx index 8a9e2103e..73405ab5e 100644 --- a/packages/esm-commons-lib/src/components/encounter-list/encounter-list.component.tsx +++ b/packages/esm-commons-lib/src/components/encounter-list/encounter-list.component.tsx @@ -15,10 +15,10 @@ import { MenuItem, } from '@carbon/react'; import { Add } from '@carbon/react/icons'; -import { FormSchema } from '@openmrs/openmrs-form-engine-lib'; +import { type FormSchema } from '@openmrs/openmrs-form-engine-lib'; import { deleteEncounter, launchEncounterForm } from './helpers'; import { useEncounterRows } from '../../hooks/useEncounterRows'; -import { OpenmrsEncounter } from '../../api/types'; +import { type OpenmrsEncounter } from '../../api/types'; import { useFormsJson } from '../../hooks/useFormsJson'; import { usePatientDeathStatus } from '../../hooks/usePatientDeathStatus'; import { mutate } from 'swr'; @@ -327,7 +327,18 @@ export const EncounterList: React.FC = ({ ); } return null; - }, [forms, hideFormLauncher, isDead, displayText, moduleName, workspaceWindowSize, onFormSave, patientUuid]); + }, [ + forms, + hideFormLauncher, + isDead, + displayText, + moduleName, + onFormSave, + workspaceWindowSize, + patientUuid, + t, + formsJson, + ]); if (isLoading === true || isLoadingForms === true || isLoadingFormsJson === true) { return ; diff --git a/packages/esm-commons-lib/src/components/encounter-list/multiple-encounter-list.component.tsx b/packages/esm-commons-lib/src/components/encounter-list/multiple-encounter-list.component.tsx index 6c666a2fa..c4a58dbf1 100644 --- a/packages/esm-commons-lib/src/components/encounter-list/multiple-encounter-list.component.tsx +++ b/packages/esm-commons-lib/src/components/encounter-list/multiple-encounter-list.component.tsx @@ -135,7 +135,7 @@ export const MultipleEncounterList: React.FC = ({ setAllRows(rows); updateTable(rows, 0, pageSize); } - }, [baseEncounterType, encountersMap, columns]); + }, [baseEncounterType, encountersMap, columns, pageSize]); const updateTable = (fullDataSet, start, itemCount) => { let currentRows = []; @@ -150,7 +150,7 @@ export const MultipleEncounterList: React.FC = ({ useEffect(() => { loadRows(encounterTypeUuids); - }, [counter]); + }, [counter, encounterTypeUuids, loadRows]); return ( <> diff --git a/packages/esm-commons-lib/src/components/modals/add-patient-to-list-modal.component.tsx b/packages/esm-commons-lib/src/components/modals/add-patient-to-list-modal.component.tsx index 2e101c112..1efe07103 100644 --- a/packages/esm-commons-lib/src/components/modals/add-patient-to-list-modal.component.tsx +++ b/packages/esm-commons-lib/src/components/modals/add-patient-to-list-modal.component.tsx @@ -1,7 +1,6 @@ import { showToast, usePatient } from '@openmrs/esm-framework'; import { ListItem, Modal, RadioButton, RadioButtonGroup, SkeletonText, UnorderedList } from '@carbon/react'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import ReactDOM from 'react-dom'; import { useTranslation } from 'react-i18next'; import { addPatientToCohort, evictCohortMembership, getCohorts, getPatientListsForPatient } from '../../api/api'; @@ -79,7 +78,7 @@ export const AddPatientToListModal: React.FC<{ setIsLoading(false); }, ); - }, [cohortType]); + }, [cohortType, excludeCohorts, patientUuid]); const availableLists = useMemo(() => { const controls = cohorts.map((cohort, index) => ( @@ -150,7 +149,7 @@ export const AddPatientToListModal: React.FC<{ } }); } - }, [selectedList, patientUuid, close, currentMemberships]); + }, [selectedList, currentMemberships, t, close, patientUuid]); return ( <> { const obs = findObs(latestEncounter, config.obsConcepts.covidVaccineAdministeredConcept_UUID); - if (typeof obs !== undefined && obs) { + if (typeof obs !== 'undefined' && obs) { if (typeof obs.value === 'object') { const vaccineNAME = obs.value.names?.find((conceptName) => conceptName.conceptNameType === 'SHORT')?.name || @@ -137,7 +137,24 @@ function CovidHomePatientTabs() { ], }, ], - [], + [ + config.cohorts.clientsAssessedForCovid, + config.cohorts.covidClientsWithPendingLabResults, + config.obsConcepts.covidCaseAssessmentEncType, + config.obsConcepts.covidLabTestEncType, + config.obsConcepts.covidOutcome, + config.obsConcepts.covidTestType, + config.obsConcepts.covidVaccinatedClients, + config.obsConcepts.covidVaccinationDose_UUID, + config.obsConcepts.covidVaccinationEncType, + config.obsConcepts.covidVaccineAdministeredConcept_UUID, + config.obsConcepts.covidVaccineConcept_UUID, + config.obsConcepts.dateSpecimenCollected, + config.obsConcepts.pcrTestResult, + config.obsConcepts.rapidTestResult, + config.obsConcepts.returnVisitDateConcept, + t, + ], ); return ; } diff --git a/packages/esm-covid-app/src/views/dashboard/summary-tiles/covid-summary-tiles.component.tsx b/packages/esm-covid-app/src/views/dashboard/summary-tiles/covid-summary-tiles.component.tsx index a2c32733c..e97602ce0 100644 --- a/packages/esm-covid-app/src/views/dashboard/summary-tiles/covid-summary-tiles.component.tsx +++ b/packages/esm-covid-app/src/views/dashboard/summary-tiles/covid-summary-tiles.component.tsx @@ -22,7 +22,11 @@ function CovidSummaryTiles() { getReportingCohort(config.cohorts.covidOutcomesCohortUUID).then((data) => { setPeopleWithCovidOutcome(data.members.length); }); - }, []); + }, [ + config.cohorts.covid19PositiveClients, + config.cohorts.covidOutcomesCohortUUID, + config.cohorts.covidVaccinatedClients, + ]); const tiles = useMemo( () => [ { @@ -50,7 +54,7 @@ function CovidSummaryTiles() { value: PeopleWithCovidOutcome, }, ], - [], + [PeopleWithCovidOutcome, activeClientsCount, covid19PositiveClientsCount, covidVaccinatedClientsCount, t], ); return ; } diff --git a/packages/esm-covid-app/src/views/dashboard/summary-tiles/outcome-list-tile.component.tsx b/packages/esm-covid-app/src/views/dashboard/summary-tiles/outcome-list-tile.component.tsx index d11bc0935..c540b2130 100644 --- a/packages/esm-covid-app/src/views/dashboard/summary-tiles/outcome-list-tile.component.tsx +++ b/packages/esm-covid-app/src/views/dashboard/summary-tiles/outcome-list-tile.component.tsx @@ -79,7 +79,13 @@ export const Outcomes: React.FC<{}> = () => { }, }, ], - [], + [ + config.obsConcepts.covidEncounterDateTime_UUID, + config.obsConcepts.covidOutcome, + config.obsConcepts.covidOutcomeUUID, + config.obsConcepts.covidPresentSymptonsConcept_UUID, + t, + ], ); useEffect(() => { @@ -88,7 +94,7 @@ export const Outcomes: React.FC<{}> = () => { setTotalPatientCount(response.length); setIsLoading(false); }); - }, [pageSize, currentPage]); + }, [pageSize, currentPage, config.cohorts.covidOutcomesCohortUUID]); useEffect(() => { attach('outcomes-table-slot', 'patient-table'); @@ -133,12 +139,12 @@ export const Outcomes: React.FC<{}> = () => { isLoading, autoFocus: true, }), - [searchTerm, filteredResults, patients, handleSearch, pagination, isLoading], + [searchTerm, filteredResults, patients, columns, t, handleSearch, pagination, isLoading], ); useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); return (
diff --git a/packages/esm-covid-app/src/views/dashboard/summary-tiles/vaccination-tile-list.component.tsx b/packages/esm-covid-app/src/views/dashboard/summary-tiles/vaccination-tile-list.component.tsx index f39f6dc87..781777b69 100644 --- a/packages/esm-covid-app/src/views/dashboard/summary-tiles/vaccination-tile-list.component.tsx +++ b/packages/esm-covid-app/src/views/dashboard/summary-tiles/vaccination-tile-list.component.tsx @@ -68,7 +68,7 @@ export const Vaccinations: React.FC<{}> = () => { }, }, ], - [], + [t], ); useEffect(() => { @@ -82,7 +82,7 @@ export const Vaccinations: React.FC<{}> = () => { setIsLoading(false); }, ); - }, [pageSize, currentPage]); + }, [pageSize, currentPage, config.cohorts.covidVaccinatedClients]); useEffect(() => { attach('covid-vaccination-table-slot', 'patient-table'); @@ -129,12 +129,12 @@ export const Vaccinations: React.FC<{}> = () => { isLoading, autoFocus: true, }), - [searchTerm, filteredResults, patients, handleSearch, pagination, isLoading], + [searchTerm, filteredResults, patients, columns, t, handleSearch, pagination, isLoading], ); useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); return (
diff --git a/packages/esm-form-render-app/src/render/forms-render-test.component.tsx b/packages/esm-form-render-app/src/render/forms-render-test.component.tsx index f62fd9d14..4631fe26c 100644 --- a/packages/esm-form-render-app/src/render/forms-render-test.component.tsx +++ b/packages/esm-form-render-app/src/render/forms-render-test.component.tsx @@ -4,9 +4,11 @@ import styles from './form-render.scss'; import { Run, Maximize, UserData } from '@carbon/react/icons'; import AceEditor from 'react-ace'; import 'ace-builds/webpack-resolver'; -import { applyFormIntent, loadSubforms, FormEngine, FormSchema } from '@openmrs/openmrs-form-engine-lib'; +import { applyFormIntent, loadSubforms, FormEngine } from '@openmrs/openmrs-form-engine-lib'; +import type { FormSchema } from '@openmrs/openmrs-form-engine-lib'; import { useTranslation } from 'react-i18next'; -import { ConfigObject, useConfig, openmrsFetch } from '@openmrs/esm-framework'; +import type { ConfigObject } from '@openmrs/esm-framework'; +import { useConfig } from '@openmrs/esm-framework'; import { handleFormValidation } from '../form-validator'; function FormRenderTest() { @@ -61,19 +63,19 @@ function FormRenderTest() { setIsSchemaLoaded(false); }; - const updateFormJsonInput = (json) => { + const updateFormJsonInput = useCallback((json) => { setInputErrorMessage(''); try { - const parsedSchema = typeof json == 'string' ? JSON.parse(json) : json; + const parsedSchema = typeof json === 'string' ? JSON.parse(json) : json; setSchemaInput(parsedSchema); setFormInput(parsedSchema); loadIntentsFromSchema(parsedSchema); - localStorage.setItem('forms-render-test:draft-form', typeof json == 'string' ? json : JSON.stringify(json)); + localStorage.setItem('forms-render-test:draft-form', typeof json === 'string' ? json : JSON.stringify(json)); } catch (err) { setInputErrorMessage(err.toString()); } setIsSchemaLoaded(false); - }; + }, []); const formValidation = () => { handleFormValidation(schemaInput, dataTypeToRenderingMap); @@ -110,9 +112,11 @@ function FormRenderTest() { const jsonObject = typeof defaultJson === 'string' ? JSON.parse(defaultJson) : defaultJson; loadIntentsFromSchema(jsonObject); setSchemaInput(jsonObject); - } catch (err) {} + } catch (err) { + /* empty */ + } } - }, [defaultJson]); + }, [defaultJson, isIntentsDropdownDisabled]); useEffect(() => { if (jsonUrl) { @@ -132,7 +136,7 @@ function FormRenderTest() { console.error(err); }); } - }, [jsonUrl]); + }, [jsonUrl, key, updateFormJsonInput]); return (
diff --git a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/care-and-treatment/summary-tiles/ct-summary-tiles.component.tsx b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/care-and-treatment/summary-tiles/ct-summary-tiles.component.tsx index 6d180737e..47a6d2507 100644 --- a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/care-and-treatment/summary-tiles/ct-summary-tiles.component.tsx +++ b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/care-and-treatment/summary-tiles/ct-summary-tiles.component.tsx @@ -12,7 +12,8 @@ function CTSummaryTiles() { getReportingCohort(cohorts.clientsEnrolledToCare).then((data) => { setActiveClientsCount(data.members.length); }); - }, []); + }, [cohorts.clientsEnrolledToCare]); + const tiles = [ { title: t('activeClients', 'Active Clients'), diff --git a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/lab-results-summary-tiles.component.tsx b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/lab-results-summary-tiles.component.tsx index 570e38680..1df0b10d4 100644 --- a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/lab-results-summary-tiles.component.tsx +++ b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/lab-results-summary-tiles.component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { OHRIProgrammeSummaryTiles, getReportingCohort } from '@ohri/openmrs-esm-ohri-commons-lib'; import { useConfig } from '@openmrs/esm-framework'; @@ -10,15 +10,17 @@ function LabResultsSummaryTiles() { const [highVlCount, setHighVlCount] = useState(0); const { cohorts } = useConfig(); + const memoizedCohorts = useMemo(() => cohorts, [cohorts]); + useEffect(() => { - getReportingCohort(cohorts.missingCd4Cohort).then((data) => { + getReportingCohort(memoizedCohorts.missingCd4Cohort).then((data) => { setMissingCd4Count(data.members.length); }); - getReportingCohort(cohorts.highVlCohort).then((results) => { + getReportingCohort(memoizedCohorts.highVlCohort).then((results) => { setHighVlCount(results.members.length); }); - }, []); + }, [memoizedCohorts.missingCd4Cohort, memoizedCohorts.highVlCohort]); const tiles = [ { diff --git a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/cd4-results.component.tsx b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/cd4-results.component.tsx index 3be47983c..24f5b11c6 100644 --- a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/cd4-results.component.tsx +++ b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/cd4-results.component.tsx @@ -55,7 +55,7 @@ const CD4ResultsList: React.FC = ({ patientUuid }) => { setPatientCount(data.total); setIsLoading(false); }); - }, [page, pageSize]); + }, [nextOffSet, page, pageSize]); useEffect(() => { let rows = []; @@ -93,6 +93,32 @@ const CD4ResultsList: React.FC = ({ patientUuid }) => { setAllRows(rows); }, [patients, patientToCd4Map]); + const fetchPatientLastCd4Encounters = useCallback( + async (patientUuid) => { + let latestCd4Encounter = { + result: '--', + date: '--', + encounterUuid: '', + }; + const query = `encounterType=${encounterTypes.CD4LabResultsEncounter_UUID}&patient=${patientUuid}`; + const viralResults = await openmrsFetch(`/ws/rest/v1/encounter?${query}&v=${encounterRepresentation}`); + if (viralResults.data.results?.length > 0) { + const sortedEncounters = viralResults.data.results.sort( + (firstEncounter, secondEncounter) => + new Date(secondEncounter.encounterDatetime).getTime() - + new Date(firstEncounter.encounterDatetime).getTime(), + ); + const lastEncounter = sortedEncounters[0]; + + latestCd4Encounter.result = getObsFromEncounter(lastEncounter, obsConcepts.hivCD4Count_UUID); + latestCd4Encounter.date = getObsFromEncounter(lastEncounter, obsConcepts.Cd4LabResultDate_UUID, true); + latestCd4Encounter.encounterUuid = lastEncounter.uuid; + } + return latestCd4Encounter; + }, + [encounterTypes.CD4LabResultsEncounter_UUID, obsConcepts.Cd4LabResultDate_UUID, obsConcepts.hivCD4Count_UUID], + ); + useEffect(() => { const patientToCd4ResultsPromises = patients.map((patient) => fetchPatientLastCd4Encounters(patient.resource.id)); Promise.all(patientToCd4ResultsPromises).then((values) => { @@ -105,7 +131,7 @@ const CD4ResultsList: React.FC = ({ patientUuid }) => { })), ); }); - }, [patients]); + }, [fetchPatientLastCd4Encounters, patients]); const handleSearch = useCallback( (searchTerm) => { @@ -114,33 +140,16 @@ const CD4ResultsList: React.FC = ({ patientUuid }) => { setFilteredResults(filtrate); return true; }, - [searchTerm], + [allRows], ); const addNewPatient = () => navigate({ to: '${openmrsSpaBase}/patient-registration' }); const getPatientURL = (patientUuid) => `/openmrs/spa/patient/${patientUuid}/chart/hts-summary`; - - async function fetchPatientLastCd4Encounters(patientUuid: string) { - let latestCd4Encounter = { - result: '--', - date: '--', - encounterUuid: '', - }; - const query = `encounterType=${encounterTypes.CD4LabResultsEncounter_UUID}&patient=${patientUuid}`; - const viralResults = await openmrsFetch(`/ws/rest/v1/encounter?${query}&v=${encounterRepresentation}`); - if (viralResults.data.results?.length > 0) { - const sortedEncounters = viralResults.data.results.sort( - (firstEncounter, secondEncounter) => - new Date(secondEncounter.encounterDatetime).getTime() - new Date(firstEncounter.encounterDatetime).getTime(), - ); - const lastEncounter = sortedEncounters[0]; - - latestCd4Encounter.result = getObsFromEncounter(lastEncounter, obsConcepts.hivCD4Count_UUID); - latestCd4Encounter.date = getObsFromEncounter(lastEncounter, obsConcepts.Cd4LabResultDate_UUID, true); - latestCd4Encounter.encounterUuid = lastEncounter.uuid; - } - return latestCd4Encounter; - } + const [latestCd4Encounter, setLatestCd4Encounter] = useState({ + result: '--', + date: '--', + encounterUuid: '', + }); return ( <> diff --git a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/viral-load-results.component.tsx b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/viral-load-results.component.tsx index 833d4460b..4b73b0622 100644 --- a/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/viral-load-results.component.tsx +++ b/packages/esm-hiv-care-treatment-app/src/views/home-dashboard/lab-results/tabs/viral-load-results.component.tsx @@ -52,7 +52,7 @@ const ViralLoadResultsList: React.FC = () => { setPatientCount(data.total); setIsLoading(false); }); - }, [page, pageSize]); + }, [nextOffSet, page, pageSize]); useEffect(() => { let rows = []; @@ -92,6 +92,36 @@ const ViralLoadResultsList: React.FC = () => { setAllRows(rows); }, [patients, patientToViralLoadMap]); + const fetchPatientLastViralEncounters = useCallback( + async (patientUuid) => { + let latestViralEncounter = { + result: '--', + date: '--', + encounterUuid: '', + }; + const query = `encounterType=${encounterTypes.ViralLoadResultsEncounter_UUID}&patient=${patientUuid}`; + const viralResults = await openmrsFetch(`/ws/rest/v1/encounter?${query}&v=${encounterRepresentation}`); + if (viralResults.data.results?.length > 0) { + const sortedEncounters = viralResults.data.results.sort( + (firstEncounter, secondEncounter) => + new Date(secondEncounter.encounterDatetime).getTime() - + new Date(firstEncounter.encounterDatetime).getTime(), + ); + const lastEncounter = sortedEncounters[0]; + + latestViralEncounter.result = getObsFromEncounter(lastEncounter, obsConcepts.ViralLoadResult_UUID); + latestViralEncounter.date = getObsFromEncounter(lastEncounter, obsConcepts.ViralLoadResultDate_UUID, true); + latestViralEncounter.encounterUuid = lastEncounter.uuid; + } + return latestViralEncounter; + }, + [ + encounterTypes.ViralLoadResultsEncounter_UUID, + obsConcepts.ViralLoadResult_UUID, + obsConcepts.ViralLoadResultDate_UUID, + ], + ); + useEffect(() => { const patientToviralLoadResultsPromises = patients.map((patient) => fetchPatientLastViralEncounters(patient.resource.id), @@ -106,7 +136,7 @@ const ViralLoadResultsList: React.FC = () => { })), ); }); - }, [patients]); + }, [fetchPatientLastViralEncounters, patients]); const handleSearch = useCallback( (searchTerm) => { @@ -115,34 +145,9 @@ const ViralLoadResultsList: React.FC = () => { setFilteredResults(filtrate); return true; }, - [searchTerm], + [allRows], ); - - const addNewPatient = () => navigate({ to: '${openmrsSpaBase}/patient-registration' }); const getPatientURL = (patientUuid) => `/openmrs/spa/patient/${patientUuid}/chart/hts-summary`; - - async function fetchPatientLastViralEncounters(patientUuid: string) { - let latestViralEncounter = { - result: '--', - date: '--', - encounterUuid: '', - }; - const query = `encounterType=${encounterTypes.ViralLoadResultsEncounter_UUID}&patient=${patientUuid}`; - const viralResults = await openmrsFetch(`/ws/rest/v1/encounter?${query}&v=${encounterRepresentation}`); - if (viralResults.data.results?.length > 0) { - const sortedEncounters = viralResults.data.results.sort( - (firstEncounter, secondEncounter) => - new Date(secondEncounter.encounterDatetime).getTime() - new Date(firstEncounter.encounterDatetime).getTime(), - ); - const lastEncounter = sortedEncounters[0]; - - latestViralEncounter.result = getObsFromEncounter(lastEncounter, obsConcepts.ViralLoadResult_UUID); - latestViralEncounter.date = getObsFromEncounter(lastEncounter, obsConcepts.ViralLoadResultDate_UUID, true); - latestViralEncounter.encounterUuid = lastEncounter.uuid; - } - return latestViralEncounter; - } - return ( <> {isLoading ? ( diff --git a/packages/esm-hiv-care-treatment-app/src/views/service-summary/encounter-list/service-summary-encounter-list.component.tsx b/packages/esm-hiv-care-treatment-app/src/views/service-summary/encounter-list/service-summary-encounter-list.component.tsx index 211b34e84..e4d944539 100644 --- a/packages/esm-hiv-care-treatment-app/src/views/service-summary/encounter-list/service-summary-encounter-list.component.tsx +++ b/packages/esm-hiv-care-treatment-app/src/views/service-summary/encounter-list/service-summary-encounter-list.component.tsx @@ -1,4 +1,9 @@ -import { findObs, getObsFromEncounter, EncounterTile, EncounterTileColumn } from '@ohri/openmrs-esm-ohri-commons-lib'; +import { + findObs, + getObsFromEncounter, + EncounterTile, + type EncounterTileColumn, +} from '@ohri/openmrs-esm-ohri-commons-lib'; import { useConfig } from '@openmrs/esm-framework'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -79,7 +84,23 @@ const ServiceSummaryOverviewList: React.FC = ({ patientUuid } }, }, ], - [], + [ + encounterTypes.ServiceDeliveryEncounterType_UUID, + encounterTypes.art_Therapy_EncounterUUID, + encounterTypes.careAndTreatmentEncounterType, + obsConcepts.CommunityDSDModel_UUID, + obsConcepts.artStopDateUUID, + obsConcepts.artTherapyDateTime_UUID, + obsConcepts.dateRestartedUUID, + obsConcepts.keyPopulationTypeConcept, + obsConcepts.populationCategoryConcept, + obsConcepts.priorityPopulationTypeConcept, + obsConcepts.regimenConcept, + obsConcepts.regimenLine_UUID, + obsConcepts.substitutionDateUUID, + obsConcepts.switchDateUUID, + t, + ], ); const columnsHIVMonitoring: EncounterTileColumn[] = useMemo( @@ -127,7 +148,17 @@ const ServiceSummaryOverviewList: React.FC = ({ patientUuid } }, }, ], - [], + [ + encounterTypes.CD4LabResultsEncounter_UUID, + encounterTypes.ViralLoadResultsEncounter_UUID, + encounterTypes.art_Therapy_EncounterUUID, + obsConcepts.Cd4LabResultDate_UUID, + obsConcepts.ReasonForViralLoad_UUID, + obsConcepts.ViralLoadResultDate_UUID, + obsConcepts.ViralLoadResult_UUID, + obsConcepts.hivCD4Count_UUID, + t, + ], ); const columnsLastVisitDetails: EncounterTileColumn[] = useMemo( @@ -179,7 +210,16 @@ const ServiceSummaryOverviewList: React.FC = ({ patientUuid } }, }, ], - [], + [ + encounterTypes.clinicalVisitEncounterType, + encounterTypes.hivProgramStatusEncounterType, + obsConcepts.dateOfEncounterConcept, + obsConcepts.generalTreatmentStatusConcept, + obsConcepts.opportunisticInfectionConcept, + obsConcepts.returnVisitDateConcept, + obsConcepts.tbScreeningOutcome, + t, + ], ); const calculateDateDifferenceInDate = (givenDate: string): string => { diff --git a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/linked-to-care-in-last-14-days-list-tile.component.tsx b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/linked-to-care-in-last-14-days-list-tile.component.tsx index 48eda37d2..033630eb6 100644 --- a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/linked-to-care-in-last-14-days-list-tile.component.tsx +++ b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/linked-to-care-in-last-14-days-list-tile.component.tsx @@ -98,7 +98,7 @@ export const LinkedToCareInLast14Days: React.FC<{}> = () => { setTotalPatientCount(response.length); setIsLoading(false); }); - }, [pageSize, currentPage]); + }, [pageSize, currentPage, obsConcepts.linkedToCareCodeConcept, obsConcepts.linkedToCareYesValueConcept]); useEffect(() => { attach('linked-to-care-last-14-days-table-slot', 'patient-table'); @@ -146,7 +146,7 @@ export const LinkedToCareInLast14Days: React.FC<{}> = () => { useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); return (
diff --git a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/positive-in-last-14-days-list-tile.component.tsx b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/positive-in-last-14-days-list-tile.component.tsx index e6ccf7c41..e01feb6cd 100644 --- a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/positive-in-last-14-days-list-tile.component.tsx +++ b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/positive-in-last-14-days-list-tile.component.tsx @@ -98,7 +98,7 @@ export const PositiveInLast14Days: React.FC<{}> = () => { setTotalPatientCount(response.length); setIsLoading(false); }); - }, [pageSize, currentPage]); + }, [pageSize, currentPage, obsConcepts.hivTestResultConceptUUID, obsConcepts.finalPositiveHIVValueConcept]); useEffect(() => { attach('positive-in-last-14-days-table-slot', 'patient-table'); @@ -146,7 +146,7 @@ export const PositiveInLast14Days: React.FC<{}> = () => { useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); return (
diff --git a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/today-client-list-tile.component.tsx b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/today-client-list-tile.component.tsx index a07d27bbc..91ca04e78 100644 --- a/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/today-client-list-tile.component.tsx +++ b/packages/esm-hiv-prevention-app/src/views/testing-services/summary-tiles/today-client-list-tile.component.tsx @@ -144,7 +144,7 @@ export const TodaysClientList: React.FC<{}> = () => { useEffect(() => { setCounter(counter + 1); - }, [state]); + }, [counter, state]); return (
diff --git a/packages/esm-ohri-core-app/src/ohri-dashboard/ohri-dashboard.component.tsx b/packages/esm-ohri-core-app/src/ohri-dashboard/ohri-dashboard.component.tsx index d4a5801a9..f7b0568c6 100644 --- a/packages/esm-ohri-core-app/src/ohri-dashboard/ohri-dashboard.component.tsx +++ b/packages/esm-ohri-core-app/src/ohri-dashboard/ohri-dashboard.component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState, useCallback } from 'react'; import { attach, detach, ExtensionSlot, isDesktop, useExtensionSlotMeta, useLayoutType } from '@openmrs/esm-framework'; import styles from './ohri-dashboard.scss'; import { useParams } from 'react-router-dom'; @@ -11,13 +11,17 @@ const OHRIDashboard = () => { const [currentDashboard, setCurrentDashboard] = useState(null); const layout = useLayoutType(); - useEffect(() => { + const updateCurrentDashboard = useCallback(() => { if (view) { setCurrentDashboard(dashboards.find((db) => db.name == view)); } else if (!currentDashboard) { setCurrentDashboard(dashboards[0]); } - }, [view, dashboards]); + }, [view, dashboards, currentDashboard]); + + useEffect(() => { + updateCurrentDashboard(); + }, [view, dashboards, currentDashboard, updateCurrentDashboard]); useEffect(() => { if (!isDesktop(layout)) { @@ -26,7 +30,7 @@ const OHRIDashboard = () => { return () => detach('nav-menu-slot', 'ohri-nav-items-ext'); }, [layout]); - useEffect(() => { + const updateDashboards = useCallback(() => { const programSpecificLinks = metaFolders ? Object.values(metaFolders).filter((link) => link.isLink) : []; const linksWithDashboardMeta = [ ...Object.values(metaLinks).filter((link) => Object.keys(link).length), @@ -35,7 +39,11 @@ const OHRIDashboard = () => { if (linksWithDashboardMeta.length) { setDashboards([...dashboards, ...linksWithDashboardMeta]); } - }, [metaLinks, metaFolders]); + }, [metaLinks, metaFolders, dashboards]); + + useEffect(() => { + updateDashboards(); + }, [metaLinks, metaFolders, updateDashboards]); const state = useMemo(() => { if (currentDashboard) { @@ -46,17 +54,15 @@ const OHRIDashboard = () => { return (
- {Object.values(metaFolders).map((f, index) => { - return ( - - ); - })} + {Object.values(metaFolders).map((f, index) => ( + + ))} {isDesktop(layout) && }
{currentDashboard && } @@ -67,14 +73,15 @@ const OHRIDashboard = () => { const GroupAbleMenuItem = ({ groupSlot, dashboards, setDashboards, updateDashboardState }) => { const meta = useExtensionSlotMeta(groupSlot); + useEffect(() => { if (meta && Object.keys(meta).length) { - dashboards.push(...Object.values(meta).filter((entry) => Object.keys(entry).length)); - updateDashboardState && setDashboards([...dashboards]); + const newDashboards = [...dashboards, ...Object.values(meta).filter((entry) => Object.keys(entry).length)]; + updateDashboardState && setDashboards(newDashboards); } - }, [meta]); + }, [dashboards, meta, setDashboards, updateDashboardState]); - return <>; + return null; }; export default OHRIDashboard; diff --git a/packages/esm-ohri-pmtct-app/src/views/mch-summary/mch-summary.component.tsx b/packages/esm-ohri-pmtct-app/src/views/mch-summary/mch-summary.component.tsx index 02da5dc63..58c064374 100644 --- a/packages/esm-ohri-pmtct-app/src/views/mch-summary/mch-summary.component.tsx +++ b/packages/esm-ohri-pmtct-app/src/views/mch-summary/mch-summary.component.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Tabs, Tab, TabList, TabPanels, TabPanel, DataTableSkeleton } from '@carbon/react'; import styles from '../common.scss'; -import { PatientChartProps } from '@ohri/openmrs-esm-ohri-commons-lib'; +import type { PatientChartProps } from '@ohri/openmrs-esm-ohri-commons-lib'; import CurrentPregnancy from './tabs/current-pregnancy.component'; import HivExposedInfant from './tabs/hiv-exposed-infant.component'; import { usePatient, useConfig } from '@openmrs/esm-framework'; diff --git a/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/current-pregnancy.component.tsx b/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/current-pregnancy.component.tsx index 0fe7a9de2..abbb0d2fa 100644 --- a/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/current-pregnancy.component.tsx +++ b/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/current-pregnancy.component.tsx @@ -1,18 +1,16 @@ -import React, { useEffect, useState, useMemo } from 'react'; +import React, { useEffect, useState, useMemo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { - PatientChartProps, ExpandableList, getObsFromEncounter, fetchPatientRelationships, - EncounterListColumn, EncounterList, basePath, fetchPatientLastEncounter, - SummaryCardColumn, SummaryCard, useDataFetch, } from '@ohri/openmrs-esm-ohri-commons-lib'; +import type { PatientChartProps, EncounterListColumn, SummaryCardColumn } from '@ohri/openmrs-esm-ohri-commons-lib'; import dayjs from 'dayjs'; import { moduleName } from '../../..'; import { Link } from '@carbon/react'; @@ -79,6 +77,42 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId key: 'finalOutcome', }, ]; + const getParentCurrentLabourAndDeliveryEncounter = useCallback(async () => { + const currentPregnancyANCEncounter = await fetchPatientLastEncounter(patientUuid, encounterTypes.antenatal); + const currentPregnancyLabourAndDeliveryEncounter = await fetchPatientLastEncounter( + patientUuid, + encounterTypes.labourAndDelivery, + ); + if ( + currentPregnancyLabourAndDeliveryEncounter?.encounterDatetime > currentPregnancyANCEncounter?.encounterDatetime || + currentPregnancyANCEncounter?.encounterDatetime == null + ) { + if (currentPregnancyLabourAndDeliveryEncounter !== null) { + setPregnancyOutcomes( + currentPregnancyLabourAndDeliveryEncounter.obs?.filter( + (obs) => obs.concept.uuid === obsConcepts.infantDeliveryGroupingConcept, + ), + ); + } + } + }, [ + encounterTypes.antenatal, + encounterTypes.labourAndDelivery, + obsConcepts.infantDeliveryGroupingConcept, + patientUuid, + ]); + + const getParentRelationships = useCallback(async () => { + let relationships = []; + const relationshipsData = await fetchPatientRelationships(patientUuid); + if (relationshipsData?.length) { + relationshipsData.forEach((item) => { + relationships.push(item); + }); + } + setRelatives(relationships); + }, [patientUuid]); + const headersPregnancyOutcome = [ { header: t('pTrackerId', 'PTracker ID'), @@ -100,48 +134,24 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId useEffect(() => { getParentCurrentLabourAndDeliveryEncounter(); getParentRelationships(); - }, []); + }, [getParentCurrentLabourAndDeliveryEncounter, getParentRelationships]); - async function getParentRelationships() { - let relationships = []; - const relationshipsData = await fetchPatientRelationships(patientUuid); - if (relationshipsData?.length) { - relationshipsData.forEach((item) => { - relationships.push(item); - }); - } - setRelatives(relationships); - } - - async function getParentCurrentLabourAndDeliveryEncounter() { - const currentPregnancyANCEncounter = await fetchPatientLastEncounter(patientUuid, encounterTypes.antenatal); - const currentPregnancyLabourAndDeliveryEncounter = await fetchPatientLastEncounter( - patientUuid, - encounterTypes.labourAndDelivery, - ); - if ( - currentPregnancyLabourAndDeliveryEncounter?.encounterDatetime > currentPregnancyANCEncounter?.encounterDatetime || - currentPregnancyANCEncounter?.encounterDatetime == null - ) { - if (currentPregnancyLabourAndDeliveryEncounter !== null) { - setPregnancyOutcomes( - currentPregnancyLabourAndDeliveryEncounter.obs?.filter( - (obs) => obs.concept.uuid === obsConcepts.infantDeliveryGroupingConcept, - ), - ); + const getChildPTracker = useCallback( + async (patientUuid) => { + let pTrackerMap = { patientId: patientUuid, pTrackerId: '--' }; + const identifiers = await fetchPatientIdentifiers(patientUuid); + if (identifiers?.length) { + pTrackerMap.pTrackerId = + identifiers.find((id) => id.identifierType.uuid === encounterTypes.PTrackerIdentifierType)?.identifier ?? + '--'; } - } - } - useEffect(() => { - const relativeToPtrackerPromises = relatives.map((relative) => getChildPTracker(relative.personB.uuid)); - Promise.all(relativeToPtrackerPromises).then((values) => { - setRelativeToIdentifierMap(values.map((value) => ({ patientId: value.patientId, pTrackerId: value.pTrackerId }))); - }); - getInfantOutcome(); - }, [relatives]); + return pTrackerMap; + }, + [encounterTypes.PTrackerIdentifierType], + ); - const getInfantOutcome = () => { - const infantOutcomes = relatives.map(async (relative) => { + const getInfantOutcome = useCallback(() => { + const infantOutcomesPromises = relatives.map(async (relative) => { const finalOutcome = await fetchChildLatestFinalOutcome( relative.personB.uuid, obsConcepts.outcomeStatus, @@ -150,20 +160,18 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId return { finalOutcome: finalOutcome, childUuid: relative.personB.uuid }; }); - Promise.all(infantOutcomes).then((values) => { + Promise.all(infantOutcomesPromises).then((values) => { setInfantOutcomes(values.map((value) => ({ finalOutcome: value.finalOutcome, childUuid: value.childUuid }))); }); - }; + }, [encounterTypes.infantPostnatal, obsConcepts.outcomeStatus, relatives]); - async function getChildPTracker(patientUuid: string) { - let pTrackerMap = { patientId: patientUuid, pTrackerId: '--' }; - const identifiers = await fetchPatientIdentifiers(patientUuid); - if (identifiers?.length) { - pTrackerMap.pTrackerId = - identifiers.find((id) => id.identifierType.uuid === encounterTypes.PTrackerIdentifierType)?.identifier ?? '--'; - } - return pTrackerMap; - } + useEffect(() => { + const relativeToPtrackerPromises = relatives.map((relative) => getChildPTracker(relative.personB.uuid)); + Promise.all(relativeToPtrackerPromises).then((values) => { + setRelativeToIdentifierMap(values.map((value) => ({ patientId: value.patientId, pTrackerId: value.pTrackerId }))); + }); + getInfantOutcome(); + }, [getChildPTracker, getInfantOutcome, relatives]); const parentRelationships: familyItemProps[] = useMemo(() => { let items = []; @@ -219,7 +227,13 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId items.push(childObject); }); return items; - }, [pregnancyOutcomes, infantOutcomes]); + }, [ + pregnancyOutcomes, + obsConcepts.infantStatusAtBirthConcept, + obsConcepts.infantPTrackerIdConcept, + obsConcepts.infantDateOfBirth, + obsConcepts.breastfeedingStatus, + ]); const currentPregnancyColumns: SummaryCardColumn[] = useMemo( () => [ @@ -302,7 +316,15 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId }, }, ], - [], + [ + encounterTypes.antenatal, + encounterTypes.labourAndDelivery, + encounterTypes.motherPostnatal, + obsConcepts.artInitiationConcept, + obsConcepts.artStartDate, + obsConcepts.pTrackerIdConcept, + t, + ], ); const appointmentsColumns: SummaryCardColumn[] = useMemo( @@ -332,7 +354,21 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId }, }, ], - [totalAncCount], + [encounterTypes.antenatal, obsConcepts.nextVisitDateConcept, t, totalAncCount], + ); + + const selectMCHFormViewAction = useCallback( + (encounter) => { + const encounterType = encounter.encounterType.name; + if (encounterType === 'Antenatal') { + return { name: formNames.antenatal }; + } else if (encounterType === 'Labor and Delivery') { + return { name: formNames.labourAndDelivery }; + } else { + return { name: formNames.motherPostnatal }; + } + }, + [formNames.antenatal, formNames.labourAndDelivery, formNames.motherPostnatal], ); const columnsMotherPreviousVisit: EncounterListColumn[] = useMemo( @@ -379,7 +415,7 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId ], }, ], - [], + [obsConcepts.followUpDateConcept, obsConcepts.visitDate, selectMCHFormViewAction, t], ); const getLatestArtDetails = (pncArtData, lndArtData, ancArtData) => { @@ -404,17 +440,6 @@ const CurrentPregnancy: React.FC = ({ patientUuid, pTrackerId return `${totalDays} day(s)`; }; - const selectMCHFormViewAction = (encounter) => { - const encounterType = encounter.encounterType.name; - if (encounterType === 'Antenatal') { - return { name: formNames.antenatal }; - } else if (encounterType === 'Labor and Delivery') { - return { name: formNames.labourAndDelivery }; - } else { - return { name: formNames.motherPostnatal }; - } - }; - return (
diff --git a/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/hiv-exposed-infant.component.tsx b/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/hiv-exposed-infant.component.tsx index f7c75a4ba..8a5b5ae1a 100644 --- a/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/hiv-exposed-infant.component.tsx +++ b/packages/esm-ohri-pmtct-app/src/views/mch-summary/tabs/hiv-exposed-infant.component.tsx @@ -1,21 +1,20 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ExpandableList, getObsFromEncounter, - EncounterListColumn, EncounterList, fetchPatientRelationships, basePath, SummaryCard, - SummaryCardColumn, } from '@ohri/openmrs-esm-ohri-commons-lib'; +import type { EncounterListColumn, SummaryCardColumn } from '@ohri/openmrs-esm-ohri-commons-lib'; import { navigate, useConfig } from '@openmrs/esm-framework'; import dayjs from 'dayjs'; import { Link } from '@carbon/react'; import { moduleName } from '../../..'; import { fetchPatientIdentifiers } from '../../../api/api'; -import { familyItemProps } from './current-pregnancy.component'; +import { type familyItemProps } from './current-pregnancy.component'; const HivExposedInfant: React.FC<{ patientUuid: string; @@ -26,9 +25,20 @@ const HivExposedInfant: React.FC<{ const [relativeToIdentifierMap, setRelativeToIdentifierMap] = useState([]); const { formNames, formUuids, encounterTypes, obsConcepts } = useConfig(); + const getParentRelationships = useCallback(async () => { + let relationships = []; + const relationshipsData = await fetchPatientRelationships(patientUuid); + if (relationshipsData?.length) { + relationshipsData.forEach((item) => { + relationships.push(item); + }); + } + setRelatives(relationships); + }, [patientUuid]); + useEffect(() => { getParentRelationships(); - }, []); + }, [getParentRelationships]); const infantSummaryColumns: SummaryCardColumn[] = useMemo( () => [ @@ -65,7 +75,14 @@ const HivExposedInfant: React.FC<{ }, }, ], - [], + [ + encounterTypes.infantPostnatal, + obsConcepts.artProphylaxisStatus, + obsConcepts.breastfeedingStatus, + obsConcepts.finalTestResults, + obsConcepts.outcomeStatus, + t, + ], ); const hivMonitoringColumns: EncounterListColumn[] = useMemo(() => { @@ -100,7 +117,7 @@ const HivExposedInfant: React.FC<{ }, }, ]; - }, []); + }, [obsConcepts.artStartDate, obsConcepts.finalTestResults, obsConcepts.testTypeConcept, t]); const familyHeaders = [ { @@ -125,35 +142,28 @@ const HivExposedInfant: React.FC<{ }, ]; - async function getParentRelationships() { - let relationships = []; - const relationshipsData = await fetchPatientRelationships(patientUuid); - if (relationshipsData?.length) { - relationshipsData.forEach((item) => { - relationships.push(item); - }); - } - setRelatives(relationships); - } + const getChildPTracker = useCallback( + async (patientUuid) => { + let pTrackerMap = { patientId: '', pTrackerId: '--' }; + const identifiers = await fetchPatientIdentifiers(patientUuid); + if (identifiers) { + pTrackerMap.pTrackerId = identifiers.find( + (id) => id.identifierType.uuid === encounterTypes.PTrackerIdentifierType, + ).identifier; + pTrackerMap.patientId = patientUuid; + } + return pTrackerMap; + }, + [encounterTypes.PTrackerIdentifierType], + ); useEffect(() => { const relativeToPtrackerPromises = relatives.map((relative) => getChildPTracker(relative.personA.uuid)); Promise.all(relativeToPtrackerPromises).then((values) => { setRelativeToIdentifierMap(values.map((value) => ({ patientId: value.patientId, pTrackerId: value.pTrackerId }))); }); - }, [relatives]); + }, [getChildPTracker, relatives]); - async function getChildPTracker(patientUuid: string) { - let pTrackerMap = { patientId: '', pTrackerId: '--' }; - const identifiers = await fetchPatientIdentifiers(patientUuid); - if (identifiers) { - pTrackerMap.pTrackerId = identifiers.find( - (id) => id.identifierType.uuid === encounterTypes.PTrackerIdentifierType, - ).identifier; - pTrackerMap.patientId = patientUuid; - } - return pTrackerMap; - } const parentRelationships: familyItemProps[] = useMemo(() => { let items = []; relatives.forEach((relative) => { @@ -225,7 +235,7 @@ const HivExposedInfant: React.FC<{ ], }, ], - [], + [obsConcepts.followUpDateConcept, obsConcepts.infantVisitDate, t], ); const previousVisitsTitle = t('previousVisitsSummary', 'Previous Visits'); diff --git a/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tb-patient-list-tabs.component.tsx b/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tb-patient-list-tabs.component.tsx index 81f9f6050..c938acc5e 100644 --- a/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tb-patient-list-tabs.component.tsx +++ b/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tb-patient-list-tabs.component.tsx @@ -75,7 +75,17 @@ function TbHomePatientTabs() { viewPatientProgramSummary: true, }, ], - [], + [ + config.cohorts.clientsEnrolledForTb, + config.encounterTypes.tbProgramEnrollment, + config.encounterTypes.tbTreatmentAndFollowUp, + config.obsConcepts.caseID, + config.obsConcepts.drugSensitivity, + config.obsConcepts.nextAppointmentDate, + config.obsConcepts.outcome, + config.obsConcepts.site, + t, + ], ); return ; } diff --git a/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tpt-patient-list-tabs.component.tsx b/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tpt-patient-list-tabs.component.tsx index 15f20b8bb..af17d923f 100644 --- a/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tpt-patient-list-tabs.component.tsx +++ b/packages/esm-tb-app/src/views/dashboard/patient-list-tabs/tpt-patient-list-tabs.component.tsx @@ -50,7 +50,14 @@ function TptPatientListTabs() { viewTptPatientProgramSummary: true, }, ], - [], + [ + cohorts.clientsEnrolledForTpt, + encounterTypes.tptCaseEnrollment, + obsConcepts.tptEnrollmentDate, + obsConcepts.tptIndication, + obsConcepts.tptTreatmentId, + t, + ], ); return ; } diff --git a/packages/esm-tb-app/src/views/dashboard/summary-tiles/tb-summary-tiles.component.tsx b/packages/esm-tb-app/src/views/dashboard/summary-tiles/tb-summary-tiles.component.tsx index e309f4970..00438fe1d 100644 --- a/packages/esm-tb-app/src/views/dashboard/summary-tiles/tb-summary-tiles.component.tsx +++ b/packages/esm-tb-app/src/views/dashboard/summary-tiles/tb-summary-tiles.component.tsx @@ -41,7 +41,7 @@ function TbSummaryTiles() { value: activeDRClientsCount, }, ], - [activeDSClientsCount, activeDRClientsCount], + [t, activeDSClientsCount, activeDRClientsCount], ); return ; diff --git a/packages/esm-tb-app/src/views/dashboard/summary-tiles/tpt-summary-tiles.component.tsx b/packages/esm-tb-app/src/views/dashboard/summary-tiles/tpt-summary-tiles.component.tsx index 2f2c367bb..66d98663a 100644 --- a/packages/esm-tb-app/src/views/dashboard/summary-tiles/tpt-summary-tiles.component.tsx +++ b/packages/esm-tb-app/src/views/dashboard/summary-tiles/tpt-summary-tiles.component.tsx @@ -14,7 +14,7 @@ function TptPreventionSummaryTiles() { value: activeTptClientsCount, }, ], - [], + [activeTptClientsCount, t], ); return ; } diff --git a/packages/esm-tb-app/src/views/program-management/tb-program-management.tsx b/packages/esm-tb-app/src/views/program-management/tb-program-management.tsx index 618843b75..40c741650 100644 --- a/packages/esm-tb-app/src/views/program-management/tb-program-management.tsx +++ b/packages/esm-tb-app/src/views/program-management/tb-program-management.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useConfig } from '@openmrs/esm-framework'; import { Tabs, Tab, TabList, TabPanels, TabPanel } from '@carbon/react'; import styles from '../common.scss'; -import { PatientChartProps, getMenuItemTabConfiguration, EncounterList } from '@ohri/openmrs-esm-ohri-commons-lib'; +import { type PatientChartProps, getMenuItemTabConfiguration, EncounterList } from '@ohri/openmrs-esm-ohri-commons-lib'; import tptProgramManagemetConfigSchema from './tb-program-management-config.json'; interface OverviewListProps { patientUuid: string;