Skip to content

Commit 6183b61

Browse files
committed
refactored (data table component for advanced navigation with realtime-server side pagination ) : Introduce sorting, filtering, pagination and dynamic column visibility to DataTable component for improved user experience.
1 parent 844c805 commit 6183b61

File tree

1 file changed

+70
-69
lines changed

1 file changed

+70
-69
lines changed

components/ui/data-table.tsx

Lines changed: 70 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,106 @@
1-
"use client";
1+
'use client';
22

33
import {
44
ColumnDef,
55
ColumnFiltersState,
66
flexRender,
77
getCoreRowModel,
8+
getSortedRowModel,
9+
SortingState,
810
getPaginationRowModel,
911
getFilteredRowModel,
1012
useReactTable,
11-
} from "@tanstack/react-table";
12-
import { Button } from "@/components/ui/button";
13-
import { Input } from "@/components/ui/input";
14-
import {
15-
Table,
16-
TableBody,
17-
TableCell,
18-
TableHead,
19-
TableHeader,
20-
TableRow,
21-
} from "@/components/ui/table";
22-
import { useState } from "react";
13+
VisibilityState,
14+
} from '@tanstack/react-table';
15+
import { Button } from '@/components/ui/button';
16+
import { Input } from '@/components/ui/input';
17+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
18+
import { useState } from 'react';
19+
import { ChevronDown, Search } from 'lucide-react';
20+
import { DataTablePagination } from './data-table-pagination';
2321

22+
import {
23+
DropdownMenu,
24+
DropdownMenuCheckboxItem,
25+
DropdownMenuContent,
26+
DropdownMenuTrigger,
27+
} from '@/components/ui/dropdown-menu';
2428
interface DataTableProps<TData, TValue> {
2529
columns: ColumnDef<TData, TValue>[];
2630
data: TData[];
2731
searchKey: string;
2832
}
2933

30-
export function DataTable<TData, TValue>({
31-
columns,
32-
data,
33-
searchKey,
34-
}: DataTableProps<TData, TValue>) {
34+
export function DataTable<TData, TValue>({ columns, data, searchKey }: DataTableProps<TData, TValue>) {
3535
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
36+
const [sorting, setSorting] = useState<SortingState>([]);
37+
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
38+
3639
const table = useReactTable({
3740
data,
3841
columns,
42+
onSortingChange: setSorting,
3943
getCoreRowModel: getCoreRowModel(),
4044
getPaginationRowModel: getPaginationRowModel(),
4145
onColumnFiltersChange: setColumnFilters,
46+
onColumnVisibilityChange: setColumnVisibility,
47+
getSortedRowModel: getSortedRowModel(),
4248
getFilteredRowModel: getFilteredRowModel(),
4349

4450
state: {
4551
columnFilters,
52+
sorting,
53+
columnVisibility,
4654
},
4755
});
4856

4957
return (
5058
<div>
5159
<div className="flex items-center py-4">
52-
<Input
53-
placeholder="Search ..."
54-
value={(table.getColumn(searchKey)?.getFilterValue() as string) ?? ""}
55-
onChange={event =>
56-
table.getColumn(searchKey)?.setFilterValue(event.target.value)
57-
}
58-
className="max-w-sm"
59-
/>
60+
<div className="relative max-w-sm">
61+
<Search className="absolute left-3 top-[0.8rem] text-gray-400" size={20} />
62+
<Input
63+
placeholder="Order ID or transaction ID..."
64+
value={(table.getColumn(searchKey)?.getFilterValue() as string) ?? ''}
65+
onChange={(event) => table.getColumn(searchKey)?.setFilterValue(event.target.value)}
66+
className="pl-10"
67+
/>
68+
</div>
69+
<DropdownMenu>
70+
<DropdownMenuTrigger asChild>
71+
<Button variant="outline" className="ml-auto">
72+
<span className="">Filter Column</span>
73+
<ChevronDown className="h-4 w-4" />
74+
</Button>
75+
</DropdownMenuTrigger>
76+
<DropdownMenuContent align="end">
77+
{table
78+
.getAllColumns()
79+
.filter((column) => column.getCanHide())
80+
.map((column) => {
81+
return (
82+
<DropdownMenuCheckboxItem
83+
key={column.id}
84+
className="capitalize"
85+
checked={column.getIsVisible()}
86+
onCheckedChange={(value) => column.toggleVisibility(!!value)}
87+
>
88+
{column.id}
89+
</DropdownMenuCheckboxItem>
90+
);
91+
})}
92+
</DropdownMenuContent>
93+
</DropdownMenu>
6094
</div>
6195
<div className="rounded-md border">
6296
<Table>
63-
<TableHeader>
64-
{table.getHeaderGroups().map(headerGroup => (
97+
<TableHeader className="bg-slate-100">
98+
{table.getHeaderGroups().map((headerGroup) => (
6599
<TableRow key={headerGroup.id}>
66-
{headerGroup.headers.map(header => {
100+
{headerGroup.headers.map((header) => {
67101
return (
68102
<TableHead key={header.id}>
69-
{header.isPlaceholder
70-
? null
71-
: flexRender(
72-
header.column.columnDef.header,
73-
header.getContext(),
74-
)}
103+
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
75104
</TableHead>
76105
);
77106
})}
@@ -80,52 +109,24 @@ export function DataTable<TData, TValue>({
80109
</TableHeader>
81110
<TableBody>
82111
{table.getRowModel().rows?.length ? (
83-
table.getRowModel().rows.map(row => (
84-
<TableRow
85-
key={row.id}
86-
data-state={row.getIsSelected() && "selected"}
87-
>
88-
{row.getVisibleCells().map(cell => (
89-
<TableCell key={cell.id}>
90-
{flexRender(
91-
cell.column.columnDef.cell,
92-
cell.getContext(),
93-
)}
94-
</TableCell>
112+
table.getRowModel().rows.map((row) => (
113+
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
114+
{row.getVisibleCells().map((cell) => (
115+
<TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
95116
))}
96117
</TableRow>
97118
))
98119
) : (
99120
<TableRow>
100-
<TableCell
101-
colSpan={columns.length}
102-
className="h-24 text-center"
103-
>
121+
<TableCell colSpan={columns.length} className="h-24 text-center">
104122
No results.
105123
</TableCell>
106124
</TableRow>
107125
)}
108126
</TableBody>
109127
</Table>
110128
</div>
111-
<div className="flex items-center justify-end space-x-2 py-4">
112-
<Button
113-
variant="outline"
114-
size="sm"
115-
onClick={() => table.previousPage()}
116-
disabled={!table.getCanPreviousPage()}
117-
>
118-
Previous
119-
</Button>
120-
<Button
121-
variant="outline"
122-
size="sm"
123-
onClick={() => table.nextPage()}
124-
disabled={!table.getCanNextPage()}
125-
>
126-
Next
127-
</Button>
128-
</div>
129+
<DataTablePagination table={table} />
129130
</div>
130131
);
131132
}

0 commit comments

Comments
 (0)