Removing Prisma and Grapql-nestjs-prisma resolvers (#2574)

* Some cleaning

* Fix seeds

* Fix all sign in, sign up flow and apiKey optimistic rendering

* Fix
This commit is contained in:
Charles Bochet
2023-11-19 18:25:47 +01:00
committed by GitHub
parent 18dac1a2b6
commit f5e1d7825a
616 changed files with 2220 additions and 23073 deletions

View File

@ -1,74 +0,0 @@
import { useEffect } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { Meta, StoryObj } from '@storybook/react';
import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard';
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
import { BoardCardIdContext } from '@/ui/layout/board/contexts/BoardCardIdContext';
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
import { BoardColumnRecoilScopeContext } from '@/ui/layout/board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { ViewScope } from '@/views/scopes/ViewScope';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress';
import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect';
import { BoardContext } from '../states/contexts/BoardContext';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
const meta: Meta<typeof CompanyBoardCard> = {
title: 'Modules/Companies/CompanyBoardCard',
component: CompanyBoardCard,
decorators: [
(Story, context) => {
const [, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState,
context.parameters.customRecoilScopeContext,
);
useEffect(() => {
setBoardCardFields(pipelineAvailableFieldDefinitions);
}, [setBoardCardFields]);
return (
<MemoryRouter>
<ViewScope viewScopeId="company-board-view">
<RecoilScope
CustomRecoilScopeContext={BoardColumnRecoilScopeContext}
>
<BoardContext.Provider
value={{
BoardRecoilScopeContext:
context.parameters.customRecoilScopeContext,
}}
>
<HooksCompanyBoardEffect />
<BoardCardIdContext.Provider
value={mockedPipelineProgressData[1].id}
>
<Story />
</BoardCardIdContext.Provider>
</BoardContext.Provider>
</RecoilScope>
</ViewScope>
</MemoryRouter>
);
},
ComponentWithRecoilScopeDecorator,
ComponentDecorator,
],
args: {},
argTypes: {},
parameters: {
msw: graphqlMocks,
customRecoilScopeContext: CompanyBoardRecoilScopeContext,
},
};
export default meta;
type Story = StoryObj<typeof CompanyBoardCard>;
export const Default: Story = {};

View File

@ -1,38 +1,34 @@
import { Pipeline } from '~/generated/graphql';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
export const pipeline = {
id: 'pipeline-1',
name: 'pipeline-1',
pipelineStages: [
{
id: 'pipeline-stage-1',
name: 'New',
position: 0,
color: 'red',
},
{
id: 'pipeline-stage-2',
name: 'Screening',
position: 1,
color: 'purple',
},
{
id: 'pipeline-stage-3',
name: 'Meeting',
position: 2,
color: 'sky',
},
{
id: 'pipeline-stage-4',
name: 'Proposal',
position: 3,
color: 'turquoise',
},
{
id: 'pipeline-stage-5',
name: 'Customer',
position: 4,
color: 'yellow',
},
],
} as Pipeline;
export const pipelineSteps = [
{
id: 'pipeline-stage-1',
name: 'New',
position: 0,
color: 'red',
},
{
id: 'pipeline-stage-2',
name: 'Screening',
position: 1,
color: 'purple',
},
{
id: 'pipeline-stage-3',
name: 'Meeting',
position: 2,
color: 'sky',
},
{
id: 'pipeline-stage-4',
name: 'Proposal',
position: 3,
color: 'turquoise',
},
{
id: 'pipeline-stage-5',
name: 'Customer',
position: 4,
color: 'yellow',
},
] as PipelineStep[];

View File

@ -1,5 +1,4 @@
import { useState } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import styled from '@emotion/styled';
import { flip, offset, useFloating } from '@floating-ui/react';
import { v4 } from 'uuid';
@ -8,7 +7,6 @@ import {
PeoplePicker,
PersonForSelect,
} from '@/people/components/PeoplePicker';
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
import { IconPlus } from '@/ui/display/icon';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
@ -16,10 +14,6 @@ import { DoubleTextInput } from '@/ui/object/field/meta-types/input/components/i
import { FieldDoubleText } from '@/ui/object/field/types/FieldDoubleText';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import {
useInsertOnePersonMutation,
useUpdateOnePersonMutation,
} from '~/generated/graphql';
const StyledContainer = styled.div`
position: static;
@ -56,8 +50,6 @@ export const AddPersonToCompany = ({
}) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [isCreationDropdownOpen, setIsCreationDropdownOpen] = useState(false);
const [updatePerson] = useUpdateOnePersonMutation();
const [insertOnePerson] = useInsertOnePersonMutation();
const { refs, floatingStyles } = useFloating({
open: isDropdownOpen,
placement: 'right-start',
@ -77,17 +69,17 @@ export const AddPersonToCompany = ({
const handlePersonSelected =
(companyId: string) => async (newPerson: PersonForSelect | null) => {
if (newPerson) {
await updatePerson({
variables: {
where: {
id: newPerson.id,
},
data: {
company: { connect: { id: companyId } },
},
},
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
});
// await updatePerson({
// variables: {
// where: {
// id: newPerson.id,
// },
// data: {
// company: { connect: { id: companyId } },
// },
// },
// refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
// });
handleClosePicker();
}
};
@ -114,17 +106,17 @@ export const AddPersonToCompany = ({
}: FieldDoubleText) => {
if (!firstValue && !secondValue) return;
const newPersonId = v4();
await insertOnePerson({
variables: {
data: {
company: { connect: { id: companyId } },
id: newPersonId,
firstName: firstValue,
lastName: secondValue,
},
},
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
});
// await insertOnePerson({
// variables: {
// data: {
// company: { connect: { id: companyId } },
// id: newPersonId,
// firstName: firstValue,
// lastName: secondValue,
// },
// },
// refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
// });
setIsCreationDropdownOpen(false);
};

View File

@ -152,7 +152,7 @@ export const CompanyBoardCard = () => {
const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => {
const { updateOneObject } = useUpdateOneObjectRecord({
objectNameSingular: 'opportunityV2',
objectNameSingular: 'opportunity',
});
const updateEntity = ({
@ -242,7 +242,7 @@ export const CompanyBoardCard = () => {
fieldDefinition: {
fieldMetadataId: viewField.fieldMetadataId,
label: viewField.label,
Icon: viewField.Icon,
iconName: viewField.iconName,
type: viewField.type,
metadata: viewField.metadata,
entityChipDisplayMapper:

View File

@ -18,7 +18,7 @@ export const CompanyChip = ({
}: CompanyChipProps) => (
<EntityChip
entityId={id}
linkToEntity={`/companies/${id}`}
linkToEntity={`/objects/companies/${id}`}
name={name}
avatarType="squared"
pictureUrl={pictureUrl}

View File

@ -33,7 +33,7 @@ export const CompanyPicker = ({
}, [initialSearchFilter, setRelationPickerSearchFilter]);
const { findManyQuery } = useFindOneObjectMetadataItem({
objectNamePlural: 'companiesV2',
objectNamePlural: 'companies',
});
const useFindManyCompanies = (options: any) =>
@ -57,7 +57,7 @@ export const CompanyPicker = ({
originalEntity: company,
}),
selectedIds: companyId ? [companyId] : [],
objectNamePlural: 'companiesV2',
objectNamePlural: 'companies',
});
const handleEntitySelected = async (

View File

@ -73,7 +73,7 @@ export const CompanyProgressPicker = ({
const selectedPipelineStage = useMemo(
() =>
currentPipelineStages.find(
(pipelineStage) => pipelineStage.id === selectedPipelineStageId,
(pipelineStage: any) => pipelineStage.id === selectedPipelineStageId,
),
[currentPipelineStages, selectedPipelineStageId],
);
@ -85,7 +85,7 @@ export const CompanyProgressPicker = ({
>
{isProgressSelectionUnfolded ? (
<DropdownMenuItemsContainer>
{currentPipelineStages.map((pipelineStage, index) => (
{currentPipelineStages.map((pipelineStage: any, index: number) => (
<MenuItem
key={pipelineStage.id}
testId={`select-pipeline-stage-${index}`}

View File

@ -1,7 +1,8 @@
import styled from '@emotion/styled';
import { Company } from '@/companies/types/Company';
import { PeopleCard } from '@/people/components/PeopleCard';
import { Company, useGetPeopleQuery } from '~/generated/graphql';
import { Person } from '@/people/types/Person';
import { AddPersonToCompany } from './AddPersonToCompany';
@ -43,16 +44,19 @@ const StyledTitle = styled.div`
`;
export const CompanyTeam = ({ company }: CompanyTeamProps) => {
const { data } = useGetPeopleQuery({
variables: {
orderBy: [],
where: {
companyId: {
equals: company.id,
},
},
},
});
// const { data } = useGetPeopleQuery({
// variables: {
// orderBy: [],
// where: {
// companyId: {
// equals: company.id,
// },
// },
// },
// });
const data = {
people: [],
};
const peopleIds = data?.people?.map(({ id }) => id);
@ -65,7 +69,7 @@ export const CompanyTeam = ({ company }: CompanyTeamProps) => {
<AddPersonToCompany companyId={company.id} peopleIds={peopleIds} />
</StyledTitleContainer>
<StyledListContainer>
{data?.people?.map((person, id) => (
{data?.people?.map((person: Person, id) => (
<PeopleCard
key={person.id}
person={person}

View File

@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useRecoilState, useRecoilValue } from 'recoil';
import { Company } from '@/companies/types/Company';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
@ -13,13 +14,11 @@ import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardCont
import { availableBoardCardFieldsScopedState } from '@/ui/layout/board/states/availableBoardCardFieldsScopedState';
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
import { turnFilterIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
import { Company } from '~/generated-metadata/graphql';
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
@ -62,7 +61,7 @@ export const HooksCompanyBoardEffect = () => {
const updateCompanyBoard = useUpdateCompanyBoard();
useFindManyObjectRecords({
objectNamePlural: 'pipelineStepsV2',
objectNamePlural: 'pipelineSteps',
filter: {},
onCompleted: useCallback(
(data: PaginatedObjectTypeResults<PipelineStep>) => {
@ -80,14 +79,14 @@ export const HooksCompanyBoardEffect = () => {
in: pipelineSteps.map((pipelineStep) => pipelineStep.id),
},
},
...(currentViewFilters?.map(turnFilterIntoWhereClause) || []),
...[],
],
};
}, [currentViewFilters, pipelineSteps]) as any;
}, [pipelineSteps]) as any;
useFindManyObjectRecords({
skip: !pipelineSteps.length,
objectNamePlural: 'opportunitiesV2',
objectNamePlural: 'opportunities',
filter: whereFilters,
onCompleted: useCallback(
(_data: PaginatedObjectTypeResults<Opportunity>) => {
@ -104,7 +103,7 @@ export const HooksCompanyBoardEffect = () => {
useFindManyObjectRecords({
skip: !opportunities.length,
objectNamePlural: 'companiesV2',
objectNamePlural: 'companies',
filter: {
id: {
in: opportunities.map((opportuntiy) => opportuntiy.companyId || ''),

View File

@ -9,7 +9,6 @@ import { BoardColumnContext } from '@/ui/layout/board/contexts/BoardColumnContex
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useCreateCompanyProgress } from '../hooks/useCreateCompanyProgress';
import { useFilteredSearchCompanyQuery } from '../hooks/useFilteredSearchCompanyQuery';
export const NewCompanyProgressButton = () => {
@ -25,8 +24,6 @@ export const NewCompanyProgressButton = () => {
setHotkeyScopeAndMemorizePreviousScope,
} = usePreviousHotkeyScope();
const createCompanyProgress = useCreateCompanyProgress();
const handleEntitySelect = (company: any) => {
setIsCreatingCard(false);
goBackToPreviousHotkeyScope();
@ -39,7 +36,7 @@ export const NewCompanyProgressButton = () => {
throw new Error('Pipeline stage id is not defined');
}
createCompanyProgress(company.id, pipelineStageId);
//createCompanyProgress(company.id, pipelineStageId);
};
const handleNewClick = useCallback(() => {

View File

@ -1,182 +0,0 @@
import {
IconBrandLinkedin,
IconBrandX,
IconBuildingSkyscraper,
IconCalendarEvent,
IconLink,
IconMap,
IconMoneybag,
IconTarget,
IconUserCircle,
IconUsers,
} from '@/ui/display/icon/index';
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import {
FieldBooleanMetadata,
FieldChipMetadata,
FieldDateMetadata,
FieldMetadata,
FieldMoneyMetadata,
FieldNumberMetadata,
FieldRelationMetadata,
FieldTextMetadata,
FieldURLMetadata,
} from '@/ui/object/field/types/FieldMetadata';
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
import { User } from '~/generated/graphql';
export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[] =
[
{
fieldMetadataId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
size: 180,
position: 0,
type: 'CHIP',
metadata: {
urlFieldName: 'domainName',
contentFieldName: 'name',
relationType: Entity.Company,
placeHolder: 'Company Name',
},
isVisible: true,
infoTooltipContent: 'The company name.',
basePathToShowPage: '/companies/',
} satisfies ColumnDefinition<FieldChipMetadata>,
{
fieldMetadataId: 'domainName',
label: 'URL',
Icon: IconLink,
size: 100,
position: 1,
type: 'URL',
metadata: {
fieldName: 'domainName',
placeHolder: 'example.com',
},
isVisible: true,
infoTooltipContent:
'The company website URL. We use this url to fetch the company icon.',
} satisfies ColumnDefinition<FieldURLMetadata>,
{
fieldMetadataId: 'accountOwner',
label: 'Account Owner',
Icon: IconUserCircle,
size: 150,
position: 2,
type: 'RELATION',
metadata: {
fieldName: 'accountOwner',
relationType: Entity.User,
},
isVisible: true,
infoTooltipContent:
'Your team member responsible for managing the company account.',
entityChipDisplayMapper: (dataObject: User) => {
return {
name: dataObject?.displayName,
pictureUrl: dataObject?.avatarUrl ?? undefined,
avatarType: 'rounded',
};
},
} satisfies ColumnDefinition<FieldRelationMetadata>,
{
fieldMetadataId: 'createdAt',
label: 'Creation',
Icon: IconCalendarEvent,
size: 150,
position: 3,
type: 'DATE',
metadata: {
fieldName: 'createdAt',
},
isVisible: true,
infoTooltipContent: "Date when the company's record was created.",
} satisfies ColumnDefinition<FieldDateMetadata>,
{
fieldMetadataId: 'employees',
label: 'Employees',
Icon: IconUsers,
size: 150,
position: 4,
type: 'NUMBER',
metadata: {
fieldName: 'employees',
isPositive: true,
placeHolder: 'Employees',
},
isVisible: true,
infoTooltipContent: 'Number of employees in the company.',
} satisfies ColumnDefinition<FieldNumberMetadata>,
{
fieldMetadataId: 'linkedin',
label: 'LinkedIn',
Icon: IconBrandLinkedin,
size: 170,
position: 5,
type: 'URL',
metadata: {
fieldName: 'linkedinUrl',
placeHolder: 'LinkedIn URL',
},
isVisible: true,
infoTooltipContent: 'The company Linkedin account.',
} satisfies ColumnDefinition<FieldURLMetadata>,
{
fieldMetadataId: 'address',
label: 'Address',
Icon: IconMap,
size: 170,
position: 6,
type: 'TEXT',
metadata: {
fieldName: 'address',
placeHolder: 'Address', // Hack: Fake character to prevent password-manager from filling the field
},
isVisible: true,
infoTooltipContent: 'The company address.',
} satisfies ColumnDefinition<FieldTextMetadata>,
{
fieldMetadataId: 'idealCustomerProfile',
label: 'ICP',
Icon: IconTarget,
size: 150,
position: 7,
type: 'BOOLEAN',
metadata: {
fieldName: 'idealCustomerProfile',
},
isVisible: false,
infoTooltipContent:
'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you.',
} satisfies ColumnDefinition<FieldBooleanMetadata>,
{
fieldMetadataId: 'annualRecurringRevenue',
label: 'ARR',
Icon: IconMoneybag,
size: 150,
position: 8,
type: 'MONEY_AMOUNT',
metadata: {
fieldName: 'annualRecurringRevenue',
placeHolder: 'ARR',
},
infoTooltipContent:
'Annual Recurring Revenue: The actual or estimated annual revenue of the company.',
} satisfies ColumnDefinition<FieldMoneyMetadata>,
{
fieldMetadataId: 'xUrl',
label: 'Twitter',
Icon: IconBrandX,
size: 150,
position: 9,
type: 'URL',
metadata: {
fieldName: 'xUrl',
placeHolder: 'X',
},
isVisible: false,
infoTooltipContent: 'The company Twitter account.',
} satisfies ColumnDefinition<FieldURLMetadata>,
];

View File

@ -1,90 +0,0 @@
import { useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { FieldRecoilScopeContext } from '@/ui/object/record-inline-cell/states/recoil-scope-contexts/FieldRecoilScopeContext';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { Company, useUpdateOneCompanyMutation } from '~/generated/graphql';
import { EditableFieldHotkeyScope } from '../types/EditableFieldHotkeyScope';
type CompanyNameEditableFieldProps = {
company: Pick<Company, 'id' | 'name'>;
};
const StyledEditableTitleInput = styled.input<{
value: string;
}>`
background: transparent;
border: none;
color: ${({ theme, value }) =>
value ? theme.font.color.primary : theme.font.color.light};
display: flex;
flex-direction: column;
font-size: ${({ theme }) => theme.font.size.xl};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
justify-content: center;
line-height: ${({ theme }) => theme.text.lineHeight.md};
outline: none;
&::placeholder {
color: ${({ theme }) => theme.font.color.light};
}
text-align: center;
width: calc(100% - ${({ theme }) => theme.spacing(2)});
`;
export const CompanyNameEditableField = ({
company,
}: CompanyNameEditableFieldProps) => {
const [internalValue, setInternalValue] = useState(company.name);
const [updateCompany] = useUpdateOneCompanyMutation();
const {
goBackToPreviousHotkeyScope,
setHotkeyScopeAndMemorizePreviousScope,
} = usePreviousHotkeyScope();
useEffect(() => {
setInternalValue(company.name);
}, [company.name]);
const handleChange = async (newValue: string) => {
setInternalValue(newValue);
};
const handleSubmit = async () => {
goBackToPreviousHotkeyScope();
await updateCompany({
variables: {
where: {
id: company.id,
},
data: {
name: internalValue ?? '',
},
},
});
};
const handleFocus = async () => {
setHotkeyScopeAndMemorizePreviousScope(
EditableFieldHotkeyScope.EditableField,
);
};
return (
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<StyledEditableTitleInput
autoComplete="off"
onChange={(event) => handleChange(event.target.value)}
onBlur={handleSubmit}
onFocus={handleFocus}
value={internalValue}
/>
</RecoilScope>
);
};

View File

@ -1,39 +0,0 @@
import { gql } from '@apollo/client';
export const BASE_COMPANY_FIELDS_FRAGMENT = gql`
fragment baseCompanyFieldsFragment on Company {
address
annualRecurringRevenue
createdAt
domainName
employees
id
idealCustomerProfile
linkedinUrl
name
xUrl
_activityCount
}
`;
export const BASE_ACCOUNT_OWNER_FRAGMENT = gql`
fragment baseAccountOwnerFragment on User {
id
email
displayName
avatarUrl
firstName
lastName
}
`;
export const COMPANY_FIELDS_FRAGMENT = gql`
${BASE_COMPANY_FIELDS_FRAGMENT}
${BASE_ACCOUNT_OWNER_FRAGMENT}
fragment companyFieldsFragment on Company {
accountOwner {
...baseAccountOwnerFragment
}
...baseCompanyFieldsFragment
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const DELETE_MANY_COMPANIES = gql`
mutation DeleteManyCompanies($ids: [String!]) {
deleteManyCompany(where: { id: { in: $ids } }) {
count
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const INSERT_MANY_COMPANY = gql`
mutation InsertManyCompany($data: [CompanyCreateManyInput!]!) {
createManyCompany(data: $data) {
count
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const INSERT_ONE_COMPANY = gql`
mutation InsertOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
...companyFieldsFragment
}
}
`;

View File

@ -1,12 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_ONE_COMPANY = gql`
mutation UpdateOneCompany(
$where: CompanyWhereUniqueInput!
$data: CompanyUpdateInput!
) {
updateOneCompany(data: $data, where: $where) {
...companyFieldsFragment
}
}
`;

View File

@ -1,18 +0,0 @@
import { Company } from '~/generated/graphql';
import { GET_COMPANIES } from '../queries/getCompanies';
export const getCompaniesOptimisticEffectDefinition = {
key: 'generic-entity-table-data-companies',
typename: 'Company',
query: GET_COMPANIES,
resolver: ({
currentData,
newData,
}: {
currentData: Company[];
newData: Company[];
}) => {
return [...newData, ...currentData];
},
};

View File

@ -1,15 +0,0 @@
import { gql } from '@apollo/client';
import { COMPANY_FIELDS_FRAGMENT } from '../fragments/companyFieldsFragment';
export const GET_COMPANIES = gql`
${COMPANY_FIELDS_FRAGMENT}
query GetCompanies(
$orderBy: [CompanyOrderByWithRelationInput!]
$where: CompanyWhereInput
) {
companies: findManyCompany(orderBy: $orderBy, where: $where) {
...companyFieldsFragment
}
}
`;

View File

@ -1,18 +0,0 @@
import { gql } from '@apollo/client';
export const GET_COMPANY = gql`
query GetCompany($where: CompanyWhereUniqueInput!) {
findUniqueCompany(where: $where) {
...companyFieldsFragment
Favorite {
id
person {
id
}
company {
id
}
}
}
}
`;

View File

@ -1,15 +0,0 @@
import { useSetRecoilState } from 'recoil';
import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState';
import { useGetCompanyQuery } from '~/generated/graphql';
export const useCompanyQuery = (id: string) => {
const updateCompanyShowPage = useSetRecoilState(entityFieldsFamilyState(id));
return useGetCompanyQuery({
variables: { where: { id } },
onCompleted: (data) => {
updateCompanyShowPage(data?.findUniqueCompany);
},
});
};

View File

@ -1,157 +0,0 @@
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import {
IconCheckbox,
IconHeart,
IconHeartOff,
IconNotes,
IconTrash,
} from '@/ui/display/icon';
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector';
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
import {
ActivityType,
useDeleteManyCompaniesMutation,
useGetFavoritesQuery,
} from '~/generated/graphql';
import { GET_COMPANY } from '../graphql/queries/getCompany';
import { useCreateActivityForCompany } from './useCreateActivityForCompany';
export const useCompanyTableContextMenuEntries = () => {
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
const createActivityForCompany = useCreateActivityForCompany();
const setTableRowIds = useSetRecoilState(tableRowIdsState);
const { resetTableRowSelection } = useRecordTable({
recordTableScopeId: 'companies',
});
const { data } = useGetFavoritesQuery();
const favorites = data?.findFavorites;
const { createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: 'companies',
});
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
const selectedCompanyId =
selectedRowIds.length === 1 ? selectedRowIds[0] : '';
const isFavorite =
!!selectedCompanyId &&
!!favorites?.find(
(favorite) => favorite.company?.id === selectedCompanyId,
);
resetTableRowSelection();
if (isFavorite) deleteFavorite(selectedCompanyId);
else createFavorite('company', selectedCompanyId);
});
const [deleteManyCompany] = useDeleteManyCompaniesMutation({
refetchQueries: [getOperationName(GET_COMPANY) ?? ''],
});
const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => {
const rowIdsToDelete = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
resetTableRowSelection();
await deleteManyCompany({
variables: {
ids: rowIdsToDelete,
},
optimisticResponse: {
__typename: 'Mutation',
deleteManyCompany: {
count: rowIdsToDelete.length,
},
},
update: () => {
setTableRowIds((tableRowIds) =>
tableRowIds.filter((id) => !rowIdsToDelete.includes(id)),
);
},
});
});
return {
setContextMenuEntries: useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
const selectedCompanyId =
selectedRowIds.length === 1 ? selectedRowIds[0] : '';
const isFavorite =
!!selectedCompanyId &&
!!favorites?.find(
(favorite) => favorite.company?.id === selectedCompanyId,
);
setContextMenuEntries([
{
label: 'New task',
Icon: IconCheckbox,
onClick: () => createActivityForCompany(ActivityType.Task),
},
{
label: 'New note',
Icon: IconNotes,
onClick: () => createActivityForCompany(ActivityType.Note),
},
...(!!selectedCompanyId
? [
{
label: isFavorite
? 'Remove from favorites'
: 'Add to favorites',
Icon: isFavorite ? IconHeartOff : IconHeart,
onClick: () => handleFavoriteButtonClick(),
},
]
: []),
{
label: 'Delete',
Icon: IconTrash,
accent: 'danger',
onClick: () => handleDeleteClick(),
},
]);
}),
setActionBarEntries: useRecoilCallback(() => () => {
setActionBarEntriesState([
{
label: 'Task',
Icon: IconCheckbox,
onClick: () => createActivityForCompany(ActivityType.Task),
},
{
label: 'Note',
Icon: IconNotes,
onClick: () => createActivityForCompany(ActivityType.Note),
},
{
label: 'Delete',
Icon: IconTrash,
accent: 'danger',
onClick: () => handleDeleteClick(),
},
]);
}),
};
};

