diff --git a/front/src/components/table/Table.tsx b/front/src/components/table/Table.tsx index 1fbf0085b..fc201a592 100644 --- a/front/src/components/table/Table.tsx +++ b/front/src/components/table/Table.tsx @@ -23,7 +23,10 @@ declare module 'react' { ): (props: P & React.RefAttributes) => React.ReactElement | null; } -type OwnProps = { +type OwnProps< + TData extends { id: string; __typename: 'companies' | 'people' }, + SortField, +> = { data: Array; columns: Array>; viewName: string; @@ -38,7 +41,7 @@ type OwnProps = { loading: boolean; }; onSortsUpdate?: (sorts: Array>) => void; - onFiltersUpdate?: (sorts: Array) => void; + onFiltersUpdate?: (sorts: Array>) => void; onFilterSearch?: ( filter: SearchConfigType | null, searchValue: string, @@ -97,7 +100,10 @@ const StyledTableScrollableContainer = styled.div` flex: 1; `; -const Table = ( +const Table = < + TData extends { id: string; __typename: 'companies' | 'people' }, + SortField, +>( { data, columns, diff --git a/front/src/components/table/editable-cell/__stories__/EditableRelation.stories.tsx b/front/src/components/table/editable-cell/__stories__/EditableRelation.stories.tsx index b2553820a..6b57af71a 100644 --- a/front/src/components/table/editable-cell/__stories__/EditableRelation.stories.tsx +++ b/front/src/components/table/editable-cell/__stories__/EditableRelation.stories.tsx @@ -72,6 +72,7 @@ const Template: StoryFn< export const EditableRelationStory = Template.bind({}); EditableRelationStory.args = { relation: { + __typename: 'companies', id: '123', name: 'Heroku', domain_name: 'heroku.com', diff --git a/front/src/components/table/editable-cell/__tests__/EditableRelation.test.tsx b/front/src/components/table/editable-cell/__tests__/EditableRelation.test.tsx index a3c3c2819..3537ad3d7 100644 --- a/front/src/components/table/editable-cell/__tests__/EditableRelation.test.tsx +++ b/front/src/components/table/editable-cell/__tests__/EditableRelation.test.tsx @@ -50,6 +50,7 @@ it('Checks the EditableRelation editing event bubbles up', async () => { await waitFor(() => { expect(func).toBeCalledWith({ + __typename: 'companies', accountOwner: undefined, address: undefined, domainName: 'abnb.com', diff --git a/front/src/components/table/table-header/FilterDropdownButton.tsx b/front/src/components/table/table-header/FilterDropdownButton.tsx index b6b68c985..a36040d21 100644 --- a/front/src/components/table/table-header/FilterDropdownButton.tsx +++ b/front/src/components/table/table-header/FilterDropdownButton.tsx @@ -3,14 +3,15 @@ import DropdownButton from './DropdownButton'; import { FilterConfigType, FilterOperandType, + FilterableFieldsType, SearchConfigType, SearchableType, SelectedFilterType, } from './interface'; -type OwnProps = { +type OwnProps = { isFilterSelected: boolean; - availableFilters: FilterConfigType[]; + availableFilters: FilterConfigType[]; filterSearchResults?: { results: { render: (value: SearchableType) => string; @@ -18,30 +19,30 @@ type OwnProps = { }[]; loading: boolean; }; - onFilterSelect: (filter: SelectedFilterType) => void; + onFilterSelect: (filter: SelectedFilterType) => void; onFilterSearch: ( filter: SearchConfigType | null, searchValue: string, ) => void; }; -export function FilterDropdownButton({ +export const FilterDropdownButton = ({ availableFilters, filterSearchResults, onFilterSearch, onFilterSelect, isFilterSelected, -}: OwnProps) { +}: OwnProps) => { const [isUnfolded, setIsUnfolded] = useState(false); const [isOptionUnfolded, setIsOptionUnfolded] = useState(false); const [selectedFilter, setSelectedFilter] = useState< - FilterConfigType | undefined + FilterConfigType | undefined >(undefined); const [selectedFilterOperand, setSelectedFilterOperand] = useState< - FilterOperandType | undefined + FilterOperandType | undefined >(undefined); const resetState = useCallback(() => { @@ -66,9 +67,9 @@ export function FilterDropdownButton({ ); const renderSearchResults = ( - filterSearchResults: NonNullable, - selectedFilter: FilterConfigType, - selectedFilterOperand: FilterOperandType, + filterSearchResults: NonNullable['filterSearchResults']>, + selectedFilter: FilterConfigType, + selectedFilterOperand: FilterOperandType, ) => { if (filterSearchResults.loading) { return ( @@ -114,8 +115,8 @@ export function FilterDropdownButton({ )); function renderFilterDropdown( - selectedFilter: FilterConfigType, - selectedFilterOperand: FilterOperandType, + selectedFilter: FilterConfigType, + selectedFilterOperand: FilterOperandType, ) { return ( <> @@ -161,4 +162,4 @@ export function FilterDropdownButton({ : renderSelectFilterITems} ); -} +}; diff --git a/front/src/components/table/table-header/SortAndFilterBar.tsx b/front/src/components/table/table-header/SortAndFilterBar.tsx index 3eb74a78e..126a15e6b 100644 --- a/front/src/components/table/table-header/SortAndFilterBar.tsx +++ b/front/src/components/table/table-header/SortAndFilterBar.tsx @@ -1,13 +1,17 @@ import styled from '@emotion/styled'; import SortOrFilterChip from './SortOrFilterChip'; import { FaArrowDown, FaArrowUp } from 'react-icons/fa'; -import { SelectedFilterType, SelectedSortType } from './interface'; +import { + FilterableFieldsType, + SelectedFilterType, + SelectedSortType, +} from './interface'; -type OwnProps = { +type OwnProps = { sorts: Array>; onRemoveSort: (sortId: SelectedSortType['key']) => void; - filters: Array; - onRemoveFilter: (filterId: SelectedFilterType['key']) => void; + filters: Array>; + onRemoveFilter: (filterId: SelectedFilterType['key']) => void; onCancelClick: () => void; }; @@ -40,13 +44,13 @@ const StyledCancelButton = styled.button` } `; -function SortAndFilterBar({ +function SortAndFilterBar({ sorts, onRemoveSort, filters, onRemoveFilter, onCancelClick, -}: OwnProps) { +}: OwnProps) { return ( {sorts.map((sort) => { diff --git a/front/src/components/table/table-header/TableHeader.tsx b/front/src/components/table/table-header/TableHeader.tsx index e8e7d6b9b..ab14e3902 100644 --- a/front/src/components/table/table-header/TableHeader.tsx +++ b/front/src/components/table/table-header/TableHeader.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { FilterConfigType, + FilterableFieldsType, SearchConfigType, SearchableType, SelectedFilterType, @@ -12,11 +13,11 @@ import { SortDropdownButton } from './SortDropdownButton'; import { FilterDropdownButton } from './FilterDropdownButton'; import SortAndFilterBar from './SortAndFilterBar'; -type OwnProps = { +type OwnProps = { viewName: string; viewIcon?: ReactNode; availableSorts?: Array>; - availableFilters?: FilterConfigType[]; + availableFilters?: FilterConfigType[]; filterSearchResults?: { results: { render: (value: SearchableType) => string; @@ -25,7 +26,7 @@ type OwnProps = { loading: boolean; }; onSortsUpdate?: (sorts: Array>) => void; - onFiltersUpdate?: (sorts: Array) => void; + onFiltersUpdate?: (sorts: Array>) => void; onFilterSearch?: ( filter: SearchConfigType | null, searchValue: string, @@ -68,7 +69,7 @@ const StyledFilters = styled.div` margin-right: ${(props) => props.theme.spacing(2)}; `; -function TableHeader({ +function TableHeader({ viewName, viewIcon, availableSorts, @@ -77,11 +78,13 @@ function TableHeader({ onSortsUpdate, onFiltersUpdate, onFilterSearch, -}: OwnProps) { +}: OwnProps) { const [sorts, innerSetSorts] = useState>>( [], ); - const [filters, innerSetFilters] = useState>([]); + const [filters, innerSetFilters] = useState>>( + [], + ); const sortSelect = useCallback( (newSort: SelectedSortType) => { @@ -102,7 +105,7 @@ function TableHeader({ ); const filterSelect = useCallback( - (filter: SelectedFilterType) => { + (filter: SelectedFilterType) => { const newFilters = updateSortOrFilterByKey(filters, filter); innerSetFilters(newFilters); @@ -112,7 +115,7 @@ function TableHeader({ ); const filterUnselect = useCallback( - (filterId: SelectedFilterType['key']) => { + (filterId: SelectedFilterType['key']) => { const newFilters = filters.filter((filter) => filter.key !== filterId); innerSetFilters(newFilters); onFiltersUpdate && onFiltersUpdate(newFilters); diff --git a/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx b/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx index ea460ec8e..3b74ae95f 100644 --- a/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx +++ b/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx @@ -2,7 +2,7 @@ import { ThemeProvider } from '@emotion/react'; import { lightTheme } from '../../../../layout/styles/themes'; import { FilterDropdownButton } from '../FilterDropdownButton'; import styled from '@emotion/styled'; -import { FilterConfigType, SelectedFilterType } from '../interface'; +import { FilterableFieldsType, SelectedFilterType } from '../interface'; import { useCallback, useState } from 'react'; import { SEARCH_PEOPLE_QUERY, @@ -20,7 +20,7 @@ const component = { export default component; -type OwnProps = { +type OwnProps = { setFilter: (filters: SelectedFilterType) => void; }; @@ -98,8 +98,8 @@ const InnerRegularFilterDropdownButton = ({ ); return ( - + availableFilters={availableFilters} isFilterSelected={true} onFilterSelect={outerSetFilters} filterSearchResults={filterSearchResults} diff --git a/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx b/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx index a60a5614e..c89323c48 100644 --- a/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx +++ b/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx @@ -3,6 +3,7 @@ import { ThemeProvider } from '@emotion/react'; import { lightTheme } from '../../../../layout/styles/themes'; import { FaArrowDown } from 'react-icons/fa'; import { SelectedFilterType } from '../interface'; +import { Person } from '../../../../interfaces/person.interface'; const component = { title: 'SortAndFilterBar', @@ -20,6 +21,31 @@ export const RegularSortAndFilterBar = ({ removeFunction, cancelFunction, }: OwnProps) => { + const personFilter = { + label: 'People', + operand: { + label: 'Include', + id: 'include', + whereTemplate: (person: Person) => { + return { email: { _eq: person.email } }; + }, + }, + key: 'test_filter', + icon: , + displayValue: 'john@doedoe.com', + value: { + __typename: 'people', + id: 'test', + email: 'john@doedoe.com', + firstname: 'John', + lastname: 'Doe', + phone: '123456789', + company: null, + creationDate: new Date(), + pipes: null, + city: 'Paris', + }, + } satisfies SelectedFilterType; return ( { - return { email: { _eq: person.email } }; - }, - }, - key: 'test_filter', - icon: , - displayValue: 'john@doedoe.com', - value: { - id: 'test', - email: 'john@doedoe.com', - firstname: 'John', - lastname: 'Doe', - phone: '123456789', - company: null, - creationDate: new Date(), - pipe: null, - city: 'Paris', - }, - } satisfies SelectedFilterType, - ]} + filters={[personFilter] as SelectedFilterType[]} /> ); diff --git a/front/src/components/table/table-header/helpers.ts b/front/src/components/table/table-header/helpers.ts index afba39c3a..f135536a9 100644 --- a/front/src/components/table/table-header/helpers.ts +++ b/front/src/components/table/table-header/helpers.ts @@ -1,7 +1,16 @@ import { Order_By } from '../../../generated/graphql'; -import { BoolExpType, SelectedFilterType, SelectedSortType } from './interface'; +import { + BoolExpType, + FilterWhereType, + FilterableFieldsType, + SelectedFilterType, + SelectedSortType, +} from './interface'; -export const reduceFiltersToWhere = ( +export const reduceFiltersToWhere = < + ValueType extends FilterableFieldsType, + WhereTemplateType extends FilterWhereType, +>( filters: Array>, ): BoolExpType => { const where = filters.reduce((acc, filter) => { diff --git a/front/src/components/table/table-header/interface.ts b/front/src/components/table/table-header/interface.ts index 2a64ba708..3f008de45 100644 --- a/front/src/components/table/table-header/interface.ts +++ b/front/src/components/table/table-header/interface.ts @@ -35,8 +35,13 @@ export type SelectedSortType = SortType & { order: 'asc' | 'desc'; }; +type AnyEntity = { + id: string; + __typename: string; +} & Record; + export type FilterableFieldsType = Person | Company; -export type FilterWhereType = Person | Company | User; +export type FilterWhereType = Person | Company | User | AnyEntity; type FilterConfigGqlType = WhereType extends Company ? GraphqlQueryCompany @@ -50,9 +55,14 @@ export type BoolExpType = T extends Company ? Companies_Bool_Exp : T extends Person ? People_Bool_Exp + : T extends User + ? Users_Bool_Exp : never; -export type FilterConfigType = { +export type FilterConfigType< + FilteredType extends FilterableFieldsType, + WhereType extends FilterWhereType = any, +> = { key: string; label: string; icon: ReactNode; @@ -77,17 +87,33 @@ export type SearchConfigType = { }; export type FilterOperandType< - FilteredType = FilterableFieldsType, - WhereType = any, + FilteredType extends FilterableFieldsType, + WhereType extends FilterWhereType = AnyEntity, +> = + | FilterOperandExactMatchType + | FilterOperandComparativeType; + +type FilterOperandExactMatchType< + FilteredType extends FilterableFieldsType, + WhereType extends FilterWhereType, > = { - label: string; - id: string; + label: 'Equal' | 'Not equal'; + id: 'equal' | 'not-equal'; + whereTemplate: (value: WhereType) => BoolExpType; +}; + +type FilterOperandComparativeType< + FilteredType extends FilterableFieldsType, + WhereType extends FilterWhereType, +> = { + label: 'Like' | 'Not like' | 'Include'; + id: 'like' | 'not_like' | 'include'; whereTemplate: (value: WhereType) => BoolExpType; }; export type SelectedFilterType< - FilteredType = FilterableFieldsType, - WhereType = any, + FilteredType extends FilterableFieldsType, + WhereType extends FilterWhereType = AnyEntity, > = { key: string; value: WhereType; diff --git a/front/src/interfaces/__tests__/company.interface.test.ts b/front/src/interfaces/__tests__/company.interface.test.ts index b0f99e948..ff1ddfbd7 100644 --- a/front/src/interfaces/__tests__/company.interface.test.ts +++ b/front/src/interfaces/__tests__/company.interface.test.ts @@ -36,6 +36,7 @@ describe('Company mappers', () => { const company = mapToCompany(graphQLCompany); expect(company).toStrictEqual({ + __typename: 'companies', id: graphQLCompany.id, name: graphQLCompany.name, domainName: graphQLCompany.domain_name, @@ -43,6 +44,7 @@ describe('Company mappers', () => { employees: graphQLCompany.employees, address: graphQLCompany.address, accountOwner: { + __typename: 'users', id: '7af20dea-0412-4c4c-8b13-d6f0e6e09e87', email: 'john@example.com', displayName: 'John Doe', @@ -66,9 +68,11 @@ describe('Company mappers', () => { id: '522d4ec4-c46b-4360-a0a7-df8df170be81', email: 'john@example.com', displayName: 'John Doe', + __typename: 'users', }, creationDate: now, - }; + __typename: 'companies', + } satisfies Company; const graphQLCompany = mapToGqlCompany(company); expect(graphQLCompany).toStrictEqual({ id: company.id, diff --git a/front/src/interfaces/__tests__/person.interface.test.ts b/front/src/interfaces/__tests__/person.interface.test.ts index af091cb5c..b2b9620e1 100644 --- a/front/src/interfaces/__tests__/person.interface.test.ts +++ b/front/src/interfaces/__tests__/person.interface.test.ts @@ -28,6 +28,7 @@ describe('Person mappers', () => { const person = mapToPerson(graphQLPerson); expect(person).toStrictEqual({ + __typename: 'people', id: graphQLPerson.id, firstname: graphQLPerson.firstname, lastname: graphQLPerson.lastname, @@ -36,6 +37,7 @@ describe('Person mappers', () => { city: graphQLPerson.city, phone: graphQLPerson.phone, company: { + __typename: 'companies', id: '7af20dea-0412-4c4c-8b13-d6f0e6e09e87', accountOwner: undefined, address: undefined, diff --git a/front/src/interfaces/__tests__/user.interface.test.ts b/front/src/interfaces/__tests__/user.interface.test.ts index 28c2a4d3a..69c1382c7 100644 --- a/front/src/interfaces/__tests__/user.interface.test.ts +++ b/front/src/interfaces/__tests__/user.interface.test.ts @@ -28,6 +28,7 @@ describe('User mappers', () => { const User = mapToUser(graphQLUser); expect(User).toStrictEqual({ + __typename: 'users', id: graphQLUser.id, displayName: graphQLUser.display_name, email: graphQLUser.email, @@ -47,6 +48,7 @@ describe('User mappers', () => { const now = new Date(); now.setMilliseconds(0); const user = { + __typename: 'users', id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', displayName: 'John Doe', email: 'john.doe@gmail.com', diff --git a/front/src/interfaces/company.interface.ts b/front/src/interfaces/company.interface.ts index bfc11e340..12d4d932c 100644 --- a/front/src/interfaces/company.interface.ts +++ b/front/src/interfaces/company.interface.ts @@ -3,6 +3,7 @@ import { GraphqlQueryUser, User, mapToUser } from './user.interface'; import { GraphqlQueryPipe } from './pipe.interface'; export type Company = { + __typename: 'companies'; id: string; name?: string; domainName?: string; @@ -43,6 +44,7 @@ export type GraphqlMutationCompany = { }; export const mapToCompany = (company: GraphqlQueryCompany): Company => ({ + __typename: 'companies', id: company.id, employees: company.employees, name: company.name, diff --git a/front/src/interfaces/person.interface.ts b/front/src/interfaces/person.interface.ts index 440f65276..409c3a17e 100644 --- a/front/src/interfaces/person.interface.ts +++ b/front/src/interfaces/person.interface.ts @@ -6,6 +6,7 @@ import { import { Pipe } from './pipe.interface'; export type Person = { + __typename: 'people'; id: string; firstname?: string; lastname?: string; @@ -44,10 +45,11 @@ export type GraphqlMutationPerson = { city?: string; created_at?: string; company_id?: string; - __typename: string; + __typename: 'people'; }; export const mapToPerson = (person: GraphqlQueryPerson): Person => ({ + __typename: 'people', id: person.id, firstname: person.firstname, lastname: person.lastname, diff --git a/front/src/interfaces/user.interface.ts b/front/src/interfaces/user.interface.ts index 24e7c1cdb..b1788cb36 100644 --- a/front/src/interfaces/user.interface.ts +++ b/front/src/interfaces/user.interface.ts @@ -5,6 +5,7 @@ import { } from './workspace_member.interface'; export interface User { + __typename: 'users'; id: string; email?: string; displayName?: string; @@ -28,6 +29,7 @@ export type GraphqlMutationUser = { }; export const mapToUser = (user: GraphqlQueryUser): User => ({ + __typename: 'users', id: user.id, email: user.email, displayName: user.display_name, diff --git a/front/src/layout/navbar/__stories__/Navbar.stories.tsx b/front/src/layout/navbar/__stories__/Navbar.stories.tsx index b942d4991..6a50306d5 100644 --- a/front/src/layout/navbar/__stories__/Navbar.stories.tsx +++ b/front/src/layout/navbar/__stories__/Navbar.stories.tsx @@ -17,6 +17,7 @@ export const NavbarOnCompanies = () => { { + const addEmptyRow = useCallback(async () => { const newCompany: Company = { id: uuidv4(), name: '', @@ -76,14 +73,15 @@ function Companies() { pipes: [], creationDate: new Date(), accountOwner: null, + __typename: 'companies', }; - insertCompany(newCompany); + await insertCompany(newCompany); setInternalData([newCompany, ...internalData]); refetch(); }, [internalData, setInternalData, refetch]); - const deleteRows = useCallback(() => { - deleteCompanies(selectedRowIds); + const deleteRows = useCallback(async () => { + await deleteCompanies(selectedRowIds); setInternalData([ ...internalData.filter((row) => !selectedRowIds.includes(row.id)), ]); @@ -111,7 +109,7 @@ function Companies() { viewName="All Companies" viewIcon={} availableSorts={availableSorts} - availableFilters={availableFilters as Array} + availableFilters={availableFilters} filterSearchResults={filterSearchResults} onSortsUpdate={updateSorts} onFiltersUpdate={updateFilters} diff --git a/front/src/pages/companies/__stories__/Companies.stories.tsx b/front/src/pages/companies/__stories__/Companies.stories.tsx index 7f3bcff0c..13b72ce05 100644 --- a/front/src/pages/companies/__stories__/Companies.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.stories.tsx @@ -5,6 +5,8 @@ import { lightTheme } from '../../../layout/styles/themes'; import { GET_COMPANIES } from '../../../services/companies'; import { mockData } from '../__tests__/__data__/mock-data'; import { MockedProvider } from '@apollo/client/testing'; +import { SEARCH_COMPANY_QUERY } from '../../../services/search/search'; +import { mockCompanySearchData } from '../../../services/search/__data__/mock-search-data'; const component = { title: 'Companies', @@ -42,6 +44,27 @@ const mocks = [ }, }, }, + { + request: { + query: SEARCH_COMPANY_QUERY, + variables: { where: { name: { _ilike: '%%' } }, limit: 5 }, + }, + result: mockCompanySearchData, + }, + { + request: { + query: GET_COMPANIES, + variables: { + orderBy: [{ created_at: 'desc' }], + where: { domain_name: { _eq: 'linkedin-searched.com' } }, + }, + }, + result: { + data: { + companies: mockData, + }, + }, + }, ]; export const CompaniesDefault = () => ( diff --git a/front/src/pages/companies/__tests__/Companies.test.tsx b/front/src/pages/companies/__tests__/Companies.test.tsx index 5a00322ab..f401698fe 100644 --- a/front/src/pages/companies/__tests__/Companies.test.tsx +++ b/front/src/pages/companies/__tests__/Companies.test.tsx @@ -136,3 +136,28 @@ it('Checks insert data is appending a new line', async () => { expect(tableRows.length).toBe(7); }); }); + +it('Checks filters are working', async () => { + const { getByText } = render(); + + await waitFor(() => { + expect(getByText('Airbnb')).toBeDefined(); + }); + + const filterDropdown = getByText('Filter'); + fireEvent.click(filterDropdown); + + await waitFor(() => { + expect(getByText('Url')).toBeDefined(); + }); + + const urlFilter = getByText('Url'); + fireEvent.click(urlFilter); + + await waitFor(() => { + expect(getByText('linkedin-searched.com')).toBeDefined(); + }); + + const filterByLinkedinOption = getByText('linkedin-searched.com'); + fireEvent.click(filterByLinkedinOption); +}); diff --git a/front/src/pages/companies/__tests__/__data__/mock-data.ts b/front/src/pages/companies/__tests__/__data__/mock-data.ts index 9202fef85..54ddbe9f5 100644 --- a/front/src/pages/companies/__tests__/__data__/mock-data.ts +++ b/front/src/pages/companies/__tests__/__data__/mock-data.ts @@ -7,7 +7,7 @@ export const mockData: Array = [ name: 'Airbnb', created_at: '2023-04-26T10:08:54.724515+00:00', address: '17 rue de clignancourt', - employees: 12, + employees: '12', account_owner: null, __typename: 'companies', }, @@ -16,8 +16,8 @@ export const mockData: Array = [ domain_name: 'aircall.io', name: 'Aircall', created_at: '2023-04-26T10:12:42.33625+00:00', - address: null, - employees: 1, + address: '', + employees: '1', account_owner: null, __typename: 'companies', }, @@ -26,8 +26,8 @@ export const mockData: Array = [ domain_name: 'algolia.com', name: 'Algolia', created_at: '2023-04-26T10:10:32.530184+00:00', - address: null, - employees: 1, + address: '', + employees: '1', account_owner: null, __typename: 'companies', }, @@ -36,8 +36,8 @@ export const mockData: Array = [ domain_name: 'apple.com', name: 'Apple', created_at: '2023-03-21T06:30:25.39474+00:00', - address: null, - employees: 10, + address: '', + employees: '10', account_owner: null, __typename: 'companies', }, @@ -47,7 +47,7 @@ export const mockData: Array = [ name: 'BeReal', created_at: '2023-04-26T10:13:29.712485+00:00', address: '10 rue de la Paix', - employees: 1, + employees: '1', account_owner: null, __typename: 'companies', }, @@ -56,8 +56,8 @@ export const mockData: Array = [ domain_name: 'claap.com', name: 'Claap', created_at: '2023-04-26T10:09:25.656555+00:00', - address: null, - employees: 1, + address: '', + employees: '1', account_owner: null, __typename: 'companies', }, diff --git a/front/src/pages/companies/companies-table.tsx b/front/src/pages/companies/companies-table.tsx index d3331e5a1..95e00c157 100644 --- a/front/src/pages/companies/companies-table.tsx +++ b/front/src/pages/companies/companies-table.tsx @@ -82,7 +82,7 @@ export const availableFilters = [ value: mapToCompany(company), }), }, - selectedValueRender: (company) => company.name, + selectedValueRender: (company) => company.name || '', operands: [ { label: 'Equal', @@ -99,7 +99,7 @@ export const availableFilters = [ }), }, ], - } as FilterConfigType, + } satisfies FilterConfigType, { key: 'company_domain_name', label: 'Url', @@ -114,7 +114,7 @@ export const availableFilters = [ value: mapToCompany(company), }), }, - selectedValueRender: (company) => company.domainName, + selectedValueRender: (company) => company.domainName || '', operands: [ { label: 'Equal', @@ -131,7 +131,7 @@ export const availableFilters = [ }), }, ], - } as FilterConfigType, + } satisfies FilterConfigType, ]; const columnHelper = createColumnHelper(); @@ -253,6 +253,7 @@ export const useCompaniesColumns = () => { company.accountOwner.id = relation.id; } else { company.accountOwner = { + __typename: 'users', id: relation.id, email: relation.email, displayName: relation.displayName, diff --git a/front/src/pages/people/People.tsx b/front/src/pages/people/People.tsx index d01c1da6e..441de17de 100644 --- a/front/src/pages/people/People.tsx +++ b/front/src/pages/people/People.tsx @@ -19,10 +19,7 @@ import { } from '../../services/people'; import { useSearch } from '../../services/search/search'; import { People_Bool_Exp } from '../../generated/graphql'; -import { - FilterConfigType, - SelectedFilterType, -} from '../../components/table/table-header/interface'; +import { SelectedFilterType } from '../../components/table/table-header/interface'; import { reduceFiltersToWhere, reduceSortsToOrderBy, @@ -64,7 +61,8 @@ function People() { }, [loading, setInternalData, data]); const addEmptyRow = useCallback(async () => { - const newCompany: Person = { + const newPerson: Person = { + __typename: 'people', id: uuidv4(), firstname: '', lastname: '', @@ -75,13 +73,13 @@ function People() { creationDate: new Date(), city: '', }; - await insertPerson(newCompany); - setInternalData([newCompany, ...internalData]); + await insertPerson(newPerson); + setInternalData([newPerson, ...internalData]); refetch(); }, [internalData, setInternalData, refetch]); - const deleteRows = useCallback(() => { - deletePeople(selectedRowIds); + const deleteRows = useCallback(async () => { + await deletePeople(selectedRowIds); setInternalData([ ...internalData.filter((row) => !selectedRowIds.includes(row.id)), ]); @@ -109,7 +107,7 @@ function People() { viewName="All People" viewIcon={} availableSorts={availableSorts} - availableFilters={availableFilters as Array} + availableFilters={availableFilters} filterSearchResults={filterSearchResults} onSortsUpdate={updateSorts} onFiltersUpdate={updateFilters} diff --git a/front/src/pages/people/people-table.tsx b/front/src/pages/people/people-table.tsx index de7e1b774..4638dbff0 100644 --- a/front/src/pages/people/people-table.tsx +++ b/front/src/pages/people/people-table.tsx @@ -227,7 +227,7 @@ export const availableFilters = [ companyFilter, emailFilter, cityFilter, -]; +] satisfies FilterConfigType[]; const columnHelper = createColumnHelper(); diff --git a/front/src/services/search/__data__/mock-search-data.ts b/front/src/services/search/__data__/mock-search-data.ts new file mode 100644 index 000000000..383de323e --- /dev/null +++ b/front/src/services/search/__data__/mock-search-data.ts @@ -0,0 +1,36 @@ +export const mockCompanySearchData = { + data: { + searchResults: [ + { + id: 'fe256b39-3ec3-4fe3-8997-b76aa0bfa408', + name: 'Linkedin', + domain_name: 'linkedin-searched.com', + __typename: 'companies', + }, + { + id: '118995f3-5d81-46d6-bf83-f7fd33ea6102', + name: 'Facebook', + domain_name: 'facebook-searched.com', + __typename: 'companies', + }, + { + id: '04b2e9f5-0713-40a5-8216-82802401d33e', + name: 'Qonto', + domain_name: 'qonto-searched.com', + __typename: 'companies', + }, + { + id: '460b6fb1-ed89-413a-b31a-962986e67bb4', + name: 'Microsoft', + domain_name: 'microsoft-searched.com', + __typename: 'companies', + }, + { + id: '0d940997-c21e-4ec2-873b-de4264d89025', + name: 'Google', + domain_name: 'google-searched.com', + __typename: 'companies', + }, + ], + }, +};