-
Notifications
You must be signed in to change notification settings - Fork 199
/
patient-search.component.tsx
116 lines (109 loc) · 3.61 KB
/
patient-search.component.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, { useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Layer, Loading, Tile } from '@carbon/react';
import EmptyDataIllustration from '../ui-components/empty-data-illustration.component';
import CompactPatientBanner from './compact-patient-banner.component';
import Loader from './loader.component';
import type { PatientSearchResponse } from '../types';
import styles from './patient-search.scss';
interface PatientSearchProps extends PatientSearchResponse {
query: string;
}
const PatientSearch = React.forwardRef<HTMLDivElement, PatientSearchProps>(
({ isLoading, data: searchResults, fetchError, loadingNewData, setPage, hasMore, totalResults }, ref) => {
const { t } = useTranslation();
const observer = useRef(null);
const loadingIconRef = useCallback(
(node) => {
if (loadingNewData) {
return;
}
if (observer.current) {
observer.current.disconnect();
}
observer.current = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasMore) {
setPage((page) => page + 1);
}
},
{
threshold: 0.75,
},
);
if (node) {
observer.current.observe(node);
}
},
[loadingNewData, hasMore, setPage],
);
if (isLoading) {
return (
<div className={styles.searchResultsContainer} role="progressbar">
{[...Array(5)].map((_, index) => (
<Loader key={index} />
))}
</div>
);
}
if (fetchError) {
return (
<div className={styles.searchResults}>
<Layer>
<Tile className={styles.emptySearchResultsTile}>
<EmptyDataIllustration />
<div>
<p className={styles.errorMessage}>{t('error', 'Error')}</p>
<p className={styles.errorCopy}>
{t(
'errorCopy',
'Sorry, there was an error. You can try to reload this page, or contact the site administrator and quote the error code above.',
)}
</p>
</div>
</Tile>
</Layer>
</div>
);
}
if (searchResults?.length) {
return (
<div className={styles.searchResultsContainer}>
<div className={styles.searchResults}>
<p className={styles.resultsText}>
{t('searchResultsCount', '{{count}} search result', {
count: totalResults,
})}
</p>
<CompactPatientBanner patients={searchResults} ref={ref} />
{hasMore && (
<div className={styles.loadingIcon} ref={loadingIconRef}>
<Loading withOverlay={false} small />
</div>
)}
</div>
</div>
);
}
return (
<div className={styles.searchResultsContainer}>
<div className={styles.searchResults}>
<Layer>
<Tile className={styles.emptySearchResultsTile}>
<EmptyDataIllustration />
<p className={styles.emptyResultText}>
{t('noPatientChartsFoundMessage', 'Sorry, no patient charts were found')}
</p>
<p className={styles.actionText}>
<span>
{t('trySearchWithPatientUniqueID', "Try to search again using the patient's unique ID number")}
</span>
</p>
</Tile>
</Layer>
</div>
</div>
);
},
);
export default PatientSearch;