Enable filtering by creation date with datepicker (#131)
Enable to filter by date with datepicker
This commit is contained in:
@ -2,7 +2,6 @@ import styled from '@emotion/styled';
|
|||||||
import { forwardRef, useState } from 'react';
|
import { forwardRef, useState } from 'react';
|
||||||
import EditableCellWrapper from './EditableCellWrapper';
|
import EditableCellWrapper from './EditableCellWrapper';
|
||||||
import DatePicker from '../form/DatePicker';
|
import DatePicker from '../form/DatePicker';
|
||||||
import { CalendarContainer } from 'react-datepicker';
|
|
||||||
import { modalBackground } from '../../layout/styles/themes';
|
import { modalBackground } from '../../layout/styles/themes';
|
||||||
|
|
||||||
export type EditableDateProps = {
|
export type EditableDateProps = {
|
||||||
@ -24,10 +23,10 @@ const StyledCalendarContainer = styled.div<StyledCalendarContainerProps>`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
border: 1px solid ${(props) => props.theme.primaryBorder};
|
border: 1px solid ${(props) => props.theme.primaryBorder};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 280px;
|
|
||||||
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09);
|
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
left: -10px;
|
left: -10px;
|
||||||
|
top: 10px;
|
||||||
${modalBackground};
|
${modalBackground};
|
||||||
`;
|
`;
|
||||||
function EditableDate({
|
function EditableDate({
|
||||||
@ -54,21 +53,11 @@ function EditableDate({
|
|||||||
);
|
);
|
||||||
|
|
||||||
interface DatePickerContainerProps {
|
interface DatePickerContainerProps {
|
||||||
className?: string;
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DatePickerContainer = ({
|
const DatePickerContainer = ({ children }: DatePickerContainerProps) => {
|
||||||
className,
|
return <StyledCalendarContainer>{children}</StyledCalendarContainer>;
|
||||||
children,
|
|
||||||
}: DatePickerContainerProps) => {
|
|
||||||
return (
|
|
||||||
<StyledCalendarContainer>
|
|
||||||
<CalendarContainer className={className}>
|
|
||||||
<div style={{ position: 'relative' }}>{children}</div>
|
|
||||||
</CalendarContainer>
|
|
||||||
</StyledCalendarContainer>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -86,7 +75,7 @@ function EditableDate({
|
|||||||
setInputValue(date);
|
setInputValue(date);
|
||||||
}}
|
}}
|
||||||
customInput={<DateDisplay />}
|
customInput={<DateDisplay />}
|
||||||
customContainer={DatePickerContainer}
|
customCalendarContainer={DatePickerContainer}
|
||||||
/>
|
/>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export type DatePickerProps = {
|
|||||||
date: Date;
|
date: Date;
|
||||||
onChangeHandler: (date: Date) => void;
|
onChangeHandler: (date: Date) => void;
|
||||||
customInput?: ReactElement;
|
customInput?: ReactElement;
|
||||||
customContainer?(props: CalendarContainerProps): React.ReactNode;
|
customCalendarContainer?(props: CalendarContainerProps): React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -22,6 +22,13 @@ const StyledContainer = styled.div`
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .react-datepicker-popper {
|
||||||
|
position: relative !important;
|
||||||
|
inset: auto !important;
|
||||||
|
transform: none !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
& .react-datepicker__triangle::after {
|
& .react-datepicker__triangle::after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -125,6 +132,10 @@ const StyledContainer = styled.div`
|
|||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .react-datepicker__month-container {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
// Days
|
// Days
|
||||||
|
|
||||||
& .react-datepicker__month {
|
& .react-datepicker__month {
|
||||||
@ -172,7 +183,7 @@ function DatePicker({
|
|||||||
date,
|
date,
|
||||||
onChangeHandler,
|
onChangeHandler,
|
||||||
customInput,
|
customInput,
|
||||||
customContainer,
|
customCalendarContainer,
|
||||||
}: DatePickerProps) {
|
}: DatePickerProps) {
|
||||||
const [startDate, setStartDate] = useState(date);
|
const [startDate, setStartDate] = useState(date);
|
||||||
|
|
||||||
@ -203,7 +214,9 @@ function DatePicker({
|
|||||||
onChangeHandler(date);
|
onChangeHandler(date);
|
||||||
}}
|
}}
|
||||||
customInput={customInput ? customInput : <DefaultDateDisplay />}
|
customInput={customInput ? customInput : <DefaultDateDisplay />}
|
||||||
calendarContainer={customContainer ? customContainer : undefined}
|
calendarContainer={
|
||||||
|
customCalendarContainer ? customCalendarContainer : undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -76,7 +76,6 @@ const StyledDropdownItem = styled.li`
|
|||||||
padding: ${(props) => props.theme.spacing(2)}
|
padding: ${(props) => props.theme.spacing(2)}
|
||||||
calc(${(props) => props.theme.spacing(2)} - 2px);
|
calc(${(props) => props.theme.spacing(2)} - 2px);
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
background: rgba(0, 0, 0, 0);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${(props) => props.theme.text60};
|
color: ${(props) => props.theme.text60};
|
||||||
|
|
||||||
@ -91,7 +90,6 @@ const StyledDropdownTopOption = styled.li`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: calc(${(props) => props.theme.spacing(2)} + 2px)
|
padding: calc(${(props) => props.theme.spacing(2)} + 2px)
|
||||||
calc(${(props) => props.theme.spacing(2)});
|
calc(${(props) => props.theme.spacing(2)});
|
||||||
background: rgba(0, 0, 0, 0);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${(props) => props.theme.text60};
|
color: ${(props) => props.theme.text60};
|
||||||
font-weight: ${(props) => props.theme.fontWeightBold};
|
font-weight: ${(props) => props.theme.fontWeightBold};
|
||||||
@ -115,7 +113,6 @@ const StyledSearchField = styled.li`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
background: rgba(0, 0, 0, 0.04);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${(props) => props.theme.text60};
|
color: ${(props) => props.theme.text60};
|
||||||
font-weight: ${(props) => props.theme.fontWeightBold};
|
font-weight: ${(props) => props.theme.fontWeightBold};
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import {
|
|||||||
SearchResultsType,
|
SearchResultsType,
|
||||||
useSearch,
|
useSearch,
|
||||||
} from '../../../services/api/search/search';
|
} from '../../../services/api/search/search';
|
||||||
|
import DatePicker from '../../form/DatePicker';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
type OwnProps<TData extends FilterableFieldsType> = {
|
type OwnProps<TData extends FilterableFieldsType> = {
|
||||||
isFilterSelected: boolean;
|
isFilterSelected: boolean;
|
||||||
@ -26,7 +28,8 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
}: OwnProps<TData>) => {
|
}: OwnProps<TData>) => {
|
||||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
|
|
||||||
const [isOptionUnfolded, setIsOptionUnfolded] = useState(false);
|
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
const [selectedFilter, setSelectedFilter] = useState<
|
const [selectedFilter, setSelectedFilter] = useState<
|
||||||
FilterConfigType<TData> | undefined
|
FilterConfigType<TData> | undefined
|
||||||
@ -39,19 +42,19 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
|
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
|
||||||
|
|
||||||
const resetState = useCallback(() => {
|
const resetState = useCallback(() => {
|
||||||
setIsOptionUnfolded(false);
|
setIsOperandSelectionUnfolded(false);
|
||||||
setSelectedFilter(undefined);
|
setSelectedFilter(undefined);
|
||||||
setSelectedFilterOperand(undefined);
|
setSelectedFilterOperand(undefined);
|
||||||
setFilterSearch(null);
|
setFilterSearch(null);
|
||||||
}, [setFilterSearch]);
|
}, [setFilterSearch]);
|
||||||
|
|
||||||
const renderSelectOptionItems = selectedFilter?.operands.map(
|
const renderOperandSelection = selectedFilter?.operands.map(
|
||||||
(filterOperand, index) => (
|
(filterOperand, index) => (
|
||||||
<DropdownButton.StyledDropdownItem
|
<DropdownButton.StyledDropdownItem
|
||||||
key={`select-filter-operand-${index}`}
|
key={`select-filter-operand-${index}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedFilterOperand(filterOperand);
|
setSelectedFilterOperand(filterOperand);
|
||||||
setIsOptionUnfolded(false);
|
setIsOperandSelectionUnfolded(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{filterOperand.label}
|
{filterOperand.label}
|
||||||
@ -59,6 +62,21 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderFilterSelection = availableFilters.map((filter, index) => (
|
||||||
|
<DropdownButton.StyledDropdownItem
|
||||||
|
key={`select-filter-${index}`}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedFilter(filter);
|
||||||
|
setSelectedFilterOperand(filter.operands[0]);
|
||||||
|
filter.searchConfig && setFilterSearch(filter.searchConfig);
|
||||||
|
setSearchInput('');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DropdownButton.StyledIcon>{filter.icon}</DropdownButton.StyledIcon>
|
||||||
|
{filter.label}
|
||||||
|
</DropdownButton.StyledDropdownItem>
|
||||||
|
));
|
||||||
|
|
||||||
const renderSearchResults = (
|
const renderSearchResults = (
|
||||||
filterSearchResults: SearchResultsType,
|
filterSearchResults: SearchResultsType,
|
||||||
selectedFilter: FilterConfigType<TData>,
|
selectedFilter: FilterConfigType<TData>,
|
||||||
@ -93,22 +111,7 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSelectFilterITems = availableFilters.map((filter, index) => (
|
function renderValueSelection(
|
||||||
<DropdownButton.StyledDropdownItem
|
|
||||||
key={`select-filter-${index}`}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedFilter(filter);
|
|
||||||
setSelectedFilterOperand(filter.operands[0]);
|
|
||||||
filter.searchConfig && setFilterSearch(filter.searchConfig);
|
|
||||||
setSearchInput('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DropdownButton.StyledIcon>{filter.icon}</DropdownButton.StyledIcon>
|
|
||||||
{filter.label}
|
|
||||||
</DropdownButton.StyledDropdownItem>
|
|
||||||
));
|
|
||||||
|
|
||||||
function renderFilterDropdown(
|
|
||||||
selectedFilter: FilterConfigType<TData>,
|
selectedFilter: FilterConfigType<TData>,
|
||||||
selectedFilterOperand: FilterOperandType<TData>,
|
selectedFilterOperand: FilterOperandType<TData>,
|
||||||
) {
|
) {
|
||||||
@ -116,38 +119,65 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
<>
|
<>
|
||||||
<DropdownButton.StyledDropdownTopOption
|
<DropdownButton.StyledDropdownTopOption
|
||||||
key={'selected-filter-operand'}
|
key={'selected-filter-operand'}
|
||||||
onClick={() => setIsOptionUnfolded(true)}
|
onClick={() => setIsOperandSelectionUnfolded(true)}
|
||||||
>
|
>
|
||||||
{selectedFilterOperand.label}
|
{selectedFilterOperand.label}
|
||||||
|
|
||||||
<DropdownButton.StyledDropdownTopOptionAngleDown />
|
<DropdownButton.StyledDropdownTopOptionAngleDown />
|
||||||
</DropdownButton.StyledDropdownTopOption>
|
</DropdownButton.StyledDropdownTopOption>
|
||||||
<DropdownButton.StyledSearchField key={'search-filter'}>
|
<DropdownButton.StyledSearchField key={'search-filter'}>
|
||||||
<input
|
{['text', 'relation'].includes(selectedFilter.type) && (
|
||||||
type="text"
|
<input
|
||||||
placeholder={selectedFilter.label}
|
type="text"
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
placeholder={selectedFilter.label}
|
||||||
if (selectedFilter.searchConfig) {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilterSearch(selectedFilter.searchConfig);
|
if (
|
||||||
setSearchInput(event.target.value);
|
selectedFilter.type === 'relation' &&
|
||||||
} else {
|
selectedFilter.searchConfig
|
||||||
if (event.target.value === '') {
|
) {
|
||||||
onFilterRemove(selectedFilter.key);
|
setFilterSearch(selectedFilter.searchConfig);
|
||||||
} else {
|
setSearchInput(event.target.value);
|
||||||
onFilterSelect({
|
|
||||||
key: selectedFilter.key,
|
|
||||||
label: selectedFilter.label,
|
|
||||||
value: event.target.value,
|
|
||||||
displayValue: event.target.value,
|
|
||||||
icon: selectedFilter.icon,
|
|
||||||
operand: selectedFilterOperand,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}}
|
if (selectedFilter.type === 'text') {
|
||||||
/>
|
if (event.target.value === '') {
|
||||||
|
onFilterRemove(selectedFilter.key);
|
||||||
|
} else {
|
||||||
|
onFilterSelect({
|
||||||
|
key: selectedFilter.key,
|
||||||
|
label: selectedFilter.label,
|
||||||
|
value: event.target.value,
|
||||||
|
displayValue: event.target.value,
|
||||||
|
icon: selectedFilter.icon,
|
||||||
|
operand: selectedFilterOperand,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedFilter.type === 'date' && (
|
||||||
|
<DatePicker
|
||||||
|
date={new Date()}
|
||||||
|
onChangeHandler={(date) => {
|
||||||
|
onFilterSelect({
|
||||||
|
key: selectedFilter.key,
|
||||||
|
label: selectedFilter.label,
|
||||||
|
value: date.toISOString(),
|
||||||
|
displayValue: date.toLocaleDateString(),
|
||||||
|
icon: selectedFilter.icon,
|
||||||
|
operand: selectedFilterOperand,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
customInput={<></>}
|
||||||
|
customCalendarContainer={styled.div`
|
||||||
|
top: -10px;
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</DropdownButton.StyledSearchField>
|
</DropdownButton.StyledSearchField>
|
||||||
{filterSearchResults &&
|
{selectedFilter.type === 'relation' &&
|
||||||
|
filterSearchResults &&
|
||||||
renderSearchResults(
|
renderSearchResults(
|
||||||
filterSearchResults,
|
filterSearchResults,
|
||||||
selectedFilter,
|
selectedFilter,
|
||||||
@ -165,11 +195,11 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
|
|||||||
setIsUnfolded={setIsUnfolded}
|
setIsUnfolded={setIsUnfolded}
|
||||||
resetState={resetState}
|
resetState={resetState}
|
||||||
>
|
>
|
||||||
{selectedFilter && selectedFilterOperand
|
{selectedFilter
|
||||||
? isOptionUnfolded
|
? isOperandSelectionUnfolded
|
||||||
? renderSelectOptionItems
|
? renderOperandSelection
|
||||||
: renderFilterDropdown(selectedFilter, selectedFilterOperand)
|
: renderValueSelection(selectedFilter, selectedFilterOperand)
|
||||||
: renderSelectFilterITems}
|
: renderFilterSelection}
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,13 @@ export type FilterConfigType<
|
|||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
|
type: WhereType extends UnknownType
|
||||||
|
? 'relation' | 'text' | 'date'
|
||||||
|
: WhereType extends AnyEntity
|
||||||
|
? 'relation'
|
||||||
|
: WhereType extends string
|
||||||
|
? 'text' | 'date'
|
||||||
|
: never;
|
||||||
operands: FilterOperandType<FilteredType, WhereType>[];
|
operands: FilterOperandType<FilteredType, WhereType>[];
|
||||||
} & (WhereType extends UnknownType
|
} & (WhereType extends UnknownType
|
||||||
? { searchConfig?: SearchConfigType<UnknownType> }
|
? { searchConfig?: SearchConfigType<UnknownType> }
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import { Company } from '../../interfaces/entities/company.interface';
|
import { Company } from '../../interfaces/entities/company.interface';
|
||||||
import { FaLink, FaBuilding, FaMapPin, FaUsers } from 'react-icons/fa';
|
import {
|
||||||
|
FaLink,
|
||||||
|
FaBuilding,
|
||||||
|
FaMapPin,
|
||||||
|
FaUsers,
|
||||||
|
FaCalendar,
|
||||||
|
} from 'react-icons/fa';
|
||||||
import { FilterConfigType } from '../../interfaces/filters/interface';
|
import { FilterConfigType } from '../../interfaces/filters/interface';
|
||||||
|
|
||||||
export const nameFilter = {
|
export const nameFilter = {
|
||||||
key: 'company_name',
|
key: 'company_name',
|
||||||
label: 'Company',
|
label: 'Company',
|
||||||
icon: <FaBuilding />,
|
icon: <FaBuilding />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
@ -28,6 +35,7 @@ export const urlFilter = {
|
|||||||
key: 'company_domain_name',
|
key: 'company_domain_name',
|
||||||
label: 'Url',
|
label: 'Url',
|
||||||
icon: <FaLink />,
|
icon: <FaLink />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
@ -50,6 +58,7 @@ export const addressFilter = {
|
|||||||
key: 'company_address',
|
key: 'company_address',
|
||||||
label: 'Address',
|
label: 'Address',
|
||||||
icon: <FaMapPin />,
|
icon: <FaMapPin />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
@ -72,6 +81,7 @@ export const employeesFilter = {
|
|||||||
key: 'company_employees',
|
key: 'company_employees',
|
||||||
label: 'Employees',
|
label: 'Employees',
|
||||||
icon: <FaUsers />,
|
icon: <FaUsers />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Greater than',
|
label: 'Greater than',
|
||||||
@ -94,9 +104,37 @@ export const employeesFilter = {
|
|||||||
],
|
],
|
||||||
} satisfies FilterConfigType<Company, string>;
|
} satisfies FilterConfigType<Company, string>;
|
||||||
|
|
||||||
|
export const creationDateFilter = {
|
||||||
|
key: 'company_created_at',
|
||||||
|
label: 'Created At',
|
||||||
|
icon: <FaCalendar />,
|
||||||
|
type: 'date',
|
||||||
|
operands: [
|
||||||
|
{
|
||||||
|
label: 'Greater than',
|
||||||
|
id: 'greater_than',
|
||||||
|
whereTemplate: (searchString) => ({
|
||||||
|
created_at: {
|
||||||
|
_gte: searchString,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Less than',
|
||||||
|
id: 'less_than',
|
||||||
|
whereTemplate: (searchString) => ({
|
||||||
|
created_at: {
|
||||||
|
_lte: searchString,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} satisfies FilterConfigType<Company, string>;
|
||||||
|
|
||||||
export const availableFilters = [
|
export const availableFilters = [
|
||||||
nameFilter,
|
nameFilter,
|
||||||
urlFilter,
|
urlFilter,
|
||||||
addressFilter,
|
addressFilter,
|
||||||
employeesFilter,
|
employeesFilter,
|
||||||
|
creationDateFilter,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const fullnameFilter = {
|
|||||||
key: 'fullname',
|
key: 'fullname',
|
||||||
label: 'People',
|
label: 'People',
|
||||||
icon: <FaUser />,
|
icon: <FaUser />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
@ -41,6 +42,7 @@ export const companyFilter = {
|
|||||||
key: 'company_name',
|
key: 'company_name',
|
||||||
label: 'Company',
|
label: 'Company',
|
||||||
icon: <FaBuilding />,
|
icon: <FaBuilding />,
|
||||||
|
type: 'relation',
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
query: SEARCH_COMPANY_QUERY,
|
query: SEARCH_COMPANY_QUERY,
|
||||||
template: (searchString: string) => ({
|
template: (searchString: string) => ({
|
||||||
@ -74,6 +76,7 @@ export const emailFilter = {
|
|||||||
key: 'email',
|
key: 'email',
|
||||||
label: 'Email',
|
label: 'Email',
|
||||||
icon: <FaEnvelope />,
|
icon: <FaEnvelope />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
@ -96,6 +99,7 @@ export const cityFilter = {
|
|||||||
key: 'city',
|
key: 'city',
|
||||||
label: 'City',
|
label: 'City',
|
||||||
icon: <FaMapPin />,
|
icon: <FaMapPin />,
|
||||||
|
type: 'text',
|
||||||
operands: [
|
operands: [
|
||||||
{
|
{
|
||||||
label: 'Contains',
|
label: 'Contains',
|
||||||
|
|||||||
Reference in New Issue
Block a user