mantine-entity
Version:
A library combining Mantine, TanStack Query, and Mantine React Table for efficient entity management
68 lines (67 loc) • 6.18 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Button, Group, Stack, Popover, Text, Table, ThemeIcon, ActionIcon, Box, Select, } from "@mantine/core";
import { useForm, useFieldArray, useWatch, Controller, } from "react-hook-form";
import { IconCheck, IconClearAll, IconFilter, IconPlus, IconTrash, } from "@tabler/icons-react";
import { useMemo } from "react";
import { RenderElements } from "../../lib/form-builder/render/render-elements";
const Filters = ({ columns, onApply, onClear, }) => {
const columnOption = useMemo(() => columns?.map((c) => ({
label: c?.label || c?.placeholder || "",
value: c.name,
})), [columns]);
const methods = useForm({
defaultValues: {
filters: [],
},
});
const { fields, append, remove } = useFieldArray({
control: methods?.control,
name: "filters",
});
const handleApplyFilters = (data) => {
onApply(data.filters);
};
const handleClearFilters = () => {
methods.reset({ filters: [] });
onClear();
};
const addFilter = () => {
append({ column: "", operator: "=", value: "" });
};
const activeFilters = useWatch({
control: methods?.control,
name: "filters",
defaultValue: [],
});
console.log(methods?.watch());
return (_jsxs(Popover, { withArrow: true, shadow: "lg", position: "bottom-end", radius: "md", children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "compact-sm", fz: 14, w: 116, leftSection: _jsx(IconFilter, { size: 14 }), rightSection: activeFilters.length > 0 && (_jsx(ThemeIcon, { size: 16, color: "white", fz: 11, c: "primary.7", fw: 600, radius: "100%", className: "flex justify-center items-center", children: activeFilters.length })), pl: 0, children: "Filters" }) }), _jsx(Popover.Dropdown, { children: _jsx("form", { onSubmit: methods.handleSubmit(handleApplyFilters), children: _jsxs(Stack, { gap: 4, children: [_jsx(Group, { children: "Filters" }), _jsx(Table, { captionSide: "top", withRowBorders: false, p: 0, classNames: {
th: "p-0",
td: " p-0 p-0.5",
}, children: _jsx(Table.Tbody, { children: fields.map((filter, index) => (_jsxs(Table.Tr, { children: [_jsx(Table.Td, { children: _jsx(Controller, { control: methods.control, name: `filters.${index}.column`, render: ({ field }) => (_jsx(Select, { placeholder: "Select column", data: columnOption, ...field, required: true, size: "xs", comboboxProps: { withinPortal: false }, w: 100 })) }) }), _jsx(Table.Td, { children: _jsx(Controller, { control: methods.control, name: `filters.${index}.operator`, render: ({ field }) => (_jsx(Select, { placeholder: "Operator", size: "xs", data: columns
?.find((col) => col.name ===
methods.watch(`filters.${index}.column`))
?.operators?.map((op) => ({
value: op,
label: op,
})) || [], ...field, required: true, comboboxProps: { withinPortal: false }, classNames: {
root: "w-[76px] min-w-[1px]",
wrapper: "w-[76px] min-w-[1px]",
} })) }) }), _jsx(Table.Td, { children: _jsx(Box, { maw: 100, children: _jsx(RenderElements, { element: {
...columns?.find((col) => col.name ===
methods.watch(`filters.${index}.column`)),
type: columns?.find((col) => col.name ===
methods.watch(`filters.${index}.column`))?.type ?? "text",
name: `filters.${index}.value`,
}, methods: methods }) }) }), _jsx(Table.Td, { children: _jsx(ActionIcon, { color: "red", variant: "transparent", size: "compact-xs", fz: 11, onClick: () => {
if (activeFilters.length === 1) {
remove(index);
onClear();
}
else {
remove(index);
}
}, children: _jsx(IconTrash, { size: 16 }) }) })] }, filter.id))) }) }), _jsxs(Stack, { gap: 4, hidden: fields.length > 0, miw: 300, children: [_jsx(Text, { fw: 600, children: "No filters applied" }), _jsx(Text, { fz: 14, c: "dimmed", children: "Add filters to refine your results." })] }), _jsxs(Group, { justify: "apart", mt: "sm", children: [_jsx(Button, { type: "button", onClick: addFilter, size: "compact-sm", fz: 11, radius: "xl", color: "blue", leftSection: _jsx(IconPlus, { size: 13, stroke: 2 }), pl: 6, children: "Add Filter" }), _jsxs(Group, { gap: "xs", children: [_jsx(Button, { type: "submit", variant: "subtle", size: "compact-sm", fz: 11, color: "green", radius: "xl", leftSection: _jsx(IconCheck, { size: 12 }), pl: 6, hidden: fields.length <= 0, children: "Apply Filters" }), _jsx(Button, { type: "button", onClick: handleClearFilters, variant: "subtle", color: "red", size: "compact-sm", fz: 11, radius: "xl", pl: 6, leftSection: _jsx(IconClearAll, { size: 12 }), hidden: fields.length <= 0, children: "Clear Filters" })] })] })] }) }) })] }));
};
export default Filters;