Skip to content

Instantly share code, notes, and snippets.

@dipeshhkc
Last active July 8, 2022 11:19
Show Gist options
  • Save dipeshhkc/7cf0e41e46a76bb24b7dfcf2e50b12a4 to your computer and use it in GitHub Desktop.
Save dipeshhkc/7cf0e41e46a76bb24b7dfcf2e50b12a4 to your computer and use it in GitHub Desktop.
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