Skip to content

Commit fe4882f

Browse files
committed
feat: add helper hook for sorting
1 parent 8a31667 commit fe4882f

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

packages/module/src/Hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './pagination';
22
export * from './selection';
33
export * from './filters';
4+
export * from './sort';

packages/module/src/Hooks/sort.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { ISortBy } from "@patternfly/react-table";
2+
import { useState, useEffect, useMemo } from "react";
3+
4+
export enum DataViewSortParams {
5+
SORT_BY = 'sortBy',
6+
DIRECTION = 'direction'
7+
};
8+
9+
const validateDirection = (direction: string | null | undefined, defaultDirection: ISortBy['direction']): ISortBy['direction'] => (
10+
direction === 'asc' || direction === 'desc' ? direction : defaultDirection
11+
);
12+
13+
export interface DataViewSortConfig {
14+
/** Attribute to sort the entries by */
15+
sortBy: string | undefined;
16+
/** Sort direction */
17+
direction: ISortBy['direction'];
18+
};
19+
20+
export interface UseDataViewSortProps {
21+
/** Initial sort config */
22+
initialSort?: DataViewSortConfig;
23+
/** Current search parameters as a string */
24+
searchParams?: URLSearchParams;
25+
/** Function to set search parameters */
26+
setSearchParams?: (params: URLSearchParams) => void;
27+
/** Default direction */
28+
defaultDirection?: ISortBy['direction'];
29+
/** Sort by URL param name */
30+
sortByParam?: string;
31+
/** Direction URL param name */
32+
directionParam?: string;
33+
};
34+
35+
export const useDataViewSort = (props?: UseDataViewSortProps) => {
36+
const {
37+
initialSort,
38+
searchParams,
39+
setSearchParams,
40+
defaultDirection = 'asc',
41+
sortByParam = DataViewSortParams.SORT_BY,
42+
directionParam = DataViewSortParams.DIRECTION
43+
} = props ?? {};
44+
45+
const isUrlSyncEnabled = useMemo(() => searchParams && !!setSearchParams, [ searchParams, setSearchParams ]);
46+
47+
const [ state, setState ] = useState<DataViewSortConfig>({
48+
sortBy: searchParams?.get(sortByParam) ?? initialSort?.sortBy,
49+
direction: validateDirection(searchParams?.get(directionParam) as ISortBy['direction'], initialSort?.direction),
50+
});
51+
52+
const updateSearchParams = (sortBy: string, direction: ISortBy['direction']) => {
53+
if (isUrlSyncEnabled && sortBy) {
54+
const params = new URLSearchParams(searchParams);
55+
params.set(sortByParam, `${sortBy}`);
56+
params.set(directionParam, `${direction}`);
57+
setSearchParams?.(params);
58+
}
59+
};
60+
61+
useEffect(() => {
62+
state.sortBy && state.direction && updateSearchParams(state.sortBy, state.direction);
63+
// eslint-disable-next-line react-hooks/exhaustive-deps
64+
}, []);
65+
66+
useEffect(() => {
67+
const currentSortBy = searchParams?.get(sortByParam) || state.sortBy;
68+
const currentDirection = searchParams?.get(directionParam) as ISortBy['direction'] || state.direction;
69+
const validDirection = validateDirection(currentDirection, defaultDirection);
70+
currentSortBy !== state.sortBy || validDirection !== state.direction && setState({ sortBy: currentSortBy, direction: validDirection });
71+
// eslint-disable-next-line react-hooks/exhaustive-deps
72+
}, [ searchParams?.toString() ]);
73+
74+
const onSort = (
75+
_event: React.MouseEvent | React.KeyboardEvent | MouseEvent | undefined,
76+
newSortBy: string,
77+
newSortDirection: ISortBy['direction']
78+
) => {
79+
setState({ sortBy: newSortBy, direction: newSortDirection });
80+
updateSearchParams(newSortBy, newSortDirection);
81+
};
82+
83+
return {
84+
...state,
85+
onSort
86+
};
87+
};

0 commit comments

Comments
 (0)