mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-14 17:06:39 +00:00
Filtering working on both access and request
This commit is contained in:
104
src/components/ColumnFilter.tsx
Normal file
104
src/components/ColumnFilter.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { useState } from "react";
|
||||
import { Button } from "@app/components/ui/button";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@app/components/ui/popover";
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@app/components/ui/command";
|
||||
import { CheckIcon, ChevronDownIcon, Filter } from "lucide-react";
|
||||
import { cn } from "@app/lib/cn";
|
||||
|
||||
interface FilterOption {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface ColumnFilterProps {
|
||||
options: FilterOption[];
|
||||
selectedValue?: string;
|
||||
onValueChange: (value: string | undefined) => void;
|
||||
placeholder?: string;
|
||||
searchPlaceholder?: string;
|
||||
emptyMessage?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function ColumnFilter({
|
||||
options,
|
||||
selectedValue,
|
||||
onValueChange,
|
||||
placeholder,
|
||||
searchPlaceholder = "Search...",
|
||||
emptyMessage = "No options found",
|
||||
className
|
||||
}: ColumnFilterProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const selectedOption = options.find(option => option.value === selectedValue);
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className={cn(
|
||||
"justify-between text-sm h-8 px-2",
|
||||
!selectedValue && "text-muted-foreground",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="h-4 w-4" />
|
||||
<span className="truncate">
|
||||
{selectedOption ? selectedOption.label : placeholder}
|
||||
</span>
|
||||
</div>
|
||||
<ChevronDownIcon className="h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0 w-[200px]" align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder={searchPlaceholder} />
|
||||
<CommandList>
|
||||
<CommandEmpty>{emptyMessage}</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{/* Clear filter option */}
|
||||
{selectedValue && (
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
onValueChange(undefined);
|
||||
setOpen(false);
|
||||
}}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
Clear filter
|
||||
</CommandItem>
|
||||
)}
|
||||
{options.map((option) => (
|
||||
<CommandItem
|
||||
key={option.value}
|
||||
value={option.label}
|
||||
onSelect={() => {
|
||||
onValueChange(
|
||||
selectedValue === option.value ? undefined : option.value
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedValue === option.value
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{option.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@@ -80,9 +80,9 @@ const getDisplayText = () => {
|
||||
|
||||
return (
|
||||
<div className={cn("flex gap-4", className)}>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
{label && (
|
||||
<Label htmlFor="date-picker" className="px-1">
|
||||
<Label htmlFor="date-picker">
|
||||
{label}
|
||||
</Label>
|
||||
)}
|
||||
@@ -193,9 +193,9 @@ export function DateRangePicker({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn("flex gap-4", className)}>
|
||||
<div className={cn("flex gap-4 items-center", className)}>
|
||||
<DateTimePicker
|
||||
// label={startLabel}
|
||||
label="Start"
|
||||
value={startValue}
|
||||
onChange={handleStartChange}
|
||||
placeholder="Start date & time"
|
||||
@@ -203,7 +203,7 @@ export function DateRangePicker({
|
||||
showTime={showTime}
|
||||
/>
|
||||
<DateTimePicker
|
||||
// label={endLabel}
|
||||
label="End"
|
||||
value={endValue}
|
||||
onChange={handleEndChange}
|
||||
placeholder="End date & time"
|
||||
|
||||
@@ -131,8 +131,8 @@ export function LogDataTable<TData, TValue>({
|
||||
isRefreshing,
|
||||
onExport,
|
||||
isExporting,
|
||||
searchPlaceholder = "Search...",
|
||||
searchColumn = "name",
|
||||
// searchPlaceholder = "Search...",
|
||||
// searchColumn = "name",
|
||||
defaultSort,
|
||||
tabs,
|
||||
defaultTab,
|
||||
@@ -354,7 +354,7 @@ export function LogDataTable<TData, TValue>({
|
||||
<Card>
|
||||
<CardHeader className="flex flex-col space-y-4 sm:flex-row sm:items-center sm:justify-between sm:space-y-0 pb-4">
|
||||
<div className="flex flex-row items-start w-full sm:mr-2 gap-2">
|
||||
<div className="relative w-full sm:max-w-sm">
|
||||
{/* <div className="relative w-full sm:max-w-sm">
|
||||
<Input
|
||||
placeholder={searchPlaceholder}
|
||||
value={globalFilter ?? ""}
|
||||
@@ -366,7 +366,7 @@ export function LogDataTable<TData, TValue>({
|
||||
className="w-full pl-8 m-0"
|
||||
/>
|
||||
<Search className="h-4 w-4 absolute left-2 top-1/2 transform -translate-y-1/2 text-muted-foreground" />
|
||||
</div>
|
||||
</div> */}
|
||||
<DateRangePicker
|
||||
startValue={startDate}
|
||||
endValue={endDate}
|
||||
|
||||
Reference in New Issue
Block a user