function DatetimeFilter()

in src/data-table/column-datetime.tsx [217:560]


function DatetimeFilter(props) {
  const [css, theme] = useStyletron();
  const locale = React.useContext(LocaleContext);
  const mountNode = React.useRef();
  const initialState = filterParamsToInitialState(props.filterParams);

  const datesSorted = React.useMemo(() => {
    return props.data.sort(sortDates);
  }, [props.data]);
  const presentYears = React.useMemo(() => {
    const dict = {};
    // @ts-ignore
    props.data.forEach((date) => {
      // @ts-ignore
      dict[getYear(date)] = true;
    });
    return Object.keys(dict).map((n) => parseInt(n));
  }, [props.data]);
  const startOfWeek = React.useMemo(() => {
    return getStartOfWeek(new Date(), props.locale);
  }, [props.locale]);
  const localizedWeekdays = React.useMemo(() => {
    return [...WEEKDAYS.slice(getDay(startOfWeek), 7), ...WEEKDAYS.slice(0, getDay(startOfWeek))];
  }, [props.locale]);

  const [exclude, setExclude] = React.useState(initialState.exclude);
  const [comparatorIndex, setComparatorIndex] = React.useState(initialState.comparatorIndex);
  const [rangeOperator, setRangeOperator] = React.useState<Value>([initialState.rangeOperator]);
  const [categoricalOperator, setCategoricalOperator] = React.useState<Value>([
    initialState.categoricalOperator,
  ]);
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const [rangeDates, setRangeDates] = React.useState<any>(
    initialState.rangeDates.length
      ? initialState.rangeDates
      : [new Date(datesSorted[0]), new Date(datesSorted[datesSorted.length - 1])]
  );

  const [years, setYears] = React.useState<number[]>(initialState.years);
  const [halves, setHalves] = React.useState<number[]>(initialState.halves);
  const [quarters, setQuarters] = React.useState<number[]>(initialState.quarters);
  const [months, setMonths] = React.useState<number[]>(initialState.months);
  const [weekdays, setWeekdays] = React.useState<number[]>(initialState.weekdays);

  const isRange = comparatorIndex === 0;
  const isCategorical = comparatorIndex === 1;

  return (
    <FilterShell
      exclude={exclude}
      onExcludeChange={() => setExclude(!exclude)}
      onApply={() => {
        if (isRange) {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          const op: DatetimeOperations = rangeOperator[0].id as any;

          let description = '';
          if (op === DATETIME_OPERATIONS.RANGE_DATETIME) {
            const left = format(rangeDates[0], FORMAT_STRING);
            const right = format(rangeDates[1], FORMAT_STRING);
            description = `${left} - ${right}`;
          } else if (op === DATETIME_OPERATIONS.RANGE_DATE) {
            const left = format(rangeDates[0], DATE_FORMAT);
            const right = format(rangeDates[1], DATE_FORMAT);
            description = `${left} - ${right}`;
          } else if (op === DATETIME_OPERATIONS.RANGE_TIME) {
            const left = format(rangeDates[0], TIME_FORMAT);
            const right = format(rangeDates[1], TIME_FORMAT);
            description = `${left} - ${right}`;
          }

          props.setFilter({
            operation: op,
            range: rangeDates,
            selection: [],
            description: description,
            exclude,
          });
        }

        if (isCategorical) {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          const op: DatetimeOperations = categoricalOperator[0].id as any;

          let selection: number[] = [];
          let operatorLocaleLabelKey = '';
          let description = '';
          if (op === DATETIME_OPERATIONS.WEEKDAY) {
            selection = weekdays;
            operatorLocaleLabelKey = CATEGORICAL_OPERATIONS[0].localeLabelKey;
            description = weekdays
              .map((w) => {
                const day = addDays(startOfWeek, localizedWeekdays.indexOf(w));

                return getWeekdayInLocale(day, props.locale);
              })
              .join(', ');
          } else if (op === DATETIME_OPERATIONS.MONTH) {
            selection = months;
            operatorLocaleLabelKey = CATEGORICAL_OPERATIONS[1].localeLabelKey;
            description = months.map((m) => getMonthInLocale(m, props.locale)).join(', ');
          } else if (op === DATETIME_OPERATIONS.QUARTER) {
            selection = quarters;
            operatorLocaleLabelKey = CATEGORICAL_OPERATIONS[2].localeLabelKey;
            description = quarters.map((q) => getQuarterInLocale(q, props.locale)).join(', ');
          } else if (op === DATETIME_OPERATIONS.HALF) {
            selection = halves;
            operatorLocaleLabelKey = CATEGORICAL_OPERATIONS[3].localeLabelKey;
            description = halves
              .map((h) =>
                h === 0
                  ? locale.datatable.datetimeFilterCategoricalFirstHalf
                  : locale.datatable.datetimeFilterCategoricalSecondHalf
              )
              .join(', ');
          } else if (op === DATETIME_OPERATIONS.YEAR) {
            selection = years;
            operatorLocaleLabelKey = CATEGORICAL_OPERATIONS[4].localeLabelKey;
            description = years.join(', ');
          }

          if (operatorLocaleLabelKey) {
            // @ts-ignore
            description = `${locale.datatable[operatorLocaleLabelKey]} - ${description}`;
          }

          props.setFilter({
            operation: op,
            range: [],
            selection,
            description,
            exclude,
          });
        }

        props.close();
      }}
    >
      {/* @ts-ignore */}
      <div ref={mountNode}>
        <ButtonGroup
          size={SIZE.compact}
          mode={MODE.radio}
          selected={comparatorIndex}
          onClick={(_, index) => setComparatorIndex(index)}
          overrides={{
            Root: {
              style: ({ $theme }) => ({ marginBottom: $theme.sizing.scale300 }),
            },
          }}
        >
          <Button type="button" overrides={{ BaseButton: { style: { width: '100%' } } }}>
            {locale.datatable.datetimeFilterRange}
          </Button>
          <Button type="button" overrides={{ BaseButton: { style: { width: '100%' } } }}>
            {locale.datatable.datetimeFilterCategorical}
          </Button>
        </ButtonGroup>

        {isRange && (
          <div>
            <Select
              value={rangeOperator}
              onChange={(params) => setRangeOperator(params.value)}
              // eslint-disable-next-line @typescript-eslint/no-explicit-any
              mountNode={mountNode.current as any}
              options={RANGE_OPERATIONS.map((op) => ({
                // @ts-ignore
                label: locale.datatable[op.localeLabelKey],
                id: op.id,
              }))}
              size="compact"
              clearable={false}
            />

            <div className={css({ paddingTop: theme.sizing.scale600 })}>
              {(rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_DATETIME ||
                rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_DATE) && (
                <Datepicker
                  // eslint-disable-next-line @typescript-eslint/no-explicit-any
                  mountNode={mountNode.current as any}
                  value={rangeDates}
                  onChange={({ date }) => {
                    if (Array.isArray(date)) {
                      if (!date.length) return;
                      const nextDates = date.map((d, i) =>
                        d ? applyDateToTime(rangeDates[i], d) : null
                      );
                      setRangeDates(nextDates);
                    }
                  }}
                  formatString={DATE_FORMAT}
                  mask={MASK}
                  placeholder="MM-DD-YYYY - MM-DD-YYYY"
                  minDate={datesSorted[0]}
                  maxDate={datesSorted[datesSorted.length - 1]}
                  timeSelectStart={rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_DATETIME}
                  timeSelectEnd={rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_DATETIME}
                  overrides={{ TimeSelect: { props: { size: 'compact' } } }}
                  range
                  size="compact"
                  locale={props.locale}
                />
              )}
            </div>

            {(rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_DATETIME ||
              rangeOperator[0].id === DATETIME_OPERATIONS.RANGE_TIME) && (
              <div
                className={css({
                  display: 'flex',
                  paddingTop: theme.sizing.scale100,
                })}
              >
                <div
                  className={css({
                    width: '100%',
                    marginRight: theme.sizing.scale300,
                  })}
                >
                  <TimePicker
                    format="24"
                    value={rangeDates[0]}
                    onChange={(time) =>
                      time && setRangeDates([applyTimeToDate(rangeDates[0], time), rangeDates[1]])
                    }
                    creatable
                    size="compact"
                  />
                </div>

                <div
                  className={css({
                    width: '100%',
                  })}
                >
                  <TimePicker
                    format="24"
                    value={rangeDates[1]}
                    onChange={(time) =>
                      time && setRangeDates([rangeDates[0], applyTimeToDate(rangeDates[1], time)])
                    }
                    creatable
                    size="compact"
                  />
                </div>
              </div>
            )}
          </div>
        )}

        {isCategorical && (
          <div>
            <Select
              value={categoricalOperator}
              onChange={(params) => setCategoricalOperator(params.value)}
              options={CATEGORICAL_OPERATIONS.map((op) => ({
                // @ts-ignore
                label: locale.datatable[op.localeLabelKey],
                id: op.id,
              }))}
              // eslint-disable-next-line @typescript-eslint/no-explicit-any
              mountNode={mountNode.current as any}
              size="compact"
              clearable={false}
            />

            <div
              className={css({
                paddingLeft: theme.sizing.scale300,
                paddingTop: theme.sizing.scale500,
              })}
            >
              {categoricalOperator[0].id === DATETIME_OPERATIONS.WEEKDAY && (
                <Checks
                  value={weekdays}
                  setValue={setWeekdays}
                  options={localizedWeekdays.map((w, offset) => {
                    const day = addDays(startOfWeek, offset);

                    return {
                      label: getWeekdayInLocale(day, props.locale),
                      id: w,
                    };
                  })}
                />
              )}

              {categoricalOperator[0].id === DATETIME_OPERATIONS.MONTH && (
                <Checks
                  value={months}
                  setValue={setMonths}
                  options={MONTHS.map((m) => ({
                    label: getMonthInLocale(m, props.locale),
                    id: m,
                  }))}
                />
              )}

              {categoricalOperator[0].id === DATETIME_OPERATIONS.QUARTER && (
                <Checks
                  value={quarters}
                  setValue={setQuarters}
                  options={QUARTERS.map((q) => ({
                    label: getQuarterInLocale(q, props.locale),
                    id: q,
                  }))}
                />
              )}

              {categoricalOperator[0].id === DATETIME_OPERATIONS.HALF && (
                <Checks
                  value={halves}
                  setValue={setHalves}
                  options={[
                    {
                      label: locale.datatable.datetimeFilterCategoricalFirstHalf,
                      id: 0,
                    },
                    {
                      label: locale.datatable.datetimeFilterCategoricalSecondHalf,
                      id: 1,
                    },
                  ]}
                />
              )}

              {categoricalOperator[0].id === DATETIME_OPERATIONS.YEAR && (
                <Checks
                  value={years}
                  setValue={setYears}
                  options={presentYears.map((year) => ({
                    label: year,
                    id: year,
                  }))}
                />
              )}
            </div>
          </div>
        )}
      </div>
    </FilterShell>
  );
}