diff --git a/frontend/src/component/common/FilterDateItem/FilterDateItem.test.tsx b/frontend/src/component/common/FilterDateItem/FilterDateItem.test.tsx
new file mode 100644
index 0000000000..6e81795a7f
--- /dev/null
+++ b/frontend/src/component/common/FilterDateItem/FilterDateItem.test.tsx
@@ -0,0 +1,81 @@
+import { screen } from '@testing-library/react';
+import { render } from 'utils/testRenderer';
+import { vi } from 'vitest';
+import { FilterItemParams } from '../FilterItem/FilterItem';
+import { FilterDateItem, IFilterDateItemProps } from './FilterDateItem';
+
+const getDate = (option: string) => screen.getByText(option);
+
+const setup = (initialState: FilterItemParams) => {
+ const recordedChanges: FilterItemParams[] = [];
+ const mockProps: IFilterDateItemProps = {
+ label: 'Test Label',
+ onChange: (value: FilterItemParams) => {
+ recordedChanges.push(value);
+ },
+ onChipClose: () => {},
+ operators: ['IS_ON_OR_AFTER', 'IS_BEFORE'],
+ state: initialState,
+ };
+
+ render();
+
+ return recordedChanges;
+};
+
+afterEach(() => {
+ vi.restoreAllMocks();
+});
+
+describe('FilterDateItem Component', () => {
+ it('renders initial state correctly', async () => {
+ const mockState = {
+ operator: 'IS_ON_OR_AFTER',
+ values: ['2015-01-21'],
+ };
+
+ const recordedChanges = setup(mockState);
+
+ const valuesElement = await screen.findByText('01/21/2015');
+ await screen.findByText('is on or after');
+ expect(valuesElement).toBeInTheDocument();
+
+ valuesElement.click();
+
+ const selectedDate = getDate('21');
+
+ expect(selectedDate).toHaveAttribute('aria-selected', 'true');
+
+ getDate('22').click();
+
+ expect(recordedChanges).toEqual([
+ {
+ operator: 'IS_ON_OR_AFTER',
+ values: ['2015-01-22'],
+ },
+ ]);
+ });
+
+ it('switches operator', async () => {
+ const mockState = {
+ operator: 'IS_ON_OR_AFTER',
+ values: ['2020-01-01'],
+ };
+
+ const recordedChanges = setup(mockState);
+
+ const operatorsElement = await screen.findByText('is on or after');
+
+ operatorsElement.click();
+ const newOperator = await screen.findByText('is before');
+
+ newOperator.click();
+
+ expect(recordedChanges).toEqual([
+ {
+ operator: 'IS_BEFORE',
+ values: ['2020-01-01'],
+ },
+ ]);
+ });
+});
diff --git a/frontend/src/component/common/FilterDateItem/FilterDateItem.tsx b/frontend/src/component/common/FilterDateItem/FilterDateItem.tsx
index 1339f20db7..95425e7b1d 100644
--- a/frontend/src/component/common/FilterDateItem/FilterDateItem.tsx
+++ b/frontend/src/component/common/FilterDateItem/FilterDateItem.tsx
@@ -2,18 +2,18 @@ import { Box } from '@mui/material';
import React, { FC, useEffect, useRef, useState } from 'react';
import { StyledPopover } from '../FilterItem/FilterItem.styles';
import { FilterItemChip } from '../FilterItem/FilterItemChip/FilterItemChip';
-import { FilterItem } from '../FilterItem/FilterItem';
import { DateCalendar, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { format } from 'date-fns';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { getLocalizedDateString } from '../util';
+import { FilterItemParams } from '../FilterItem/FilterItem';
-interface IFilterDateItemProps {
+export interface IFilterDateItemProps {
label: string;
- onChange: (value: FilterItem | undefined) => void;
+ onChange: (value: FilterItemParams) => void;
onChipClose: () => void;
- state: FilterItem | null | undefined;
+ state: FilterItemParams | null | undefined;
operators: [string, ...string[]];
}
@@ -47,16 +47,11 @@ export const FilterDateItem: FC = ({
const selectedDate = state ? new Date(state.values[0]) : null;
const currentOperator = state ? state.operator : operators[0];
const onDelete = () => {
- onChange(undefined);
+ onChange({ operator: operators[0], values: [] });
onClose();
onChipClose();
};
- const setValue = (value: Date | null) => {
- const formattedValue = value ? format(value, 'yyyy-MM-dd') : '';
- onChange({ operator: currentOperator, values: [formattedValue] });
- };
-
useEffect(() => {
if (state && !operators.includes(state.operator)) {
onChange({
@@ -77,7 +72,10 @@ export const FilterDateItem: FC = ({
operator={currentOperator}
operatorOptions={operators}
onChangeOperator={(operator) => {
- onChange({ operator, values: selectedOptions ?? [] });
+ const formattedValue = selectedDate
+ ? format(selectedDate, 'yyyy-MM-dd')
+ : '';
+ onChange({ operator, values: [formattedValue] ?? [] });
}}
/>
@@ -98,7 +96,15 @@ export const FilterDateItem: FC = ({
setValue(newValue)}
+ onChange={(value) => {
+ const formattedValue = value
+ ? format(value, 'yyyy-MM-dd')
+ : '';
+ onChange({
+ operator: currentOperator,
+ values: [formattedValue],
+ });
+ }}
/>
diff --git a/frontend/src/component/common/FilterItem/FilterItem.test.tsx b/frontend/src/component/common/FilterItem/FilterItem.test.tsx
index d44392002b..b4e3793750 100644
--- a/frontend/src/component/common/FilterItem/FilterItem.test.tsx
+++ b/frontend/src/component/common/FilterItem/FilterItem.test.tsx
@@ -1,12 +1,12 @@
import { screen } from '@testing-library/react';
import { render } from 'utils/testRenderer';
-import { FilterItem, IFilterItemProps } from './FilterItem';
+import { FilterItem, FilterItemParams, IFilterItemProps } from './FilterItem';
const getOption = (option: string) =>
screen.getByText(option).closest('li')!.querySelector('input')!;
-const setup = (initialState: FilterItem) => {
- const recordedChanges: FilterItem[] = [];
+const setup = (initialState: FilterItemParams) => {
+ const recordedChanges: FilterItemParams[] = [];
const mockProps: IFilterItemProps = {
label: 'Test Label',
options: [
@@ -23,7 +23,7 @@ const setup = (initialState: FilterItem) => {
value: '3',
},
],
- onChange: (value: FilterItem) => {
+ onChange: (value: FilterItemParams) => {
recordedChanges.push(value);
},
onChipClose: () => {},
diff --git a/frontend/src/component/common/FilterItem/FilterItem.tsx b/frontend/src/component/common/FilterItem/FilterItem.tsx
index 86012e80ca..1502a427ae 100644
--- a/frontend/src/component/common/FilterItem/FilterItem.tsx
+++ b/frontend/src/component/common/FilterItem/FilterItem.tsx
@@ -13,14 +13,14 @@ import { FilterItemChip } from './FilterItemChip/FilterItemChip';
export interface IFilterItemProps {
label: string;
options: Array<{ label: string; value: string }>;
- onChange: (value: FilterItem) => void;
+ onChange: (value: FilterItemParams) => void;
onChipClose: () => void;
- state: FilterItem | null | undefined;
+ state: FilterItemParams | null | undefined;
singularOperators: [string, ...string[]];
pluralOperators: [string, ...string[]];
}
-export type FilterItem = {
+export type FilterItemParams = {
operator: string;
values: string[];
};
diff --git a/frontend/src/component/feature/FeatureToggleList/FeatureToggleFilters/FeatureToggleFilters.tsx b/frontend/src/component/feature/FeatureToggleList/FeatureToggleFilters/FeatureToggleFilters.tsx
index f39065f50e..55fe341d34 100644
--- a/frontend/src/component/feature/FeatureToggleList/FeatureToggleFilters/FeatureToggleFilters.tsx
+++ b/frontend/src/component/feature/FeatureToggleList/FeatureToggleFilters/FeatureToggleFilters.tsx
@@ -1,11 +1,14 @@
import { useEffect, useState, VFC } from 'react';
import { Box, styled } from '@mui/material';
-import { FilterItem } from 'component/common/FilterItem/FilterItem';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import AddFilterButton from './AddFilterButton';
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
-import { FilterDateItem } from '../../../common/FilterDateItem/FilterDateItem';
+import { FilterDateItem } from 'component/common/FilterDateItem/FilterDateItem';
+import {
+ FilterItem,
+ FilterItemParams,
+} from 'component/common/FilterItem/FilterItem';
const StyledBox = styled(Box)(({ theme }) => ({
display: 'flex',
@@ -14,10 +17,10 @@ const StyledBox = styled(Box)(({ theme }) => ({
}));
export type FeatureTogglesListFilters = {
- project?: FilterItem | null | undefined;
- state?: FilterItem | null | undefined;
- segment?: FilterItem | null | undefined;
- createdAt?: FilterItem | null | undefined;
+ project?: FilterItemParams | null | undefined;
+ state?: FilterItemParams | null | undefined;
+ segment?: FilterItemParams | null | undefined;
+ createdAt?: FilterItemParams | null | undefined;
};
interface IFeatureToggleFiltersProps {