Last active
July 8, 2022 11:19
-
-
Save dipeshhkc/7cf0e41e46a76bb24b7dfcf2e50b12a4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/outline"; | |
import c from "classnames"; | |
import { Fragment } from "react"; | |
import Select from "react-select"; | |
import {usePagination, useSortBy, useTable } from "react-table"; | |
const sizeOptions = [10, 25, 50, 100].map((pageSize) => { | |
return { | |
value: pageSize, | |
label: "Show " + pageSize, | |
}; | |
}); | |
export const PageWithText = ({ | |
activeClassNames = "btn-tag", | |
inactiveClassNames = "btn btn-default bg-transparent hover:bg-gray-200 text-gray-900 dark:text-white", | |
children, | |
active = false, | |
onClick, | |
}) => { | |
if (active) { | |
return ( | |
<button onClick={onClick} className={activeClassNames}> | |
{children} | |
</button> | |
); | |
} | |
return ( | |
<button onClick={onClick} className={inactiveClassNames}> | |
{children} | |
</button> | |
); | |
}; | |
export const Datatable = ({ | |
columns, | |
data, | |
trClassName = "", | |
rowClick = null, | |
showPagination = data.length > 10, | |
}) => { | |
const { | |
getTableProps, | |
getTableBodyProps, | |
headerGroups, | |
prepareRow, | |
page, | |
canPreviousPage, | |
canNextPage, | |
pageOptions, | |
pageCount, | |
gotoPage, | |
nextPage, | |
previousPage, | |
setPageSize, | |
state: { pageIndex, pageSize }, | |
} = useTable( | |
{ | |
columns, | |
data, | |
initialState: { | |
pageIndex: 0, | |
pageSize: 10, | |
}, | |
}, | |
useSortBy, | |
usePagination | |
); | |
// Render the UI for your table | |
return ( | |
<> | |
<div className="flex flex-col"> | |
<div className="overflow-x-auto"> | |
<div className="py-2 align-middle inline-block min-w-full"> | |
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg"> | |
<table | |
{...getTableProps()} | |
className="min-w-full divide-y divide-gray-200" | |
> | |
<thead className="bg-gray-200"> | |
{headerGroups.map((headerGroup, index) => { | |
return ( | |
<tr {...headerGroup.getHeaderGroupProps()} key={index}> | |
{headerGroup.headers.map((column, index) => { | |
return ( | |
<th | |
{...column.getHeaderProps( | |
column.getSortByToggleProps() | |
)} | |
key={index} | |
scope="col" | |
className="px-6 py-4 text-left text-xs font-medium text-black uppercase tracking-wider" | |
> | |
<div className="flex flex-row items-center justify-start"> | |
<span>{column.render("Header")}</span> | |
{/* Add a sort direction indicator */} | |
<span className="ml-auto"> | |
{column.isSorted ? ( | |
column.isSortedDesc ? ( | |
<ChevronDownIcon className="stroke-current text-2xs" /> | |
) : ( | |
<ChevronUpIcon className="stroke-current text-2xs" /> | |
) | |
) : ( | |
"" | |
)} | |
</span> | |
</div> | |
</th> | |
); | |
})} | |
</tr> | |
); | |
})} | |
</thead> | |
<tbody {...getTableBodyProps()}> | |
{page.map((row, index) => { | |
prepareRow(row); | |
return ( | |
// Use a React.Fragment here so the table markup is still valid | |
<Fragment key={index}> | |
<tr | |
{...row.getRowProps()} | |
onClick={() => { | |
if (rowClick) { | |
rowClick(row?.original); | |
} | |
}} | |
className={c( | |
"cursor-pointer hover:bg-gray-50 group", | |
trClassName | |
)} | |
> | |
{row.cells.map((cell, index) => { | |
return ( | |
<td | |
{...cell.getCellProps()} | |
key={index} | |
className="px-6 py-3 whitespace-nowrap text-sm text-gray-500" | |
> | |
{cell.render("Cell")} | |
</td> | |
); | |
})} | |
</tr> | |
</Fragment> | |
); | |
})} | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> | |
</div> | |
{showPagination && ( | |
<div className="flex flex-row items-center justify-between my-4"> | |
<div className="flex flex-wrap items-center justify-start space-x-2 pagination"> | |
{pageIndex !== 0 && ( | |
<PageWithText | |
onClick={() => { | |
return gotoPage(0); | |
}} | |
> | |
First | |
</PageWithText> | |
)} | |
{canPreviousPage && ( | |
<PageWithText | |
onClick={() => { | |
return previousPage(); | |
}} | |
> | |
Previous | |
</PageWithText> | |
)} | |
{canNextPage && ( | |
<PageWithText | |
onClick={() => { | |
return nextPage(); | |
}} | |
active={canNextPage} | |
> | |
Next | |
</PageWithText> | |
)} | |
{pageIndex !== pageCount - 1 && ( | |
<PageWithText | |
onClick={() => { | |
return gotoPage(pageCount - 1); | |
}} | |
active={canNextPage} | |
> | |
Last | |
</PageWithText> | |
)} | |
</div> | |
<div className="flex flex-col items-center space-y-2"> | |
<span className="text-gray-500"> | |
Page{" "} | |
<span className="font-bold"> | |
{pageIndex + 1} of {pageOptions.length} | |
</span>{" "} | |
</span> | |
<span className="text-gray-500 hidden md:inline-block"> | |
<span className="mx-1 font-semibold"> | |
{pageIndex * pageSize + 1}- | |
{(pageIndex + 1) * pageSize - (pageSize - page.length)} | |
</span> | |
of {data.length} items | |
</span> | |
</div> | |
<Select | |
className="w-40 form-select" | |
onChange={(e) => { | |
setPageSize(Number(e?.value)); | |
}} | |
isSearchable={false} | |
defaultValue={sizeOptions[0]} | |
options={sizeOptions} | |
/> | |
</div> | |
)} | |
</> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment