Files
supabase/apps/studio/components/grid/hooks/useTableSort.ts
Jonathan Summers-Muir 62d00873c5 Feat/sort via column header (#35139)
* init

* update Popovers to use new hooks

* init

* Update SortPopover.tsx

* Update Header.tsx

* made primitive components for filter and sorts

* Delete FilterPopoverWrapper.tsx

* Delete SortPopoverWrapper.tsx

* remove

* Create README.md

* Update README.md

* fix sort popover issues

* Update SupabaseGrid.tsx

* move DeleteConfirmationDialogs into context

* fix issue with

* more stuff for alaister

* fix ts and tables pages

* Update ColumnMenu.tsx

* Update Header.tsx

* Update useTableSort.ts

---------

Co-authored-by: Alaister Young <a@alaisteryoung.com>
2025-05-05 21:51:33 +08:00

100 lines
3.6 KiB
TypeScript

import { useCallback, useMemo } from 'react'
import { formatSortURLParams, sortsToUrlParams } from 'components/grid/SupabaseGrid.utils'
import type { Sort } from 'components/grid/types'
import { useTableEditorFiltersSort } from 'hooks/misc/useTableEditorFiltersSort'
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
import { useSaveTableEditorState } from './useSaveTableEditorState'
/**
* Hook for managing table sort URL parameters and saving.
* Uses snapshot ONLY to get table name for formatting/mapping.
* Uses useSaveTableEditorState for saving and side effects.
* Does NOT format initial sorts (needs table name externally).
* Does NOT interact with snapshot directly.
*/
export function useTableSort() {
const { sorts: urlSorts, setParams } = useTableEditorFiltersSort()
const snap = useTableEditorTableStateSnapshot()
const { saveSortsAndTriggerSideEffects } = useSaveTableEditorState()
const tableName = useMemo(() => snap.table?.name || '', [snap])
const sorts = useMemo(() => {
return formatSortURLParams(tableName, urlSorts)
}, [tableName, urlSorts])
const onApplySorts = useCallback(
(appliedSorts: Sort[]) => {
if (!tableName) {
return console.warn(
'[useTableSort] Table name missing in callback, cannot apply sort correctly.'
)
}
const sortsWithTable = appliedSorts.map((sort) => ({ ...sort, table: tableName }))
const newUrlSorts = sortsToUrlParams(sortsWithTable)
setParams((prevParams) => ({ ...prevParams, sort: newUrlSorts }))
saveSortsAndTriggerSideEffects(newUrlSorts)
},
[snap, setParams, saveSortsAndTriggerSideEffects]
)
/**
* Adds a new sort for a column or updates the direction of an existing one.
* New sorts are added to the beginning of the array (highest precedence).
* If the column already exists, its `ascending` direction is updated.
* Calls `onApplySorts` to update URL parameters and trigger side effects.
*
* @param columnKey The key/name of the column to sort.
* @param ascending The sort direction (true for ascending, false for descending).
*/
const addOrUpdateSort = useCallback(
(columnKey: string, ascending: boolean) => {
if (!tableName || !columnKey) return
// Use the derived 'sorts' state from the hook
const existingSortIndex = sorts.findIndex((s) => s.column === columnKey)
let newSorts = [...sorts] // Create a mutable copy
if (existingSortIndex !== -1) {
// Column already exists in sorts: Update the existing sort (toggle handled by removeSort)
newSorts[existingSortIndex] = { ...newSorts[existingSortIndex], ascending: ascending }
} else {
// Column doesn't exist in sorts: Add it to the beginning
newSorts.unshift({ table: tableName, column: columnKey, ascending: ascending })
}
onApplySorts(newSorts)
},
[tableName, sorts, onApplySorts] // Depend on derived sorts and callback
)
/**
* Removes a sort criterion for a specific column.
* Calls `onApplySorts` with the filtered array to update URL parameters and trigger side effects.
*
* @param columnKey The key/name of the column to remove from sorting.
*/
const removeSort = useCallback(
(columnKey: string) => {
if (!tableName || !columnKey) return
// Use the derived 'sorts' state from the hook
const newSorts = sorts.filter((s) => s.column !== columnKey)
onApplySorts(newSorts)
},
[tableName, sorts, onApplySorts] // Depend on derived sorts and callback
)
return {
sorts,
urlSorts,
onApplySorts,
addOrUpdateSort,
removeSort,
}
}