diff options
| author | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
| commit | 396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch) | |
| tree | b9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/components/hooks/useFilters.ts | |
| download | umami-main.tar.xz umami-main.zip | |
Created from https://vercel.com/new
Diffstat (limited to 'src/components/hooks/useFilters.ts')
| -rw-r--r-- | src/components/hooks/useFilters.ts | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/components/hooks/useFilters.ts b/src/components/hooks/useFilters.ts new file mode 100644 index 0000000..850e2af --- /dev/null +++ b/src/components/hooks/useFilters.ts @@ -0,0 +1,99 @@ +import { FILTER_COLUMNS, OPERATORS } from '@/lib/constants'; +import { safeDecodeURIComponent } from '@/lib/url'; +import { useFields } from './useFields'; +import { useMessages } from './useMessages'; +import { useNavigation } from './useNavigation'; + +export function useFilters() { + const { formatMessage, labels } = useMessages(); + const { query } = useNavigation(); + const { fields } = useFields(); + + const operators = [ + { name: 'eq', type: 'string', label: formatMessage(labels.is) }, + { name: 'neq', type: 'string', label: formatMessage(labels.isNot) }, + { name: 'c', type: 'string', label: formatMessage(labels.contains) }, + { name: 'dnc', type: 'string', label: formatMessage(labels.doesNotContain) }, + { name: 'i', type: 'array', label: formatMessage(labels.includes) }, + { name: 'dni', type: 'array', label: formatMessage(labels.doesNotInclude) }, + { name: 't', type: 'boolean', label: formatMessage(labels.isTrue) }, + { name: 'f', type: 'boolean', label: formatMessage(labels.isFalse) }, + { name: 'eq', type: 'number', label: formatMessage(labels.is) }, + { name: 'neq', type: 'number', label: formatMessage(labels.isNot) }, + { name: 'gt', type: 'number', label: formatMessage(labels.greaterThan) }, + { name: 'lt', type: 'number', label: formatMessage(labels.lessThan) }, + { name: 'gte', type: 'number', label: formatMessage(labels.greaterThanEquals) }, + { name: 'lte', type: 'number', label: formatMessage(labels.lessThanEquals) }, + { name: 'bf', type: 'date', label: formatMessage(labels.before) }, + { name: 'af', type: 'date', label: formatMessage(labels.after) }, + { name: 'eq', type: 'uuid', label: formatMessage(labels.is) }, + ]; + + const operatorLabels = { + [OPERATORS.equals]: formatMessage(labels.is), + [OPERATORS.notEquals]: formatMessage(labels.isNot), + [OPERATORS.set]: formatMessage(labels.isSet), + [OPERATORS.notSet]: formatMessage(labels.isNotSet), + [OPERATORS.contains]: formatMessage(labels.contains), + [OPERATORS.doesNotContain]: formatMessage(labels.doesNotContain), + [OPERATORS.true]: formatMessage(labels.true), + [OPERATORS.false]: formatMessage(labels.false), + [OPERATORS.greaterThan]: formatMessage(labels.greaterThan), + [OPERATORS.lessThan]: formatMessage(labels.lessThan), + [OPERATORS.greaterThanEquals]: formatMessage(labels.greaterThanEquals), + [OPERATORS.lessThanEquals]: formatMessage(labels.lessThanEquals), + [OPERATORS.before]: formatMessage(labels.before), + [OPERATORS.after]: formatMessage(labels.after), + }; + + const typeFilters = { + string: [OPERATORS.equals, OPERATORS.notEquals, OPERATORS.contains, OPERATORS.doesNotContain], + array: [OPERATORS.contains, OPERATORS.doesNotContain], + boolean: [OPERATORS.true, OPERATORS.false], + number: [ + OPERATORS.equals, + OPERATORS.notEquals, + OPERATORS.greaterThan, + OPERATORS.lessThan, + OPERATORS.greaterThanEquals, + OPERATORS.lessThanEquals, + ], + date: [OPERATORS.before, OPERATORS.after], + uuid: [OPERATORS.equals], + }; + + const filters = Object.keys(query).reduce((arr, key) => { + if (FILTER_COLUMNS[key]) { + let operator = 'eq'; + let value = safeDecodeURIComponent(query[key]); + const label = fields.find(({ name }) => name === key)?.label; + + const match = value.match(/^([a-z]+)\.(.*)/); + + if (match) { + operator = match[1]; + value = match[2]; + } + + return arr.concat({ + name: key, + operator, + value, + label, + }); + } + return arr; + }, []); + + const getFilters = (type: string) => { + return ( + typeFilters[type]?.map((key: string | number) => ({ + type, + value: key, + label: operatorLabels[key], + })) ?? [] + ); + }; + + return { fields, operators, filters, operatorLabels, typeFilters, getFilters }; +} |