1
1
import { Fragment , useCallback , useContext , useMemo , useState } from 'react' ;
2
- import {
3
- RotateCw ,
4
- CircleAlert ,
5
- Search ,
6
- Loader ,
7
- LogOutIcon ,
8
- Heart ,
9
- } from 'lucide-react' ;
2
+ import { RotateCw , CircleAlert , Search , Loader , ListFilter , LogOutIcon , Heart } from 'lucide-react' ;
10
3
11
4
import { Alert , Header , NoFoundSearch , ShelterListItem } from '@/components' ;
12
5
import { Input } from '@/components/ui/input' ;
13
6
import { useShelters , useThrottle } from '@/hooks' ;
14
7
import { Button } from '@/components/ui/button' ;
15
8
import { SessionContext } from '@/contexts' ;
9
+ import { Filter } from './components/Filter' ;
10
+ import { IUseShelterSearchParams } from '@/hooks/useShelters/types' ;
16
11
17
12
const alertDescription =
18
13
'Você pode consultar a lista de abrigos disponíveis. Ver e editar os itens que necessitam de doações.' ;
19
14
20
15
const Home = ( ) => {
21
- const { data : shelters , loading, refresh } = useShelters ( ) ;
16
+ const { data : shelters , loading, search , resetSearch } = useShelters ( ) ;
22
17
const {
23
18
loading : loadingSession ,
24
19
refreshSession,
25
20
session,
26
21
} = useContext ( SessionContext ) ;
27
22
const [ searchValue , setSearchValue ] = useState < string > ( '' ) ;
23
+ const [ isModalOpen , setOpenModal ] = useState < boolean > ( false ) ;
28
24
const [ , setSearch ] = useThrottle < string > (
29
25
{
30
26
throttle : 400 ,
31
27
callback : ( v ) => {
32
28
const params = {
33
- search : `address:contains:${ v } ,name:contains:${ v } ` ,
34
- or : 'true' ,
29
+ ...shelters . filters ,
30
+ search : v ? v : '' ,
31
+ page : shelters . page ,
32
+ perPage : shelters . perPage ,
35
33
} ;
36
- refresh ( {
37
- params : v ? params : { } ,
34
+
35
+ search ( {
36
+ params : params ,
38
37
} ) ;
39
38
} ,
40
39
} ,
41
40
[ ]
42
41
) ;
42
+
43
+ const clearSearch = ( ) => {
44
+ setSearchValue ( '' ) ;
45
+ resetSearch ( ) ;
46
+ }
47
+
43
48
const hasMore = useMemo (
44
49
( ) => shelters . page * shelters . perPage < shelters . count ,
45
50
[ shelters . page , shelters . perPage , shelters . count ]
46
51
) ;
47
52
53
+ const closeModal = ( ) => {
54
+ setOpenModal ( false ) ;
55
+ }
56
+
57
+ const handleSearch = ( values : IUseShelterSearchParams ) => {
58
+ setOpenModal ( false ) ;
59
+ setSearchValue ( values . search ?? '' ) ;
60
+ search ( {
61
+ params : {
62
+ ...values
63
+ }
64
+ } ) ;
65
+ }
66
+
48
67
const handleFetchMore = useCallback ( ( ) => {
49
68
const params = {
69
+ ...shelters . filters ,
50
70
page : shelters . page + 1 ,
51
71
perPage : shelters . perPage ,
72
+ search : searchValue ? searchValue : '' ,
52
73
} ;
53
74
54
- if ( searchValue )
55
- Object . assign ( params , {
56
- search : `address:contains:${ searchValue } ,name:contains:${ searchValue } ` ,
57
- or : 'true' ,
58
- } ) ;
75
+ search ( {
76
+ params : params ,
77
+ } , true ) ;
59
78
60
- refresh (
61
- {
62
- params,
63
- } ,
64
- true
65
- ) ;
66
- } , [ refresh , searchValue , shelters . page , shelters . perPage ] ) ;
79
+ } , [ search , searchValue , shelters . filters , shelters . page , shelters . perPage ] ) ;
67
80
68
81
return (
69
82
< div className = "flex flex-col h-screen items-center" >
83
+ { isModalOpen && < Filter handleSearch = { handleSearch } isModalOpen = { isModalOpen } closeModal = { closeModal } filters = { shelters . filters } /> }
70
84
< Header
71
85
title = "SOS Rio Grande do Sul"
72
86
endAdornment = {
@@ -80,7 +94,7 @@ const Home = () => {
80
94
loading = { loading }
81
95
variant = "ghost"
82
96
size = "sm"
83
- onClick = { ( ) => refresh ( ) }
97
+ onClick = { ( ) => search ( ) }
84
98
className = "disabled:bg-red-500 hover:bg-red-400"
85
99
>
86
100
< RotateCw size = { 20 } className = "stroke-white" />
@@ -126,6 +140,24 @@ const Home = () => {
126
140
< Search name = "search" size = "20" className = "stroke-zinc-300" />
127
141
</ div >
128
142
</ div >
143
+ < div className = "flex flex-row" >
144
+ < Button variant = "ghost" size = "sm"
145
+ className = "flex gap-2 items-center [&_svg]:stroke-blue-500"
146
+ onClick = { ( ) => setOpenModal ( true ) } >
147
+ < ListFilter className = "h-5 w-5" />
148
+ < h1 className = "font-semibold text-[16px] text-blue-500" >
149
+ Filtros
150
+ </ h1 >
151
+ </ Button >
152
+ < Button variant = "ghost" size = "sm"
153
+ className = "flex gap-2 items-center [&_svg]:stroke-blue-500"
154
+ onClick = { ( ) => clearSearch ( ) } >
155
+ < CircleAlert className = "h-5 w-5" />
156
+ < h1 className = "font-semibold text-[16px] text-blue-500" >
157
+ Limpar Filtros
158
+ </ h1 >
159
+ </ Button >
160
+ </ div >
129
161
< main className = "flex flex-col gap-4" >
130
162
{ loading ? (
131
163
< Loader className = "justify-self-center self-center w-5 h-5 animate-spin" />
0 commit comments