View File

@ -1,16 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds';
import { ActivityType } from '@/activities/types/Activity';
export const useCreateActivityForCompany = () => {
const openCreateActivityRightDrawer =
useOpenCreateActivityDrawerForSelectedRowIds();
return useRecoilCallback(
() => (type: ActivityType) => {
openCreateActivityRightDrawer(type, 'Company');
},
[openCreateActivityRightDrawer],
);
};

View File

@ -1,38 +0,0 @@
import { useRecoilCallback, useRecoilState } from 'recoil';
import { v4 } from 'uuid';
import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord';
import { currentPipelineState } from '@/pipeline/states/currentPipelineState';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState';
export const useCreateCompanyProgress = () => {
const { createOneObject: createOneOpportunity } =
useCreateOneObjectRecord<Opportunity>({
objectNameSingular: 'opportunityV2',
});
const [currentPipeline] = useRecoilState(currentPipelineState);
return useRecoilCallback(
({ set }) =>
async (companyId: string, pipelineStageId: string) => {
if (!currentPipeline?.id) {
throw new Error('Pipeline not found');
}
const newUuid = v4();
set(boardCardIdsByColumnIdFamilyState(pipelineStageId), (oldValue) => [
...oldValue,
newUuid,
]);
await createOneOpportunity?.({
pipelineStepId: pipelineStageId,
companyId: companyId,
});
},
[createOneOpportunity, currentPipeline?.id],
);
};

