Skip to content

Commit 359b2a1

Browse files
authored
Merge pull request #17 from AlbuquerqueRafael/feat/filters-2
feat: Adição do componente de filtros
2 parents 384fc8d + 0555f27 commit 359b2a1

File tree

13 files changed

+779
-3633
lines changed

13 files changed

+779
-3633
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v18.19.1

package-lock.json

Lines changed: 334 additions & 3598 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"react-hook-form": "^7.51.4",
3333
"react-input-mask": "^2.0.4",
3434
"react-router-dom": "^6.23.0",
35+
"react-select": "^5.8.0",
3536
"tailwind-merge": "^2.3.0",
3637
"tailwindcss-animate": "^1.0.7",
3738
"yup": "^1.4.0",

src/global.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,9 @@
8585
margin: 0;
8686
padding: 0;
8787
}
88+
89+
#root {
90+
max-width: 100vw;
91+
overflow-x: hidden;
92+
}
8893
}

src/hooks/usePaginatedQuery/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export interface IPaginatedResponse<T = any> {
33
page: number;
44
perPage: number;
55
results: T[];
6+
filters?: any
67
}

src/hooks/useShelters/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@ export interface IUseSheltersDataSupplyData {
2020
supply: { name: string };
2121
priority: number;
2222
}
23+
24+
export interface IUseShelterSearchParams {
25+
priority: number | undefined;
26+
supplies: string[] | undefined;
27+
supplyCategories: number[] | undefined;
28+
search: string | undefined;
29+
filterAvailableShelter: boolean;
30+
filterUnavailableShelter: boolean;
31+
waitingShelterAvailability: boolean;
32+
}

src/hooks/useShelters/useShelters.tsx

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { AxiosRequestConfig } from 'axios';
33

44
import { api } from '@/api';
55
import { IServerResponse } from '@/types';
6-
import { PaginatedQueryPath } from '../usePaginatedQuery/paths';
76
import { IPaginatedResponse } from '../usePaginatedQuery/types';
87
import { IUseSheltersData } from './types';
98

@@ -14,14 +13,40 @@ const useShelters = () => {
1413
page: 1,
1514
perPage: 20,
1615
results: [],
16+
filters: {
17+
search: '',
18+
priority: undefined,
19+
supplies: [],
20+
supplyCategories: [],
21+
filterAvailableShelter: false,
22+
filterUnavailableShelter: false,
23+
waitingShelterAvailability: false
24+
}
1725
});
1826

19-
const refresh = useCallback(
27+
const resetSearch = () => {
28+
const params = {
29+
search: '',
30+
priority: undefined,
31+
supplies: [],
32+
supplyCategories: [],
33+
filterAvailableShelter: false,
34+
filterUnavailableShelter: false,
35+
waitingShelterAvailability: false,
36+
page: 1,
37+
perPage: 20,
38+
}
39+
search({
40+
params: params,
41+
});
42+
}
43+
44+
const search = useCallback(
2045
(config: AxiosRequestConfig<any> = {}, append: boolean = false) => {
2146
if (!append) setLoading(true);
2247
api
23-
.get<IServerResponse<IPaginatedResponse<IUseSheltersData>>>(
24-
PaginatedQueryPath.Shelters,
48+
.get<IServerResponse<any>>(
49+
'/shelters/search',
2550
{
2651
...config,
2752
params: {
@@ -37,23 +62,45 @@ const useShelters = () => {
3762
...prev,
3863
...data.data,
3964
results: [...prev.results, ...data.data.results],
65+
filters: {
66+
search: '',
67+
priority: config.params.priority,
68+
supplies: config.params.supplies ?? [],
69+
supplyCategories: config.params.supplyCategories ?? [],
70+
filterAvailableShelter: config.params.filterAvailableShelter ?? false,
71+
filterUnavailableShelter: config.params.filterUnavailableShelter ?? false,
72+
waitingShelterAvailability: config.params.waitingShelterAvailability ?? false,
73+
}
4074
}));
4175
} else {
42-
setData(data.data);
76+
setData((prev) => ({
77+
...prev,
78+
...data.data,
79+
results: [...data.data.results],
80+
filters: {
81+
search: config.params.search,
82+
priority: config.params.priority,
83+
supplies: config.params.supplies ?? [],
84+
supplyCategories: config.params.supplyCategories ?? [],
85+
filterAvailableShelter: config.params.filterAvailableShelter ?? false,
86+
filterUnavailableShelter: config.params.filterUnavailableShelter ?? false,
87+
waitingShelterAvailability: config.params.waitingShelterAvailability ?? false,
88+
}
89+
}));
4390
}
4491
})
4592
.finally(() => {
46-
if (!append) setLoading(false);
93+
if(!append) setLoading(false);
4794
});
4895
},
4996
[]
5097
);
5198

