Added segment filtering to filter form.

This commit is contained in:
Mike Cao 2025-07-27 02:08:19 -07:00
parent 2e69e57445
commit 2ad624ccc8
15 changed files with 301 additions and 193 deletions

View file

@ -1,99 +1,68 @@
import { useState, Key } from 'react';
import { Grid, Row, Column, Label, List, ListItem, Button, Heading } from '@umami/react-zen';
import { useDateRange, useFilters, useMessages } from '@/components/hooks';
import { FilterRecord } from '@/components/common/FilterRecord';
import { Empty } from '@/components/common/Empty';
import { useState } from 'react';
import { Column, Tabs, TabList, Tab, TabPanel, Row, Button } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { FieldFilters } from '@/components/input/FieldFilters';
import { SegmentFilters } from '@/components/input/SegmentFilters';
export interface FilterEditFormProps {
websiteId?: string;
data: any[];
onChange?: (filters: { name: string; type: string; operator: string; value: string }[]) => void;
filters: any[];
segmentId?: string;
onChange?: (params: { filters: any[]; segment: any }) => void;
onClose?: () => void;
}
export function FilterEditForm({ websiteId, data = [], onChange, onClose }: FilterEditFormProps) {
const { formatMessage, labels, messages } = useMessages();
const [filters, setFilters] = useState(data);
const { fields } = useFilters();
const {
dateRange: { startDate, endDate },
} = useDateRange(websiteId);
export function FilterEditForm({
websiteId,
filters = [],
segmentId,
onChange,
onClose,
}: FilterEditFormProps) {
const { formatMessage, labels } = useMessages();
const [currentFilters, setCurrentFilters] = useState(filters);
const [currentSegment, setCurrentSegment] = useState(null);
const updateFilter = (name: string, props: Record<string, any>) => {
setFilters(filters =>
filters.map(filter => (filter.name === name ? { ...filter, ...props } : filter)),
);
const handleReset = () => {
setCurrentFilters([]);
};
const handleAdd = (name: Key) => {
setFilters(filters.concat({ name, operator: 'eq', value: '' }));
};
const handleChange = (name: string, value: Key) => {
updateFilter(name, { value });
};
const handleSelect = (name: string, operator: Key) => {
updateFilter(name, { operator });
};
const handleRemove = (name: string) => {
setFilters(filters.filter(filter => filter.name !== name));
};
const handleApply = () => {
onChange?.(filters.filter(f => f.value));
const handleSave = () => {
onChange?.({ filters: currentFilters.filter(f => f.value), segment: currentSegment });
onClose?.();
};
const handleSegmentChange = (segment?: { id: string }) => {
setCurrentSegment(segment);
};
return (
<Grid columns="160px 1fr" width="760px" overflow="hidden" gapY="6">
<Row gridColumn="span 2">
<Heading>{formatMessage(labels.filters)}</Heading>
<Column>
<Tabs>
<TabList>
<Tab id="fields">{formatMessage(labels.fields)}</Tab>
<Tab id="segments">{formatMessage(labels.segments)}</Tab>
</TabList>
<TabPanel id="fields">
<FieldFilters websiteId={websiteId} filters={currentFilters} onSave={setCurrentFilters} />
</TabPanel>
<TabPanel id="segments">
<SegmentFilters
websiteId={websiteId}
segmentId={segmentId}
onSave={handleSegmentChange}
/>
</TabPanel>
</Tabs>
<Row alignItems="center" justifyContent="space-between" gridColumn="span 2" gap>
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
<Row alignItems="center" justifyContent="flex-end" gridColumn="span 2" gap>
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
<Button variant="primary" onPress={handleSave}>
{formatMessage(labels.apply)}
</Button>
</Row>
</Row>
<Column border="right" paddingRight="3">
<Label>Fields</Label>
<List onAction={handleAdd}>
{fields.map((field: any) => {
const isDisabled = filters.find(({ name }) => name === field.name);
return (
<ListItem key={field.name} id={field.name} isDisabled={isDisabled}>
{field.label}
</ListItem>
);
})}
</List>
</Column>
<Column
paddingLeft="6"
overflow="auto"
gapY="4"
maxHeight="600px"
style={{ contain: 'layout' }}
>
{filters.map(filter => {
return (
<FilterRecord
key={filter.name}
websiteId={websiteId}
type={filter.name}
startDate={startDate}
endDate={endDate}
{...filter}
onSelect={handleSelect}
onRemove={handleRemove}
onChange={handleChange}
/>
);
})}
{!filters.length && <Empty message={formatMessage(messages.nothingSelected)} />}
</Column>
<Row alignItems="center" justifyContent="flex-end" gridColumn="span 2" gap>
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
<Button variant="primary" onPress={handleApply}>
{formatMessage(labels.apply)}
</Button>
</Row>
</Grid>
</Column>
);
}