Refactor Filters and Search (#119)
This commit is contained in:
@@ -2,8 +2,7 @@ import { ChangeEvent, ComponentType, useState } from 'react';
|
||||
import EditableCellWrapper from './EditableCellWrapper';
|
||||
import styled from '@emotion/styled';
|
||||
import { useSearch } from '../../../services/search/search';
|
||||
import { FilterType } from '../table-header/interface';
|
||||
import { People_Bool_Exp } from '../../../generated/graphql';
|
||||
import { SearchConfigType, SearchableType } from '../table-header/interface';
|
||||
|
||||
const StyledEditModeContainer = styled.div`
|
||||
width: 200px;
|
||||
@@ -48,10 +47,13 @@ const StyledEditModeResultItem = styled.div`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
export type EditableRelationProps<RelationType, ChipComponentPropsType> = {
|
||||
export type EditableRelationProps<
|
||||
RelationType extends SearchableType,
|
||||
ChipComponentPropsType,
|
||||
> = {
|
||||
relation?: RelationType | null;
|
||||
searchPlaceholder: string;
|
||||
searchFilter: FilterType<People_Bool_Exp>;
|
||||
searchConfig: SearchConfigType<RelationType>;
|
||||
changeHandler: (relation: RelationType) => void;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
ChipComponent: ComponentType<ChipComponentPropsType>;
|
||||
@@ -60,10 +62,13 @@ export type EditableRelationProps<RelationType, ChipComponentPropsType> = {
|
||||
) => ChipComponentPropsType & JSX.IntrinsicAttributes;
|
||||
};
|
||||
|
||||
function EditableRelation<RelationType, ChipComponentPropsType>({
|
||||
function EditableRelation<
|
||||
RelationType extends SearchableType,
|
||||
ChipComponentPropsType,
|
||||
>({
|
||||
relation,
|
||||
searchPlaceholder,
|
||||
searchFilter,
|
||||
searchConfig,
|
||||
changeHandler,
|
||||
editModeHorizontalAlign,
|
||||
ChipComponent,
|
||||
@@ -72,7 +77,8 @@ function EditableRelation<RelationType, ChipComponentPropsType>({
|
||||
const [selectedRelation, setSelectedRelation] = useState(relation);
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
|
||||
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
|
||||
const [filterSearchResults, setSearchInput, setFilterSearch] =
|
||||
useSearch<RelationType>();
|
||||
|
||||
return (
|
||||
<EditableCellWrapper
|
||||
@@ -97,16 +103,16 @@ function EditableRelation<RelationType, ChipComponentPropsType>({
|
||||
<StyledEditModeSearchInput
|
||||
placeholder={searchPlaceholder}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
setFilterSearch(searchFilter);
|
||||
setFilterSearch(searchConfig);
|
||||
setSearchInput(event.target.value);
|
||||
}}
|
||||
/>
|
||||
</StyledEditModeSearchContainer>
|
||||
<StyledEditModeResults>
|
||||
{filterSearchResults.results &&
|
||||
filterSearchResults.results.map((result) => (
|
||||
filterSearchResults.results.map((result, index) => (
|
||||
<StyledEditModeResultItem
|
||||
key={result.value.id}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setSelectedRelation(result.value);
|
||||
changeHandler(result.value);
|
||||
|
||||
@@ -3,16 +3,11 @@ import { ThemeProvider } from '@emotion/react';
|
||||
import { lightTheme } from '../../../../layout/styles/themes';
|
||||
import { StoryFn } from '@storybook/react';
|
||||
import CompanyChip, { CompanyChipPropsType } from '../../../chips/CompanyChip';
|
||||
import {
|
||||
GraphqlQueryCompany,
|
||||
PartialCompany,
|
||||
} from '../../../../interfaces/company.interface';
|
||||
import { Company, mapCompany } from '../../../../interfaces/company.interface';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { SEARCH_COMPANY_QUERY } from '../../../../services/search/search';
|
||||
import styled from '@emotion/styled';
|
||||
import { People_Bool_Exp } from '../../../../generated/graphql';
|
||||
import { FilterType } from '../../table-header/interface';
|
||||
import { FaBuilding } from 'react-icons/fa';
|
||||
import { SearchConfigType } from '../../table-header/interface';
|
||||
|
||||
const component = {
|
||||
title: 'editable-cell/EditableRelation',
|
||||
@@ -58,13 +53,13 @@ const mocks = [
|
||||
];
|
||||
|
||||
const Template: StoryFn<
|
||||
typeof EditableRelation<PartialCompany, CompanyChipPropsType>
|
||||
> = (args: EditableRelationProps<PartialCompany, CompanyChipPropsType>) => {
|
||||
typeof EditableRelation<Company, CompanyChipPropsType>
|
||||
> = (args: EditableRelationProps<Company, CompanyChipPropsType>) => {
|
||||
return (
|
||||
<MockedProvider mocks={mocks}>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<StyledParent data-testid="content-editable-parent">
|
||||
<EditableRelation<PartialCompany, CompanyChipPropsType> {...args} />
|
||||
<EditableRelation<Company, CompanyChipPropsType> {...args} />
|
||||
</StyledParent>
|
||||
</ThemeProvider>
|
||||
</MockedProvider>
|
||||
@@ -77,36 +72,25 @@ EditableRelationStory.args = {
|
||||
id: '123',
|
||||
name: 'Heroku',
|
||||
domain_name: 'heroku.com',
|
||||
} as PartialCompany,
|
||||
} as Company,
|
||||
ChipComponent: CompanyChip,
|
||||
chipComponentPropsMapper: (company: PartialCompany): CompanyChipPropsType => {
|
||||
chipComponentPropsMapper: (company: Company): CompanyChipPropsType => {
|
||||
return {
|
||||
name: company.name,
|
||||
picture: `https://www.google.com/s2/favicons?domain=${company.domain_name}&sz=256`,
|
||||
};
|
||||
},
|
||||
changeHandler: (relation: PartialCompany) => {
|
||||
changeHandler: (relation: Company) => {
|
||||
console.log('changed', relation);
|
||||
},
|
||||
searchFilter: {
|
||||
key: 'company_name',
|
||||
label: 'Company',
|
||||
icon: <FaBuilding />,
|
||||
whereTemplate: () => {
|
||||
return {};
|
||||
},
|
||||
searchQuery: SEARCH_COMPANY_QUERY,
|
||||
searchTemplate: (searchInput: string) => ({
|
||||
searchConfig: {
|
||||
query: SEARCH_COMPANY_QUERY,
|
||||
template: (searchInput: string) => ({
|
||||
name: { _ilike: `%${searchInput}%` },
|
||||
}),
|
||||
searchResultMapper: (company: GraphqlQueryCompany) => ({
|
||||
displayValue: company.name,
|
||||
value: {
|
||||
id: company.id,
|
||||
name: company.name,
|
||||
domain_name: company.domain_name,
|
||||
},
|
||||
resultMapper: (company) => ({
|
||||
render: (company) => company.name,
|
||||
value: mapCompany(company),
|
||||
}),
|
||||
operands: [],
|
||||
} satisfies FilterType<People_Bool_Exp>,
|
||||
} satisfies SearchConfigType<Company>,
|
||||
};
|
||||
|
||||
@@ -2,17 +2,17 @@ import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
|
||||
import { EditableRelationStory } from '../__stories__/EditableRelation.stories';
|
||||
import { CompanyChipPropsType } from '../../../chips/CompanyChip';
|
||||
import { PartialCompany } from '../../../../interfaces/company.interface';
|
||||
|
||||
import { EditableRelationProps } from '../EditableRelation';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { Company } from '../../../../interfaces/company.interface';
|
||||
|
||||
it('Checks the EditableRelation editing event bubbles up', async () => {
|
||||
const func = jest.fn(() => null);
|
||||
const { getByTestId, getByText } = render(
|
||||
<EditableRelationStory
|
||||
{...(EditableRelationStory.args as EditableRelationProps<
|
||||
PartialCompany,
|
||||
Company,
|
||||
CompanyChipPropsType
|
||||
>)}
|
||||
changeHandler={func}
|
||||
@@ -49,10 +49,16 @@ it('Checks the EditableRelation editing event bubbles up', async () => {
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(func).toBeCalledWith({
|
||||
domain_name: 'abnb.com',
|
||||
id: 'abnb',
|
||||
name: 'Airbnb',
|
||||
});
|
||||
expect(func).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
accountOwner: null,
|
||||
address: undefined,
|
||||
domain_name: 'abnb.com',
|
||||
employees: undefined,
|
||||
id: 'abnb',
|
||||
name: 'Airbnb',
|
||||
opportunities: [],
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user