@@ -2,76 +2,120 @@ import React, { useState, useEffect, useMemo, useCallback } from 'react';
2
2
import { usePatientListData } from '../patientListData' ;
3
3
import { useTranslation } from 'react-i18next' ;
4
4
import { addPatientToList , getPatientListsForPatient } from '../patientListData/api' ;
5
- import { toOmrsIsoString } from '@openmrs/esm-framework' ;
5
+ import { toOmrsIsoString , showToast , showModal , usePagination } from '@openmrs/esm-framework' ;
6
6
import Search from 'carbon-components-react/lib/components/Search' ;
7
7
import Button from 'carbon-components-react/lib/components/Button' ;
8
+ import Pagination from 'carbon-components-react/lib/components/Pagination' ;
8
9
import Checkbox from 'carbon-components-react/lib/components/Checkbox' ;
9
10
import SkeletonText from 'carbon-components-react/es/components/SkeletonText' ;
10
11
import styles from './add-patient-to-list.scss' ;
11
12
13
+ function getPatientUuidFromUrl ( ) : string {
14
+ const match = / \/ p a t i e n t \/ ( [ a - z A - Z 0 - 9 \- ] + ) \/ ? / . exec ( location . pathname ) ;
15
+ return match && match [ 1 ] ;
16
+ }
17
+
12
18
interface AddPatientProps {
13
- close : ( ) => void ;
14
- patientUuid : string ;
19
+ closeModal : ( ) => void ;
20
+ }
21
+
22
+ interface PatientListProp {
23
+ name : string ;
24
+ visible : boolean ;
25
+ selected : boolean ;
15
26
}
16
27
17
- const AddPatient : React . FC < AddPatientProps > = ( { close, patientUuid } ) => {
28
+ type PatientListObj = Record < string , PatientListProp > ;
29
+
30
+ const AddPatient : React . FC < AddPatientProps > = ( { closeModal } ) => {
18
31
const { t } = useTranslation ( ) ;
19
32
const [ searchValue , setSearchValue ] = useState ( '' ) ;
20
33
const { loading, data } = usePatientListData ( ) ;
21
- const [ selectedLists , setSelectedList ] = useState ( { } ) ;
34
+ const [ page , setPage ] = useState ( 1 ) ;
35
+ const [ patientListsObj , setPatientListsObj ] = useState < PatientListObj | null > ( null ) ;
36
+ const patientUuid = getPatientUuidFromUrl ( ) ;
22
37
23
38
useEffect ( ( ) => {
24
39
if ( data ) {
25
- const lists = { } ;
40
+ const lists : PatientListObj = { } ;
26
41
data . map ( ( patientList ) => {
27
42
lists [ patientList . id ] = {
28
43
visible : true ,
29
44
selected : false ,
45
+ name : patientList ?. display ,
30
46
} ;
31
47
} ) ;
32
48
getPatientListsForPatient ( patientUuid ) . then ( ( enrolledPatientLists ) => {
33
49
enrolledPatientLists . forEach ( ( patientList ) => {
34
50
lists [ patientList . cohort . uuid ] . visible = false ;
35
51
} ) ;
36
- setSelectedList ( lists ) ;
52
+ setPatientListsObj ( lists ) ;
37
53
} ) ;
38
54
}
39
55
} , [ data ] ) ;
40
56
41
- const searchResults = useMemo ( ( ) => {
42
- if ( data ) {
43
- if ( searchValue && searchValue . trim ( ) !== '' ) {
44
- const search = searchValue . toLowerCase ( ) ;
45
- return data . filter ( ( patientList ) => patientList . display . toLowerCase ( ) . includes ( search ) ) ;
46
- } else {
47
- return data ;
48
- }
49
- } else {
50
- return [ ] ;
51
- }
52
- } , [ searchValue , data ] ) ;
53
-
54
57
const handleChange = useCallback ( ( uuid , e ) => {
55
- setSelectedList ( ( selectedLists ) => ( {
56
- ...selectedLists ,
58
+ setPatientListsObj ( ( patientListsObj ) => ( {
59
+ ...patientListsObj ,
57
60
[ uuid ] : {
58
- ...selectedLists [ uuid ] ,
61
+ ...patientListsObj [ uuid ] ,
59
62
selected : e ,
60
63
} ,
61
64
} ) ) ;
62
65
} , [ ] ) ;
63
66
67
+ const handleClose = useCallback ( ( ) => {
68
+ closeModal ( ) ;
69
+ } , [ ] ) ;
70
+
64
71
const handleSubmit = useCallback ( ( ) => {
65
- Object . keys ( selectedLists ) . forEach ( ( patientListUuid ) => {
66
- if ( selectedLists [ patientListUuid ] . selected ) {
72
+ Object . keys ( patientListsObj ) . forEach ( ( patientListUuid ) => {
73
+ if ( patientListsObj [ patientListUuid ] . selected ) {
67
74
addPatientToList ( {
68
75
patient : patientUuid ,
69
76
cohort : patientListUuid ,
70
77
startDate : toOmrsIsoString ( new Date ( ) ) ,
71
- } ) ;
78
+ } )
79
+ . then ( ( ) =>
80
+ showToast ( {
81
+ title : 'Successfully added' ,
82
+ kind : 'success' ,
83
+ description : `Patient added to ${ patientListsObj [ patientListUuid ] . name } list successfully.` ,
84
+ } ) ,
85
+ )
86
+ . catch ( ( ) =>
87
+ showToast ( {
88
+ title : 'Error' ,
89
+ kind : 'error' ,
90
+ description : `Patient not added to ${ patientListsObj [ patientListUuid ] . name } list.` ,
91
+ } ) ,
92
+ ) ;
72
93
}
73
94
} ) ;
74
- } , [ selectedLists ] ) ;
95
+ handleClose ( ) ;
96
+ } , [ patientListsObj ] ) ;
97
+
98
+ const searchResults = useMemo ( ( ) => {
99
+ if ( data && patientListsObj ) {
100
+ if ( searchValue && searchValue . trim ( ) !== '' ) {
101
+ const search = searchValue . toLowerCase ( ) ;
102
+ setPage ( 1 ) ;
103
+ return data . filter (
104
+ ( patientList ) =>
105
+ patientListsObj [ patientList . id ] ?. visible && patientList . display . toLowerCase ( ) . includes ( search ) ,
106
+ ) ;
107
+ } else {
108
+ return data . filter ( ( patientList ) => patientListsObj [ patientList . id ] ?. visible ) ;
109
+ }
110
+ } else {
111
+ return [ ] ;
112
+ }
113
+ } , [ searchValue , data , patientListsObj ] ) ;
114
+ const { results, goTo, currentPage, paginated } = usePagination ( searchResults , 5 ) ;
115
+
116
+ useEffect ( ( ) => {
117
+ goTo ( page ) ;
118
+ } , [ page ] ) ;
75
119
76
120
return (
77
121
< div className = { styles . modalContent } >
@@ -89,33 +133,25 @@ const AddPatient: React.FC<AddPatientProps> = ({ close, patientUuid }) => {
89
133
onChange = { ( { target } ) => {
90
134
setSearchValue ( target . value ) ;
91
135
} }
92
- onKeyPress = { ( e ) => {
93
- if ( e . key === 'Enter' ) {
94
- // trigger search or search on typing?
95
- }
96
- } }
97
136
value = { searchValue }
98
137
/>
99
138
</ div >
100
139
< div className = { styles . patientListList } >
101
140
< fieldset className = "bx--fieldset" >
102
141
< p className = "bx--label" > Patient Lists</ p >
103
- { ! loading && searchResults ? (
104
- searchResults . length > 0 ? (
105
- searchResults . map (
106
- ( patientList , ind ) =>
107
- selectedLists [ patientList . id ] ?. visible && (
108
- < div key = { ind } className = { styles . checkbox } >
109
- < Checkbox
110
- key = { ind }
111
- onChange = { ( e ) => handleChange ( patientList . id , e ) }
112
- checked = { selectedLists [ patientList . id ] ?. selected }
113
- labelText = { patientList . display }
114
- id = { patientList . id }
115
- />
116
- </ div >
117
- ) ,
118
- )
142
+ { ! loading && patientListsObj && results ? (
143
+ results . length > 0 ? (
144
+ results . map ( ( patientList , ind ) => (
145
+ < div key = { ind } className = { styles . checkbox } >
146
+ < Checkbox
147
+ key = { ind }
148
+ onChange = { ( e ) => handleChange ( patientList . id , e ) }
149
+ checked = { patientListsObj [ patientList . id ] ?. selected }
150
+ labelText = { patientList . display }
151
+ id = { patientList . id }
152
+ />
153
+ </ div >
154
+ ) )
119
155
) : (
120
156
< p className = { styles . bodyLong01 } > No patient list found</ p >
121
157
)
@@ -124,10 +160,27 @@ const AddPatient: React.FC<AddPatientProps> = ({ close, patientUuid }) => {
124
160
) }
125
161
</ fieldset >
126
162
</ div >
163
+ { paginated && (
164
+ < div className = { styles . paginationContainer } >
165
+ < span className = { `${ styles . itemsCountDisplay } ${ styles . bodyLong01 } ` } >
166
+ { results . length * currentPage } / { searchResults . length } items
167
+ </ span >
168
+ < Pagination
169
+ className = { styles . pagination }
170
+ forwardText = ""
171
+ backwardText = ""
172
+ page = { currentPage }
173
+ pageSize = { 5 }
174
+ pageSizes = { [ 5 ] }
175
+ totalItems = { searchResults . length }
176
+ onChange = { ( { page } ) => setPage ( page ) }
177
+ />
178
+ </ div >
179
+ ) }
127
180
< div className = { styles . buttonSet } >
128
181
< Button kind = "ghost" > { t ( 'createNewPatientList' , 'Create new patient list' ) } </ Button >
129
182
< div >
130
- < Button kind = "secondary" className = { styles . largeButtons } onClick = { close } >
183
+ < Button kind = "secondary" className = { styles . largeButtons } onClick = { handleClose } >
131
184
{ t ( 'cancel' , 'Cancel' ) }
132
185
</ Button >
133
186
< Button onClick = { handleSubmit } className = { styles . largeButtons } >
0 commit comments