import React, { useContext, useState, useMemo } from 'react'; import classNames from 'classnames'; import { AccordionSkeleton, Button, DataTableSkeleton, Layer } from '@carbon/react'; import { useTranslation } from 'react-i18next'; import { useLayoutType, TreeViewAltIcon, useConfig } from '@openmrs/esm-framework'; import { EmptyState, ErrorState } from '@openmrs/esm-patient-common-lib'; import { type ConfigObject } from '../../config-schema'; import { type GroupedObservation, type viewOpts } from '../../types'; import FilterSet, { FilterContext } from '../filter'; import GroupedTimeline, { useGetManyObstreeData } from '../grouped-timeline'; import IndividualResultsTable from '../individual-results-table/individual-results-table.component'; import TabletOverlay from '../tablet-overlay'; import styles from '../results-viewer/results-viewer.scss'; interface TreeViewProps { patientUuid: string; expanded: boolean; view?: viewOpts; error?: string; } const GroupedPanelsTables: React.FC<{ patientUuid: string; className: string; loadingPanelData: boolean }> = ({ className, loadingPanelData, patientUuid, }) => { const { t } = useTranslation(); const { checkboxes, someChecked, tableData } = useContext(FilterContext); const selectedCheckboxes = Object.keys(checkboxes).filter((key) => checkboxes[key]); // An entry can represent several collapsed branches; match a checkbox against // every flatName that contributed to it, not just the one it carries. const entryMatchesCheckbox = (entry: GroupedObservation['entries'][number], selectedKey: string) => (entry.flatNames ?? [entry.flatName]).includes(selectedKey) || entry.key === selectedKey; const tableFilteredSubRows = useMemo( () => tableData ?.filter( (row) => !someChecked || (row.entries && Array.isArray(row.entries) && row.entries.some((entry) => selectedCheckboxes.some((selectedKey) => entryMatchesCheckbox(entry, selectedKey)), )), ) .map((subRows: GroupedObservation, index) => { return { ...subRows, entries: subRows.entries && Array.isArray(subRows.entries) ? subRows.entries.filter( (entry) => !someChecked || selectedCheckboxes.some((selectedKey) => entryMatchesCheckbox(entry, selectedKey)), ) : [], }; }), [tableData, someChecked, selectedCheckboxes], ); if (!tableData?.length) { return ; } return ( {tableFilteredSubRows.map((filteredSubRows, index) => { return filteredSubRows.entries?.length > 0 ? (
) : null; })}
); }; const TreeView: React.FC = ({ patientUuid, expanded, view }) => { const { t } = useTranslation(); const tablet = useLayoutType() === 'tablet'; const [showTreeOverlay, setShowTreeOverlay] = useState(false); const config = useConfig(); const conceptUuids = config?.resultsViewerConcepts?.map((c) => c.conceptUuid) ?? []; const { roots, error } = useGetManyObstreeData(patientUuid, conceptUuids); const { timelineData, tableData, totalResultsCount, filteredResultsCount, resetTree, isLoading } = useContext(FilterContext); if (error) { return ; } // Don't show empty state while loading - wait for data to finish loading if (isLoading) { return ; } if (!roots || roots.length === 0) { return ( ); } if (tablet) { return ( <>
{!isLoading && view === 'over-time' ? ( ) : view === 'individual-test' ? ( ) : ( )}
{showTreeOverlay && ( setShowTreeOverlay(false)} buttonsGroup={
} > {!isLoading ? : }
)} ); } return ( <> {!expanded && (
{!isLoading ? : }
)}
{isLoading ? ( ) : view === 'individual-test' ? ( tableData && tableData.length > 0 ? (
) : ( ) ) : view === 'over-time' ? ( ) : null}
); }; export default TreeView;