5299
useEffect(() => {
53-
refresh();
54-
}, [refresh]);
100+
resetSearch();
101+
}, []);
55102

56-
return { data, loading, refresh };
103+
return { data, loading, search, resetSearch };
57104
};
58105

59106
export { useShelters };

src/pages/Home/Home.tsx

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,86 @@
11
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';
103

114
import { Alert, Header, NoFoundSearch, ShelterListItem } from '@/components';
125
import { Input } from '@/components/ui/input';
136
import { useShelters, useThrottle } from '@/hooks';
147
import { Button } from '@/components/ui/button';
158
import { SessionContext } from '@/contexts';
9+
import { Filter } from './components/Filter';
10+
import { IUseShelterSearchParams } from '@/hooks/useShelters/types';
1611

1712
const alertDescription =
1813
'Você pode consultar a lista de abrigos disponíveis. Ver e editar os itens que necessitam de doações.';
1914

2015
const Home = () => {
21-
const { data: shelters, loading, refresh } = useShelters();
16+
const { data: shelters, loading, search, resetSearch } = useShelters();
2217
const {
2318
loading: loadingSession,
2419
refreshSession,
2520
session,
2621
} = useContext(SessionContext);
2722
const [searchValue, setSearchValue] = useState<string>('');
23+
const [isModalOpen, setOpenModal] = useState<boolean>(false);
2824
const [, setSearch] = useThrottle<string>(
2925
{
3026
throttle: 400,
3127
callback: (v) => {
3228
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,
3533
};
36-
refresh({
37-
params: v ? params : {},
34+
35+
search({
36+
params: params,
3837
});
3938
},
4039
},
4140
[]
4241
);
42+
43+
const clearSearch = () => {
44+
setSearchValue('');
45+
resetSearch();
46+
}
47+
4348
const hasMore = useMemo(
4449
() => shelters.page * shelters.perPage < shelters.count,
4550
[shelters.page, shelters.perPage, shelters.count]
4651
);
4752

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+
4867
const handleFetchMore = useCallback(() => {
4968
const params = {
69+
...shelters.filters,
5070
page: shelters.page + 1,
5171
perPage: shelters.perPage,
72+
search: searchValue ? searchValue : '',
5273
};
5374

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);
5978

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]);
6780

6881
return (
6982
<div className="flex flex-col h-screen items-center">
83+
{isModalOpen && <Filter handleSearch={handleSearch} isModalOpen={isModalOpen} closeModal={closeModal} filters={shelters.filters} />}
7084
<Header
7185
title="SOS Rio Grande do Sul"
7286
endAdornment={
@@ -80,7 +94,7 @@ const Home = () => {
8094
loading={loading}
8195
variant="ghost"
8296
size="sm"
83-
onClick={() => refresh()}
97+
onClick={() => search()}
8498
className="disabled:bg-red-500 hover:bg-red-400"
8599
>
86100
<RotateCw size={20} className="stroke-white" />
@@ -126,6 +140,24 @@ const Home = () => {
126140
<Search name="search" size="20" className="stroke-zinc-300" />
127141
</div>
128142
</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>
129161
<main className="flex flex-col gap-4">
130162
{loading ? (
131163
<Loader className="justify-self-center self-center w-5 h-5 animate-spin" />

0 commit comments

Comments
 (0)