- {datasheetList
- ?.slice((pagination.page - 1) * pagination.limit, pagination.page * pagination.limit)
- .map((datasheet: Datasheet) =>
)}
+ {paginatedItems.map((datasheet: Datasheet) => (
+
+ ))}
({
- ...routes.datasheet_list({ datastoreId, page: pageNumber, limit: pagination.limit }).link,
+ ...routes.datasheet_list({ ...filters, datastoreId, page: pageNumber, limit: limit, search, sortBy, sortOrder }).link,
})}
- defaultPage={pagination.page}
+ defaultPage={page}
/>
diff --git a/assets/entrepot/pages/datasheet/DatasheetList/DatasheetList.types.tsx b/assets/entrepot/pages/datasheet/DatasheetList/DatasheetList.types.tsx
index f05028d3..79068b6b 100644
--- a/assets/entrepot/pages/datasheet/DatasheetList/DatasheetList.types.tsx
+++ b/assets/entrepot/pages/datasheet/DatasheetList/DatasheetList.types.tsx
@@ -1,17 +1,4 @@
-export enum FilterEnum {
- ALL = 0,
- PUBLISHED = 1,
- NOT_PUBLISHED = 2,
-}
-
export enum SortByEnum {
NAME = 1,
NB_SERVICES = 2,
}
-
-export enum SortOrderEnum {
- ASCENDING = 1,
- DESCENDING = -1,
-}
-
-export type Sort = { by: SortByEnum; order: SortOrderEnum };
diff --git a/assets/hooks/useFilters.ts b/assets/hooks/useFilters.ts
new file mode 100644
index 00000000..8a01dbc1
--- /dev/null
+++ b/assets/hooks/useFilters.ts
@@ -0,0 +1,53 @@
+import { useRoute } from "@/router/router";
+
+export enum FilterEnum {
+ ALL = 0,
+ ENABLED = 1,
+ DISABLED = 2,
+}
+
+export type IFilters = Record
;
+
+const availableValues = Object.values(FilterEnum);
+
+const defaultTests = {
+ [FilterEnum.ENABLED]: (item, key) => Boolean(item[key]),
+ [FilterEnum.DISABLED]: (item, key) => !item[key],
+};
+
+function getFilteredList(list: T[], filters: IFilters, tests = defaultTests): T[] {
+ const entries = Object.entries(filters);
+ if (entries.length === 0) {
+ return list;
+ }
+
+ let filtered: T[] = list;
+ for (const [key, value] of entries) {
+ if ((value instanceof Array && value.includes(FilterEnum.ENABLED)) || value === FilterEnum.ENABLED) {
+ filtered = filtered.filter((item) => tests[FilterEnum.ENABLED](item, key));
+ }
+ if ((value instanceof Array && value.includes(FilterEnum.DISABLED)) || value === FilterEnum.DISABLED) {
+ filtered = filtered.filter((item) => tests[FilterEnum.DISABLED](item, key));
+ }
+ }
+ return filtered;
+}
+
+interface IUseFiltersResult {
+ filteredItems: T[];
+ filters: IFilters;
+}
+
+export function useFilters(data: T[], availableFilters: string[], tests = defaultTests): IUseFiltersResult {
+ const { params } = useRoute();
+ const filters = Object.fromEntries(
+ availableFilters.map((key) => {
+ const value = params[key] ? parseInt(params[key]) : FilterEnum.ALL;
+ return [key, availableValues.includes(value) ? value : FilterEnum.ALL];
+ })
+ );
+ return {
+ filteredItems: getFilteredList(data, filters, tests),
+ filters,
+ };
+}
diff --git a/assets/hooks/usePagination.ts b/assets/hooks/usePagination.ts
new file mode 100644
index 00000000..2aad51c3
--- /dev/null
+++ b/assets/hooks/usePagination.ts
@@ -0,0 +1,29 @@
+import { useRoute } from "@/router/router";
+
+interface IUsePaginationResult {
+ limit: number;
+ page: number;
+ paginatedItems: T[];
+ totalPages: number;
+}
+
+export function usePagination(data: T[], availableLimits = [20], defaultPage = 1, defaultLimit = 20): IUsePaginationResult {
+ const { params } = useRoute();
+ let limit = params["limit"] ? parseInt(params["limit"]) : defaultLimit;
+ if (!availableLimits.includes(limit)) {
+ limit = defaultLimit;
+ }
+ const totalPages = Math.ceil(data.length / limit);
+ let page = params["page"] ? parseInt(params["page"]) : defaultPage;
+ if (page > totalPages) {
+ page = totalPages;
+ } else if (page < 1) {
+ page = 1;
+ }
+ return {
+ limit,
+ page,
+ paginatedItems: data?.slice((page - 1) * limit, page * limit),
+ totalPages,
+ };
+}
diff --git a/assets/hooks/useSearch.ts b/assets/hooks/useSearch.ts
new file mode 100644
index 00000000..dfb170f5
--- /dev/null
+++ b/assets/hooks/useSearch.ts
@@ -0,0 +1,15 @@
+import { useRoute } from "@/router/router";
+
+interface IUseSearchResult {
+ search: string;
+ searchedItems: T[];
+}
+
+export function useSearch(data: T[], searchProperty = "name"): IUseSearchResult {
+ const { params } = useRoute();
+ const search = params["search"] ?? "";
+ return {
+ search,
+ searchedItems: search ? data.filter((d) => d[searchProperty].toLowerCase().includes(search.toLowerCase())) : data,
+ };
+}
diff --git a/assets/hooks/useSort.ts b/assets/hooks/useSort.ts
new file mode 100644
index 00000000..74809d30
--- /dev/null
+++ b/assets/hooks/useSort.ts
@@ -0,0 +1,42 @@
+import { useRoute } from "@/router/router";
+
+export enum SortOrderEnum {
+ ASCENDING = 1,
+ DESCENDING = -1,
+}
+
+const availableSortOrder = Object.values(SortOrderEnum);
+
+function getSortedList(list: T[], sortBy: string, sortOrder: SortOrderEnum): T[] {
+ return [...list].sort((a, b) => {
+ if (typeof a[sortBy] === "string") {
+ return a[sortBy].localeCompare(b[sortBy]) * sortOrder;
+ } else if (typeof a[sortBy] === "number") {
+ return (a[sortBy] - b[sortBy]) * sortOrder;
+ }
+ return 0;
+ });
+}
+
+interface IUseSortResult {
+ sortBy: string;
+ sortOrder: SortOrderEnum;
+ sortedItems: T[];
+}
+
+export function useSort(data: T[], availableSortBy = ["name"], defaultSortBy = "name", defaultSortOrder = SortOrderEnum.ASCENDING): IUseSortResult {
+ const { params } = useRoute();
+ let sortBy = params["sortBy"] ?? defaultSortBy;
+ if (!availableSortBy.includes(sortBy)) {
+ sortBy = defaultSortBy;
+ }
+ let sortOrder = params["sortOrder"] ? parseInt(params["sortOrder"]) : defaultSortOrder;
+ if (!availableSortOrder.includes(sortOrder)) {
+ sortOrder = defaultSortOrder;
+ }
+ return {
+ sortBy,
+ sortOrder,
+ sortedItems: getSortedList(data, sortBy, sortOrder),
+ };
+}
diff --git a/assets/router/router.ts b/assets/router/router.ts
index 14ade3e1..c954554b 100644
--- a/assets/router/router.ts
+++ b/assets/router/router.ts
@@ -81,6 +81,9 @@ const communityRoutes = {
members_list: communityRoute.extend(
{
userId: param.query.optional.string,
+ page: param.query.optional.number.default(1),
+ limit: param.query.optional.number.default(20),
+ search: param.query.optional.string.default(""),
},
() => "/membres"
),
@@ -110,6 +113,10 @@ const datastoreRoutes = {
{
page: param.query.optional.number.default(1),
limit: param.query.optional.number.default(20),
+ search: param.query.optional.string,
+ sortBy: param.query.optional.string,
+ sortOrder: param.query.optional.number.default(1),
+ published: param.query.optional.number.default(0),
},
() => "/donnees"
),