mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -1,5 +1,41 @@
|
||||
import { Filter, X } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { BOOLEAN_FIELD_LABELS } from "@/utils/table.util";
|
||||
|
||||
// Resolves a filter's raw value(s) into what should actually be shown on the
|
||||
// pill. Handles every shape ColumnFilter/FilterSheet can produce:
|
||||
// - date range: { from, to }
|
||||
// - boolean columns: "true" / "false" (or an array of those)
|
||||
// - id-backed columns (e.g. createdBy/updatedBy): raw ids — resolved via
|
||||
// fieldOptions[field], the { value, label } picklist DataTable cached
|
||||
// from the last time that column's filter sheet was opened
|
||||
// - everything else (free text, plain enum values): shown as-is
|
||||
function resolveFilterDisplay(filter, fieldOptions) {
|
||||
const raw = filter.value;
|
||||
|
||||
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
||||
const { from, to } = raw;
|
||||
if (from && to) return `${from} – ${to}`;
|
||||
if (from) return `From ${from}`;
|
||||
if (to) return `Until ${to}`;
|
||||
return "";
|
||||
}
|
||||
|
||||
const values = Array.isArray(raw) ? raw : [raw];
|
||||
const boolLabels = BOOLEAN_FIELD_LABELS[filter.id];
|
||||
const options = fieldOptions?.[filter.id];
|
||||
|
||||
const labels = values.map((v) => {
|
||||
if (boolLabels) return boolLabels[v === "true" ? 1 : 0];
|
||||
if (Array.isArray(options)) {
|
||||
const match = options.find((o) => String(o?.value ?? o) === String(v));
|
||||
if (match !== undefined) return match?.label ?? match?.value ?? match;
|
||||
}
|
||||
return v;
|
||||
});
|
||||
|
||||
return labels.join(", ");
|
||||
}
|
||||
|
||||
/**
|
||||
* ActiveFilterPills
|
||||
@@ -9,6 +45,8 @@ import { Button } from "@/components/ui/button";
|
||||
* Props:
|
||||
* @param {Array} filters - Array of { id, value } (TanStack columnFilters shape)
|
||||
* @param {Array} attributes - Array of { field, name } for display labels
|
||||
* @param {Object} [fieldOptions] - { [field]: [{ value, label }] } picklist cache,
|
||||
* used to resolve id-backed filters (createdBy, etc.)
|
||||
* @param {Function} onRemove - (id: string) => void — remove a single filter
|
||||
* @param {Function} [onClearAll] - () => void — clear all filters
|
||||
* @param {boolean} [showClearButton]- Render the "Clear filters (n)" button instead of pills
|
||||
@@ -17,6 +55,7 @@ import { Button } from "@/components/ui/button";
|
||||
export function ActiveFilterPills({
|
||||
filters = [],
|
||||
attributes = [],
|
||||
fieldOptions = {},
|
||||
onRemove,
|
||||
onClearAll,
|
||||
showClearButton = false,
|
||||
@@ -50,7 +89,7 @@ export function ActiveFilterPills({
|
||||
className="inline-flex items-center gap-1 text-xs bg-primary/10 text-primary border border-primary/20 rounded-full px-2.5 py-0.5"
|
||||
>
|
||||
<span className="font-medium">{attr?.name ?? f.id}:</span>
|
||||
{String(f.value)}
|
||||
{resolveFilterDisplay(f, fieldOptions)}
|
||||
<button
|
||||
onClick={() => onRemove(f.id)}
|
||||
className="ml-0.5 hover:text-destructive transition-colors"
|
||||
|
||||
@@ -47,6 +47,11 @@ export default function DataTable({
|
||||
const [filterState, setFilterState] = useState({
|
||||
open: false, column: null, attr: null, data: [],
|
||||
});
|
||||
// Caches the { value, label } picklist fetched per field (e.g. createdBy's
|
||||
// [{value: 56, label: "Obsequio, Russell..."}]) so ActiveFilterPills can
|
||||
// show a name instead of a raw id once a filter is applied — the sheet
|
||||
// itself only holds this data while open.
|
||||
const [fieldOptions, setFieldOptions] = useState({});
|
||||
|
||||
const activeFilters = columnFilters.filter((f) => f.value !== "");
|
||||
|
||||
@@ -108,6 +113,7 @@ export default function DataTable({
|
||||
|
||||
const data = await onFetchFilterData(attr.field);
|
||||
setFilterState({ open: true, column, attr, data });
|
||||
setFieldOptions((prev) => ({ ...prev, [attr.field]: data }));
|
||||
};
|
||||
|
||||
const table = useReactTable({
|
||||
@@ -204,6 +210,7 @@ export default function DataTable({
|
||||
<ActiveFilterPills
|
||||
filters={activeFilters}
|
||||
attributes={attributes}
|
||||
fieldOptions={fieldOptions}
|
||||
onClearAll={() => {
|
||||
setColumnFilters([]);
|
||||
filtersRef.current = [];
|
||||
@@ -227,6 +234,7 @@ export default function DataTable({
|
||||
<ActiveFilterPills
|
||||
filters={activeFilters}
|
||||
attributes={attributes}
|
||||
fieldOptions={fieldOptions}
|
||||
onRemove={(id) => {
|
||||
const next = columnFilters.filter((c) => c.id !== id);
|
||||
const newFilters = next.filter((f) => f.value !== "");
|
||||
|
||||
Reference in New Issue
Block a user