Presupuestador_web/client/src/lib/hooks/useDataTable/useDataTable.tsx
2024-08-25 22:06:24 +02:00

218 lines
5.3 KiB
TypeScript

import {
InitialTableState,
OnChangeFn,
PaginationState,
getCoreRowModel,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getSortedRowModel,
useReactTable,
type ColumnDef,
type SortingState,
type VisibilityState,
} from "@tanstack/react-table";
import { getDataTableSelectionColumn } from "@/components";
import React, { useCallback } from "react";
import { DataTableFilterField } from "./types";
import { useDataTableContext } from "./useDataTableContext";
//import { useDebounce } from "@/hooks/use-debounce";
interface UseDataTableProps<TData, TValue> {
/**
* The data for the table.
* @default []
* @type TData[]
*/
data: TData[];
/**
* The columns of the table.
* @default []
* @type ColumnDef<TData, TValue>[]
*/
columns: ColumnDef<TData, TValue>[];
/**
* The number of pages in the table.
* @type number
*/
pageCount: number;
/**
* Enable sorting columns.
* @default false
* @type boolean
*/
enableSorting?: boolean;
/**
* Enable hiding columns.
* @default false
* @type boolean
*/
enableHiding?: boolean;
/**
* Enable selection rows.
* @default false
* @type boolean
*/
enableRowSelection?: boolean;
/**
* The default number of rows per page.
* @default 10
* @type number | undefined
* @example 20
*/
defaultPerPage?: number;
/**
* The default sort order.
* @default undefined
* @type `${Extract<keyof TData, string | number>}.${"asc" | "desc"}` | undefined
* @example "createdAt.desc"
*/
defaultSort?: `${Extract<keyof TData, string | number>}.${"asc" | "desc"}`;
/**
* Defines filter fields for the table. Supports both dynamic faceted filters and search filters.
* - Faceted filters are rendered when `options` are provided for a filter field.
* - Otherwise, search filters are rendered.
*
* The indie filter field `value` represents the corresponding column name in the database table.
* @default []
* @type { label: string, value: keyof TData, placeholder?: string, options?: { label: string, value: string, icon?: React.ComponentType<{ className?: string }> }[] }[]
* @example
* ```ts
* // Render a search filter
* const filterFields = [
* { label: "Title", value: "title", placeholder: "Search titles" }
* ];
* // Render a faceted filter
* const filterFields = [
* {
* label: "Status",
* value: "status",
* options: [
* { label: "Todo", value: "todo" },
* { label: "In Progress", value: "in-progress" },
* { label: "Done", value: "done" },
* { label: "Canceled", value: "canceled" }
* ]
* }
* ];
* ```
*/
filterFields?: DataTableFilterField<TData>[];
/**
* Enable notion like column filters.
* Advanced filters and column filters cannot be used at the same time.
* @default false
* @type boolean
*/
enableAdvancedFilter?: boolean;
initialState?: InitialTableState;
onPaginationChange?: OnChangeFn<PaginationState>;
}
export function useDataTable<TData, TValue>({
data,
columns,
pageCount,
enableSorting = false,
enableHiding = false,
enableRowSelection = false,
initialState,
onPaginationChange,
}: UseDataTableProps<TData, TValue>) {
const { pagination, setPagination, sorting } = useDataTableContext();
// Table states
const [rowSelection, setRowSelection] = React.useState({});
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>(
initialState?.columnVisibility || {}
);
const paginationUpdater: OnChangeFn<PaginationState> = (updater) => {
if (typeof updater === "function") {
const newPagination = updater(pagination);
setPagination(newPagination);
}
if (onPaginationChange) {
onPaginationChange(updater);
}
};
const sortingUpdater: OnChangeFn<SortingState> = (updater) => {
if (typeof updater === "function") {
const newSorting = updater(sorting);
console.log(newSorting);
//setSorting(newSorting);
}
};
const getTableColumns = useCallback(() => {
const _columns = columns;
if (enableRowSelection) {
_columns.unshift(getDataTableSelectionColumn());
}
return _columns;
}, [columns, enableRowSelection]);
const table = useReactTable({
data,
columns: getTableColumns(),
//autoResetPageIndex: true,
pageCount: pageCount ?? -1,
getCoreRowModel: getCoreRowModel(),
initialState,
state: {
pagination,
sorting,
columnVisibility,
rowSelection,
},
enableRowSelection,
onRowSelectionChange: setRowSelection,
manualSorting: true,
enableSorting,
getSortedRowModel: getSortedRowModel(),
onSortingChange: sortingUpdater,
enableHiding,
onColumnVisibilityChange: setColumnVisibility,
manualPagination: true,
onPaginationChange: paginationUpdater,
manualFiltering: true,
getFilteredRowModel: getFilteredRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
debugTable: false,
debugHeaders: false,
debugColumns: false,
defaultColumn: {
minSize: 0, //starting column size
size: Number.MAX_SAFE_INTEGER, //enforced during column resizing
maxSize: Number.MAX_SAFE_INTEGER, //enforced during column resizing
},
});
return { table };
}