try to deploy

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-13 21:27:56 +08:00
parent bfc4b9fc67
commit b1805cfe4d
87 changed files with 798 additions and 718 deletions
@@ -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 !== "");