persistent filters
This commit is contained in:
@@ -55,6 +55,7 @@ const FoodsList: FC = () => {
|
||||
onChange={handleFiltersChange}
|
||||
initialValues={filters}
|
||||
searchField="search"
|
||||
showClearButton
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,15 +1,69 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import { useState, useMemo, useCallback, useEffect } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import type { FilterValues } from "@/components/Filters";
|
||||
import type { GetFoodsParams } from "../types/Types";
|
||||
|
||||
const DEFAULT_PAGE = 1;
|
||||
const DEFAULT_LIMIT = 10;
|
||||
|
||||
const getFiltersFromParams = (searchParams: URLSearchParams): FilterValues => {
|
||||
const filters: FilterValues = {};
|
||||
const search = searchParams.get("search");
|
||||
const categoryId = searchParams.get("categoryId");
|
||||
|
||||
if (search) filters.search = search;
|
||||
if (categoryId) filters.categoryId = categoryId;
|
||||
|
||||
return filters;
|
||||
};
|
||||
|
||||
const getPageFromParams = (searchParams: URLSearchParams): number => {
|
||||
const page = searchParams.get("page");
|
||||
const parsed = page ? parseInt(page, 10) : DEFAULT_PAGE;
|
||||
return Number.isNaN(parsed) || parsed < 1 ? DEFAULT_PAGE : parsed;
|
||||
};
|
||||
|
||||
const buildSearchParams = (filters: FilterValues, page: number): URLSearchParams => {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (page > DEFAULT_PAGE) {
|
||||
params.set("page", String(page));
|
||||
}
|
||||
|
||||
if (filters.search) {
|
||||
params.set("search", filters.search as string);
|
||||
}
|
||||
|
||||
if (filters.categoryId) {
|
||||
params.set("categoryId", filters.categoryId as string);
|
||||
}
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
export const useFoodFilters = () => {
|
||||
const [filters, setFilters] = useState<FilterValues>({});
|
||||
const [currentPage, setCurrentPage] = useState(DEFAULT_PAGE);
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const [filters, setFilters] = useState<FilterValues>(() =>
|
||||
getFiltersFromParams(searchParams),
|
||||
);
|
||||
const [currentPage, setCurrentPage] = useState(() =>
|
||||
getPageFromParams(searchParams),
|
||||
);
|
||||
const [limit] = useState(DEFAULT_LIMIT);
|
||||
|
||||
useEffect(() => {
|
||||
setFilters(getFiltersFromParams(searchParams));
|
||||
setCurrentPage(getPageFromParams(searchParams));
|
||||
}, [searchParams]);
|
||||
|
||||
const updateUrlParams = useCallback(
|
||||
(newFilters: FilterValues, page: number) => {
|
||||
setSearchParams(buildSearchParams(newFilters, page), { replace: true });
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const apiParams = useMemo<GetFoodsParams>(() => {
|
||||
const params: GetFoodsParams = {
|
||||
page: currentPage,
|
||||
@@ -20,17 +74,29 @@ export const useFoodFilters = () => {
|
||||
params.search = filters.search as string;
|
||||
}
|
||||
|
||||
if (filters.categoryId) {
|
||||
params.categoryId = filters.categoryId as string;
|
||||
}
|
||||
|
||||
return params;
|
||||
}, [filters, currentPage, limit]);
|
||||
|
||||
const handleFiltersChange = (newFilters: FilterValues) => {
|
||||
setFilters(newFilters);
|
||||
setCurrentPage(DEFAULT_PAGE);
|
||||
};
|
||||
const handleFiltersChange = useCallback(
|
||||
(newFilters: FilterValues) => {
|
||||
setFilters(newFilters);
|
||||
setCurrentPage(DEFAULT_PAGE);
|
||||
updateUrlParams(newFilters, DEFAULT_PAGE);
|
||||
},
|
||||
[updateUrlParams],
|
||||
);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
const handlePageChange = useCallback(
|
||||
(page: number) => {
|
||||
setCurrentPage(page);
|
||||
updateUrlParams(filters, page);
|
||||
},
|
||||
[filters, updateUrlParams],
|
||||
);
|
||||
|
||||
return {
|
||||
filters,
|
||||
|
||||
Reference in New Issue
Block a user