mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-28 23:03:41 +03:00
282 on opportunities page data pipeline + companies + people is fetched from be (#285)
* feature: get pipelines columns from backend * feature: display item not found instead of crashing * feature: add BoardCard component * feature: display items from the backend * refactor: extract useBoard in a hook * refactor: export only loading and error from useBoard * refactor: create var pipelineStage * feature: implement support for Company boards
This commit is contained in:
parent
eb8fc50ff1
commit
bf6fb0ba70
@ -1159,6 +1159,11 @@ export type DeleteCompaniesMutationVariables = Exact<{
|
||||
|
||||
export type DeleteCompaniesMutation = { __typename?: 'Mutation', deleteManyCompany: { __typename?: 'AffectedRows', count: number } };
|
||||
|
||||
export type GetPipelinesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetPipelinesQuery = { __typename?: 'Query', findManyPipeline: Array<{ __typename?: 'Pipeline', id: string, name: string, pipelineStages?: Array<{ __typename?: 'PipelineStage', name: string, color: string, pipelineProgresses?: Array<{ __typename?: 'PipelineProgress', id: string, associableType: PipelineProgressableType, associableId: string }> | null }> | null }> };
|
||||
|
||||
export type GetPeopleQueryVariables = Exact<{
|
||||
orderBy?: InputMaybe<Array<PersonOrderByWithRelationInput> | PersonOrderByWithRelationInput>;
|
||||
where?: InputMaybe<PersonWhereInput>;
|
||||
@ -1623,6 +1628,50 @@ export function useDeleteCompaniesMutation(baseOptions?: Apollo.MutationHookOpti
|
||||
export type DeleteCompaniesMutationHookResult = ReturnType<typeof useDeleteCompaniesMutation>;
|
||||
export type DeleteCompaniesMutationResult = Apollo.MutationResult<DeleteCompaniesMutation>;
|
||||
export type DeleteCompaniesMutationOptions = Apollo.BaseMutationOptions<DeleteCompaniesMutation, DeleteCompaniesMutationVariables>;
|
||||
export const GetPipelinesDocument = gql`
|
||||
query GetPipelines {
|
||||
findManyPipeline(skip: 1) {
|
||||
id
|
||||
name
|
||||
pipelineStages {
|
||||
name
|
||||
color
|
||||
pipelineProgresses {
|
||||
id
|
||||
associableType
|
||||
associableId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetPipelinesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetPipelinesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetPipelinesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetPipelinesQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetPipelinesQuery(baseOptions?: Apollo.QueryHookOptions<GetPipelinesQuery, GetPipelinesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetPipelinesQuery, GetPipelinesQueryVariables>(GetPipelinesDocument, options);
|
||||
}
|
||||
export function useGetPipelinesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetPipelinesQuery, GetPipelinesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetPipelinesQuery, GetPipelinesQueryVariables>(GetPipelinesDocument, options);
|
||||
}
|
||||
export type GetPipelinesQueryHookResult = ReturnType<typeof useGetPipelinesQuery>;
|
||||
export type GetPipelinesLazyQueryHookResult = ReturnType<typeof useGetPipelinesLazyQuery>;
|
||||
export type GetPipelinesQueryResult = Apollo.QueryResult<GetPipelinesQuery, GetPipelinesQueryVariables>;
|
||||
export const GetPeopleDocument = gql`
|
||||
query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) {
|
||||
people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) {
|
||||
|
@ -22,6 +22,8 @@ import {
|
||||
import { BoardItem } from '../../ui/components/board/BoardItem';
|
||||
import { NewButton } from '../../ui/components/board/BoardNewButton';
|
||||
|
||||
import { BoardCard } from './BoardCard';
|
||||
|
||||
type BoardProps = {
|
||||
initialBoard: Column[];
|
||||
items: Items;
|
||||
@ -41,8 +43,8 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<StyledBoard>
|
||||
<StyledBoard>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
{board.map((column) => (
|
||||
<Droppable key={column.id} droppableId={column.id}>
|
||||
{(droppableProvided) => (
|
||||
@ -59,7 +61,9 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
||||
>
|
||||
{(draggableProvided) => (
|
||||
<BoardItem draggableProvided={draggableProvided}>
|
||||
<p>{items[itemKey].content}</p>
|
||||
<BoardCard>
|
||||
{items[itemKey]?.id || 'Item not found'}
|
||||
</BoardCard>
|
||||
</BoardItem>
|
||||
)}
|
||||
</Draggable>
|
||||
@ -70,7 +74,7 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
||||
)}
|
||||
</Droppable>
|
||||
))}
|
||||
</StyledBoard>
|
||||
</DragDropContext>
|
||||
</DragDropContext>
|
||||
</StyledBoard>
|
||||
);
|
||||
};
|
||||
|
5
front/src/modules/opportunities/components/BoardCard.tsx
Normal file
5
front/src/modules/opportunities/components/BoardCard.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const BoardCard = styled.p`
|
||||
color: ${(props) => props.theme.text80};
|
||||
`;
|
75
front/src/modules/opportunities/hooks/useBoard.ts
Normal file
75
front/src/modules/opportunities/hooks/useBoard.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import {
|
||||
GetCompaniesQuery,
|
||||
GetPeopleQuery,
|
||||
useGetCompaniesQuery,
|
||||
useGetPeopleQuery,
|
||||
useGetPipelinesQuery,
|
||||
} from '../../../generated/graphql';
|
||||
import { BoardItemKey, Column, Items } from '../../ui/components/board/Board';
|
||||
|
||||
type Entities = GetCompaniesQuery | GetPeopleQuery;
|
||||
|
||||
function isGetCompaniesQuery(
|
||||
entities: Entities,
|
||||
): entities is GetCompaniesQuery {
|
||||
return (entities as GetCompaniesQuery).companies !== undefined;
|
||||
}
|
||||
|
||||
function isGetPeopleQuery(entities: Entities): entities is GetPeopleQuery {
|
||||
return (entities as GetPeopleQuery).people !== undefined;
|
||||
}
|
||||
|
||||
export const useBoard = () => {
|
||||
const pipelines = useGetPipelinesQuery();
|
||||
const pipelineStages = pipelines.data?.findManyPipeline[0].pipelineStages;
|
||||
const initialBoard: Column[] =
|
||||
pipelineStages?.map((pipelineStage) => ({
|
||||
id: pipelineStage.name,
|
||||
title: pipelineStage.name,
|
||||
colorCode: pipelineStage.color,
|
||||
itemKeys:
|
||||
pipelineStage.pipelineProgresses?.map(
|
||||
(item) => `item-${item.associableId}` as BoardItemKey,
|
||||
) || [],
|
||||
})) || [];
|
||||
|
||||
const pipelineEntityIds = pipelineStages?.reduce(
|
||||
(acc, pipelineStage) => [
|
||||
...acc,
|
||||
...(pipelineStage.pipelineProgresses?.map((item) => item.associableId) ||
|
||||
[]),
|
||||
],
|
||||
[] as string[],
|
||||
);
|
||||
|
||||
const pipelineEntityType: 'Person' | 'Company' | undefined =
|
||||
pipelineStages?.[0].pipelineProgresses?.[0].associableType;
|
||||
console.log(pipelineEntityType);
|
||||
|
||||
const query =
|
||||
pipelineEntityType === 'Person' ? useGetPeopleQuery : useGetCompaniesQuery;
|
||||
|
||||
const entitiesQueryResult = query({
|
||||
variables: { where: { id: { in: pipelineEntityIds } } },
|
||||
});
|
||||
|
||||
const indexByIdReducer = (acc: Items, entity: { id: string }) => ({
|
||||
...acc,
|
||||
[`item-${entity.id}`]: entity,
|
||||
});
|
||||
|
||||
const items: Items | undefined = entitiesQueryResult.data
|
||||
? isGetCompaniesQuery(entitiesQueryResult.data)
|
||||
? entitiesQueryResult.data.companies.reduce(indexByIdReducer, {} as Items)
|
||||
: isGetPeopleQuery(entitiesQueryResult.data)
|
||||
? entitiesQueryResult.data.people.reduce(indexByIdReducer, {} as Items)
|
||||
: undefined
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
initialBoard,
|
||||
items,
|
||||
loading: pipelines.loading || entitiesQueryResult.loading,
|
||||
error: pipelines.error || entitiesQueryResult.error,
|
||||
};
|
||||
};
|
19
front/src/modules/opportunities/queries/index.ts
Normal file
19
front/src/modules/opportunities/queries/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PIPELINES = gql`
|
||||
query GetPipelines {
|
||||
findManyPipeline(skip: 1) {
|
||||
id
|
||||
name
|
||||
pipelineStages {
|
||||
name
|
||||
color
|
||||
pipelineProgresses {
|
||||
id
|
||||
associableType
|
||||
associableId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
@ -7,10 +7,10 @@ export const StyledBoard = styled.div`
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export type BoardItemKey = `item-${number}`;
|
||||
export type BoardItemKey = `item-${number | string}`;
|
||||
export interface Item {
|
||||
id: string;
|
||||
content: string;
|
||||
content?: string;
|
||||
}
|
||||
export interface Items {
|
||||
[key: string]: Item;
|
||||
|
@ -2,13 +2,16 @@ import { IconTarget } from '@/ui/icons/index';
|
||||
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
||||
import { AppPage } from '~/AppPage';
|
||||
|
||||
import {
|
||||
initialBoard,
|
||||
items,
|
||||
} from '../../modules/opportunities/components/__stories__/mock-data';
|
||||
import { Board } from '../../modules/opportunities/components/Board';
|
||||
import { useBoard } from '../../modules/opportunities/hooks/useBoard';
|
||||
|
||||
export function Opportunities() {
|
||||
const { initialBoard, items, loading, error } = useBoard();
|
||||
|
||||
if (loading) return <div>Loading...</div>;
|
||||
if (error) return <div>Error...</div>;
|
||||
if (!initialBoard || !items)
|
||||
return <div>Initial board or items not found</div>;
|
||||
return (
|
||||
<AppPage>
|
||||
<WithTopBarContainer title="Opportunities" icon={<IconTarget />}>
|
||||
|
Loading…
Reference in New Issue
Block a user