View File

@ -1,6 +1,8 @@
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
import { useSearchCompanyQuery } from '~/generated/graphql';
import { getLogoUrlFromDomainName } from '~/utils';
import { useQuery } from '@apollo/client';
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2';
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
export const useFilteredSearchCompanyQuery = ({
searchFilter,
@ -11,25 +13,32 @@ export const useFilteredSearchCompanyQuery = ({
selectedIds?: string[];
limit?: number;
}) => {
return useFilteredSearchEntityQuery({
queryHook: useSearchCompanyQuery,
const { findManyQuery } = useFindOneObjectMetadataItem({
objectNameSingular: 'company',
});
const useFindManyCompanies = (options: any) =>
useQuery(findManyQuery, options);
return useFilteredSearchEntityQueryV2({
queryHook: useFindManyCompanies,
filters: [
{
fieldNames: ['name'],
fieldNames: ['name.firstName', 'name.lastName'],
filter: searchFilter,
},
],
orderByField: 'name',
orderByField: 'createdAt',
mappingFunction: (company) => ({
entityType: Entity.Company,
id: company.id,
entityType: 'Company',
name: company.name,
avatarUrl: getLogoUrlFromDomainName(company.domainName),
domainName: company.domainName,
avatarType: 'squared',
avatarUrl: '',
originalEntity: company,
}),
selectedIds: selectedIds,
objectNamePlural: 'workspaceMembers',
limit,
});
};

View File

@ -1,59 +0,0 @@
import { v4 as uuidv4 } from 'uuid';
import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport';
import { SpreadsheetOptions } from '@/spreadsheet-import/types';
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
import { useInsertManyCompanyMutation } from '~/generated/graphql';
import { fieldsForCompany } from '../utils/fieldsForCompany';
export type FieldCompanyMapping = (typeof fieldsForCompany)[number]['key'];
export const useSpreadsheetCompanyImport = () => {
const { openSpreadsheetImport } = useSpreadsheetImport<FieldCompanyMapping>();
const { enqueueSnackBar } = useSnackBar();
const [createManyCompany] = useInsertManyCompanyMutation();
const openCompanySpreadsheetImport = (
options?: Omit<
SpreadsheetOptions<FieldCompanyMapping>,
'fields' | 'isOpen' | 'onClose'
>,
) => {
openSpreadsheetImport({
...options,
onSubmit: async (data) => {
// TODO: Add better type checking in spreadsheet import later
const createInputs = data.validData.map((company) => ({
id: uuidv4(),
name: (company.name ?? '') as string,
domainName: (company.domainName ?? '') as string,
address: (company.address ?? '') as string,
employees: parseInt((company.employees ?? '') as string, 10),
linkedinUrl: (company.linkedinUrl ?? '') as string | undefined,
}));
try {
const result = await createManyCompany({
variables: {
data: createInputs,
},
refetchQueries: 'active',
});
if (result.errors) {
throw result.errors;
}
} catch (error: any) {
enqueueSnackBar(error?.message || 'Something went wrong', {
variant: 'error',
});
}
},
fields: fieldsForCompany,
});
};
return { openCompanySpreadsheetImport };
};

View File

@ -1,149 +0,0 @@
import styled from '@emotion/styled';
import { useRecoilCallback } from 'recoil';
import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions';
import { getCompaniesOptimisticEffectDefinition } from '@/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition';
import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries';
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
import { RecordTableEffect } from '@/ui/object/record-table/components/RecordTableEffect';
import { RecordTableV1 } from '@/ui/object/record-table/components/RecordTableV1';
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown';
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
import { ViewBar } from '@/views/components/ViewBar';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { useView } from '@/views/hooks/useView';
import { ViewScope } from '@/views/scopes/ViewScope';
import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
import {
UpdateOneCompanyMutationVariables,
useGetCompaniesQuery,
useGetWorkspaceMembersLazyQuery,
useUpdateOneCompanyMutation,
} from '~/generated/graphql';
import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions';
import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions';
import CompanyTableEffect from './CompanyTableEffect';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
overflow: auto;
`;
export const CompanyTable = () => {
const viewScopeId = 'company-table-view';
const tableScopeId = 'companies';
const {
setTableFilters,
setTableSorts,
setTableColumns,
upsertRecordTableItem,
} = useRecordTable({
recordTableScopeId: tableScopeId,
});
const [updateEntityMutation] = useUpdateOneCompanyMutation();
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
const { persistViewFields } = useViewFields(viewScopeId);
const { setEntityCountInCurrentView } = useView({ viewScopeId });
const { setContextMenuEntries, setActionBarEntries } =
useCompanyTableContextMenuEntries();
const updateCompany = async (
variables: UpdateOneCompanyMutationVariables,
) => {
if (variables.data.accountOwner?.connect?.id) {
const workspaceMemberAccountOwner = (
await getWorkspaceMember({
variables: {
where: {
userId: { equals: variables.data.accountOwner.connect?.id },
},
},
})
).data?.workspaceMembers?.[0];
variables.data.workspaceMemberAccountOwner = {
connect: { id: workspaceMemberAccountOwner?.id },
};
}
updateEntityMutation({
variables: variables,
onCompleted: (data) => {
if (!data.updateOneCompany) {
return;
}
upsertRecordTableItem(data.updateOneCompany);
},
});
};
const { openCompanySpreadsheetImport: onImport } =
useSpreadsheetCompanyImport();
return (
<ViewScope
viewScopeId={viewScopeId}
onViewFieldsChange={(viewFields) => {
setTableColumns(
mapViewFieldsToColumnDefinitions(
viewFields,
companiesAvailableFieldDefinitions,
),
);
}}
onViewFiltersChange={(viewFilters) => {
setTableFilters(mapViewFiltersToFilters(viewFilters));
}}
onViewSortsChange={(viewSorts) => {
setTableSorts(mapViewSortsToSorts(viewSorts));
}}
>
<StyledContainer>
<RecordTableScope
recordTableScopeId={tableScopeId}
onColumnsChange={useRecoilCallback(() => (columns) => {
persistViewFields(mapColumnDefinitionsToViewFields(columns));
})}
onEntityCountChange={useRecoilCallback(() => (entityCount) => {
setEntityCountInCurrentView(entityCount);
})}
>
<ViewBar
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
optionsDropdownScopeId={TableOptionsDropdownId}
/>
<CompanyTableEffect />
<RecordTableEffect
getRequestResultKey="companies"
useGetRequest={useGetCompaniesQuery}
getRequestOptimisticEffectDefinition={
getCompaniesOptimisticEffectDefinition
}
filterDefinitionArray={companyTableFilterDefinitions}
sortDefinitionArray={companyTableSortDefinitions}
setContextMenuEntries={setContextMenuEntries}
setActionBarEntries={setActionBarEntries}
/>
<RecordTableV1
updateEntityMutation={({
variables,
}: {
variables: UpdateOneCompanyMutationVariables;
}) => updateCompany(variables)}
/>
</RecordTableScope>
</StyledContainer>
</ViewScope>
);
};

View File

@ -1,41 +0,0 @@
import { useEffect } from 'react';
import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { useView } from '@/views/hooks/useView';
import { ViewType } from '@/views/types/ViewType';
import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions';
import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions';
const CompanyTableEffect = () => {
const {
setAvailableSortDefinitions,
setAvailableFilterDefinitions,
setAvailableFieldDefinitions,
setViewType,
setViewObjectMetadataId,
} = useView();
const { setAvailableTableColumns } = useRecordTable();
useEffect(() => {
setAvailableSortDefinitions?.(companyTableSortDefinitions);
setAvailableFilterDefinitions?.(companyTableFilterDefinitions);
setAvailableFieldDefinitions?.(companiesAvailableFieldDefinitions);
setViewObjectMetadataId?.('company');
setViewType?.(ViewType.Table);
setAvailableTableColumns(companiesAvailableFieldDefinitions);
}, [
setAvailableFieldDefinitions,
setAvailableFilterDefinitions,
setAvailableSortDefinitions,
setAvailableTableColumns,
setViewObjectMetadataId,
setViewType,
]);
return <></>;
};
export default CompanyTableEffect;

View File

@ -1,17 +0,0 @@
import { useEffect } from 'react';
import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { mockedCompaniesData } from './companies-mock-data';
export const CompanyTableMockDataEffect = () => {
const { setRecordTableData, setTableColumns } = useRecordTable();
useEffect(() => {
setRecordTableData(mockedCompaniesData);
setTableColumns(companiesAvailableFieldDefinitions);
}, [setRecordTableData, setTableColumns]);
return <></>;
};

View File

@ -1,42 +0,0 @@
import styled from '@emotion/styled';
import { RecordTable } from '@/ui/object/record-table/components/RecordTable';
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown';
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
import { ViewBar } from '@/views/components/ViewBar';
import { ViewScope } from '@/views/scopes/ViewScope';
import { useUpdateOneCompanyMutation } from '~/generated/graphql';
import CompanyTableEffect from './CompanyTableEffect';
import { CompanyTableMockDataEffect } from './CompanyTableMockDataEffect';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
overflow: auto;
`;
export const CompanyTableMockMode = () => {
return (
<StyledContainer>
<ViewScope viewScopeId="company-table-mock-mode">
<RecordTableScope
recordTableScopeId="company-table-mock-mode-table"
onColumnsChange={() => {}}
onEntityCountChange={() => {}}
>
<CompanyTableEffect />
<CompanyTableMockDataEffect />
<ViewBar
optionsDropdownButton={<TableOptionsDropdown />}
optionsDropdownScopeId={TableOptionsDropdownId}
/>
<RecordTable updateEntityMutation={useUpdateOneCompanyMutation} />
</RecordTableScope>
</ViewScope>
</StyledContainer>
);
};

View File

@ -1,112 +0,0 @@
import { Favorite } from '@/favorites/types/Favorite';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { Company } from '../../../../generated/graphql';
type MockedCompany = Pick<
Company,
| 'id'
| 'name'
| 'domainName'
| '__typename'
| 'createdAt'
| 'address'
| 'employees'
| 'linkedinUrl'
| 'xUrl'
| 'annualRecurringRevenue'
| 'idealCustomerProfile'
| '_activityCount'
> & {
accountOwner: Pick<WorkspaceMember, 'id' | 'avatarUrl' | 'name'> | null;
} & { Favorite: Pick<Favorite, 'id'> | null };
export const mockedCompaniesData: Array<MockedCompany> = [
{
id: '89bb825c-171e-4bcc-9cf7-43448d6fb278',
domainName: 'airbnb.com',
name: 'Airbnb',
linkedinUrl: 'https://www.linkedin.com/company/airbnb/',
xUrl: 'https://twitter.com/airbnb',
annualRecurringRevenue: 500000,
idealCustomerProfile: true,
createdAt: '2023-04-26T10:08:54.724515+00:00',
address: 'San Francisco, CA',
employees: 5000,
Favorite: null,
_activityCount: 0,
accountOwner: {
name: {
firstName: 'Charles',
lastName: 'Test',
},
avatarUrl: null,
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
},
__typename: 'Company',
},
{
id: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae',
domainName: 'qonto.com',
name: 'Qonto',
linkedinUrl: 'https://www.linkedin.com/company/qonto/',
xUrl: 'https://twitter.com/qonto',
annualRecurringRevenue: 500000,
idealCustomerProfile: false,
createdAt: '2023-04-26T10:12:42.33625+00:00',
address: 'Paris, France',
employees: 800,
Favorite: null,
_activityCount: 0,
accountOwner: null,
__typename: 'Company',
},
{
id: 'a674fa6c-1455-4c57-afaf-dd5dc086361d',
domainName: 'stripe.com',
name: 'Stripe',
linkedinUrl: 'https://www.linkedin.com/company/stripe/',
xUrl: 'https://twitter.com/stripe',
annualRecurringRevenue: 5000000,
idealCustomerProfile: false,
createdAt: '2023-04-26T10:10:32.530184+00:00',
address: 'San Francisco, CA',
employees: 8000,
Favorite: null,
_activityCount: 0,
accountOwner: null,
__typename: 'Company',
},
{
id: 'b1cfd51b-a831-455f-ba07-4e30671e1dc3',
domainName: 'figma.com',
linkedinUrl: 'https://www.linkedin.com/company/figma/',
xUrl: 'https://twitter.com/figma',
annualRecurringRevenue: 50000,
idealCustomerProfile: true,
name: 'Figma',
createdAt: '2023-03-21T06:30:25.39474+00:00',
address: 'San Francisco, CA',
employees: 800,
Favorite: null,
_activityCount: 0,
accountOwner: null,
__typename: 'Company',
},
{
id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb',
domainName: 'notion.com',
linkedinUrl: 'https://www.linkedin.com/company/notion/',
xUrl: 'https://twitter.com/notion',
annualRecurringRevenue: 500000,
idealCustomerProfile: false,
name: 'Notion',
createdAt: '2023-04-26T10:13:29.712485+00:00',
address: 'San Francisco, CA',
employees: 400,
Favorite: null,
_activityCount: 0,
accountOwner: null,
__typename: 'Company',
},
];

View File

@ -0,0 +1,15 @@
export type Company = {
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
name: string;
domainName: string;
address: string;
accountOwnerId: string | null;
linkedinUrl: { url: string; label: string };
xUrl: { url: string; label: string };
annualRecurringRevenue: { amountMicros: number | null; currencyCode: string };
employees: number | null;
idealCustomerProfile: boolean;
};

View File

@ -1,5 +1,5 @@
import { Company } from '@/companies/types/Company';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { Company } from '~/generated/graphql';
export type CompanyForBoard = Pick<Company, 'id' | 'name' | 'domainName'>;
export type PipelineProgressForBoard = Opportunity;