aboutsummaryrefslogtreecommitdiff
path: root/src/components/input/FieldFilters.tsx
blob: 2174068fc5cc3891daeedff858ab4fe7bc6c1018 (plain) (blame)
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>
  );
}