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:
Sammy Teillet 2023-06-14 10:37:44 +02:00 committed by GitHub
parent eb8fc50ff1
commit bf6fb0ba70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 166 additions and 11 deletions

View File

@ -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) {

View File

@ -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>
);
};

View File

@ -0,0 +1,5 @@
import styled from '@emotion/styled';
export const BoardCard = styled.p`
color: ${(props) => props.theme.text80};
`;

View 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,
};
};

View 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
}
}
}
}
`;

View File

@ -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;

View File

@ -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 />}>