Simplifies search through relations usage (#126)

This commit is contained in:
Charles Bochet
2023-05-17 23:10:00 +02:00
committed by GitHub
parent 434e020846
commit cdc9e24ac0
15 changed files with 455 additions and 491 deletions

View File

@ -1,4 +1,5 @@
import * as React from 'react';
import styled from '@emotion/styled';
import {
ColumnDef,
@ -7,15 +8,10 @@ import {
useReactTable,
} from '@tanstack/react-table';
import TableHeader from './table-header/TableHeader';
import styled from '@emotion/styled';
import {
FilterConfigType,
SelectedFilterType,
} from '../../interfaces/filters/interface';
import {
SearchableType,
SearchConfigType,
} from '../../interfaces/search/interface';
import { SortType, SelectedSortType } from '../../interfaces/sorts/interface';
declare module 'react' {
@ -34,19 +30,8 @@ type OwnProps<
viewIcon?: React.ReactNode;
availableSorts?: Array<SortType<SortField>>;
availableFilters?: FilterConfigType<TData>[];
filterSearchResults?: {
results: {
render: (value: SearchableType) => string;
value: SearchableType;
}[];
loading: boolean;
};
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onFiltersUpdate?: (sorts: Array<SelectedFilterType<TData>>) => void;
onFilterSearch?: (
filter: SearchConfigType<any> | null,
searchValue: string,
) => void;
onRowSelectionChange?: (rowSelection: string[]) => void;
};
@ -112,10 +97,8 @@ const Table = <
viewIcon,
availableSorts,
availableFilters,
filterSearchResults,
onSortsUpdate,
onFiltersUpdate,
onFilterSearch,
onRowSelectionChange,
}: OwnProps<TData, SortField>,
ref: React.ForwardedRef<{ resetRowSelection: () => void } | undefined>,
@ -156,10 +139,8 @@ const Table = <
viewIcon={viewIcon}
availableSorts={availableSorts}
availableFilters={availableFilters as FilterConfigType<any>[]}
filterSearchResults={filterSearchResults}
onSortsUpdate={onSortsUpdate}
onFiltersUpdate={onFiltersUpdate}
onFilterSearch={onFilterSearch}
/>
<StyledTableScrollableContainer>
<StyledTable>

View File

@ -7,31 +7,19 @@ import {
SelectedFilterType,
} from '../../../interfaces/filters/interface';
import {
SearchConfigType,
SearchableType,
} from '../../../interfaces/search/interface';
SearchResultsType,
useSearch,
} from '../../../services/api/search/search';
import { SearchableType } from '../../../interfaces/search/interface';
type OwnProps<TData extends FilterableFieldsType> = {
isFilterSelected: boolean;
availableFilters: FilterConfigType<TData>[];
filterSearchResults?: {
results: {
render: (value: SearchableType) => string;
value: SearchableType;
}[];
loading: boolean;
};
onFilterSelect: (filter: SelectedFilterType<TData>) => void;
onFilterSearch: (
filter: SearchConfigType<any> | null,
searchValue: string,
) => void;
};
export const FilterDropdownButton = <TData extends FilterableFieldsType>({
availableFilters,
filterSearchResults,
onFilterSearch,
onFilterSelect,
isFilterSelected,
}: OwnProps<TData>) => {
@ -47,12 +35,14 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
FilterOperandType<TData> | undefined
>(undefined);
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
const resetState = useCallback(() => {
setIsOptionUnfolded(false);
setSelectedFilter(undefined);
setSelectedFilterOperand(undefined);
onFilterSearch(null, '');
}, [onFilterSearch]);
setFilterSearch(null);
}, [setFilterSearch]);
const renderSelectOptionItems = selectedFilter?.operands.map(
(filterOperand, index) => (
@ -69,7 +59,7 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
);
const renderSearchResults = (
filterSearchResults: NonNullable<OwnProps<TData>['filterSearchResults']>,
filterSearchResults: SearchResultsType<SearchableType>,
selectedFilter: FilterConfigType<TData>,
selectedFilterOperand: FilterOperandType<TData>,
) => {
@ -108,7 +98,8 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
onClick={() => {
setSelectedFilter(filter);
setSelectedFilterOperand(filter.operands[0]);
onFilterSearch(filter.searchConfig, '');
setFilterSearch(filter.searchConfig);
setSearchInput('');
}}
>
<DropdownButton.StyledIcon>{filter.icon}</DropdownButton.StyledIcon>
@ -134,9 +125,10 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
<input
type="text"
placeholder={selectedFilter.label}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
onFilterSearch(selectedFilter.searchConfig, event.target.value)
}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setFilterSearch(selectedFilter.searchConfig);
setSearchInput(event.target.value);
}}
/>
</DropdownButton.StyledSearchField>
{filterSearchResults &&

View File

@ -9,10 +9,6 @@ import {
FilterConfigType,
SelectedFilterType,
} from '../../../interfaces/filters/interface';
import {
SearchableType,
SearchConfigType,
} from '../../../interfaces/search/interface';
import {
SortType,
SelectedSortType,
@ -23,19 +19,8 @@ type OwnProps<SortField, TData extends FilterableFieldsType> = {
viewIcon?: ReactNode;
availableSorts?: Array<SortType<SortField>>;
availableFilters?: FilterConfigType<TData>[];
filterSearchResults?: {
results: {
render: (value: SearchableType) => string;
value: SearchableType;
}[];
loading: boolean;
};
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onFiltersUpdate?: (sorts: Array<SelectedFilterType<TData>>) => void;
onFilterSearch?: (
filter: SearchConfigType<any> | null,
searchValue: string,
) => void;
};
const StyledContainer = styled.div`
@ -79,10 +64,8 @@ function TableHeader<SortField, TData extends FilterableFieldsType>({
viewIcon,
availableSorts,
availableFilters,
filterSearchResults,
onSortsUpdate,
onFiltersUpdate,
onFilterSearch,
}: OwnProps<SortField, TData>) {
const [sorts, innerSetSorts] = useState<Array<SelectedSortType<SortField>>>(
[],
@ -128,13 +111,6 @@ function TableHeader<SortField, TData extends FilterableFieldsType>({
[onFiltersUpdate, filters],
);
const filterSearch = useCallback(
(filter: SearchConfigType<any> | null, searchValue: string) => {
onFilterSearch && onFilterSearch(filter, searchValue);
},
[onFilterSearch],
);
return (
<StyledContainer>
<StyledTableHeader>
@ -146,9 +122,7 @@ function TableHeader<SortField, TData extends FilterableFieldsType>({
<FilterDropdownButton
isFilterSelected={filters.length > 0}
availableFilters={availableFilters || []}
filterSearchResults={filterSearchResults}
onFilterSelect={filterSelect}
onFilterSearch={filterSearch}
/>
<SortDropdownButton<SortField>
isSortSelected={sorts.length > 0}

View File

@ -3,13 +3,10 @@ import { lightTheme } from '../../../../layout/styles/themes';
import { FilterDropdownButton } from '../FilterDropdownButton';
import styled from '@emotion/styled';
import { useCallback, useState } from 'react';
import {
SEARCH_PEOPLE_QUERY,
useSearch,
} from '../../../../services/api/search/search';
import { SEARCH_PEOPLE_QUERY } from '../../../../services/api/search/search';
import { MockedProvider } from '@apollo/client/testing';
import { mockData } from '../../../../pages/people/__tests__/__data__/mock-data';
import { availableFilters } from '../../../../pages/people/people-table';
import { availableFilters } from '../../../../pages/people/people-filters';
import { Person } from '../../../../interfaces/entities/person.interface';
import {
FilterableFieldsType,
@ -90,7 +87,6 @@ const InnerRegularFilterDropdownButton = ({
setFilter: setFilters,
}: OwnProps<Person>) => {
const [, innerSetFilters] = useState<SelectedFilterType<Person>>();
const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
const outerSetFilters = useCallback(
(filter: SelectedFilterType<Person>) => {
@ -105,11 +101,6 @@ const InnerRegularFilterDropdownButton = ({
availableFilters={availableFilters}
isFilterSelected={true}
onFilterSelect={outerSetFilters}
filterSearchResults={filterSearchResults}
onFilterSearch={(filter, searchValue) => {
setSearhInput(searchValue);
setFilterSearch(filter);
}}
/>
</StyleDiv>
);

View File

@ -3,11 +3,28 @@ import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { FaRegBuilding, FaCalendar } from 'react-icons/fa';
import { SortType } from '../../../../interfaces/sorts/interface';
import { MockedProvider } from '@apollo/client/testing';
import { EMPTY_QUERY } from '../../../../services/api/search/search';
const component = {
title: 'TableHeader',
component: TableHeader,
};
const mocks = [
{
request: {
query: EMPTY_QUERY,
variables: {
where: undefined,
},
},
result: {
data: {
searchResults: [],
},
},
},
];
export default component;
@ -21,12 +38,14 @@ export const RegularTableHeader = () => {
},
];
return (
<ThemeProvider theme={lightTheme}>
<TableHeader
viewName="Test"
viewIcon={<FaRegBuilding />}
availableSorts={availableSorts}
/>
</ThemeProvider>
<MockedProvider mocks={mocks}>
<ThemeProvider theme={lightTheme}>
<TableHeader
viewName="Test"
viewIcon={<FaRegBuilding />}
availableSorts={availableSorts}
/>
</ThemeProvider>
</MockedProvider>
);
};