From 6cad7ac1d131b8b1de4cc72ba0f2b05b4851202b Mon Sep 17 00:00:00 2001 From: Eunjae Lee Date: Fri, 7 Feb 2025 14:43:25 +0100 Subject: [PATCH] fix: selected filters for numeric and text filters (#19129) * fix: selected filters for numeric and text filters * little adjustment --- .../components/filters/FilterPopover.tsx | 116 +++++++++++++++--- .../filters/NumberFilterOptions.tsx | 17 +-- .../components/filters/TextFilterOptions.tsx | 23 +--- .../data-table/components/filters/types.ts | 12 ++ .../data-table/components/filters/utils.ts | 26 ++++ 5 files changed, 138 insertions(+), 56 deletions(-) create mode 100644 packages/features/data-table/components/filters/types.ts create mode 100644 packages/features/data-table/components/filters/utils.ts diff --git a/packages/features/data-table/components/filters/FilterPopover.tsx b/packages/features/data-table/components/filters/FilterPopover.tsx index 4a6d1ee8b6..72bbdeab11 100644 --- a/packages/features/data-table/components/filters/FilterPopover.tsx +++ b/packages/features/data-table/components/filters/FilterPopover.tsx @@ -2,7 +2,7 @@ import startCase from "lodash/startCase"; import type { IconName } from "@calcom/ui"; -import { Button, Icon, Popover, PopoverContent, PopoverTrigger } from "@calcom/ui"; +import { Button, Icon, Popover, PopoverContent, PopoverTrigger, Badge } from "@calcom/ui"; import { useFilterValue } from "../../hooks"; import { type FilterableColumn, type FilterValue, ZFilterValue, ColumnFilterType } from "../../lib/types"; @@ -13,6 +13,7 @@ import { isNumberFilterValue, } from "../../lib/utils"; import { FilterOptions } from "./FilterOptions"; +import { numberFilterOperatorOptions, useTextFilterOperatorOptions } from "./utils"; const FILTER_ICONS: Record = { [ColumnFilterType.TEXT]: "file-text", @@ -26,42 +27,117 @@ type FilterPopoverProps = { column: FilterableColumn; }; -const useSelectedLabels = ({ +type SelectedLabelsProps = { + column: FilterableColumn; + filterValue?: FilterValue; +}; + +function Operator({ children }: { children: React.ReactNode }) { + return {children}; +} + +function AppliedTextFilterValue({ filterValue }: SelectedLabelsProps) { + const textFilterOperatorOptions = useTextFilterOperatorOptions(); + if (!isTextFilterValue(filterValue)) return null; + + const operator = filterValue.data.operator; + const operatorOption = textFilterOperatorOptions.find((o) => o.value === operator); + if (!operatorOption) return null; + + if (!operatorOption.requiresOperand) { + return {operatorOption.label}; + } + + const operand = filterValue.data.operand; + return ( + <> + {operatorOption.label} + + {operand} + + + ); +} + +function AppliedNumberFilterValue({ filterValue }: SelectedLabelsProps) { + if (!isNumberFilterValue(filterValue)) return null; + + const operator = filterValue.data.operator; + const operatorOption = numberFilterOperatorOptions.find((o) => o.value === operator); + if (!operatorOption) return null; + + return ( + <> + {operatorOption.label} + + {filterValue.data.operand} + + + ); +} + +function AppliedSelectFilterValue({ column, filterValue }: SelectedLabelsProps) { + let text: string | undefined; + let moreCount = 0; + + if (isSingleSelectFilterValue(filterValue)) { + const options = (column as Extract).options; + text = options.find((opt) => opt.value === filterValue.data)?.label; + moreCount = 0; + } else if (isMultiSelectFilterValue(filterValue)) { + const options = (column as Extract).options; + text = options.find((opt) => opt.value === filterValue.data[0])?.label; + moreCount = filterValue.data.length - 1; + } + + if (!text) return null; + + return ( + <> + + {text} + + {moreCount > 0 && ( + + +{moreCount} + + )} + + ); +} + +function AppliedFilterValue({ column, filterValue, }: { column: FilterableColumn; filterValue?: FilterValue; -}) => { - if (isTextFilterValue(filterValue)) { - return { text: filterValue.data.operand, moreCount: 0 }; - } else if (isNumberFilterValue(filterValue)) { - return { text: filterValue.data.operand, moreCount: 0 }; - } else if (isSingleSelectFilterValue(filterValue)) { - const options = (column as Extract).options; - const text = options.find((opt) => opt.value === filterValue.data)?.label; - return { text, moreCount: 0 }; - } else if (isMultiSelectFilterValue(filterValue)) { - const options = (column as Extract).options; - const text = options.find((opt) => opt.value === filterValue.data[0])?.label; - return { text, moreCount: filterValue.data.length - 1 }; +}) { + if (column.type === ColumnFilterType.TEXT) { + return ; + } else if (column.type === ColumnFilterType.NUMBER) { + return ; + } else if ( + column.type === ColumnFilterType.SINGLE_SELECT || + column.type === ColumnFilterType.MULTI_SELECT + ) { + return ; } else { - return { text: "", moreCount: 0 }; + return null; } -}; +} export function FilterPopover({ column }: FilterPopoverProps) { const icon = column.icon || FILTER_ICONS[column.type]; const filterValue = useFilterValue(column.id, ZFilterValue); - const { text, moreCount } = useSelectedLabels({ column, filterValue }); + return ( diff --git a/packages/features/data-table/components/filters/NumberFilterOptions.tsx b/packages/features/data-table/components/filters/NumberFilterOptions.tsx index 1a5a9c7ffc..f30055006c 100644 --- a/packages/features/data-table/components/filters/NumberFilterOptions.tsx +++ b/packages/features/data-table/components/filters/NumberFilterOptions.tsx @@ -6,22 +6,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Form, Input, Select, Button } from "@calcom/ui"; import { useFilterValue, useDataTable } from "../../hooks"; -import type { FilterableColumn, NumberFilterOperator } from "../../lib/types"; +import type { FilterableColumn } from "../../lib/types"; import { ZNumberFilterValue, ColumnFilterType } from "../../lib/types"; - -export type NumberFilterOperatorOption = { - label: string; - value: NumberFilterOperator; -}; - -const numberFilterOperatorOptions: NumberFilterOperatorOption[] = [ - { value: "eq", label: "=" }, - { value: "neq", label: "≠" }, - { value: "gt", label: ">" }, - { value: "gte", label: "≥" }, - { value: "lt", label: "<" }, - { value: "lte", label: "≤" }, -]; +import { numberFilterOperatorOptions } from "./utils"; export type NumberFilterOptionsProps = { column: Extract; diff --git a/packages/features/data-table/components/filters/TextFilterOptions.tsx b/packages/features/data-table/components/filters/TextFilterOptions.tsx index 048d13b6b5..70ba4f3311 100644 --- a/packages/features/data-table/components/filters/TextFilterOptions.tsx +++ b/packages/features/data-table/components/filters/TextFilterOptions.tsx @@ -6,28 +6,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Form, Input, Select, Button } from "@calcom/ui"; import { useFilterValue, useDataTable } from "../../hooks"; -import type { FilterableColumn, TextFilterOperator } from "../../lib/types"; +import type { FilterableColumn } from "../../lib/types"; import { ZTextFilterValue, ColumnFilterType } from "../../lib/types"; - -export type TextFilterOperatorOption = { - label: string; - value: TextFilterOperator; - requiresOperand: boolean; -}; - -const useTextFilterOperatorOptions = (): TextFilterOperatorOption[] => { - const { t } = useLocale(); - return [ - { value: "equals", label: t("filter_operator_is"), requiresOperand: true }, - { value: "notEquals", label: t("filter_operator_is_not"), requiresOperand: true }, - { value: "contains", label: t("filter_operator_contains"), requiresOperand: true }, - { value: "notContains", label: t("filter_operator_does_not_contain"), requiresOperand: true }, - { value: "startsWith", label: t("filter_operator_starts_with"), requiresOperand: true }, - { value: "endsWith", label: t("filter_operator_ends_with"), requiresOperand: true }, - { value: "isEmpty", label: t("filter_operator_is_empty"), requiresOperand: false }, - { value: "isNotEmpty", label: t("filter_operator_not_empty"), requiresOperand: false }, - ]; -}; +import { useTextFilterOperatorOptions } from "./utils"; export type TextFilterOptionsProps = { column: Extract; diff --git a/packages/features/data-table/components/filters/types.ts b/packages/features/data-table/components/filters/types.ts new file mode 100644 index 0000000000..839a5eff99 --- /dev/null +++ b/packages/features/data-table/components/filters/types.ts @@ -0,0 +1,12 @@ +import type { NumberFilterOperator, TextFilterOperator } from "../../lib/types"; + +export type NumberFilterOperatorOption = { + label: string; + value: NumberFilterOperator; +}; + +export type TextFilterOperatorOption = { + label: string; + value: TextFilterOperator; + requiresOperand: boolean; +}; diff --git a/packages/features/data-table/components/filters/utils.ts b/packages/features/data-table/components/filters/utils.ts new file mode 100644 index 0000000000..00099c28f5 --- /dev/null +++ b/packages/features/data-table/components/filters/utils.ts @@ -0,0 +1,26 @@ +import { useLocale } from "@calcom/lib/hooks/useLocale"; + +import type { TextFilterOperatorOption, NumberFilterOperatorOption } from "./types"; + +export const numberFilterOperatorOptions: NumberFilterOperatorOption[] = [ + { value: "eq", label: "=" }, + { value: "neq", label: "≠" }, + { value: "gt", label: ">" }, + { value: "gte", label: "≥" }, + { value: "lt", label: "<" }, + { value: "lte", label: "≤" }, +]; + +export const useTextFilterOperatorOptions = (): TextFilterOperatorOption[] => { + const { t } = useLocale(); + return [ + { value: "equals", label: t("filter_operator_is"), requiresOperand: true }, + { value: "notEquals", label: t("filter_operator_is_not"), requiresOperand: true }, + { value: "contains", label: t("filter_operator_contains"), requiresOperand: true }, + { value: "notContains", label: t("filter_operator_does_not_contain"), requiresOperand: true }, + { value: "startsWith", label: t("filter_operator_starts_with"), requiresOperand: true }, + { value: "endsWith", label: t("filter_operator_ends_with"), requiresOperand: true }, + { value: "isEmpty", label: t("filter_operator_is_empty"), requiresOperand: false }, + { value: "isNotEmpty", label: t("filter_operator_not_empty"), requiresOperand: false }, + ]; +};