// @flow strict import * as React from 'react'; import get from 'lodash/get'; import sortBy from 'lodash/sortBy'; import type {GenericObject} from './Table'; export type SortDirection = 'asc' | 'desc' | 'original'; export function useSortableEntries( entries: Array, idName: $Keys, { defaultSortKey = 'id', defaultSortDirection = 'original', onSort, enableInternalSorting = true, }: { defaultSortKey?: $Keys, defaultSortDirection?: SortDirection, onSort?: (sortKey: string, sortDirection: SortDirection) => mixed, enableInternalSorting?: boolean, }, ): { handleSortClick: (sortKey: $Keys) => mixed, sortDirection: SortDirection, sortKey?: string, sortedEntries: T[], sortedKeys: $Keys[], } { const [sortKey, setSortKey] = React.useState(defaultSortKey); const [sortDirection, setSortDirection] = React.useState(defaultSortDirection); const getNextDirection = (direction: SortDirection): SortDirection => { switch (direction) { case 'original': return 'desc'; case 'asc': return 'original'; case 'desc': return 'asc'; default: return 'original'; } }; const advanceSortDirection = (dir: SortDirection) => { const nextDirection = getNextDirection(dir); // eslint-disable-next-line unused-imports/no-unused-vars setSortDirection((dir) => nextDirection); return nextDirection; }; const handleSortClick = React.useCallback( (nextSortKey: string) => { let nextSortDirection; if (nextSortKey === sortKey) { nextSortDirection = advanceSortDirection(sortDirection); } else { setSortKey(nextSortKey); nextSortDirection = 'desc'; } setSortDirection(nextSortDirection); onSort?.(nextSortKey, nextSortDirection); }, [sortKey, sortDirection, entries], ); const sortedEntries = React.useMemo(() => { if (!enableInternalSorting || sortDirection === 'original') { return entries; } const caseInsensitiveSortFunction = (entry) => { if (typeof entry[sortKey] === 'string') { return entry[sortKey].toLowerCase(); } return entry[sortKey]; }; const sortedAsc = sortBy(entries, caseInsensitiveSortFunction); return sortDirection === 'asc' ? sortedAsc : sortedAsc.reverse(); }, [sortDirection, sortKey, entries, enableInternalSorting]); const sortedKeys = React.useMemo( () => sortedEntries.map((ent) => get(ent, idName)), [sortedEntries], ); return { sortedEntries, sortedKeys, sortDirection, sortKey, handleSortClick, }; }