Files
backroad/app/react/components/datatables/NestedDatatable.tsx
2026-03-06 14:17:34 -03:00

113 lines
3.1 KiB
TypeScript

import { useMemo } from 'react';
import { difference } from 'lodash';
import {
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
TableOptions,
TableState,
useReactTable,
} from '@tanstack/react-table';
import { AutomationTestingProps } from '@/types';
import { defaultGetRowId } from './defaultGetRowId';
import { Table } from './Table';
import { NestedTable } from './NestedTable';
import { DatatableContent } from './DatatableContent';
import { DatatableFooter } from './DatatableFooter';
import { BasicTableSettings, DefaultType } from './types';
interface Props<D extends DefaultType> extends AutomationTestingProps {
dataset: D[];
columns: TableOptions<D>['columns'];
getRowId?(row: D): string;
emptyContentLabel?: string;
initialTableState?: Partial<TableState>;
isLoading?: boolean;
initialSortBy?: BasicTableSettings['sortBy'];
enablePagination?: boolean;
/**
* keyword to filter by
*/
search?: string;
'aria-label'?: string;
}
export function NestedDatatable<D extends DefaultType>({
columns,
dataset,
getRowId = defaultGetRowId,
emptyContentLabel,
initialTableState = {},
isLoading,
initialSortBy,
enablePagination = true,
search,
'data-cy': dataCy,
'aria-label': ariaLabel,
}: Props<D>) {
const tableInstance = useReactTable<D>({
columns,
data: dataset,
initialState: {
sorting: initialSortBy ? [initialSortBy] : [],
...initialTableState,
},
defaultColumn: {
enableColumnFilter: false,
enableHiding: false,
},
state: {
globalFilter: search,
},
getRowId,
autoResetExpanded: false,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(),
...(enablePagination && { getPaginationRowModel: getPaginationRowModel() }),
});
const tableState = tableInstance.getState();
const selectedRowModel = tableInstance.getSelectedRowModel();
const selectedItems = selectedRowModel.rows.map((row) => row.original);
const filteredItems = tableInstance
.getFilteredRowModel()
.rows.map((row) => row.original);
const hiddenSelectedItems = useMemo(
() => difference(selectedItems, filteredItems),
[selectedItems, filteredItems]
);
return (
<NestedTable>
<Table.Container noWidget>
<DatatableContent<D>
tableInstance={tableInstance}
isLoading={isLoading}
emptyContentLabel={emptyContentLabel}
renderRow={(row) => <Table.Row<D> cells={row.getVisibleCells()} />}
aria-label={ariaLabel}
data-cy={dataCy}
/>
{enablePagination && (
<DatatableFooter
onPageChange={tableInstance.setPageIndex}
onPageSizeChange={tableInstance.setPageSize}
page={tableState.pagination.pageIndex}
pageSize={tableState.pagination.pageSize}
pageCount={tableInstance.getPageCount()}
totalSelected={selectedItems.length}
totalHiddenSelected={hiddenSelectedItems.length}
/>
)}
</Table.Container>
</NestedTable>
);
}