Files
twenty_crm/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts
Charles Bochet 10febd9aeb Improve Board performances (#2626)
Improve app performances
2023-11-22 09:58:49 +01:00

137 lines
4.7 KiB
TypeScript

import { useRecoilCallback } from 'recoil';
import { currentPipelineStepsState } from '@/pipeline/states/currentPipelineStepsState';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState';
import { boardColumnsState } from '@/ui/layout/board/states/boardColumnsState';
import { savedBoardColumnsState } from '@/ui/layout/board/states/savedBoardColumnsState';
import { BoardColumnDefinition } from '@/ui/layout/board/types/BoardColumnDefinition';
import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState';
import { isThemeColor } from '@/ui/theme/utils/castStringAsThemeColor';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { logError } from '~/utils/logError';
import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState';
import { CompanyForBoard, CompanyProgressDict } from '../types/CompanyProgress';
export const useUpdateCompanyBoard = () =>
useRecoilCallback(
({ set, snapshot }) =>
(
pipelineSteps: PipelineStep[],
opportunities: Opportunity[],
companies: CompanyForBoard[],
) => {
const indexCompanyByIdReducer = (
acc: { [key: string]: CompanyForBoard },
company: CompanyForBoard,
) => ({
...acc,
[company.id]: company,
});
const companiesDict =
companies.reduce(
indexCompanyByIdReducer,
{} as { [key: string]: CompanyForBoard },
) ?? {};
const indexOpportunityByIdReducer = (
acc: CompanyProgressDict,
opportunity: Opportunity,
) => {
const company =
opportunity.companyId && companiesDict[opportunity.companyId];
if (!company) return acc;
return {
...acc,
[opportunity.id]: {
opportunity,
company,
},
};
};
const companyBoardIndex = opportunities.reduce(
indexOpportunityByIdReducer,
{} as CompanyProgressDict,
);
for (const [id, companyProgress] of Object.entries(companyBoardIndex)) {
const currentCompanyProgress = snapshot
.getLoadable(companyProgressesFamilyState(id))
.valueOrThrow();
if (!isDeeplyEqual(currentCompanyProgress, companyProgress)) {
set(companyProgressesFamilyState(id), companyProgress);
set(entityFieldsFamilyState(id), companyProgress.opportunity);
}
}
const currentPipelineSteps = snapshot
.getLoadable(currentPipelineStepsState)
.valueOrThrow();
const currentBoardColumns = snapshot
.getLoadable(boardColumnsState)
.valueOrThrow();
if (!isDeeplyEqual(pipelineSteps, currentPipelineSteps)) {
set(currentPipelineStepsState, pipelineSteps);
}
const orderedPipelineSteps = [...pipelineSteps].sort((a, b) => {
if (!a.position || !b.position) return 0;
return a.position - b.position;
});
const newBoardColumns: BoardColumnDefinition[] =
orderedPipelineSteps?.map((pipelineStep) => {
if (!isThemeColor(pipelineStep.color)) {
logError(
`Color ${pipelineStep.color} is not recognized in useUpdateCompanyBoard.`,
);
}
return {
id: pipelineStep.id,
title: pipelineStep.name,
colorCode: isThemeColor(pipelineStep.color)
? pipelineStep.color
: undefined,
position: pipelineStep.position ?? 0,
};
});
if (
currentBoardColumns.length === 0 &&
!isDeeplyEqual(newBoardColumns, currentBoardColumns)
) {
set(boardColumnsState, newBoardColumns);
set(savedBoardColumnsState, newBoardColumns);
}
for (const boardColumn of newBoardColumns) {
const boardCardIds = opportunities
.filter(
(opportunityToFilter) =>
opportunityToFilter.pipelineStepId === boardColumn.id,
)
.map((opportunity) => opportunity.id);
const currentBoardCardIds = snapshot
.getLoadable(boardCardIdsByColumnIdFamilyState(boardColumn.id))
.valueOrThrow();
if (!isDeeplyEqual(currentBoardCardIds, boardCardIds)) {
set(
boardCardIdsByColumnIdFamilyState(boardColumn.id),
boardCardIds,
);
}
}
},
[],
);