All checks were successful
continuous-integration/drone/push Build is passing
82 lines
2.4 KiB
TypeScript
82 lines
2.4 KiB
TypeScript
import { useCallback, useMemo, useState } from 'react';
|
|
|
|
export type SortDirection = 'asc' | 'desc';
|
|
|
|
export type SortState = {
|
|
field: string;
|
|
direction: SortDirection;
|
|
};
|
|
|
|
function invertDirection(direction: SortDirection): SortDirection {
|
|
return direction === 'asc' ? 'desc' : 'asc';
|
|
}
|
|
|
|
export function formatSortParam(sort: SortState | null | undefined): string | undefined {
|
|
if (!sort) {
|
|
return undefined;
|
|
}
|
|
return sort.direction === 'desc' ? `-${sort.field}` : sort.field;
|
|
}
|
|
|
|
type UseSortingResult = {
|
|
activeSort: SortState | null;
|
|
sortParam: string | undefined;
|
|
toggleSort: (field: string) => void;
|
|
setSort: (next: SortState | null) => void;
|
|
resetSort: () => void;
|
|
};
|
|
|
|
export function useSorting(defaultSort?: SortState | null): UseSortingResult {
|
|
const [overrideSort, setOverrideSort] = useState<SortState | null>(null);
|
|
|
|
const activeSort = overrideSort ?? defaultSort ?? null;
|
|
|
|
const toggleSort = useCallback(
|
|
(field: string) => {
|
|
setOverrideSort((previousOverride) => {
|
|
const baselineSort = defaultSort ?? null;
|
|
const currentSort = previousOverride ?? baselineSort;
|
|
|
|
if (!currentSort || currentSort.field !== field) {
|
|
return { field, direction: 'asc' };
|
|
}
|
|
|
|
if (baselineSort && baselineSort.field === field) {
|
|
if (previousOverride == null) {
|
|
return { field, direction: invertDirection(baselineSort.direction) };
|
|
}
|
|
if (previousOverride.direction === baselineSort.direction) {
|
|
return { field, direction: invertDirection(baselineSort.direction) };
|
|
}
|
|
return null;
|
|
}
|
|
|
|
if (previousOverride == null || previousOverride.direction === 'desc') {
|
|
return null;
|
|
}
|
|
|
|
return { field, direction: 'desc' };
|
|
});
|
|
},
|
|
[defaultSort],
|
|
);
|
|
|
|
const setSort = useCallback((next: SortState | null) => {
|
|
setOverrideSort(next);
|
|
}, []);
|
|
|
|
const resetSort = useCallback(() => {
|
|
setOverrideSort(null);
|
|
}, []);
|
|
|
|
const sortParam = useMemo(() => formatSortParam(activeSort), [activeSort]);
|
|
|
|
return {
|
|
activeSort,
|
|
sortParam,
|
|
toggleSort,
|
|
setSort,
|
|
resetSort,
|
|
};
|
|
}
|