import { useMemo, useState } from "react"; import { type ColumnDef, type OnChangeFn, type SortingState, type Updater, type VisibilityState, getCoreRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table"; import { type GatewayRead } from "@/api/generated/model"; import { DataTable, type DataTableEmptyState, } from "@/components/tables/DataTable"; import { dateCell, linkifyCell } from "@/components/tables/cell-formatters"; import { truncateText as truncate } from "@/lib/formatters"; type GatewaysTableProps = { gateways: GatewayRead[]; isLoading?: boolean; sorting?: SortingState; onSortingChange?: OnChangeFn; stickyHeader?: boolean; showActions?: boolean; hiddenColumns?: string[]; columnOrder?: string[]; disableSorting?: boolean; onDelete?: (gateway: GatewayRead) => void; emptyMessage?: string; emptyState?: Omit & { icon?: DataTableEmptyState["icon"]; }; }; const DEFAULT_EMPTY_ICON = ( ); export function GatewaysTable({ gateways, isLoading = false, sorting, onSortingChange, stickyHeader = false, showActions = true, hiddenColumns, columnOrder, disableSorting = false, onDelete, emptyMessage = "No gateways found.", emptyState, }: GatewaysTableProps) { const [internalSorting, setInternalSorting] = useState([ { id: "name", desc: false }, ]); const resolvedSorting = sorting ?? internalSorting; const handleSortingChange: OnChangeFn = onSortingChange ?? ((updater: Updater) => { setInternalSorting(updater); }); const sortedGateways = useMemo(() => [...gateways], [gateways]); const columnVisibility = useMemo( () => Object.fromEntries( (hiddenColumns ?? []).map((columnId) => [columnId, false]), ), [hiddenColumns], ); const columns = useMemo[]>(() => { const baseColumns: ColumnDef[] = [ { accessorKey: "name", header: "Gateway", cell: ({ row }) => linkifyCell({ href: `/gateways/${row.original.id}`, label: row.original.name, subtitle: truncate(row.original.url, 36), }), }, { accessorKey: "workspace_root", header: "Workspace root", cell: ({ row }) => ( {truncate(row.original.workspace_root, 28)} ), }, { accessorKey: "updated_at", header: "Updated", cell: ({ row }) => dateCell(row.original.updated_at), }, ]; return baseColumns; }, []); // eslint-disable-next-line react-hooks/incompatible-library const table = useReactTable({ data: sortedGateways, columns, enableSorting: !disableSorting, state: { ...(!disableSorting ? { sorting: resolvedSorting } : {}), ...(columnOrder ? { columnOrder } : {}), columnVisibility, }, ...(disableSorting ? {} : { onSortingChange: handleSortingChange }), getCoreRowModel: getCoreRowModel(), ...(disableSorting ? {} : { getSortedRowModel: getSortedRowModel() }), }); return ( `/gateways/${gateway.id}/edit`, onDelete, } : undefined } emptyState={ emptyState ? { icon: emptyState.icon ?? DEFAULT_EMPTY_ICON, title: emptyState.title, description: emptyState.description, actionHref: emptyState.actionHref, actionLabel: emptyState.actionLabel, } : undefined } /> ); }