diff options
| author | joonhoekim <26rote@gmail.com> | 2025-12-01 16:14:04 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-12-01 16:14:04 +0900 |
| commit | 4953e770929b82ef77da074f77071ebd0f428529 (patch) | |
| tree | 01de1f1a27c33609200679aec2fa8a9e948d0a78 /components/client-table-v2/client-table-filter.tsx | |
| parent | 41bb0f9f67a85ac8e17d766492f79a2997d3c6e9 (diff) | |
| parent | 7d2af2af79acd2f674920e8ceeae39fb4a4903e6 (diff) | |
Merge branch 'dynamic-data-table' into dujinkim
Diffstat (limited to 'components/client-table-v2/client-table-filter.tsx')
| -rw-r--r-- | components/client-table-v2/client-table-filter.tsx | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/components/client-table-v2/client-table-filter.tsx b/components/client-table-v2/client-table-filter.tsx new file mode 100644 index 00000000..138f77eb --- /dev/null +++ b/components/client-table-v2/client-table-filter.tsx @@ -0,0 +1,101 @@ +"use client" + +import * as React from "react" +import { Column } from "@tanstack/react-table" +import { Input } from "@/components/ui/input" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { ClientTableColumnMeta } from "./types" + +interface ClientTableFilterProps<TData, TValue> { + column: Column<TData, TValue> +} + +export function ClientTableFilter<TData, TValue>({ + column, +}: ClientTableFilterProps<TData, TValue>) { + const columnFilterValue = column.getFilterValue() + // Cast meta to our local type + const meta = column.columnDef.meta as ClientTableColumnMeta | undefined + + // Handle Boolean Filter + if (meta?.filterType === "boolean") { + return ( + <div onClick={(e) => e.stopPropagation()} className="mt-2"> + <Select + value={(columnFilterValue as string) ?? "all"} + onValueChange={(value) => + column.setFilterValue(value === "all" ? undefined : value === "true") + } + > + <SelectTrigger className="h-8 w-full"> + <SelectValue placeholder="All" /> + </SelectTrigger> + <SelectContent> + <SelectItem value="all">All</SelectItem> + <SelectItem value="true">Yes</SelectItem> + <SelectItem value="false">No</SelectItem> + </SelectContent> + </Select> + </div> + ) + } + + // Handle Select Filter (for specific options) + if (meta?.filterType === "select" && meta.filterOptions) { + return ( + <div onClick={(e) => e.stopPropagation()} className="mt-2"> + <Select + value={(columnFilterValue as string) ?? "all"} + onValueChange={(value) => + column.setFilterValue(value === "all" ? undefined : value) + } + > + <SelectTrigger className="h-8 w-full"> + <SelectValue placeholder="All" /> + </SelectTrigger> + <SelectContent> + <SelectItem value="all">All</SelectItem> + {meta.filterOptions.map((option) => ( + <SelectItem key={option.value} value={option.value}> + {option.label} + </SelectItem> + ))} + </SelectContent> + </Select> + </div> + ) + } + + // Default Text Filter + const [value, setValue] = React.useState(columnFilterValue) + + React.useEffect(() => { + setValue(columnFilterValue) + }, [columnFilterValue]) + + React.useEffect(() => { + const timeout = setTimeout(() => { + column.setFilterValue(value) + }, 500) + + return () => clearTimeout(timeout) + }, [value, column]) + + return ( + <div onClick={(e) => e.stopPropagation()} className="mt-2"> + <Input + type="text" + value={(value ?? "") as string} + onChange={(e) => setValue(e.target.value)} + placeholder="Search..." + className="h-8 w-full font-normal bg-background" + /> + </div> + ) +} |
