Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use client';
- import React from "react";
- import {
- Table,
- TableHeader,
- TableColumn,
- TableBody,
- TableRow,
- TableCell,
- Input,
- Button,
- DropdownTrigger,
- Dropdown,
- DropdownMenu,
- DropdownItem,
- Chip,
- User,
- Pagination,
- Selection,
- ChipProps,
- SortDescriptor
- } from "@nextui-org/react";
- import {PlusIcon} from "./PlusIcon";
- import {VerticalDotsIcon} from "./VerticalDotsIcon";
- import {ChevronDownIcon} from "./ChevronDownIcon";
- import {SearchIcon} from "./SearchIcon";
- import {columns, Rule, statusOptions} from "../../lib/definitions";
- import {capitalize} from "./utils";
- import { Key } from "@react-types/shared";
- const statusColorMap: Record<string, ChipProps["color"]> = {
- active: "success",
- paused: "danger",
- vacation: "warning",
- };
- const INITIAL_VISIBLE_COLUMNS = ["all"];
- export default function RulesTable({rules}: {rules: Rule[];}) {
- const [filterValue, setFilterValue] = React.useState("");
- const [selectedKeys, setSelectedKeys] = React.useState<Selection>(new Set([]));
- const [visibleColumns, setVisibleColumns] = React.useState<Selection>(new Set(INITIAL_VISIBLE_COLUMNS));
- const [statusFilter, setStatusFilter] = React.useState<Selection>("all");
- const [rowsPerPage, setRowsPerPage] = React.useState(5);
- const [sortDescriptor, setSortDescriptor] = React.useState<SortDescriptor>({
- column: "name",
- direction: "ascending",
- });
- const [page, setPage] = React.useState(1);
- const hasSearchFilter = Boolean(filterValue);
- const headerColumns = React.useMemo(() => {
- if (visibleColumns === "all") return columns;
- return columns.filter((column: { uid: Key; }) => Array.from(visibleColumns).includes(column.uid));
- }, [visibleColumns]);
- const filteredItems = React.useMemo(() => {
- //let filteredUsers = [...users];
- let filteredRules = [...rules];
- if (hasSearchFilter) {
- filteredRules = filteredRules.filter((rule) =>
- rule.name.toLowerCase().includes(filterValue.toLowerCase()),
- );
- }
- if (statusFilter !== "all" && Array.from(statusFilter).length !== statusOptions.length) {
- filteredRules = filteredRules.filter((rule) =>
- Array.from(statusFilter).includes(rule.status),
- );
- }
- return filteredRules;
- }, [rules, hasSearchFilter, statusFilter, filterValue]);
- const pages = Math.ceil(filteredItems.length / rowsPerPage);
- const items = React.useMemo(() => {
- const start = (page - 1) * rowsPerPage;
- const end = start + rowsPerPage;
- return filteredItems.slice(start, end);
- }, [page, filteredItems, rowsPerPage]);
- const sortedItems = React.useMemo(() => {
- return [...items].sort((a: Rule, b: Rule) => {
- const first = a[sortDescriptor.column as keyof Rule] as string;
- const second = b[sortDescriptor.column as keyof Rule] as string;
- const cmp = first < second ? -1 : first > second ? 1 : 0;
- return sortDescriptor.direction === "descending" ? -cmp : cmp;
- });
- }, [sortDescriptor, items]);
- const renderCell = React.useCallback((rule: Rule, columnKey: React.Key) => {
- const cellValue = rule[columnKey as keyof Rule];
- console.log(rule)
- return cellValue;
- }, []);
- const onNextPage = React.useCallback(() => {
- if (page < pages) {
- setPage(page + 1);
- }
- }, [page, pages]);
- const onPreviousPage = React.useCallback(() => {
- if (page > 1) {
- setPage(page - 1);
- }
- }, [page]);
- const onRowsPerPageChange = React.useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
- setRowsPerPage(Number(e.target.value));
- setPage(1);
- }, []);
- const onSearchChange = React.useCallback((value?: string) => {
- if (value) {
- setFilterValue(value);
- setPage(1);
- } else {
- setFilterValue("");
- }
- }, []);
- const onClear = React.useCallback(()=>{
- setFilterValue("")
- setPage(1)
- },[])
- const topContent = React.useMemo(() => {
- return (
- <div className="flex flex-col gap-4">
- <div className="flex justify-between gap-3 items-end">
- <Input
- isClearable
- className="w-full sm:max-w-[44%]"
- placeholder="Search by name..."
- startContent={<SearchIcon />}
- value={filterValue}
- onClear={() => onClear()}
- onValueChange={onSearchChange}
- />
- <div className="flex gap-3">
- <Dropdown>
- <DropdownTrigger className="hidden sm:flex">
- <Button endContent={<ChevronDownIcon className="text-small" />} variant="flat">
- Status
- </Button>
- </DropdownTrigger>
- <DropdownMenu
- disallowEmptySelection
- aria-label="Table Columns"
- closeOnSelect={false}
- selectedKeys={statusFilter}
- selectionMode="multiple"
- onSelectionChange={setStatusFilter}
- >
- {statusOptions.map((status) => (
- <DropdownItem key={status.uid} className="capitalize">
- {capitalize(status.name)}
- </DropdownItem>
- ))}
- </DropdownMenu>
- </Dropdown>
- <Dropdown>
- <DropdownTrigger className="hidden sm:flex">
- <Button endContent={<ChevronDownIcon className="text-small" />} variant="flat">
- Columns
- </Button>
- </DropdownTrigger>
- <DropdownMenu
- disallowEmptySelection
- aria-label="Table Columns"
- closeOnSelect={false}
- selectedKeys={visibleColumns}
- selectionMode="multiple"
- onSelectionChange={setVisibleColumns}
- >
- {columns.map((column) => (
- <DropdownItem key={column.uid} className="capitalize">
- {capitalize(column.name)}
- </DropdownItem>
- ))}
- </DropdownMenu>
- </Dropdown>
- </div>
- </div>
- <div className="flex justify-between items-center">
- <span className="text-default-400 text-small">Total {rules.length} rules</span>
- <label className="flex items-center text-default-400 text-small">
- Rows per page:
- <select
- className="bg-transparent outline-none text-default-400 text-small"
- onChange={onRowsPerPageChange}
- >
- <option value="5">5</option>
- <option value="10">10</option>
- <option value="15">15</option>
- <option value="15">25</option>
- <option value="15">40</option>
- <option value="15">60</option>
- </select>
- </label>
- </div>
- </div>
- );
- }, [filterValue, onSearchChange, statusFilter, visibleColumns, rules.length, onRowsPerPageChange, onClear]);
- const bottomContent = React.useMemo(() => {
- return (
- <div className="py-2 px-2 flex justify-between items-center">
- <Pagination
- isCompact
- showControls
- showShadow
- color="primary"
- page={page}
- total={pages}
- onChange={setPage}
- />
- <div className="hidden sm:flex w-[30%] justify-end gap-2">
- <Button isDisabled={pages === 1} size="sm" variant="flat" onPress={onPreviousPage}>
- Previous
- </Button>
- <Button isDisabled={pages === 1} size="sm" variant="flat" onPress={onNextPage}>
- Next
- </Button>
- </div>
- </div>
- );
- }, [page, pages, onPreviousPage, onNextPage]);
- console.log(sortedItems)
- return (
- <Table
- aria-label="Example table with custom cells, pagination and sorting"
- isHeaderSticky
- bottomContent={bottomContent}
- bottomContentPlacement="outside"
- classNames={{
- wrapper: "max-h-[382px]",
- }}
- selectedKeys={selectedKeys}
- selectionMode="multiple"
- sortDescriptor={sortDescriptor}
- topContent={topContent}
- topContentPlacement="outside"
- onSelectionChange={setSelectedKeys}
- onSortChange={setSortDescriptor}
- >
- <TableHeader columns={headerColumns}>
- {(column) => (
- <TableColumn
- key={column.uid}
- align={column.uid === "actions" ? "center" : "start"}
- allowsSorting={column.sortable}
- >
- {column.name}
- </TableColumn>
- )}
- </TableHeader>
- <TableBody emptyContent={"No users found"} items={sortedItems}>
- {(item) => (
- <TableRow key={item.id}>
- {(columnKey) => <TableCell>{renderCell(item, columnKey)}</TableCell>}
- </TableRow>
- )}
- </TableBody>
- </Table>
- );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement