feat: add pagination on data table

This commit is contained in:
Orace.A 2025-03-25 23:58:55 +01:00
parent 130473d3e4
commit 98d68a535b
2 changed files with 165 additions and 13 deletions

View File

@ -1,10 +1,129 @@
"use client"
import Table from "#/components/table/table"
import { ColumnDef } from "@tanstack/react-table"
export default function HomePage () { export default function HomePage () {
type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
const data: Payment[] = [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
{
id: "728ed521",
amount: 200,
status: "pending",
email: "j@example.com",
},
{
id: "728ed528",
amount: 300,
status: "processing",
email: "f@example.com",
},
{
id: "728ed52g",
amount: 600,
status: "success",
email: "h@example.com",
},
{
id: "728ed520",
amount: 50,
status: "failed",
email: "k@example.com",
},
{
id: "728ed529",
amount: 200,
status: "pending",
email: "l@example.com",
},
{
id: "728ed526",
amount: 150,
status: "processing",
email: "d@example.com",
},
{
id: "728ed523",
amount: 100,
status: "success",
email: "o@example.com",
},
{
id: "728ed52y",
amount: 100,
status: "failed",
email: "v@example.com",
},
// ...
]
const columns: ColumnDef<Payment>[] = [
{
id: "select",
header: ({ table }) => (
<input checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && undefined)
} onChange={(value) => table.toggleAllPageRowsSelected(!!value)} type="checkbox" name="" id="" />
),
cell: ({ row }) => (
<input checked={row.getIsSelected()} onChange={(value) => row.toggleSelected(!!value)} type="checkbox" name="" id="" />
),
},
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: ({ column }) => {
return (
<p>Email</p>
)
},
},
{
accessorKey: "amount",
header: () => <div className="">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount)
return <div className="font-medium">{formatted}</div>
},
},
]
return( return(
<> <>
<Table
columns={columns}
data={data}
pageSize={5}
/>
</> </>
) )
} }

View File

@ -10,15 +10,18 @@ import {
getFilteredRowModel, getFilteredRowModel,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { useState } from "react"; import { useState } from "react";
import { clsx, type ClassValue } from "clsx"
interface DataTableProps<TData, TValue> { interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[] columns: ColumnDef<TData, TValue>[]
data: TData[] data: TData[],
pageSize?: number
} }
export default function Table<TData, TValue>({ export default function Table<TData, TValue>({
columns, columns,
data, data,
pageSize = 10
}: DataTableProps<TData, TValue>) { }: DataTableProps<TData, TValue>) {
const [rowSelection, setRowSelection] = useState({}) const [rowSelection, setRowSelection] = useState({})
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>( const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
@ -35,26 +38,37 @@ export default function Table<TData, TValue>({
rowSelection, rowSelection,
columnFilters, columnFilters,
}, },
initialState: {
pagination: {
pageSize: pageSize,
}
},
getFilteredRowModel: getFilteredRowModel(), getFilteredRowModel: getFilteredRowModel(),
onRowSelectionChange: setRowSelection, onRowSelectionChange: setRowSelection,
onColumnFiltersChange: setColumnFilters, onColumnFiltersChange: setColumnFilters,
}) })
const totalPages = table.getPageCount()
const currentPage = table.getState().pagination.pageIndex + 1
function clsx(arg0: string, arg1: { 'bg-gray-300': boolean; }): string | undefined { const getPageNumbers = () => {
throw new Error("Function not implemented."); const pages = []
for (let i = 1; i <= totalPages; i++) {
pages.push(i)
}
return pages
} }
return( return(
<div> <div>
<div className="rounded-md border"> <div className="rounded-lg border border-gray-200">
<table> <table className="w-full overflow-x-auto rounded-lg " style={{ borderTopLeftRadius: '10px', borderTopRightRadius: '10px', }}>
<thead> <thead className="h-10">
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}> <tr key={headerGroup.id} className="rounded-lg">
{headerGroup.headers.map((header) => { {headerGroup.headers.map((header) => {
return( return(
<th key={header.id}> <th key={header.id} className="bg-blue-300 p-3 text-start">
{flexRender( {flexRender(
header.column.columnDef.header, header.column.columnDef.header,
header.getContext() header.getContext()
@ -68,9 +82,9 @@ export default function Table<TData, TValue>({
<tbody> <tbody>
{table.getRowModel().rows.length ? ( {table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => ( table.getRowModel().rows.map((row) => (
<tr key={row.id} className={clsx('hover:bg-gray-300', { 'bg-gray-300': row.getIsSelected()})}> <tr key={row.id} className={clsx('hover:bg-gray-300 border-t border-gray-200', { 'bg-gray-300': row.getIsSelected()})}>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td key={cell.id}> <td key={cell.id} className="p-3 text-start">
{flexRender(cell.column.columnDef.cell, cell.getContext())} {flexRender(cell.column.columnDef.cell, cell.getContext())}
</td> </td>
))} ))}
@ -79,7 +93,7 @@ export default function Table<TData, TValue>({
) )
: ( : (
<tr> <tr>
<td> <td colSpan={columns.length}>
Aucun résultats Aucun résultats
</td> </td>
</tr> </tr>
@ -90,13 +104,32 @@ export default function Table<TData, TValue>({
<div className="flex items-center justify-end space-x-2 py-4"> <div className="flex items-center justify-end space-x-2 py-4">
<button <button
className="border bg-gray-200 shadow-xs hover:bg-gray-300 hover:text-black" className="border bg-gray-200 shadow-xs hover:bg-gray-300 hover:text-black px-3 py-1 rounded"
onClick={() => table.previousPage()} onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()} disabled={!table.getCanPreviousPage()}
> >
Précédent Précédent
</button> </button>
<div className="flex space-x-1">
{getPageNumbers().map((pageNumber) => (
<button
key={pageNumber}
className={clsx(
"px-3 py-1 rounded",
pageNumber === currentPage
? "bg-blue-500 text-white"
: "bg-gray-200 hover:bg-gray-300"
)}
onClick={() => table.setPageIndex(pageNumber - 1)}
>
{pageNumber}
</button>
))}
</div>
<button <button
className="border bg-gray-200 shadow-xs hover:bg-gray-300 hover:text-black px-3 py-1 rounded"
onClick={() => table.nextPage()} onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()} disabled={!table.getCanNextPage()}
> >