This commit is contained in:
2026-04-01 15:34:50 +03:00
parent 13b56d4960
commit 5f3d208158
120 changed files with 36338 additions and 21265 deletions
@@ -10,6 +10,7 @@ import {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
@@ -26,6 +27,8 @@ export function DataTable<TData>({
sorting = [],
onChange,
isLoading = false,
onRowClick,
slots,
}: DataViewProps<TData>) {
const table = useReactTable({
data,
@@ -67,9 +70,12 @@ export function DataTable<TData>({
onChange={onChange}
isLoading={isLoading}
>
<div data-slot="data-view" className="flex flex-col gap-4">
<div className="rounded-md border">
<Table>
<div data-slot="data-view" className="flex flex-col gap-2">
{slots?.actions && (
<div data-slot="data-view-actions">{slots.actions}</div>
)}
<div className="rounded-md border overflow-auto">
<Table className="w-full">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
@@ -85,6 +91,7 @@ export function DataTable<TData>({
))}
</TableRow>
))}
{slots?.extraHeader}
</TableHeader>
<TableBody>
{isLoading ? (
@@ -99,7 +106,12 @@ export function DataTable<TData>({
))
) : table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
className={onRowClick ? "cursor-pointer" : undefined}
onClick={() => onRowClick?.(row.original)}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
@@ -117,7 +129,11 @@ export function DataTable<TData>({
</TableCell>
</TableRow>
)}
{slots?.extraBody}
</TableBody>
{slots?.footer && (
<TableFooter>{slots.footer}</TableFooter>
)}
</Table>
</div>
<DataViewPagination table={table} />
@@ -11,6 +11,7 @@ export type {
DataViewSorting,
DataViewState,
DataViewChangeEvent,
DataViewSlots,
} from "./types"
export type { DataTableSearchParams } from "./search-params"
export type { ActionsColumnOptions } from "./actions-column"
@@ -1,4 +1,5 @@
import type { ColumnDef, SortingState } from "@tanstack/react-table"
import type { ReactNode } from "react"
export type DataViewPaginationState = {
page: number
@@ -18,6 +19,13 @@ export type DataViewChangeEvent =
| { type: "pagination"; pagination: DataViewPaginationState }
| { type: "sorting"; sorting: DataViewSorting }
export type DataViewSlots = {
actions?: ReactNode
extraHeader?: ReactNode
extraBody?: ReactNode
footer?: ReactNode
}
export type DataViewProps<TData> = {
columns: ColumnDef<TData, any>[]
data: TData[]
@@ -25,4 +33,6 @@ export type DataViewProps<TData> = {
sorting?: DataViewSorting
onChange: (event: DataViewChangeEvent) => void
isLoading?: boolean
onRowClick?: (row: TData) => void
slots?: DataViewSlots
}
@@ -14,21 +14,24 @@ type UseDataTableQueryOptions<C extends DataTableClient> = {
queryKey: string[]
client: C
queryOptions?: Omit<UseQueryOptions<CrudListResponse<C>>, "queryKey" | "queryFn">
extraParams?: Record<string, unknown>
}
export function useDataTableQuery<C extends DataTableClient>({
queryKey,
client,
queryOptions,
extraParams,
}: UseDataTableQueryOptions<C>) {
const [params, setParams] = useQueryStates(dataTableSearchParams)
const _queryKey = [...queryKey, params]
const _queryKey = [...queryKey, params, ...(extraParams ? [extraParams] : [])]
const query = useQuery<CrudListResponse<C>>({
queryKey: _queryKey,
queryFn: () => {
const apiParams: Record<string, unknown> = {
page: params.page,
per_page: params.per_page,
...extraParams,
}
if (params.sort_by) apiParams.sort_by = params.sort_by
if (params.sort_order) apiParams.sort_order = params.sort_order