@ -1,16 +1,18 @@
|
||||
import { FaRegBuilding, FaList } from 'react-icons/fa';
|
||||
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import {
|
||||
CompaniesSelectedSortType,
|
||||
defaultOrderBy,
|
||||
insertCompany,
|
||||
useCompaniesQuery,
|
||||
} from '../../services/companies';
|
||||
import Table from '../../components/table/Table';
|
||||
import { mapCompany } from '../../interfaces/company.interface';
|
||||
import { Company, mapCompany } from '../../interfaces/company.interface';
|
||||
import {
|
||||
companiesColumns,
|
||||
useCompaniesColumns,
|
||||
availableFilters,
|
||||
availableSorts,
|
||||
} from './companies-table';
|
||||
@ -33,6 +35,7 @@ const StyledCompaniesContainer = styled.div`
|
||||
function Companies() {
|
||||
const [orderBy, setOrderBy] = useState<Companies_Order_By[]>(defaultOrderBy);
|
||||
const [where, setWhere] = useState<Companies_Bool_Exp>({});
|
||||
const [internalData, setInternalData] = useState<Array<Company>>([]);
|
||||
|
||||
const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
|
||||
|
||||
@ -47,13 +50,43 @@ function Companies() {
|
||||
[],
|
||||
);
|
||||
|
||||
const { data } = useCompaniesQuery(orderBy, where);
|
||||
const { data, loading, refetch } = useCompaniesQuery(orderBy, where);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
if (data) {
|
||||
setInternalData(data.companies.map(mapCompany));
|
||||
}
|
||||
}
|
||||
}, [loading, setInternalData, data]);
|
||||
|
||||
const addEmptyRow = useCallback(() => {
|
||||
const newCompany: Company = {
|
||||
id: uuidv4(),
|
||||
name: '',
|
||||
domain_name: '',
|
||||
employees: 0,
|
||||
address: '',
|
||||
opportunities: [],
|
||||
creationDate: new Date(),
|
||||
accountOwner: null,
|
||||
};
|
||||
insertCompany(newCompany);
|
||||
setInternalData([newCompany, ...internalData]);
|
||||
refetch();
|
||||
}, [internalData, setInternalData, refetch]);
|
||||
|
||||
const companiesColumns = useCompaniesColumns();
|
||||
|
||||
return (
|
||||
<WithTopBarContainer title="Companies" icon={<FaRegBuilding />}>
|
||||
<WithTopBarContainer
|
||||
title="Companies"
|
||||
icon={<FaRegBuilding />}
|
||||
onAddButtonClick={addEmptyRow}
|
||||
>
|
||||
<StyledCompaniesContainer>
|
||||
<Table
|
||||
data={data ? data.companies.map(mapCompany) : []}
|
||||
data={internalData}
|
||||
columns={companiesColumns}
|
||||
viewName="All Companies"
|
||||
viewIcon={<FaList />}
|
||||
|
||||
@ -18,7 +18,7 @@ const mocks = [
|
||||
request: {
|
||||
query: GET_COMPANIES,
|
||||
variables: {
|
||||
orderBy: [{ name: 'asc' }],
|
||||
orderBy: [{ created_at: 'desc' }],
|
||||
where: {},
|
||||
},
|
||||
},
|
||||
|
||||
@ -115,3 +115,24 @@ it('Checks company address edit is updating data', async () => {
|
||||
expect(getByText('21 rue de clignancourt')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('Checks insert data is appending a new line', async () => {
|
||||
const { getByText, getByTestId, container } = render(<CompaniesDefault />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText('Airbnb')).toBeDefined();
|
||||
});
|
||||
const tableRows = container.querySelectorAll<HTMLElement>('table tbody tr');
|
||||
|
||||
expect(tableRows.length).toBe(6);
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(getByTestId('add-button'));
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
const tableRows = container.querySelectorAll<HTMLElement>('table tbody tr');
|
||||
|
||||
expect(tableRows.length).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
@ -38,6 +38,7 @@ import {
|
||||
import EditableDate from '../../components/table/editable-cell/EditableDate';
|
||||
import EditableRelation from '../../components/table/editable-cell/EditableRelation';
|
||||
import { GraphqlQueryUser, PartialUser } from '../../interfaces/user.interface';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const availableSorts = [
|
||||
{
|
||||
@ -136,139 +137,150 @@ export const availableFilters = [
|
||||
] satisfies Array<FilterType<Companies_Bool_Exp>>;
|
||||
|
||||
const columnHelper = createColumnHelper<Company>();
|
||||
export const companiesColumns = [
|
||||
columnHelper.accessor('id', {
|
||||
header: () => (
|
||||
<Checkbox id="company-select-all" name="company-select-all" />
|
||||
),
|
||||
cell: (props) => (
|
||||
<Checkbox
|
||||
id={`company-selected-${props.row.original.id}`}
|
||||
name={`company-selected-${props.row.original.id}`}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('name', {
|
||||
header: () => <ColumnHead viewName="Name" viewIcon={<FaRegBuilding />} />,
|
||||
cell: (props) => (
|
||||
<EditableChip
|
||||
value={props.row.original.name}
|
||||
placeholder="Name"
|
||||
picture={`https://www.google.com/s2/favicons?domain=${props.row.original.domain_name}&sz=256`}
|
||||
changeHandler={(value: string) => {
|
||||
const company = props.row.original;
|
||||
company.name = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
ChipComponent={CompanyChip}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('employees', {
|
||||
header: () => <ColumnHead viewName="Employees" viewIcon={<FaUsers />} />,
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.employees.toFixed(0)}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.employees = parseInt(value);
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('domain_name', {
|
||||
header: () => <ColumnHead viewName="URL" viewIcon={<FaLink />} />,
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.domain_name}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.domain_name = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('address', {
|
||||
header: () => <ColumnHead viewName="Address" viewIcon={<FaMapPin />} />,
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.address}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.address = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('creationDate', {
|
||||
header: () => <ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />,
|
||||
cell: (props) => (
|
||||
<EditableDate
|
||||
value={props.row.original.creationDate}
|
||||
changeHandler={(value: Date) => {
|
||||
const company = props.row.original;
|
||||
company.creationDate = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('accountOwner', {
|
||||
header: () => (
|
||||
<ColumnHead viewName="Account Owner" viewIcon={<FaRegUser />} />
|
||||
),
|
||||
cell: (props) => (
|
||||
<EditableRelation<PartialUser, PersonChipPropsType>
|
||||
relation={props.row.original.accountOwner}
|
||||
searchPlaceholder="Account Owner"
|
||||
ChipComponent={PersonChip}
|
||||
chipComponentPropsMapper={(
|
||||
accountOwner: PartialUser,
|
||||
): PersonChipPropsType => {
|
||||
return {
|
||||
name: accountOwner.displayName,
|
||||
};
|
||||
}}
|
||||
changeHandler={(relation: PartialUser) => {
|
||||
const company = props.row.original;
|
||||
if (company.accountOwner) {
|
||||
company.accountOwner.id = relation.id;
|
||||
} else {
|
||||
company.accountOwner = {
|
||||
id: relation.id,
|
||||
email: relation.email,
|
||||
displayName: relation.displayName,
|
||||
};
|
||||
}
|
||||
updateCompany(company);
|
||||
}}
|
||||
searchFilter={
|
||||
{
|
||||
key: 'account_owner_name',
|
||||
label: 'Account Owner',
|
||||
icon: <FaUser />,
|
||||
whereTemplate: () => {
|
||||
return {};
|
||||
},
|
||||
searchQuery: SEARCH_USER_QUERY,
|
||||
searchTemplate: (searchInput: string) => ({
|
||||
displayName: { _ilike: `%${searchInput}%` },
|
||||
}),
|
||||
searchResultMapper: (accountOwner: GraphqlQueryUser) => ({
|
||||
displayValue: accountOwner.displayName,
|
||||
value: {
|
||||
id: accountOwner.id,
|
||||
email: accountOwner.email,
|
||||
displayName: accountOwner.displayName,
|
||||
},
|
||||
}),
|
||||
operands: [],
|
||||
} satisfies FilterType<Users_Bool_Exp>
|
||||
}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
];
|
||||
|
||||
export const useCompaniesColumns = () => {
|
||||
return useMemo(() => {
|
||||
return [
|
||||
columnHelper.accessor('id', {
|
||||
header: () => (
|
||||
<Checkbox id="company-select-all" name="company-select-all" />
|
||||
),
|
||||
cell: (props) => (
|
||||
<Checkbox
|
||||
id={`company-selected-${props.row.original.id}`}
|
||||
name={`company-selected-${props.row.original.id}`}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('name', {
|
||||
header: () => (
|
||||
<ColumnHead viewName="Name" viewIcon={<FaRegBuilding />} />
|
||||
),
|
||||
cell: (props) => (
|
||||
<EditableChip
|
||||
value={props.row.original.name}
|
||||
placeholder="Name"
|
||||
picture={`https://www.google.com/s2/favicons?domain=${props.row.original.domain_name}&sz=256`}
|
||||
changeHandler={(value: string) => {
|
||||
const company = props.row.original;
|
||||
company.name = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
ChipComponent={CompanyChip}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('employees', {
|
||||
header: () => (
|
||||
<ColumnHead viewName="Employees" viewIcon={<FaUsers />} />
|
||||
),
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.employees.toFixed(0)}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.employees = parseInt(value);
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('domain_name', {
|
||||
header: () => <ColumnHead viewName="URL" viewIcon={<FaLink />} />,
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.domain_name}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.domain_name = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('address', {
|
||||
header: () => <ColumnHead viewName="Address" viewIcon={<FaMapPin />} />,
|
||||
cell: (props) => (
|
||||
<EditableText
|
||||
content={props.row.original.address}
|
||||
changeHandler={(value) => {
|
||||
const company = props.row.original;
|
||||
company.address = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('creationDate', {
|
||||
header: () => (
|
||||
<ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />
|
||||
),
|
||||
cell: (props) => (
|
||||
<EditableDate
|
||||
value={props.row.original.creationDate}
|
||||
changeHandler={(value: Date) => {
|
||||
const company = props.row.original;
|
||||
company.creationDate = value;
|
||||
updateCompany(company);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('accountOwner', {
|
||||
header: () => (
|
||||
<ColumnHead viewName="Account Owner" viewIcon={<FaRegUser />} />
|
||||
),
|
||||
cell: (props) => (
|
||||
<EditableRelation<PartialUser, PersonChipPropsType>
|
||||
relation={props.row.original.accountOwner}
|
||||
searchPlaceholder="Account Owner"
|
||||
ChipComponent={PersonChip}
|
||||
chipComponentPropsMapper={(
|
||||
accountOwner: PartialUser,
|
||||
): PersonChipPropsType => {
|
||||
return {
|
||||
name: accountOwner.displayName,
|
||||
};
|
||||
}}
|
||||
changeHandler={(relation: PartialUser) => {
|
||||
const company = props.row.original;
|
||||
if (company.accountOwner) {
|
||||
company.accountOwner.id = relation.id;
|
||||
} else {
|
||||
company.accountOwner = {
|
||||
id: relation.id,
|
||||
email: relation.email,
|
||||
displayName: relation.displayName,
|
||||
};
|
||||
}
|
||||
updateCompany(company);
|
||||
}}
|
||||
searchFilter={
|
||||
{
|
||||
key: 'account_owner_name',
|
||||
label: 'Account Owner',
|
||||
icon: <FaUser />,
|
||||
whereTemplate: () => {
|
||||
return {};
|
||||
},
|
||||
searchQuery: SEARCH_USER_QUERY,
|
||||
searchTemplate: (searchInput: string) => ({
|
||||
displayName: { _ilike: `%${searchInput}%` },
|
||||
}),
|
||||
searchResultMapper: (accountOwner: GraphqlQueryUser) => ({
|
||||
displayValue: accountOwner.displayName,
|
||||
value: {
|
||||
id: accountOwner.id,
|
||||
email: accountOwner.email,
|
||||
displayName: accountOwner.displayName,
|
||||
},
|
||||
}),
|
||||
operands: [],
|
||||
} satisfies FilterType<Users_Bool_Exp>
|
||||
}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
];
|
||||
}, []);
|
||||
};
|
||||
|
||||
@ -44,10 +44,18 @@ function People() {
|
||||
[],
|
||||
);
|
||||
|
||||
const addEmptyRow = useCallback(() => {
|
||||
console.log('add row');
|
||||
}, []);
|
||||
|
||||
const { data } = usePeopleQuery(orderBy, where);
|
||||
|
||||
return (
|
||||
<WithTopBarContainer title="People" icon={<FaRegUser />}>
|
||||
<WithTopBarContainer
|
||||
title="People"
|
||||
icon={<FaRegUser />}
|
||||
onAddButtonClick={addEmptyRow}
|
||||
>
|
||||
<StyledPeopleContainer>
|
||||
{
|
||||
<Table
|
||||
|
||||
Reference in New Issue
Block a user