1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
import {
Button,
Column,
Grid,
Icon,
List,
ListItem,
Menu,
MenuItem,
MenuTrigger,
Popover,
Row,
} from '@umami/react-zen';
import { endOfDay, subMonths } from 'date-fns';
import type { Key } from 'react';
import { Empty } from '@/components/common/Empty';
import { FilterRecord } from '@/components/common/FilterRecord';
import { useFields, useMessages, useMobile } from '@/components/hooks';
import { Plus } from '@/components/icons';
export interface FieldFiltersProps {
websiteId: string;
value?: { name: string; operator: string; value: string }[];
exclude?: string[];
onChange?: (data: any) => void;
}
export function FieldFilters({ websiteId, value, exclude = [], onChange }: FieldFiltersProps) {
const { formatMessage, messages } = useMessages();
const { fields } = useFields();
const startDate = subMonths(endOfDay(new Date()), 6);
const endDate = endOfDay(new Date());
const { isMobile } = useMobile();
const updateFilter = (name: string, props: Record<string, any>) => {
onChange(value.map(filter => (filter.name === name ? { ...filter, ...props } : filter)));
};
const handleAdd = (name: Key) => {
onChange(value.concat({ name: name.toString(), 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) => {
onChange(value.filter(filter => filter.name !== name));
};
return (
<Grid columns={{ xs: '1fr', md: '180px 1fr' }} overflow="hidden" gapY="6">
<Row display={{ xs: 'flex', md: 'none' }}>
<MenuTrigger>
<Button>
<Icon>
<Plus />
</Icon>
</Button>
<Popover placement={isMobile ? 'left' : 'bottom start'} shouldFlip>
<Menu
onAction={handleAdd}
style={{ maxHeight: 'calc(100vh - 2rem)', overflowY: 'auto' }}
>
{fields
.filter(({ name }) => !exclude.includes(name))
.map(field => {
const isDisabled = !!value.find(({ name }) => name === field.name);
return (
<MenuItem key={field.name} id={field.name} isDisabled={isDisabled}>
{field.label}
</MenuItem>
);
})}
</Menu>
</Popover>
</MenuTrigger>
</Row>
<Column display={{ xs: 'none', md: 'flex' }} border="right" paddingRight="3" marginRight="6">
<List onAction={handleAdd}>
{fields
.filter(({ name }) => !exclude.includes(name))
.map(field => {
const isDisabled = !!value.find(({ name }) => name === field.name);
return (
<ListItem key={field.name} id={field.name} isDisabled={isDisabled}>
{field.label}
</ListItem>
);
})}
</List>
</Column>
<Column overflow="auto" gapY="4" style={{ contain: 'layout' }}>
{value.map(filter => {
return (
<FilterRecord
key={filter.name}
websiteId={websiteId}
type={filter.name}
startDate={startDate}
endDate={endDate}
{...filter}
onSelect={handleSelect}
onRemove={handleRemove}
onChange={handleChange}
/>
);
})}
{!value.length && <Empty message={formatMessage(messages.nothingSelected)} />}
</Column>
</Grid>
);
}
|