1
+ /* eslint-disable no-mixed-spaces-and-tabs */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1
3
/* eslint-disable react-hooks/exhaustive-deps */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- import { ReactNode , useEffect , useState } from 'react' ;
4
+ import { ReactNode , useEffect , useRef , useState } from 'react' ;
4
5
import { IoMdMore } from 'react-icons/io' ;
5
6
import { useAppDispatch , useAppSelector } from '../../redux/hooks/hooks' ;
6
7
import { Link } from 'react-router-dom' ;
7
- import { FaUserCircle } from 'react-icons/fa' ;
8
8
import { FaEdit } from 'react-icons/fa' ;
9
9
import { userType } from '../../@types/userType' ;
10
10
import { getRoles } from '../../redux/features/getRolesSlice' ;
11
11
import { roleType } from '../../@types/roleTypes' ;
12
- import { DynamicData } from '../../@types/DynamicData' ;
13
12
import { GrNext , GrPrevious } from 'react-icons/gr' ;
14
13
import ReactPaginate from 'react-paginate' ;
15
- import { getUser } from '../../redux/features/getUserSlice' ;
16
14
import { HashLoader } from 'react-spinners' ;
17
-
15
+ import { getUserPag } from '../../redux/features/getUserPagination' ;
16
+ import useToast from '../../hooks/useToast' ;
18
17
interface getUserType {
19
18
arrow ?: ReactNode ;
20
19
searchIcon ?: ReactNode ;
20
+ location ?: string ;
21
21
}
22
22
const GetUser = ( props : getUserType ) => {
23
23
const [ currentPage , setCurrentPage ] = useState ( 0 ) ;
24
24
const [ searchQuery , setSearchQuery ] = useState ( '' ) ;
25
25
const [ butOverlay , setButOverlay ] = useState ( '' ) ;
26
26
const roles = useAppSelector ( ( state ) => state . allRoles ?. data [ 0 ] ) ;
27
27
const roleLoading = useAppSelector ( ( state ) => state . allRoles . isLoading ) ;
28
- const { isLoading, data } = useAppSelector ( ( state ) => state . allUsers ) ;
28
+ const { isLoading, data } = useAppSelector ( ( state ) => state . userPagination ) ;
29
29
const pathname = window . location . pathname ;
30
30
const dispatch = useAppDispatch ( ) ;
31
- const itemsPerPage = 8 ;
31
+ const prevPage = useRef ( 0 ) ;
32
+ const { showErrorMessage } = useToast ( ) ;
32
33
33
34
useEffect ( ( ) => {
34
35
if ( ! roles ) {
35
- dispatch ( getRoles ( ) ) . unwrap ( ) ;
36
+ dispatch ( getRoles ( ) )
37
+ . unwrap ( )
38
+ . catch ( ( error ) => {
39
+ showErrorMessage ( error . message || 'Failed to load wishes' ) ;
40
+ } ) ;
36
41
}
37
42
} , [ dispatch ] ) ;
38
-
39
- useEffect ( ( ) => {
40
- setCurrentPage ( 0 ) ;
41
- } , [ searchQuery ] ) ;
42
-
43
43
useEffect ( ( ) => {
44
- if ( data . length === 0 ) {
45
- dispatch ( getUser ( ) ) . unwrap ( ) ;
44
+ if ( props . location ?. includes ( 'users' ) ) {
45
+ dispatch ( getUserPag ( { page : currentPage , search : searchQuery } ) )
46
+ . unwrap ( )
47
+ . catch ( ( error ) => {
48
+ showErrorMessage ( error . message || 'Failed to load wishes' ) ;
49
+ } ) ;
46
50
}
47
- } , [ dispatch ] ) ;
51
+ } , [ dispatch , currentPage , searchQuery ] ) ;
48
52
49
53
const getRoleName = ( roleId : string ) => {
50
54
return roles ?. data . find ( ( role : roleType ) => role . id === roleId ) . roleName ;
51
55
} ;
52
56
const handleOverlay = ( userId : string ) => {
53
57
setButOverlay ( userId === butOverlay ? '' : userId ) ;
54
58
} ;
59
+ useEffect ( ( ) => {
60
+ if ( data [ data ?. length - 1 ] ?. data ?. totalPages < prevPage . current ) {
61
+ setCurrentPage ( 1 ) ;
62
+ } else {
63
+ setCurrentPage ( prevPage . current ) ;
64
+ }
65
+ } , [ searchQuery , data [ data ?. length - 1 ] ?. data ?. totalPages ] ) ;
55
66
const handleSearch = ( event : React . ChangeEvent < HTMLInputElement > ) => {
56
67
setSearchQuery ( event . target . value ) ;
68
+ if ( event . target . value . length < 1 ) {
69
+ setCurrentPage ( prevPage . current ) ;
70
+ }
71
+ if ( event . target . value . length === 1 && currentPage !== 1 ) {
72
+ prevPage . current = currentPage ;
73
+ }
57
74
} ;
58
- const offset = currentPage * itemsPerPage ;
59
- const currentItems = data [ data . length - 1 ] ?. data
60
- . filter ( ( user : DynamicData ) =>
61
- user . email . toLowerCase ( ) . includes ( searchQuery . toLowerCase ( ) ) ,
62
- )
63
- . slice ( offset , offset + itemsPerPage ) ;
64
- let pageCount = 0 ;
65
- if ( data [ 0 ] ?. data ?. length ) {
66
- pageCount = Math . ceil ( data [ 0 ] ?. data ?. length / itemsPerPage ) ;
67
- }
75
+
68
76
const handlePageClick = ( event : { selected : number } ) => {
69
- setCurrentPage ( event . selected ) ;
77
+ setCurrentPage ( event . selected + 1 ) ;
78
+ prevPage . current = event . selected + 1 ;
70
79
} ;
71
80
const handleButOverlayApp = ( ) => {
72
81
if ( butOverlay ) {
73
82
setButOverlay ( '' ) ;
74
83
}
75
84
} ;
76
-
77
85
return (
78
86
< div className = "relative w-full ipad:w-[93%] ipad:m-auto shadow-2xl rounded-2xl flex flex-col h-full ipad:h-[90%] ipad:pt-6 " >
79
87
{ isLoading && roleLoading ? (
@@ -97,7 +105,6 @@ const GetUser = (props: getUserType) => {
97
105
All Users
98
106
</ p >
99
107
</ div >
100
-
101
108
< div className = "py-1 w-full flex items-center justify-center" >
102
109
< form className = "search w-[80%] flex border items-center rounded-xl py-1 px-[2%] overflow-hidden mobile:max-w-[19rem] " >
103
110
< p className = "text-[29px] flex-none " > { props . searchIcon } </ p >
@@ -110,60 +117,40 @@ const GetUser = (props: getUserType) => {
110
117
</ form >
111
118
</ div >
112
119
113
- < div className = "div-table w-full overflow-x-auto ipad:pt-1 " >
114
- < table className = " table-fixed rounded-3xl m-auto shadow-xl ipad:mt-2 " >
115
- < thead className = " w-full text-neutral-white " >
116
- < tr >
117
- < th className = " bg-primary-lightblue px-[3rem] mobile:px-[2rem] py-3 rounded-l-lg ipad:px-[1.5rem] " >
118
- No
119
- </ th >
120
- < th className = " bg-primary-lightblue px-[3rem] py-3 ipad:px-[1rem]" >
121
- Firstname
122
- </ th >
123
- < th className = " bg-primary-lightblue px-[3rem] py-3 ipad:px-[1rem]" >
124
- Lastname
125
- </ th >
126
- < th className = " bg-primary-lightblue px-[3rem] py-3 ipad:px-[1rem]" >
127
- Email
128
- </ th >
129
- < th className = " bg-primary-lightblue px-[3rem] mobile:px-[1.5rem] py-3" >
130
- Active
131
- </ th >
132
- < th className = " bg-primary-lightblue px-[3rem] mobile:px-[3rem] py-3 ipad:px-[2.5rem]" >
133
- Role
134
- </ th >
135
- < th className = " bg-primary-lightblue px-[3rem] mobile:px-[3rem] py-3 rounded-r-lg ipad:px-[1rem] " >
136
- Action
137
- </ th >
120
+ < div className = "tableWrapper mt-1 text-[1rem] mx-5 laptop:mx-10 bg-neutral-white p-4 rounded-md max-w-[95%]" >
121
+ < table className = "tables pt-2 p-3 overflow-hidden overflow-x-scroll max-w-[18rem] tablet:max-w-[100%]" >
122
+ < thead className = "bg-[#256490] text-neutral-white text-left overflow-hidden rounded-3xl p2" >
123
+ < tr className = "rounded-xl text-sm" >
124
+ < th className = "" > No</ th >
125
+ < th > Firstname</ th >
126
+ < th > Lastname</ th >
127
+ < th > Email</ th >
128
+ < th > Active</ th >
129
+ < th > Role</ th >
130
+ < th className = "expand" > Action</ th >
138
131
</ tr >
139
132
</ thead >
140
-
141
- < tbody className = " text-center rounded-3xl" >
142
- { currentItems && currentItems . length > 0 ? (
143
- currentItems . map ( ( item : userType , index : number ) => (
144
- < tr
145
- key = { item ?. id }
146
- className = { `${ index % 2 !== 0 ? 'bg-neutral-white' : 'bg-overlay bg-opacity-15' } ` }
147
- >
148
- < td className = " py-3" > { index + 1 + offset } </ td >
149
- < td className = "pl-[3rem] ipad:pl-[1rem] text-left" >
150
- { item ?. firstName }
151
- </ td >
152
- < td className = " pl-[3rem] ipad:pl-[1rem] text-left" >
153
- { ' ' }
154
- { item ?. lastName }
155
- </ td >
156
- < td className = "ipad:pl-[1rem] pl-[3rem] text-left" >
157
- { item ?. email }
158
- </ td >
159
- < td >
160
- { ' ' }
161
- { item ?. isActive === true ? 'active' : 'unactive' }
162
- </ td >
163
- < td > { getRoleName ( item . role as string ) } </ td >
164
- < td >
165
- { ' ' }
166
- < div className = "relative" >
133
+ < tbody className = "text-slate-700" >
134
+ { data [ data ?. length - 1 ] ?. data &&
135
+ data [ data ?. length - 1 ] ?. data ?. users ?. length > 0 ? (
136
+ data [ data ?. length - 1 ] ?. data ?. users . map (
137
+ ( item : userType , index : number ) => (
138
+ < tr
139
+ key = { index }
140
+ className = { `relative text-sm ${ index % 2 !== 0 ? 'bg-[#DDDD]' : '' } ` }
141
+ >
142
+ < td className = "w-20 h-16" >
143
+ { index + 1 + data [ data ?. length - 1 ] ?. data ?. offset }
144
+ </ td >
145
+ < td className = " text-sm" > { item ?. firstName } </ td >
146
+ < td > { item ?. lastName } </ td >
147
+ < td > { item ?. email } </ td >
148
+ < td >
149
+ { ' ' }
150
+ { item ?. isActive === true ? 'active' : 'unactive' }
151
+ </ td >
152
+ < td > { getRoleName ( item . role as string ) } </ td >
153
+ < td className = "cursor-ponter " >
167
154
< button
168
155
type = "button"
169
156
onClick = { ( ) => {
@@ -174,34 +161,35 @@ const GetUser = (props: getUserType) => {
174
161
< IoMdMore />
175
162
</ button >
176
163
{ butOverlay === item . id && (
177
- < div
178
- className = { ` absolute h-[6rem] w-[15rem] rounded shadow-2xl left-20 z-[900] bg-neutral-white px-4 flex flex-col gap-4 tablet:-left-40 py-2
179
- ${ index + 1 >= currentItems . length - 1 ? 'bottom-0 ' : 'left-20' }
180
- ` }
181
- >
182
- < Link to = "" className = "" >
183
- < div className = "text-[26px] flex text-center items-center gap-4 bg-neutral-grey px-2 py-1 rounded-xl bg-opacity-35 hover:bg-opacity-70" >
184
- < FaUserCircle />
185
- < p className = "text-[17px] fontp" >
186
- view user details
187
- </ p >
164
+ < div className = "absolute desktop:w-[15%] right-2 laptop:right-16 z-50 -top-10 flex p-2 rounded-lg pt-5 pl-5" >
165
+ < div className = "flex flex-col justify-between relative w-full" >
166
+ < div className = "relative" >
167
+ < div
168
+ className = { ` absolute h-[3rem] w-[15rem] rounded shadow-2xl right-3 z-[900] bg-neutral-white px-4 flex flex-col gap-4 tablet:-left-40 py-2
169
+ ${ index + 1 === 1 ? 'top-7 ' : '' }
170
+
171
+ ` }
172
+ >
173
+ < Link
174
+ to = { `/dashboard/roles/${ item . id } ` }
175
+ className = ""
176
+ >
177
+ < div className = "text-[26px] flex text-center items-center gap-4 px-2 py-1 rounded-xl bg-neutral-grey bg-opacity-35 hover:bg-opacity-70" >
178
+ < FaEdit />
179
+ < p className = "text-[17px]" >
180
+ Edit roles
181
+ </ p >
182
+ </ div >
183
+ </ Link >
184
+ </ div >
188
185
</ div >
189
- </ Link >
190
- < Link
191
- to = { `/dashboard/roles/${ item . id } ` }
192
- className = ""
193
- >
194
- < div className = "text-[26px] flex text-center items-center gap-4 px-2 py-1 rounded-xl bg-neutral-grey bg-opacity-35 hover:bg-opacity-70" >
195
- < FaEdit />
196
- < p className = "text-[17px]" > Edit roles</ p >
197
- </ div >
198
- </ Link >
186
+ </ div >
199
187
</ div >
200
188
) }
201
- </ div >
202
- </ td >
203
- </ tr >
204
- ) )
189
+ </ td >
190
+ </ tr >
191
+ ) ,
192
+ )
205
193
) : (
206
194
< tr >
207
195
< td
@@ -221,7 +209,7 @@ const GetUser = (props: getUserType) => {
221
209
nextLabel = { < GrNext /> }
222
210
breakLabel = { '...' }
223
211
breakClassName = { 'break-me' }
224
- pageCount = { pageCount }
212
+ pageCount = { data [ data ?. length - 1 ] ?. data ?. totalPages || 0 }
225
213
marginPagesDisplayed = { 2 }
226
214
pageRangeDisplayed = { 2 }
227
215
onPageChange = { handlePageClick }
@@ -239,5 +227,4 @@ const GetUser = (props: getUserType) => {
239
227
</ div >
240
228
) ;
241
229
} ;
242
-
243
230
export default GetUser ;
0 commit comments