diff --git a/compass/components/FilterBox/index.tsx b/compass/components/FilterBox/FilterBox.tsx similarity index 99% rename from compass/components/FilterBox/index.tsx rename to compass/components/FilterBox/FilterBox.tsx index be0e6fa..6e6fe6b 100644 --- a/compass/components/FilterBox/index.tsx +++ b/compass/components/FilterBox/FilterBox.tsx @@ -1,4 +1,3 @@ -// FilterBox.tsx import { useState } from "react"; import { ChevronDownIcon } from "@heroicons/react/24/solid"; import { ContainsDropdown } from "./ContainsDropdown"; diff --git a/compass/components/Table/ResourceTable.tsx b/compass/components/Table/ResourceTable.tsx index a1e6391..590b264 100644 --- a/compass/components/Table/ResourceTable.tsx +++ b/compass/components/Table/ResourceTable.tsx @@ -118,6 +118,9 @@ export default function ResourceTable({ </Tag> </div> ), + meta: { + filterVariant: "select", + } }), columnHelper.accessor("summary", { header: () => ( diff --git a/compass/components/Table/Table.tsx b/compass/components/Table/Table.tsx index 538e546..95b0047 100644 --- a/compass/components/Table/Table.tsx +++ b/compass/components/Table/Table.tsx @@ -5,17 +5,13 @@ import { getCoreRowModel, flexRender, createColumnHelper, + getFilteredRowModel, + ColumnFiltersState, + getSortedRowModel, + SortingState, } from "@tanstack/react-table"; -import { - ChangeEvent, - useState, - useEffect, - Key, - Dispatch, - SetStateAction, -} from "react"; +import { ChangeEvent, useState, Dispatch, SetStateAction } from "react"; import { TableAction } from "./TableAction"; -import { PlusIcon } from "@heroicons/react/24/solid"; import { rankItem } from "@tanstack/match-sorter-utils"; import { RowOptionMenu } from "./RowOptionMenu"; import DataPoint from "@/utils/models/DataPoint"; @@ -81,7 +77,8 @@ export default function Table<T extends DataPoint>({ createEndpoint, isAdmin = false, }: TableProps<T>) { - console.log(data); + const [filters, setFilters] = useState<ColumnFiltersState>([]); + const [sorting, setSorting] = useState<SortingState>([]); const columnHelper = createColumnHelper<T>(); @@ -166,10 +163,16 @@ export default function Table<T extends DataPoint>({ }, state: { globalFilter: query, + columnFilters: filters, + sorting, }, onGlobalFilterChange: setQuery, globalFilterFn: fuzzyFilter, getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getSortedRowModel: getSortedRowModel(), + onColumnFiltersChange: setFilters, + onSortingChange: setSorting, }); return ( @@ -185,12 +188,24 @@ export default function Table<T extends DataPoint>({ <th scope="col" className={ - "p-2 border-gray-200 border-y font-medium " + + "p-2 border-gray-200 border-y font-medium cursor-pointer select-none" + (1 < i && i < columns.length - 1 ? "border-x" : "") } key={header.id} + onClick={header.column.getToggleSortingHandler()} + title={ + header.column.getCanSort() + ? header.column.getNextSortingOrder() === + "asc" + ? "Sort ascending" + : header.column.getNextSortingOrder() === + "desc" + ? "Sort descending" + : "Clear sort" + : undefined + } > {header.isPlaceholder ? null @@ -198,6 +213,14 @@ export default function Table<T extends DataPoint>({ header.column.columnDef.header, header.getContext() )} + {{ + asc: "🔼", + desc: "🔽", + }[header.column.getIsSorted() as string] ?? + null} + {header.column.getCanFilter() && ( + <Filter column={header.column} /> + )} </th> ))} </tr> @@ -266,3 +289,19 @@ export default function Table<T extends DataPoint>({ </div> ); } + +function Filter({ column }: { column: any }) { + return ( + <div> + <input + type="text" + value={(column.getFilterValue() ?? "") as string} + onChange={(e) => { + column.setFilterValue(e.target.value); + }} + placeholder="Search..." + className="border border-gray-300 rounded p-1" + /> + </div> + ); +} diff --git a/compass/components/Table/TableAction.tsx b/compass/components/Table/TableAction.tsx index c8cecc9..ff9a77f 100644 --- a/compass/components/Table/TableAction.tsx +++ b/compass/components/Table/TableAction.tsx @@ -1,7 +1,7 @@ // TableAction.tsx import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; import { ChangeEventHandler, FunctionComponent, useRef, useState } from "react"; -import { FilterBox } from "../FilterBox"; +import { FilterBox } from "../FilterBox/FilterBox"; type TableActionProps = { query: string;