Add Filters on Table views (#95)

* Add filter search logic

WIP Filter search

Implement filters

test: fix sorts tests

test: fix filter test

feature: search person and display firstname in results

feature: fix test for filter component

test: mock search filters

refactor: create a useSearch hook

refactor: move debounce in useSearch and reset status of filter selection

feature: debounce set filters

refactor: remove useless setSorts

feature: add where variable to people query

feature: strongly type Filters

feature: update WhereTemplate method

feature: implement filtering on full name

feature: type the useSearch hook

feature: use where reducer

refactor: create a type for readability

feature: use query and mapper from filters

feature: implement filter by company

feature: search filter results on filter select

feature: add loading and results to search results in filters

refactor: move render search results in a function

feature: display a LOADING when it loads

feature: split search input and search filter for different debounce

refactor: remove some warnings

refactor: remove some warnings

* Write test 1

* Write test 2

* test: useSearch is tested

* test: update names of default people data

* test: add a filter search

* Test 3

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Sammy Teillet
2023-05-04 13:54:46 +02:00
committed by GitHub
parent 27d5edc031
commit 6a8a8f0728
33 changed files with 913 additions and 316 deletions

View File

@ -0,0 +1,105 @@
import { gql, useQuery } from '@apollo/client';
import { People_Bool_Exp } from '../../generated/graphql';
import {} from '../../interfaces/company.interface';
import { useMemo, useState } from 'react';
import { FilterType } from '../../components/table/table-header/interface';
export const SEARCH_PEOPLE_QUERY = gql`
query SearchQuery($where: people_bool_exp, $limit: Int) {
searchResults: people(where: $where, limit: $limit) {
id
phone
email
city
firstname
lastname
created_at
}
}
`;
const EMPTY_QUERY = gql`
query EmptyQuery {
_
}
`;
export const SEARCH_COMPANY_QUERY = gql`
query SearchQuery($where: companies_bool_exp, $limit: Int) {
searchResults: companies(where: $where, limit: $limit) {
id
name
}
}
`;
const debounce = <FuncArgs extends any[]>(
func: (...args: FuncArgs) => void,
delay: number,
) => {
let timeoutId: ReturnType<typeof setTimeout>;
return (...args: FuncArgs) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
};
export const useSearch = (): [
{ results: { displayValue: string; value: any }[]; loading: boolean },
React.Dispatch<React.SetStateAction<string>>,
React.Dispatch<React.SetStateAction<FilterType<People_Bool_Exp> | null>>,
] => {
const [filter, setFilter] = useState<FilterType<People_Bool_Exp> | null>(
null,
);
const [searchInput, setSearchInput] = useState<string>('');
const debouncedsetSearchInput = useMemo(
() => debounce(setSearchInput, 500),
[],
);
const where = useMemo(() => {
return (
filter && filter.searchTemplate && filter.searchTemplate(searchInput)
);
}, [filter, searchInput]);
const searchFilterQueryResults = useQuery(
filter?.searchQuery || EMPTY_QUERY,
{
variables: {
where,
},
skip: !filter,
},
);
const searchFilterResults = useMemo<{
results: { displayValue: string; value: any }[];
loading: boolean;
}>(() => {
if (filter == null) {
return {
loading: false,
results: [],
};
}
if (searchFilterQueryResults.loading) {
return {
loading: true,
results: [],
};
}
return {
loading: false,
results: searchFilterQueryResults.data.searchResults.map(
filter.searchResultMapper,
),
};
}, [filter, searchFilterQueryResults]);
return [searchFilterResults, debouncedsetSearchInput, setFilter];
};