diff --git a/front/src/__stories__/App.stories.tsx b/front/src/__stories__/App.stories.tsx
new file mode 100644
index 000000000..2c1964016
--- /dev/null
+++ b/front/src/__stories__/App.stories.tsx
@@ -0,0 +1,66 @@
+import { MockedProvider } from '@apollo/client/testing';
+import App from '../App';
+import { GET_CURRENT_USER } from '../services/users';
+import { MemoryRouter } from 'react-router-dom';
+import { GET_PEOPLE } from '../services/people';
+
+const component = {
+ title: 'App',
+ component: App,
+};
+
+localStorage.setItem('refreshToken', 'xxx-refresh');
+localStorage.setItem('accessToken', 'xxx-access');
+
+const mocks = [
+ {
+ request: {
+ query: GET_CURRENT_USER,
+ },
+ result: {
+ data: {
+ users: [
+ {
+ id: '16506ba8-196c-4c13-a4a7-a22cb5eccfa1',
+ email: 'charles@twenty.com',
+ displayName: 'Charles Bochet',
+ workspace_member: {
+ workspace: {
+ id: '7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
+ domain_name: 'twenty.com',
+ display_name: 'Twenty',
+ logo: 'data:image/png;base64,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',
+ __typename: 'workspaces',
+ },
+ __typename: 'workspace_members',
+ },
+ __typename: 'users',
+ },
+ ],
+ },
+ },
+ },
+ {
+ request: {
+ query: GET_PEOPLE,
+ variables: { orderBy: [{ created_at: 'desc' }], where: {} },
+ },
+ result: {
+ data: {
+ people: [],
+ },
+ },
+ },
+];
+
+export default component;
+
+export const RegularApp = () => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/front/src/__tests__/App.test.tsx b/front/src/__tests__/App.test.tsx
new file mode 100644
index 000000000..d88a1017c
--- /dev/null
+++ b/front/src/__tests__/App.test.tsx
@@ -0,0 +1,17 @@
+import { render, waitFor } from '@testing-library/react';
+import { RegularApp } from '../__stories__/App.stories';
+
+const assignMock = jest.fn();
+
+delete window.location;
+window.location = { assign: assignMock };
+
+it('Checks the App component renders', async () => {
+ const { getByText } = render();
+
+ expect(getByText('Companies')).toBeDefined();
+ expect(getByText('Opportunities')).toBeDefined();
+ await waitFor(() => {
+ expect(getByText('Twenty')).toBeDefined();
+ });
+});
diff --git a/front/src/components/chips/PipeChip.tsx b/front/src/components/chips/PipeChip.tsx
index 50c2fafed..758c363d6 100644
--- a/front/src/components/chips/PipeChip.tsx
+++ b/front/src/components/chips/PipeChip.tsx
@@ -1,9 +1,9 @@
import * as React from 'react';
import styled from '@emotion/styled';
+import { Opportunity } from '../../interfaces/company.interface';
type OwnProps = {
- name: string;
- picture?: string;
+ opportunity: Opportunity;
};
const StyledContainer = styled.span`
@@ -20,11 +20,11 @@ const StyledContainer = styled.span`
}
`;
-function PipeChip({ name, picture }: OwnProps) {
+function PipeChip({ opportunity }: OwnProps) {
return (
-
- {picture && {picture}}
- {name}
+
+ {opportunity.icon && {opportunity.icon}}
+ {opportunity.name}
);
}
diff --git a/front/src/components/table/Table.tsx b/front/src/components/table/Table.tsx
index 4fde47658..e2164b0fc 100644
--- a/front/src/components/table/Table.tsx
+++ b/front/src/components/table/Table.tsx
@@ -10,18 +10,30 @@ import TableHeader from './table-header/TableHeader';
import styled from '@emotion/styled';
import {
FilterType,
+ SelectedFilterType,
SelectedSortType,
SortType,
} from './table-header/interface';
-type OwnProps = {
+type OwnProps = {
data: Array;
columns: Array>;
viewName: string;
viewIcon?: React.ReactNode;
- onSortsUpdate?: (sorts: Array>) => void;
availableSorts?: Array>;
- availableFilters?: FilterType[];
+ availableFilters?: FilterType[];
+ filterSearchResults?: {
+ results: { displayValue: string; value: any }[];
+ loading: boolean;
+ };
+ onSortsUpdate?: (sorts: Array>) => void;
+ onFiltersUpdate?: (
+ sorts: Array>,
+ ) => void;
+ onFilterSearch?: (
+ filter: FilterType | null,
+ searchValue: string,
+ ) => void;
};
const StyledTable = styled.table`
@@ -75,15 +87,18 @@ const StyledTableScrollableContainer = styled.div`
flex: 1;
`;
-function Table({
+function Table({
data,
columns,
viewName,
viewIcon,
- onSortsUpdate,
availableSorts,
availableFilters,
-}: OwnProps) {
+ filterSearchResults,
+ onSortsUpdate,
+ onFiltersUpdate,
+ onFilterSearch,
+}: OwnProps) {
const table = useReactTable({
data,
columns,
@@ -95,9 +110,12 @@ function Table({
diff --git a/front/src/components/table/__stories__/EditableCell.stories.tsx b/front/src/components/table/__stories__/EditableCell.stories.tsx
index 9cd427caa..c9e51ca60 100644
--- a/front/src/components/table/__stories__/EditableCell.stories.tsx
+++ b/front/src/components/table/__stories__/EditableCell.stories.tsx
@@ -1,24 +1,31 @@
import EditableCell from '../EditableCell';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../layout/styles/themes';
+import { StoryFn } from '@storybook/react';
const component = {
title: 'EditableCell',
component: EditableCell,
};
-export default component;
-
type OwnProps = {
- changeHandler: () => void;
+ content: string;
+ changeHandler: (updated: string) => void;
};
-export const RegularEditableCell = ({ changeHandler }: OwnProps) => {
+export default component;
+
+const Template: StoryFn = (args: OwnProps) => {
return (
- ,
+
);
};
+
+export const EditableCellStory = Template.bind({});
+EditableCellStory.args = {
+ content: 'Test string',
+};
diff --git a/front/src/components/table/__tests__/EditableCell.test.tsx b/front/src/components/table/__tests__/EditableCell.test.tsx
index fa9d1c2f4..eb48568f1 100644
--- a/front/src/components/table/__tests__/EditableCell.test.tsx
+++ b/front/src/components/table/__tests__/EditableCell.test.tsx
@@ -1,10 +1,12 @@
import { fireEvent, render } from '@testing-library/react';
-import { RegularEditableCell } from '../__stories__/EditableCell.stories';
+import { EditableCellStory } from '../__stories__/EditableCell.stories';
it('Checks the EditableCell editing event bubbles up', async () => {
const func = jest.fn(() => null);
- const { getByTestId } = render();
+ const { getByTestId } = render(
+ ,
+ );
const parent = getByTestId('content-editable-parent');
const editableInput = parent.querySelector('input');
diff --git a/front/src/components/table/table-header/FilterDropdownButton.tsx b/front/src/components/table/table-header/FilterDropdownButton.tsx
index cb0b50b46..5fe6480a0 100644
--- a/front/src/components/table/table-header/FilterDropdownButton.tsx
+++ b/front/src/components/table/table-header/FilterDropdownButton.tsx
@@ -1,47 +1,40 @@
-import { useCallback, useState } from 'react';
+import { ChangeEvent, useCallback, useState } from 'react';
import DropdownButton from './DropdownButton';
-import { FilterType, SelectedFilterType } from './interface';
+import { FilterOperandType, FilterType, SelectedFilterType } from './interface';
-type OwnProps = {
- filters: SelectedFilterType[];
- setFilters: (sorts: SelectedFilterType[]) => void;
- availableFilters: FilterType[];
+type OwnProps = {
+ isFilterSelected: boolean;
+ availableFilters: FilterType[];
+ filterSearchResults?: {
+ results: { displayValue: string; value: any }[];
+ loading: boolean;
+ };
+ onFilterSelect: (filter: SelectedFilterType) => void;
+ onFilterSearch: (
+ filter: FilterType | null,
+ searchValue: string,
+ ) => void;
};
-type FilterOperandType = { label: string; id: string };
-
const filterOperands: FilterOperandType[] = [
- { label: 'Include', id: 'include' },
- { label: "Doesn't include", id: 'not-include' },
+ { label: 'Include', id: 'include', keyWord: 'ilike' },
+ { label: "Doesn't include", id: 'not-include', keyWord: 'not_ilike' },
];
-const someFieldRandomValue = [
- 'John Doe',
- 'Jane Doe',
- 'John Smith',
- 'Jane Smith',
- 'John Johnson',
- 'Jane Johnson',
- 'John Williams',
- 'Jane Williams',
- 'John Brown',
- 'Jane Brown',
- 'John Jones',
- 'Jane Jones',
-];
-
-export function FilterDropdownButton({
+export function FilterDropdownButton({
availableFilters,
- setFilters,
- filters,
-}: OwnProps) {
+ filterSearchResults,
+ onFilterSearch,
+ onFilterSelect,
+ isFilterSelected,
+}: OwnProps) {
const [isUnfolded, setIsUnfolded] = useState(false);
const [isOptionUnfolded, setIsOptionUnfolded] = useState(false);
- const [selectedFilter, setSelectedFilter] = useState(
- undefined,
- );
+ const [selectedFilter, setSelectedFilter] = useState<
+ FilterType | undefined
+ >(undefined);
const [selectedFilterOperand, setSelectedFilterOperand] =
useState(filterOperands[0]);
@@ -50,7 +43,8 @@ export function FilterDropdownButton({
setIsOptionUnfolded(false);
setSelectedFilter(undefined);
setSelectedFilterOperand(filterOperands[0]);
- }, []);
+ onFilterSearch(null, '');
+ }, [onFilterSearch]);
const renderSelectOptionItems = filterOperands.map((filterOperand, index) => (
));
+ const renderSearchResults = (
+ filterSearchResults: NonNullable<
+ OwnProps['filterSearchResults']
+ >,
+ selectedFilter: FilterType,
+ ) => {
+ if (filterSearchResults.loading) {
+ return 'LOADING';
+ }
+ return filterSearchResults.results.map((value, index) => (
+ {
+ onFilterSelect({
+ key: value.displayValue,
+ operand: selectedFilterOperand,
+ searchQuery: selectedFilter.searchQuery,
+ searchTemplate: selectedFilter.searchTemplate,
+ whereTemplate: selectedFilter.whereTemplate,
+ label: selectedFilter.label,
+ value: value.displayValue,
+ icon: selectedFilter.icon,
+ where: selectedFilter.whereTemplate(
+ selectedFilterOperand,
+ value.value,
+ ),
+ searchResultMapper: selectedFilter.searchResultMapper,
+ });
+ setIsUnfolded(false);
+ setSelectedFilter(undefined);
+ }}
+ >
+ {value.displayValue}
+
+ ));
+ };
+
const renderSelectFilterITems = availableFilters.map((filter, index) => (
{
setSelectedFilter(filter);
+ onFilterSearch(filter, '');
}}
>
{filter.icon}
@@ -76,46 +108,36 @@ export function FilterDropdownButton({
));
- function renderFilterDropdown(selectedFilter: FilterType) {
- return [
- setIsOptionUnfolded(true)}
- >
- {selectedFilterOperand.label}
-
-
- ,
-
-
- ,
- someFieldRandomValue.map((value, index) => (
- {
- setFilters([
- {
- id: value,
- operand: selectedFilterOperand,
- label: selectedFilter.label,
- value: value,
- icon: selectedFilter.icon,
- },
- ]);
- setIsUnfolded(false);
- setSelectedFilter(undefined);
- }}
+ function renderFilterDropdown(selectedFilter: FilterType) {
+ return (
+ <>
+ setIsOptionUnfolded(true)}
>
- {value}
-
- )),
- ];
+ {selectedFilterOperand.label}
+
+
+
+
+ ) =>
+ onFilterSearch(selectedFilter, event.target.value)
+ }
+ />
+
+ {filterSearchResults &&
+ renderSearchResults(filterSearchResults, selectedFilter)}
+ >
+ );
}
return (
0}
+ isActive={isFilterSelected}
isUnfolded={isUnfolded}
setIsUnfolded={setIsUnfolded}
resetState={resetState}
diff --git a/front/src/components/table/table-header/SortAndFilterBar.tsx b/front/src/components/table/table-header/SortAndFilterBar.tsx
index 5fd5ea34a..447c19b33 100644
--- a/front/src/components/table/table-header/SortAndFilterBar.tsx
+++ b/front/src/components/table/table-header/SortAndFilterBar.tsx
@@ -3,11 +3,13 @@ import SortOrFilterChip from './SortOrFilterChip';
import { FaArrowDown, FaArrowUp } from 'react-icons/fa';
import { SelectedFilterType, SelectedSortType } from './interface';
-type OwnProps = {
+type OwnProps = {
sorts: Array>;
onRemoveSort: (sortId: SelectedSortType['key']) => void;
- filters: Array;
- onRemoveFilter: (filterId: SelectedFilterType['id']) => void;
+ filters: Array>;
+ onRemoveFilter: (
+ filterId: SelectedFilterType['key'],
+ ) => void;
};
const StyledBar = styled.div`
@@ -39,12 +41,12 @@ const StyledCancelButton = styled.button`
}
`;
-function SortAndFilterBar({
+function SortAndFilterBar({
sorts,
onRemoveSort,
filters,
onRemoveFilter,
-}: OwnProps) {
+}: OwnProps) {
return (
{sorts.map((sort) => {
@@ -61,12 +63,12 @@ function SortAndFilterBar({
{filters.map((filter) => {
return (
onRemoveFilter(filter.id)}
+ onRemove={() => onRemoveFilter(filter.key)}
/>
);
})}
@@ -75,7 +77,7 @@ function SortAndFilterBar({
data-testid={'cancel-button'}
onClick={() => {
sorts.forEach((i) => onRemoveSort(i.key));
- filters.forEach((i) => onRemoveFilter(i.id));
+ filters.forEach((i) => onRemoveFilter(i.key));
}}
>
Cancel
diff --git a/front/src/components/table/table-header/SortDropdownButton.tsx b/front/src/components/table/table-header/SortDropdownButton.tsx
index 70a50a6f8..8e67cf9b0 100644
--- a/front/src/components/table/table-header/SortDropdownButton.tsx
+++ b/front/src/components/table/table-header/SortDropdownButton.tsx
@@ -3,17 +3,17 @@ import DropdownButton from './DropdownButton';
import { SelectedSortType, SortType } from './interface';
type OwnProps = {
- sorts: SelectedSortType[];
- setSorts: (sorts: SelectedSortType[]) => void;
+ isSortSelected: boolean;
+ onSortSelect: (sort: SelectedSortType) => void;
availableSorts: SortType[];
};
const options: Array['order']> = ['asc', 'desc'];
export function SortDropdownButton({
+ isSortSelected,
availableSorts,
- setSorts,
- sorts,
+ onSortSelect,
}: OwnProps) {
const [isUnfolded, setIsUnfolded] = useState(false);
@@ -24,10 +24,9 @@ export function SortDropdownButton({
const onSortItemSelect = useCallback(
(sort: SortType) => {
- const newSorts = [{ ...sort, order: selectedSortDirection }];
- setSorts(newSorts);
+ onSortSelect({ ...sort, order: selectedSortDirection });
},
- [setSorts, selectedSortDirection],
+ [onSortSelect, selectedSortDirection],
);
const resetState = useCallback(() => {
@@ -38,7 +37,7 @@ export function SortDropdownButton({
return (
0}
+ isActive={isSortSelected}
isUnfolded={isUnfolded}
setIsUnfolded={setIsUnfolded}
resetState={resetState}
diff --git a/front/src/components/table/table-header/TableHeader.tsx b/front/src/components/table/table-header/TableHeader.tsx
index d4e340b52..5181dfcf2 100644
--- a/front/src/components/table/table-header/TableHeader.tsx
+++ b/front/src/components/table/table-header/TableHeader.tsx
@@ -11,13 +11,23 @@ import { SortDropdownButton } from './SortDropdownButton';
import { FilterDropdownButton } from './FilterDropdownButton';
import SortAndFilterBar from './SortAndFilterBar';
-type OwnProps = {
+type OwnProps = {
viewName: string;
viewIcon?: ReactNode;
- onSortsUpdate?: (sorts: Array>) => void;
- onFiltersUpdate?: (sorts: Array) => void;
availableSorts?: Array>;
- availableFilters?: FilterType[];
+ availableFilters?: FilterType[];
+ filterSearchResults?: {
+ results: { displayValue: string; value: any }[];
+ loading: boolean;
+ };
+ onSortsUpdate?: (sorts: Array>) => void;
+ onFiltersUpdate?: (
+ sorts: Array>,
+ ) => void;
+ onFilterSearch?: (
+ filter: FilterType | null,
+ searchValue: string,
+ ) => void;
};
const StyledContainer = styled.div`
@@ -56,27 +66,32 @@ const StyledFilters = styled.div`
margin-right: ${(props) => props.theme.spacing(2)};
`;
-function TableHeader({
+function TableHeader({
viewName,
viewIcon,
- onSortsUpdate,
- onFiltersUpdate,
availableSorts,
availableFilters,
-}: OwnProps) {
+ filterSearchResults,
+ onSortsUpdate,
+ onFiltersUpdate,
+ onFilterSearch,
+}: OwnProps) {
const [sorts, innerSetSorts] = useState>>(
[],
);
+ const [filters, innerSetFilters] = useState<
+ Array>
+ >([]);
- const setSorts = useCallback(
- (sorts: SelectedSortType[]) => {
- innerSetSorts(sorts);
- onSortsUpdate && onSortsUpdate(sorts);
+ const sortSelect = useCallback(
+ (sort: SelectedSortType) => {
+ innerSetSorts([sort]);
+ onSortsUpdate && onSortsUpdate([sort]);
},
[onSortsUpdate],
);
- const onSortItemUnSelect = useCallback(
+ const sortUnselect = useCallback(
(sortId: string) => {
const newSorts = [] as SelectedSortType[];
innerSetSorts(newSorts);
@@ -85,25 +100,30 @@ function TableHeader({
[onSortsUpdate],
);
- const [filters, innerSetFilters] = useState>([]);
-
- const setFilters = useCallback(
- (filters: SelectedFilterType[]) => {
- innerSetFilters(filters);
- onFiltersUpdate && onFiltersUpdate(filters);
+ const filterSelect = useCallback(
+ (filter: SelectedFilterType) => {
+ innerSetFilters([filter]);
+ onFiltersUpdate && onFiltersUpdate([filter]);
},
[onFiltersUpdate],
);
- const onFilterItemUnSelect = useCallback(
- (filterId: SelectedFilterType['id']) => {
- const newFilters = [] as SelectedFilterType[];
+ const filterUnselect = useCallback(
+ (filterId: SelectedFilterType['key']) => {
+ const newFilters = [] as SelectedFilterType[];
innerSetFilters(newFilters);
onFiltersUpdate && onFiltersUpdate(newFilters);
},
[onFiltersUpdate],
);
+ const filterSearch = useCallback(
+ (filter: FilterType | null, searchValue: string) => {
+ onFilterSearch && onFilterSearch(filter, searchValue);
+ },
+ [onFilterSearch],
+ );
+
return (
@@ -113,14 +133,16 @@ function TableHeader({
0}
availableFilters={availableFilters || []}
+ filterSearchResults={filterSearchResults}
+ onFilterSelect={filterSelect}
+ onFilterSearch={filterSearch}
/>
-
+ isSortSelected={sorts.length > 0}
availableSorts={availableSorts || []}
+ onSortSelect={sortSelect}
/>
@@ -129,9 +151,9 @@ function TableHeader({
{sorts.length + filters.length > 0 && (
)}
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 f04c49204..b2a1cb026 100644
--- a/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx
+++ b/front/src/components/table/table-header/__stories__/FilterDropdownButton.stories.tsx
@@ -3,15 +3,15 @@ import { lightTheme } from '../../../../layout/styles/themes';
import { FilterDropdownButton } from '../FilterDropdownButton';
import styled from '@emotion/styled';
import { FilterType, SelectedFilterType } from '../interface';
-import {
- FaRegUser,
- FaRegBuilding,
- FaEnvelope,
- FaPhone,
- FaCalendar,
- FaMapPin,
-} from 'react-icons/fa';
import { useCallback, useState } from 'react';
+import { People_Bool_Exp } from '../../../../generated/graphql';
+import { FaUsers } from 'react-icons/fa';
+import {
+ SEARCH_PEOPLE_QUERY,
+ useSearch,
+} from '../../../../services/search/search';
+import { MockedProvider } from '@apollo/client/testing';
+import { defaultData } from '../../../../pages/people/default-data';
const component = {
title: 'FilterDropdownButton',
@@ -20,58 +20,129 @@ const component = {
export default component;
-type OwnProps = {
- setFilters: (filters: SelectedFilterType[]) => void;
+type OwnProps = {
+ setFilter: (filters: SelectedFilterType) => void;
};
+const mocks = [
+ {
+ request: {
+ query: SEARCH_PEOPLE_QUERY, // TODO this should not be called for empty filters
+ variables: {
+ where: undefined,
+ },
+ },
+ result: {
+ data: {
+ searchResults: defaultData,
+ },
+ },
+ },
+ {
+ request: {
+ query: SEARCH_PEOPLE_QUERY, // TODO this should not be called for empty filters
+ variables: {
+ where: {
+ _or: [
+ { firstname: { _ilike: '%%' } },
+ { lastname: { _ilike: '%%' } },
+ ],
+ },
+ },
+ },
+ result: {
+ data: {
+ searchResults: defaultData,
+ },
+ },
+ },
+ {
+ request: {
+ query: SEARCH_PEOPLE_QUERY, // TODO this should not be called for empty filters
+ variables: {
+ where: {
+ _or: [
+ { firstname: { _ilike: '%Jane%' } },
+ { lastname: { _ilike: '%Jane%' } },
+ ],
+ },
+ },
+ },
+ result: {
+ data: {
+ searchResults: [defaultData.find((p) => p.firstname === 'Jane')],
+ },
+ },
+ },
+];
+
const availableFilters = [
{
key: 'fullname',
label: 'People',
- icon: ,
+ icon: ,
+ searchQuery: SEARCH_PEOPLE_QUERY,
+ searchTemplate: (searchInput: string) => ({
+ _or: [
+ { firstname: { _ilike: `%${searchInput}%` } },
+ { lastname: { _ilike: `%${searchInput}%` } },
+ ],
+ }),
+ whereTemplate: () => ({
+ _or: [
+ { firstname: { _ilike: 'value' } },
+ { lastname: { _ilike: 'value' } },
+ ],
+ }),
+ searchResultMapper: (data) => ({
+ displayValue: data.firstname + ' ' + data.lastname,
+ value: data.firstname,
+ }),
},
- {
- key: 'company_name',
- label: 'Company',
- icon: ,
- },
- {
- key: 'email',
- label: 'Email',
- icon: ,
- },
- { key: 'phone', label: 'Phone', icon: },
- {
- key: 'created_at',
- label: 'Created at',
- icon: ,
- },
- { key: 'city', label: 'City', icon: },
-] satisfies FilterType[];
+] satisfies FilterType[];
const StyleDiv = styled.div`
height: 200px;
width: 200px;
`;
-export const RegularFilterDropdownButton = ({ setFilters }: OwnProps) => {
- const [filters, innerSetFilters] = useState([]);
+const InnerRegularFilterDropdownButton = ({
+ setFilter: setFilters,
+}: OwnProps) => {
+ const [, innerSetFilters] = useState>();
+ const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
+
const outerSetFilters = useCallback(
- (filters: SelectedFilterType[]) => {
- innerSetFilters(filters);
- setFilters(filters);
+ (filter: SelectedFilterType) => {
+ innerSetFilters(filter);
+ setFilters(filter);
},
[setFilters],
);
return (
-
-
-
-
-
+
+ {
+ setSearhInput(searchValue);
+ setFilterSearch(filter);
+ }}
+ />
+
+ );
+};
+
+export const RegularFilterDropdownButton = ({
+ setFilter: setFilters,
+}: OwnProps) => {
+ return (
+
+
+
+
+
);
};
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 694224e7c..df605d4b1 100644
--- a/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx
+++ b/front/src/components/table/table-header/__stories__/SortAndFilterBar.stories.tsx
@@ -1,6 +1,7 @@
import SortAndFilterBar from '../SortAndFilterBar';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
+import { GET_PEOPLE } from '../../../../services/people';
import { FaArrowDown } from 'react-icons/fa';
const component = {
@@ -37,10 +38,24 @@ export const RegularSortAndFilterBar = ({ removeFunction }: OwnProps) => {
filters={[
{
label: 'People',
- operand: { id: 'include', label: 'Include' },
- id: 'test_filter',
+ operand: { label: 'Include', id: 'include', keyWord: 'ilike' },
+ key: 'test_filter',
icon: ,
value: 'John Doe',
+ where: {
+ firstname: { _ilike: 'John Doe' },
+ },
+ searchQuery: GET_PEOPLE,
+ searchTemplate: () => ({
+ firstname: { _ilike: 'John Doe' },
+ }),
+ whereTemplate: () => {
+ return { firstname: { _ilike: 'John Doe' } };
+ },
+ searchResultMapper: (data) => ({
+ displayValue: 'John Doe',
+ value: data.firstname,
+ }),
},
]}
/>
diff --git a/front/src/components/table/table-header/__stories__/SortDropdownButton.stories.tsx b/front/src/components/table/table-header/__stories__/SortDropdownButton.stories.tsx
index 512d011a7..b7d9a0ced 100644
--- a/front/src/components/table/table-header/__stories__/SortDropdownButton.stories.tsx
+++ b/front/src/components/table/table-header/__stories__/SortDropdownButton.stories.tsx
@@ -1,4 +1,4 @@
-import { SelectedSortType, SortType } from '../interface';
+import { SortType } from '../interface';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import {
@@ -23,8 +23,6 @@ type OwnProps = {
setSorts: () => void;
};
-const sorts = [] satisfies SelectedSortType[];
-
const availableSorts = [
{
key: 'fullname',
@@ -60,9 +58,9 @@ export const RegularSortDropdownButton = ({ setSorts }: OwnProps) => {
diff --git a/front/src/components/table/table-header/__tests__/FilterDropdownButton.test.tsx b/front/src/components/table/table-header/__tests__/FilterDropdownButton.test.tsx
index 0e5e4aa9a..a4641cedb 100644
--- a/front/src/components/table/table-header/__tests__/FilterDropdownButton.test.tsx
+++ b/front/src/components/table/table-header/__tests__/FilterDropdownButton.test.tsx
@@ -1,44 +1,53 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import { RegularFilterDropdownButton } from '../__stories__/FilterDropdownButton.stories';
-import { FaEnvelope } from 'react-icons/fa';
+import { FaUsers } from 'react-icons/fa';
it('Checks the default top option is Include', async () => {
- const setSorts = jest.fn();
+ const setFilters = jest.fn();
const { getByText } = render(
- ,
+ ,
);
const sortDropdownButton = getByText('Filter');
fireEvent.click(sortDropdownButton);
- const sortByEmail = getByText('Email');
- fireEvent.click(sortByEmail);
+ const filterByPeople = getByText('People');
+ fireEvent.click(filterByPeople);
- const filterByJohn = getByText('John Doe');
+ await waitFor(() => {
+ const firstSearchResult = getByText('Alexandre Prot');
+ expect(firstSearchResult).toBeDefined();
+ });
+
+ const filterByJohn = getByText('Alexandre Prot');
fireEvent.click(filterByJohn);
- expect(setSorts).toHaveBeenCalledWith([
- {
- id: 'John Doe',
- value: 'John Doe',
- label: 'Email',
- operand: { id: 'include', label: 'Include' },
- icon: ,
- },
- ]);
+ expect(setFilters).toHaveBeenCalledWith(
+ expect.objectContaining({
+ key: 'Alexandre Prot',
+ value: 'Alexandre Prot',
+ label: 'People',
+ operand: {
+ id: 'include',
+ keyWord: 'ilike',
+ label: 'Include',
+ },
+ icon: ,
+ }),
+ );
});
it('Checks the selection of top option for Doesnot include', async () => {
- const setSorts = jest.fn();
+ const setFilters = jest.fn();
const { getByText } = render(
- ,
+ ,
);
const sortDropdownButton = getByText('Filter');
fireEvent.click(sortDropdownButton);
- const sortByEmail = getByText('Email');
- fireEvent.click(sortByEmail);
+ const filterByPeople = getByText('People');
+ fireEvent.click(filterByPeople);
const openOperandOptions = getByText('Include');
fireEvent.click(openOperandOptions);
@@ -46,19 +55,80 @@ it('Checks the selection of top option for Doesnot include', async () => {
const selectOperand = getByText("Doesn't include");
fireEvent.click(selectOperand);
- const filterByJohn = getByText('John Doe');
+ await waitFor(() => {
+ const firstSearchResult = getByText('Alexandre Prot');
+ expect(firstSearchResult).toBeDefined();
+ });
+
+ const filterByJohn = getByText('Alexandre Prot');
fireEvent.click(filterByJohn);
- expect(setSorts).toHaveBeenCalledWith([
- {
- id: 'John Doe',
- value: 'John Doe',
- label: 'Email',
- operand: { id: 'not-include', label: "Doesn't include" },
- icon: ,
- },
- ]);
-
+ expect(setFilters).toHaveBeenCalledWith(
+ expect.objectContaining({
+ key: 'Alexandre Prot',
+ value: 'Alexandre Prot',
+ label: 'People',
+ operand: {
+ id: 'not-include',
+ keyWord: 'not_ilike',
+ label: "Doesn't include",
+ },
+ icon: ,
+ }),
+ );
+ const blueSortDropdownButton = getByText('Filter');
+ await waitFor(() => {
+ expect(blueSortDropdownButton).toHaveAttribute('aria-selected', 'true');
+ });
+});
+
+it('Calls the filters when typing a new name', async () => {
+ const setFilters = jest.fn();
+ const { getByText, getByPlaceholderText, queryByText } = render(
+ ,
+ );
+
+ const sortDropdownButton = getByText('Filter');
+ fireEvent.click(sortDropdownButton);
+
+ const filterByPeople = getByText('People');
+ fireEvent.click(filterByPeople);
+
+ const filterSearch = getByPlaceholderText('People');
+ fireEvent.click(filterSearch);
+
+ fireEvent.change(filterSearch, { target: { value: 'Jane' } });
+
+ await waitFor(() => {
+ const loadingDiv = getByText('LOADING');
+ expect(loadingDiv).toBeDefined();
+ });
+
+ await waitFor(() => {
+ const firstSearchResult = getByText('Jane Doe');
+ expect(firstSearchResult).toBeDefined();
+
+ const alexandreSearchResult = queryByText('Alexandre Prot');
+ expect(alexandreSearchResult).not.toBeInTheDocument();
+ });
+
+ const filterByJane = getByText('Jane Doe');
+
+ fireEvent.click(filterByJane);
+
+ expect(setFilters).toHaveBeenCalledWith(
+ expect.objectContaining({
+ key: 'Jane Doe',
+ value: 'Jane Doe',
+ label: 'People',
+ operand: {
+ id: 'include',
+ keyWord: 'ilike',
+ label: 'Include',
+ },
+ icon: ,
+ }),
+ );
const blueSortDropdownButton = getByText('Filter');
await waitFor(() => {
expect(blueSortDropdownButton).toHaveAttribute('aria-selected', 'true');
diff --git a/front/src/components/table/table-header/__tests__/SortDropdownButton.test.tsx b/front/src/components/table/table-header/__tests__/SortDropdownButton.test.tsx
index 86719a153..6633660b6 100644
--- a/front/src/components/table/table-header/__tests__/SortDropdownButton.test.tsx
+++ b/front/src/components/table/table-header/__tests__/SortDropdownButton.test.tsx
@@ -14,14 +14,12 @@ it('Checks the default top option is Ascending', async () => {
const sortByEmail = getByText('Email');
fireEvent.click(sortByEmail);
- expect(setSorts).toHaveBeenCalledWith([
- {
- label: 'Email',
- key: 'email',
- icon: ,
- order: 'asc',
- },
- ]);
+ expect(setSorts).toHaveBeenCalledWith({
+ label: 'Email',
+ key: 'email',
+ icon: ,
+ order: 'asc',
+ });
});
it('Checks the selection of Descending', async () => {
@@ -42,12 +40,10 @@ it('Checks the selection of Descending', async () => {
const sortByEmail = getByText('Email');
fireEvent.click(sortByEmail);
- expect(setSorts).toHaveBeenCalledWith([
- {
- label: 'Email',
- key: 'email',
- icon: ,
- order: 'desc',
- },
- ]);
+ expect(setSorts).toHaveBeenCalledWith({
+ label: 'Email',
+ key: 'email',
+ icon: ,
+ order: 'desc',
+ });
});
diff --git a/front/src/components/table/table-header/interface.ts b/front/src/components/table/table-header/interface.ts
index 485e79606..b274843f1 100644
--- a/front/src/components/table/table-header/interface.ts
+++ b/front/src/components/table/table-header/interface.ts
@@ -1,4 +1,10 @@
+import { DocumentNode } from 'graphql';
import { ReactNode } from 'react';
+import {
+ Companies_Bool_Exp,
+ People_Bool_Exp,
+ Users_Bool_Exp,
+} from '../../../generated/graphql';
export type SortType = {
label: string;
@@ -6,20 +12,30 @@ export type SortType = {
icon?: ReactNode;
};
-export type FilterType = {
- label: string;
- key: FilterKey;
- icon: ReactNode;
-};
-
-export type SelectedFilterType = {
- id: string;
- label: string;
- value: string;
- operand: { id: string; label: string };
- icon: ReactNode;
-};
-
export type SelectedSortType = SortType & {
order: 'asc' | 'desc';
};
+
+export type FilterType> = {
+ label: string;
+ key: string;
+ icon: ReactNode;
+ whereTemplate: (operand: FilterOperandType, value: T) => WhereTemplate;
+ searchQuery: DocumentNode;
+ searchTemplate: (
+ searchInput: string,
+ ) => People_Bool_Exp | Companies_Bool_Exp | Users_Bool_Exp;
+ searchResultMapper: (data: any) => { displayValue: string; value: T };
+};
+
+export type FilterOperandType = {
+ label: string;
+ id: string;
+ keyWord: 'ilike' | 'not_ilike';
+};
+
+export type SelectedFilterType = FilterType & {
+ value: string;
+ operand: FilterOperandType;
+ where: WhereTemplate;
+};
diff --git a/front/src/interfaces/company.interface.test.ts b/front/src/interfaces/company.interface.test.ts
index 489589eb0..23d7c0c64 100644
--- a/front/src/interfaces/company.interface.test.ts
+++ b/front/src/interfaces/company.interface.test.ts
@@ -13,6 +13,7 @@ describe('mapCompany', () => {
id: '7af20dea-0412-4c4c-8b13-d6f0e6e09e87',
email: 'john@example.com',
displayName: 'John Doe',
+ __typename: 'User',
},
employees: 10,
address: '1 Infinite Loop, 95014 Cupertino, California, USA',
diff --git a/front/src/interfaces/company.interface.ts b/front/src/interfaces/company.interface.ts
index c68545105..2952448eb 100644
--- a/front/src/interfaces/company.interface.ts
+++ b/front/src/interfaces/company.interface.ts
@@ -1,6 +1,7 @@
-import { User } from './user.interface';
+import { GraphqlQueryUser, User } from './user.interface';
export interface Opportunity {
+ id: string;
name: string;
icon: string;
}
@@ -16,17 +17,11 @@ export interface Company {
creationDate: Date;
}
-export type GraphqlQueryAccountOwner = {
- id: string;
- email: string;
- displayName: string;
-};
-
export type GraphqlQueryCompany = {
id: string;
name: string;
domain_name: string;
- account_owner?: GraphqlQueryAccountOwner;
+ account_owner?: GraphqlQueryUser;
employees: number;
address: string;
created_at: string;
@@ -54,7 +49,7 @@ export const mapCompany = (company: GraphqlQueryCompany): Company => ({
}
: undefined,
creationDate: new Date(company.created_at),
- opportunities: [{ name: 'Sales Pipeline', icon: '' }],
+ opportunities: [],
});
export const mapGqlCompany = (company: Company): GraphqlMutationCompany => ({
diff --git a/front/src/interfaces/user.interface.test.ts b/front/src/interfaces/user.interface.test.ts
new file mode 100644
index 000000000..fa7c2cd03
--- /dev/null
+++ b/front/src/interfaces/user.interface.test.ts
@@ -0,0 +1,36 @@
+import { mapUser } from './user.interface';
+
+describe('mapUser', () => {
+ it('should map person', () => {
+ const graphQLUser = {
+ id: '16506ba8-196c-4c13-a4a7-a22cb5eccfa1',
+ email: 'charles@twenty.com',
+ displayName: 'Charles Bochet',
+ workspace_member: {
+ workspace: {
+ id: '7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
+ domain_name: 'twenty.com',
+ display_name: 'Twenty',
+ logo: 'data:image/png;base64,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',
+ __typename: 'workspaces',
+ },
+ __typename: 'workspace_members',
+ },
+ __typename: 'users',
+ };
+ const user = mapUser(graphQLUser);
+ expect(user).toStrictEqual({
+ id: graphQLUser.id,
+ email: graphQLUser.email,
+ displayName: graphQLUser.displayName,
+ workspace_member: {
+ workspace: {
+ id: graphQLUser?.workspace_member?.workspace.id,
+ displayName: graphQLUser?.workspace_member?.workspace.display_name,
+ domainName: graphQLUser?.workspace_member?.workspace.domain_name,
+ logo: graphQLUser?.workspace_member?.workspace.logo,
+ },
+ },
+ });
+ });
+});
diff --git a/front/src/interfaces/user.interface.ts b/front/src/interfaces/user.interface.ts
index 715c9c62d..e64498cca 100644
--- a/front/src/interfaces/user.interface.ts
+++ b/front/src/interfaces/user.interface.ts
@@ -1,15 +1,39 @@
-import { GraphqlQueryAccountOwner } from './company.interface';
-import { Workspace } from './workspace.interface';
+import {
+ GraphqlQueryWorkspaceMember,
+ WorkspaceMember,
+} from './workspace.interface';
+
+export type GraphqlQueryUser = {
+ id: string;
+ email: string;
+ displayName: string;
+ workspace_member?: GraphqlQueryWorkspaceMember;
+ __typename: string;
+};
export interface User {
id: string;
email: string;
displayName: string;
- workspace_member?: {
- workspace: Workspace;
- };
+ workspace_member?: WorkspaceMember;
}
-export const mapUser = (user: GraphqlQueryAccountOwner): User => ({
- ...user,
-});
+export const mapUser = (user: GraphqlQueryUser): User => {
+ const mappedUser = {
+ id: user.id,
+ email: user.email,
+ displayName: user.displayName,
+ } as User;
+ if (user.workspace_member) {
+ mappedUser['workspace_member'] = {
+ workspace: {
+ id: user.workspace_member.workspace.id,
+ displayName: user.workspace_member.workspace.display_name,
+ domainName: user.workspace_member.workspace.domain_name,
+ logo: user.workspace_member.workspace.logo,
+ },
+ };
+ }
+
+ return mappedUser;
+};
diff --git a/front/src/interfaces/workspace.interface.ts b/front/src/interfaces/workspace.interface.ts
index 437c396c2..32f9fc041 100644
--- a/front/src/interfaces/workspace.interface.ts
+++ b/front/src/interfaces/workspace.interface.ts
@@ -1,5 +1,22 @@
export interface Workspace {
id: string;
- display_name: string;
+ domainName: string;
+ displayName: string;
logo: string;
}
+
+export interface WorkspaceMember {
+ workspace: Workspace;
+}
+
+export type GraphqlQueryWorkspace = {
+ id: string;
+ display_name: string;
+ domain_name: string;
+ logo: string;
+ __typename: string;
+};
+export type GraphqlQueryWorkspaceMember = {
+ workspace: GraphqlQueryWorkspace;
+ __typename: string;
+};
diff --git a/front/src/layout/navbar/WorkspaceContainer.tsx b/front/src/layout/navbar/WorkspaceContainer.tsx
index 30936d9b4..9b7f870b3 100644
--- a/front/src/layout/navbar/WorkspaceContainer.tsx
+++ b/front/src/layout/navbar/WorkspaceContainer.tsx
@@ -43,7 +43,7 @@ function WorkspaceContainer({ workspace }: OwnProps) {
return (
- {workspace?.display_name}
+ {workspace?.displayName}
);
}
diff --git a/front/src/layout/navbar/__stories__/Navbar.stories.tsx b/front/src/layout/navbar/__stories__/Navbar.stories.tsx
index c44af3cb3..305a04ca7 100644
--- a/front/src/layout/navbar/__stories__/Navbar.stories.tsx
+++ b/front/src/layout/navbar/__stories__/Navbar.stories.tsx
@@ -23,7 +23,8 @@ export const NavbarOnCompanies = () => {
workspace_member: {
workspace: {
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
- display_name: 'Claap',
+ displayName: 'Claap',
+ domainName: 'claap.com',
logo: 'data:image/png;base64,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',
},
},
diff --git a/front/src/pages/companies/__stories__/mock-data.ts b/front/src/pages/companies/__stories__/mock-data.ts
index a0aa9a36b..9ada5e568 100644
--- a/front/src/pages/companies/__stories__/mock-data.ts
+++ b/front/src/pages/companies/__stories__/mock-data.ts
@@ -9,6 +9,7 @@ export const defaultData: Array = [
id: '91510aa5-ede6-451f-8029-a7fa69e4bad6',
email: 'john@example.com',
displayName: 'John Doe',
+ __typename: 'User',
},
employees: 10,
address: '1 Infinity Loop, 95014 Cupertino, California',
diff --git a/front/src/pages/companies/companies-table.tsx b/front/src/pages/companies/companies-table.tsx
index 0650ef111..c5d2d4181 100644
--- a/front/src/pages/companies/companies-table.tsx
+++ b/front/src/pages/companies/companies-table.tsx
@@ -96,7 +96,7 @@ export const companiesColumns = [
cell: (props) => (
{props.row.original.opportunities.map((opportunity) => (
-
+
))}
),
diff --git a/front/src/pages/people/People.tsx b/front/src/pages/people/People.tsx
index 1e55b5015..190b06f84 100644
--- a/front/src/pages/people/People.tsx
+++ b/front/src/pages/people/People.tsx
@@ -12,9 +12,13 @@ import { useCallback, useState } from 'react';
import {
PeopleSelectedSortType,
defaultOrderBy,
+ reduceFiltersToWhere,
reduceSortsToOrderBy,
usePeopleQuery,
} from '../../services/people';
+import { useSearch } from '../../services/search/search';
+import { People_Bool_Exp } from '../../generated/graphql';
+import { SelectedFilterType } from '../../components/table/table-header/interface';
const StyledPeopleContainer = styled.div`
display: flex;
@@ -23,15 +27,22 @@ const StyledPeopleContainer = styled.div`
`;
function People() {
- const [, setSorts] = useState([] as Array);
const [orderBy, setOrderBy] = useState(defaultOrderBy);
+ const [where, setWhere] = useState({});
+ const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
const updateSorts = useCallback((sorts: Array) => {
- setSorts(sorts);
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
}, []);
- const { data } = usePeopleQuery(orderBy);
+ const updateFilters = useCallback(
+ (filters: Array>) => {
+ setWhere(reduceFiltersToWhere(filters));
+ },
+ [],
+ );
+
+ const { data } = usePeopleQuery(orderBy, where);
return (
}>
@@ -42,9 +53,15 @@ function People() {
columns={peopleColumns}
viewName="All People"
viewIcon={}
- onSortsUpdate={updateSorts}
availableSorts={availableSorts}
availableFilters={availableFilters}
+ filterSearchResults={filterSearchResults}
+ onSortsUpdate={updateSorts}
+ onFiltersUpdate={updateFilters}
+ onFilterSearch={(filter, searchValue) => {
+ setSearhInput(searchValue);
+ setFilterSearch(filter);
+ }}
/>
}
diff --git a/front/src/pages/people/__stories__/People.stories.tsx b/front/src/pages/people/__stories__/People.stories.tsx
index 9f9cf8a35..f33525e3c 100644
--- a/front/src/pages/people/__stories__/People.stories.tsx
+++ b/front/src/pages/people/__stories__/People.stories.tsx
@@ -5,6 +5,7 @@ import { lightTheme } from '../../../layout/styles/themes';
import { MockedProvider } from '@apollo/client/testing';
import { defaultData } from '../default-data';
import { GET_PEOPLE } from '../../../services/people';
+import { SEARCH_PEOPLE_QUERY } from '../../../services/search/search';
const component = {
title: 'People',
@@ -19,6 +20,7 @@ const mocks = [
query: GET_PEOPLE,
variables: {
orderBy: [{ created_at: 'desc' }],
+ where: {},
},
},
result: {
@@ -27,6 +29,19 @@ const mocks = [
},
},
},
+ {
+ request: {
+ query: SEARCH_PEOPLE_QUERY, // TODO this should not be called for empty filters
+ variables: {
+ where: undefined,
+ },
+ },
+ result: {
+ data: {
+ people: [],
+ },
+ },
+ },
];
export const PeopleDefault = () => (
diff --git a/front/src/pages/people/default-data.ts b/front/src/pages/people/default-data.ts
index f0e608ce7..de446cae6 100644
--- a/front/src/pages/people/default-data.ts
+++ b/front/src/pages/people/default-data.ts
@@ -21,9 +21,9 @@ export const defaultData: Array = [
{
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d',
__typename: 'Person',
- firstname: 'Alexandre',
- lastname: 'Prot',
- email: 'alexandre@qonto.com',
+ firstname: 'John',
+ lastname: 'Doe',
+ email: 'john@linkedin.com',
company: {
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e',
name: 'LinkedIn',
@@ -38,9 +38,9 @@ export const defaultData: Array = [
{
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6f',
__typename: 'Person',
- firstname: 'Alexandre',
- lastname: 'Prot',
- email: 'alexandre@qonto.com',
+ firstname: 'Jane',
+ lastname: 'Doe',
+ email: 'jane@sequoiacap.com',
company: {
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g',
name: 'Sequoia',
@@ -56,9 +56,9 @@ export const defaultData: Array = [
{
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6h',
__typename: 'Person',
- firstname: 'Alexandre',
- lastname: 'Prot',
- email: 'alexandre@qonto.com',
+ firstname: 'Janice',
+ lastname: 'Dane',
+ email: 'janice@facebook.com',
company: {
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i',
name: 'Facebook',
diff --git a/front/src/pages/people/people-table.tsx b/front/src/pages/people/people-table.tsx
index 727e8bc57..767e0c8f1 100644
--- a/front/src/pages/people/people-table.tsx
+++ b/front/src/pages/people/people-table.tsx
@@ -6,6 +6,8 @@ import {
FaMapPin,
FaPhone,
FaStream,
+ FaUser,
+ FaBuilding,
} from 'react-icons/fa';
import { createColumnHelper } from '@tanstack/react-table';
import ClickableCell from '../../components/table/ClickableCell';
@@ -15,7 +17,7 @@ import Checkbox from '../../components/form/Checkbox';
import HorizontalyAlignedContainer from '../../layout/containers/HorizontalyAlignedContainer';
import CompanyChip from '../../components/chips/CompanyChip';
import PersonChip from '../../components/chips/PersonChip';
-import { Person } from '../../interfaces/person.interface';
+import { GraphqlQueryPerson, Person } from '../../interfaces/person.interface';
import PipeChip from '../../components/chips/PipeChip';
import EditableCell from '../../components/table/EditableCell';
import { OrderByFields, updatePerson } from '../../services/people';
@@ -23,6 +25,12 @@ import {
FilterType,
SortType,
} from '../../components/table/table-header/interface';
+import { People_Bool_Exp } from '../../generated/graphql';
+import {
+ SEARCH_COMPANY_QUERY,
+ SEARCH_PEOPLE_QUERY,
+} from '../../services/search/search';
+import { GraphqlQueryCompany } from '../../interfaces/company.interface';
export const availableSorts = [
{
@@ -53,26 +61,74 @@ export const availableFilters = [
{
key: 'fullname',
label: 'People',
- icon: ,
+ icon: ,
+ whereTemplate: (_operand, { firstname, lastname }) => ({
+ _and: [
+ { firstname: { _ilike: `${firstname}` } },
+ { lastname: { _ilike: `${lastname}` } },
+ ],
+ }),
+ searchQuery: SEARCH_PEOPLE_QUERY,
+ searchTemplate: (searchInput: string) => ({
+ _or: [
+ { firstname: { _ilike: `%${searchInput}%` } },
+ { lastname: { _ilike: `%${searchInput}%` } },
+ ],
+ }),
+ searchResultMapper: (person: GraphqlQueryPerson) => ({
+ displayValue: `${person.firstname} ${person.lastname}`,
+ value: { firstname: person.firstname, lastname: person.lastname },
+ }),
},
{
key: 'company_name',
label: 'Company',
- icon: ,
+ icon: ,
+ whereTemplate: (_operand, { companyName }) => ({
+ company: { name: { _ilike: `%${companyName}%` } },
+ }),
+ searchQuery: SEARCH_COMPANY_QUERY,
+ searchTemplate: (searchInput: string) => ({
+ name: { _ilike: `%${searchInput}%` },
+ }),
+ searchResultMapper: (company: GraphqlQueryCompany) => ({
+ displayValue: company.name,
+ value: { companyName: company.name },
+ }),
},
- {
- key: 'email',
- label: 'Email',
- icon: ,
- },
- { key: 'phone', label: 'Phone', icon: },
- {
- key: 'created_at',
- label: 'Created at',
- icon: ,
- },
- { key: 'city', label: 'City', icon: },
-] satisfies FilterType[];
+ // {
+ // key: 'email',
+ // label: 'Email',
+ // icon: faEnvelope,
+ // whereTemplate: () => ({ email: { _ilike: '%value%' } }),
+ // searchQuery: GET_PEOPLE,
+ // searchTemplate: { email: { _ilike: '%value%' } },
+ // },
+ // {
+ // key: 'phone',
+ // label: 'Phone',
+ // icon: faPhone,
+ // whereTemplate: () => ({ phone: { _ilike: '%value%' } }),
+ // searchQuery: GET_PEOPLE,
+ // searchTemplate: { phone: { _ilike: '%value%' } },
+ // },
+ // {
+ // key: 'created_at',
+ // label: 'Created at',
+ // icon: faCalendar,
+ // whereTemplate: () => ({ created_at: { _eq: '%value%' } }),
+ // searchQuery: GET_PEOPLE,
+ // searchTemplate: { created_at: { _eq: '%value%' } },
+ // },
+ // {
+ // key: 'city',
+ // label: 'City',
+ // icon: faMapPin,
+ // whereTemplate: () => ({ city: { _ilike: '%value%' } }),
+ // searchQuery: GET_PEOPLE,
+ // searchTemplate: { city: { _ilike: '%value%' } },
+ // },
+] satisfies FilterType[];
const columnHelper = createColumnHelper();
export const peopleColumns = [
@@ -151,10 +207,7 @@ export const peopleColumns = [
header: () => } />,
cell: (props) => (
-
+
),
}),
diff --git a/front/src/services/people/select.ts b/front/src/services/people/select.ts
index 06866ce08..728f84651 100644
--- a/front/src/services/people/select.ts
+++ b/front/src/services/people/select.ts
@@ -1,7 +1,14 @@
import { QueryResult, gql, useQuery } from '@apollo/client';
import { GraphqlQueryPerson } from '../../interfaces/person.interface';
-import { Order_By, People_Order_By } from '../../generated/graphql';
-import { SelectedSortType } from '../../components/table/table-header/interface';
+import {
+ Order_By,
+ People_Bool_Exp,
+ People_Order_By,
+} from '../../generated/graphql';
+import {
+ SelectedFilterType,
+ SelectedSortType,
+} from '../../components/table/table-header/interface';
export type OrderByFields = keyof People_Order_By | 'fullname' | 'company_name';
@@ -11,6 +18,16 @@ const mapOrder = (order: 'asc' | 'desc'): Order_By => {
return order === 'asc' ? Order_By.Asc : Order_By.Desc;
};
+export const reduceFiltersToWhere = (
+ filters: Array>,
+): T => {
+ const where = filters.reduce((acc, filter) => {
+ const { where } = filter;
+ return { ...acc, ...where };
+ }, {} as T);
+ return where;
+};
+
export const reduceSortsToOrderBy = (
sorts: Array,
): People_Order_By[] => {
@@ -31,8 +48,12 @@ export const reduceSortsToOrderBy = (
};
export const GET_PEOPLE = gql`
- query GetPeople($orderBy: [people_order_by!]) {
- people(order_by: $orderBy) {
+ query GetPeople(
+ $orderBy: [people_order_by!]
+ $where: people_bool_exp
+ $limit: Int
+ ) {
+ people(order_by: $orderBy, where: $where, limit: $limit) {
id
phone
email
@@ -51,9 +72,10 @@ export const GET_PEOPLE = gql`
export function usePeopleQuery(
orderBy: People_Order_By[],
+ where: People_Bool_Exp,
): QueryResult<{ people: GraphqlQueryPerson[] }> {
return useQuery<{ people: GraphqlQueryPerson[] }>(GET_PEOPLE, {
- variables: { orderBy },
+ variables: { orderBy, where },
});
}
diff --git a/front/src/services/search/search.ts b/front/src/services/search/search.ts
new file mode 100644
index 000000000..9353efbb9
--- /dev/null
+++ b/front/src/services/search/search.ts
@@ -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 = (
+ func: (...args: FuncArgs) => void,
+ delay: number,
+) => {
+ let timeoutId: ReturnType;
+ return (...args: FuncArgs) => {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(() => {
+ func(...args);
+ }, delay);
+ };
+};
+
+export const useSearch = (): [
+ { results: { displayValue: string; value: any }[]; loading: boolean },
+ React.Dispatch>,
+ React.Dispatch | null>>,
+] => {
+ const [filter, setFilter] = useState | null>(
+ null,
+ );
+ const [searchInput, setSearchInput] = useState('');
+
+ 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];
+};
diff --git a/front/src/services/users/__tests_/index.test.ts b/front/src/services/users/__tests_/index.test.ts
deleted file mode 100644
index 8e29157a8..000000000
--- a/front/src/services/users/__tests_/index.test.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-describe('Get Current user', () => {
- it('should return a parsed user if api returns it', () => {
- // TBD
- });
-
- it('should not return a user if api does not return it', () => {
- // TBD
- });
-});
-
-export {};
diff --git a/front/src/services/users/index.tsx b/front/src/services/users/index.tsx
index 2d2afb4c1..744b202ec 100644
--- a/front/src/services/users/index.tsx
+++ b/front/src/services/users/index.tsx
@@ -1,5 +1,5 @@
import { QueryResult, gql, useQuery } from '@apollo/client';
-import { GraphqlQueryAccountOwner } from '../../interfaces/company.interface';
+import { GraphqlQueryUser } from '../../interfaces/user.interface';
export const GET_CURRENT_USER = gql`
query GetCurrentUser {
@@ -20,7 +20,7 @@ export const GET_CURRENT_USER = gql`
`;
export function useGetCurrentUserQuery(): QueryResult<{
- users: GraphqlQueryAccountOwner[];
+ users: GraphqlQueryUser[];
}> {
- return useQuery<{ users: GraphqlQueryAccountOwner[] }>(GET_CURRENT_USER);
+ return useQuery<{ users: GraphqlQueryUser[] }>(GET_CURRENT_USER);
}