import { useEffect, useState } from 'react' import CountsConditionValues from '@/components/counts/CountsConditionValues' import DateTimeField from '@/components/common/DateTimeField' import { Button } from '@/components/ui/button' import { countsConditionInputs, countsEventTypes, countsFieldLabel, countsFilterFields, countsSetOperators, useCountsDefinition } from '@/lib/countsDefinitions' import useDialogue from '@/lib/dialogues/useDialogue' import { countsConditionValue } from '@/lib/countsDisplay' import { countsAxisLabel } from '@/lib/countsDefinitions' import { useLocale } from '@/lib/useLocale' import { inputClass } from '@/lib/utils' import { useUITranslation } from '@/lib/useUITranslation' import { readCountState, encodeCountState } from '@/lib/queryState' import type { CountsResult } from '@/lib/counts' import type { DialogueFormControls } from '@/lib/dialogues/useDialogue' import type { CountsCondition, CountsDefinition } from '@/lib/countsDefinitions' const ConditionEditor = ( { definition, initial, controls, save }: { definition: CountsDefinition; initial?: CountsCondition controls: DialogueFormControls save: (condition: CountsCondition) => void }, ) => { const { label, message } = useUITranslation ('counts') const fields = definition.filterFields ?? definition.fields const fieldName = (key: string) => (fields.find (item => item.key === key)?.labels ?? [countsFieldLabel (key)]).map (label => message ( label, fields.find (item => item.key === key)?.labelValues).text).join (' › ') const [condition, setCondition] = useState (() => { const next = { ...initial, field: initial?.field ?? 'resource_id', operator: initial?.operator ?? 'eq' } if (next.operator !== 'range') delete next.end return next }) const { field, operator } = condition const operators = fields.find (item => item.key === field)?.operators ?? [] const inputs = countsConditionInputs (fields.find (item => item.key === field), operator) useEffect (() => { controls.setActions ([{ label: label (initial == null ? 'add' : 'shared:actions.edit'), onSelect: () => save (condition) }]) }, [controls, condition, initial, label, save]) return
{inputs.length > 1 && }
} const CountsAdditionalConditions = ({ params, update, conditionLabels }: { conditionLabels?: CountsResult['conditionLabels'] params: URLSearchParams update: (key: string, value: string) => void }, ) => { const { label, message } = useUITranslation ('counts') const definition = useCountsDefinition () const dialogue = useDialogue () const locale = useLocale () const conditions = readCountState (params, 'conditions', []) const metadata = definition.filterFields ?? definition.fields const fields = metadata.filter (field => field.operators.length > 0 && !field.legacy) const fieldName = (key: string) => (metadata.find (item => item.key === key)?.labels ?? [countsFieldLabel (key)]).map (label => message ( label, metadata.find (item => item.key === key)?.labelValues).text).join (' › ') const write = (next: CountsCondition[]) => update ( 'conditions', encodeCountState ('conditions', next)) const replace = (index: number, condition: CountsCondition) => write ( conditions.map ((item, position) => position === index ? condition : item)) const patch = (index: number, change: Partial) => replace (index, { ...conditions[index], ...change }) const edit = (index?: number) => { const initial = index == null ? undefined : conditions[index] const save = (condition: CountsCondition) => { if (index == null) write ([...conditions, condition]) else replace (index, condition) } void dialogue.form ({ title: label ('additionalConditions'), footerLayout: 'inline', body: controls => }) } const valueInput = (condition: CountsCondition, index: number, key: 'value' | 'end') => { const type = countsFilterFields (definition)[condition.field] const aria = message (key === 'end' ? 'through' : (condition.operator === 'range' ? 'from' : 'value')) if (type === 'boolean' || condition.field === 'event_type') { const options: string[] = type === 'boolean' ? ['true', 'false'] : [...countsEventTypes] const namespace = type === 'boolean' ? 'truthValues' : 'events' return } if (type === 'datetime') return patch (index, { [key]: value ?? '' })}/> return patch (index, { [key]: event.target.value })}/> } return
{label ('additionalConditions')} {conditions.map ((condition, index) => condition.operator === 'axis_eq' ? (
{countsAxisLabel (condition, definition, locale).text} {label ('operatorSymbols.eq')} {countsConditionValue (condition.value, condition, locale, params.get ('timezone') ?? 'UTC', conditionLabels)}
) : (
{countsSetOperators.includes (condition.operator) ? ( field.key === condition.field)!} definition={definition} params={params} maximum={Math.max (0, 100 - conditions.reduce ((sum, item, position) => sum + (position === index ? 0 : item.values?.length ?? 0), 0))} change={values => patch (index, { values })}/>) : (
{valueInput (condition, index, 'value')} {condition.operator === 'range' && <> {valueInput (condition, index, 'end')} }
)}
))}
} export default CountsAdditionalConditions