mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 17:21:41 +10:00
feat: rework document table filters
This commit is contained in:
103
packages/ui/primitives/data-table/data-table-toolbar.tsx
Normal file
103
packages/ui/primitives/data-table/data-table-toolbar.tsx
Normal file
@ -0,0 +1,103 @@
|
||||
import type { Table } from '@tanstack/react-table';
|
||||
import { Calendar, CircleDashedIcon, ListFilter, X, XCircle } from 'lucide-react';
|
||||
|
||||
import { Button } from '../button';
|
||||
import { Input } from '../input';
|
||||
import { DataTableFacetedFilter } from './data-table-faceted-filter';
|
||||
import { DataTableSingleFilter } from './data-table-single-filter';
|
||||
import { statuses, timePeriodGroups, timePeriods } from './data/data';
|
||||
|
||||
interface DataTableToolbarProps<TData> {
|
||||
table: Table<TData>;
|
||||
stats?: Record<string, number>;
|
||||
onStatusFilterChange?: (values: string[]) => void;
|
||||
selectedStatusValues?: string[];
|
||||
onTimePeriodFilterChange?: (values: string[]) => void;
|
||||
selectedTimePeriodValues?: string[];
|
||||
onResetFilters?: () => void;
|
||||
isStatusFiltered?: boolean;
|
||||
isTimePeriodFiltered?: boolean;
|
||||
}
|
||||
|
||||
export function DataTableToolbar<TData>({
|
||||
table,
|
||||
stats,
|
||||
onStatusFilterChange,
|
||||
selectedStatusValues,
|
||||
onTimePeriodFilterChange,
|
||||
selectedTimePeriodValues,
|
||||
onResetFilters,
|
||||
isStatusFiltered,
|
||||
isTimePeriodFiltered,
|
||||
}: DataTableToolbarProps<TData>) {
|
||||
const isFiltered =
|
||||
table.getState().columnFilters.length > 0 || isStatusFiltered || isTimePeriodFiltered;
|
||||
const searchValue = (table.getColumn('title')?.getFilterValue() as string) ?? '';
|
||||
|
||||
const handleClearFilter = () => {
|
||||
table.getColumn('title')?.setFilterValue('');
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
table.resetColumnFilters();
|
||||
onResetFilters?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-1 items-center gap-2">
|
||||
<div className="relative">
|
||||
<Input
|
||||
className="peer h-8 w-[150px] pe-9 ps-9 lg:w-[250px]"
|
||||
placeholder="Search documents..."
|
||||
value={searchValue}
|
||||
onChange={(event) => table.getColumn('title')?.setFilterValue(event.target.value)}
|
||||
/>
|
||||
<div className="text-muted-foreground/80 pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 peer-disabled:opacity-50">
|
||||
<ListFilter size={16} aria-hidden="true" />
|
||||
</div>
|
||||
{searchValue && (
|
||||
<button
|
||||
className="text-muted-foreground/80 hover:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md outline-none transition-[color,box-shadow] focus:z-10 focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
aria-label="Clear filter"
|
||||
onClick={handleClearFilter}
|
||||
>
|
||||
<XCircle className="size-3" aria-hidden="true" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{table.getColumn('status') && (
|
||||
<DataTableFacetedFilter
|
||||
column={table.getColumn('status')}
|
||||
title="Status"
|
||||
options={statuses}
|
||||
icon={CircleDashedIcon}
|
||||
stats={stats}
|
||||
onFilterChange={onStatusFilterChange}
|
||||
selectedValues={selectedStatusValues}
|
||||
/>
|
||||
)}
|
||||
|
||||
{table.getColumn('createdAt') && (
|
||||
<DataTableSingleFilter
|
||||
column={table.getColumn('createdAt')}
|
||||
title="Time Period"
|
||||
options={timePeriods}
|
||||
groups={timePeriodGroups}
|
||||
icon={Calendar}
|
||||
onFilterChange={onTimePeriodFilterChange}
|
||||
selectedValues={selectedTimePeriodValues}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isFiltered && (
|
||||
<Button variant="ghost" className="h-8 gap-2" size="sm" onClick={handleReset}>
|
||||
Reset
|
||||
<X className="size-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user