214 lines
8.2 KiB
TypeScript

"use client";
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getPaginationRowModel,
ColumnFiltersState,
getFilteredRowModel,
Table as TableType,
} from "@tanstack/react-table"
import { ReactNode, useEffect, useRef, useState } from "react";
import Image from "next/image";
import { icons } from "#/assets/icons";
import clsx from "clsx";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[],
pageSize?: number,
header?: ReactNode | ((table: TableType<TData>) => ReactNode),
isDataLoading?: boolean
}
export default function Table<TData, TValue>({
columns,
data,
pageSize = 10,
header,
isDataLoading = true
}: DataTableProps<TData, TValue>) {
const [rowSelection, setRowSelection] = useState({})
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
[]
)
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
state: {
rowSelection,
columnFilters,
},
initialState: {
pagination: {
pageSize: pageSize,
}
},
enableRowSelection: true,
getFilteredRowModel: getFilteredRowModel(),
onRowSelectionChange: setRowSelection,
onColumnFiltersChange: setColumnFilters,
})
const headerCheckboxRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (headerCheckboxRef.current) {
headerCheckboxRef.current.indeterminate =
table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected();
}
const selectedRows = table.getSelectedRowModel().rows;
const filteredSelectedRows = table
.getRowModel()
.rows.filter((row) => row.getIsSelected())
.map((row) => row.original);
console.log("SELECTED ALL = ", selectedRows);
console.log("SELECTED = ", filteredSelectedRows);
}, [
table
]);
const totalPages = table.getPageCount()
const currentPage = table.getState().pagination.pageIndex + 1
const getPageNumbers = () => {
const pages = []
for (let i = 1; i <= totalPages; i++) {
pages.push(i)
}
return pages
}
const render = () => {
if(!header) return null
return(
<div className="mb-4">
{typeof header === 'function'
? header(table)
: header}
</div>
)
}
return(
<div className="w-full">
{render()}
<div className="rounded-lg border border-gray-200 w-auto">
<div className="overflow-x-auto">
<table className="w-full overflow-x-auto rounded-lg">
<thead className="h-10">
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id} className="rounded-lg">
{header
?
<th className="bg-[#E9F0FF] p-3 text-start first:rounded-tl-lg">
</th>
:
<th className="bg-[#E9F0FF] p-3 text-start first:rounded-tl-lg">
<input
ref={headerCheckboxRef}
checked={!!table.getIsAllPageRowsSelected()}
onChange={(e) => table.toggleAllPageRowsSelected(e.target.checked)}
type="checkbox" name="" id=""
/>
</th>
}
{headerGroup.headers.map((header) => {
return(
<th key={header.id} className="bg-[#E9F0FF] p-3 text-start last:rounded-tr-lg">
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
)
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => (
<tr key={row.id} className={clsx('hover:bg-gray-100 border-t border-gray-200', { 'bg-gray-300': row.getIsSelected()})}>
<td className="p-3 text-start">
<input
checked={row.getIsSelected()}
onChange={(e) => row.toggleSelected(e.target.checked)}
type="checkbox" name="" id=""
/>
</td>
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="p-3 text-start">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))
)
: isDataLoading ?
(
<tr>
<td colSpan={columns.length} className="h-20 text-center">
Chargement...
</td>
</tr>
)
: (
<tr>
<td colSpan={columns.length} className="h-20 text-center">
Aucun résultats
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<button
className="bg-gray-100 shadow-xs hover:bg-gray-300 px-3 py-1 rounded w-9 h-9"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
<Image alt="" src={icons.arrowLeft} className="hover:text-blue-400"/>
</button>
<div className="flex space-x-1">
{getPageNumbers().map((pageNumber) => (
<button
key={pageNumber}
className={clsx(
"px-3 py-1 rounded w-9 h-9",
pageNumber === currentPage
? "bg-[#E9F0FF] text-blue-400"
: "bg-gray-100 hover:bg-gray-300"
)}
onClick={() => table.setPageIndex(pageNumber - 1)}
>
{pageNumber}
</button>
))}
</div>
<button
className="w-9 h-9 bg-gray-100 shadow-xs hover:bg-gray-300 hover:text-black px-3 py-1 rounded"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
<Image alt="" src={icons.arrowRight} />
</button>
</div>
</div>
)
}