From 95a1cfeec370ec754e418d2aa0d010d87d54d408 Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:15:20 +0100 Subject: [PATCH] 2426 timebox refactor board with the new scope architecture (#2789) * scoped states: wip * scoped states: wip * wip * wip * create boardFiltersScopedState and boardSortsScopedState * wip * reorganize hooks * update hooks * wip * wip * fix options dropdown * clean unused selectors * fields are working * fix filter an sort * fix entity count * rename hooks * rename states * clean unused context * fix recoil scope bug * objectNameSingular instead of objectNamePlural --- .../companies/__stories__/Board.stories.tsx | 7 +- .../board/components/CompanyBoard.tsx | 56 ++--- .../companies/components/CompanyBoardCard.tsx | 25 +-- .../components/HooksCompanyBoardEffect.tsx | 191 ++++++------------ .../components/NewOpportunityButton.tsx | 4 +- .../companies/hooks/useUpdateBoardCardIds.ts | 27 --- .../companies/states/contexts/BoardContext.ts | 13 -- .../CompanyBoardRecoilScopeContext.ts | 5 - .../hooks/useObjectRecordBoard.ts | 118 +++++++++++ .../pipeline/components/PipelineAddButton.tsx | 4 +- .../hooks/useEntitySelectSearch.ts | 5 +- .../components/RecordBoardActionBar.tsx | 4 +- .../record-board/components/RecordBoard.tsx | 91 +++++---- .../components/RecordBoardCard.tsx | 11 +- .../components/RecordBoardColumn.tsx | 184 +++++++++-------- .../RecordBoardColumnDropdownMenu.tsx | 4 +- .../RecordBoardColumnEditTitleMenu.tsx | 8 +- .../components/RecordBoardEffect.tsx | 25 +++ .../components/RecordBoardInternalEffect.tsx | 66 ++++++ .../components/RecordBoardContextMenu.tsx | 5 +- .../contexts/BoardOptionsContext.ts | 5 - .../hooks/internal}/useCreateOpportunity.ts | 12 +- ...CurrentRecordBoardCardSelectedInternal.ts} | 14 +- ...DeleteSelectedRecordBoardCardsInternal.ts} | 18 +- ...useRecordBoardActionBarEntriesInternal.ts} | 6 +- .../useRecordBoardCardFieldsInternal.ts | 73 +++++++ .../useRecordBoardColumnsInternal.ts} | 7 +- ...eRecordBoardContextMenuEntriesInternal.ts} | 6 +- .../internal/useRecordBoardScopedStates.ts | 59 ++++++ .../useRemoveRecordBoardCardIdsInternal.ts} | 20 +- .../useSetRecordBoardCardSelectedInternal.ts} | 23 ++- .../useUpdateCompanyBoardCardIdsInternal.ts | 32 +++ .../useUpdateCompanyBoardColumnsInternal.ts} | 28 ++- .../useUpdateRecordBoardCardIdsInternal.ts} | 43 +++- .../record-board/hooks/useBoardCardFields.ts | 61 ------ .../record-board/hooks/useBoardContext.ts | 7 - .../record-board/hooks/useRecordBoard.ts | 37 ++++ ...own.tsx => RecordBoardOptionsDropdown.tsx} | 26 ++- ...x => RecordBoardOptionsDropdownButton.tsx} | 2 +- ... => RecordBoardOptionsDropdownContent.tsx} | 43 ++-- .../record-board/scopes/RecordBoardScope.tsx | 23 +++ .../RecordBoardScopeInternalContext.ts | 7 + .../record-board/states/activeCardIdsState.ts | 6 - .../activeRecordBoardCardIdsScopedState.ts | 6 + ...ailableRecordBoardCardFieldsScopedState.ts | 11 + .../states/boardCardFieldsScopedState.ts | 13 -- .../boardCardIdsByColumnIdFamilyState.ts | 6 - .../record-board/states/boardColumnsState.ts | 8 - .../record-board/states/isBoardLoadedState.ts | 6 - .../states/isCardInCompactViewState.ts | 6 - .../states/isCardSelectedFamilyState.ts | 6 - .../states/isCompactViewEnabledScopedState.ts | 6 + .../states/isCompactViewEnabledState.ts | 6 - ...RecordBoardCardInCompactViewFamilyState.ts | 9 + .../isRecordBoardCardSelectedFamilyState.ts | 8 + .../states/isRecordBoardLoadedScopedState.ts | 6 + .../states/onFieldsChangeScopedState.ts | 10 + .../BoardColumnRecoilScopeContext.ts | 3 - ...ts => recordBoardCardFieldsScopedState.ts} | 4 +- ...recordBoardCardIdsByColumnIdFamilyState.ts | 9 + .../states/recordBoardColumnsScopedState.ts | 9 + .../states/recordBoardFiltersScopedState.ts | 7 + .../states/recordBoardSortsScopedState.ts | 8 + .../states/savedBoardCardFieldsFamilyState.ts | 13 -- .../states/savedBoardColumnsState.ts | 8 - .../states/savedOpportunitiesScopedState.ts | 7 + .../states/savedPipelineStepsScopedState.ts | 7 + .../savedRecordBoardCardFieldsScopedState.ts | 11 + .../savedRecordBoardColumnsScopedState.ts | 10 + .../states/savedRecordsScopedState.ts | 7 + ...sistBoardCardFieldsScopedFamilySelector.ts | 23 --- .../canPersistBoardColumnsSelector.ts | 12 -- .../hiddenBoardCardFieldsScopedSelector.ts | 22 -- ...ddenRecordBoardCardFieldsScopedSelector.ts | 22 ++ ...cordBoardCardFieldsByKeyScopedSelector.ts} | 8 +- ... recordBoardColumnTotalsFamilySelector.ts} | 10 +- ...savedBoardCardFieldsByKeyFamilySelector.ts | 16 -- .../selectors/selectedCardIdsSelector.ts | 22 -- ...electedRecordBoardCardIdsScopedSelector.ts | 26 +++ .../visibleBoardCardFieldsScopedSelector.ts | 13 -- ...ibleRecordBoardCardFieldsScopedSelector.ts | 13 ++ .../utils/getRecordBoardScopedStates.ts | 120 +++++++++++ .../src/pages/opportunities/Opportunities.tsx | 34 ++-- .../opportunitiesBoardOptions.tsx | 7 +- 84 files changed, 1204 insertions(+), 765 deletions(-) delete mode 100644 front/src/modules/companies/hooks/useUpdateBoardCardIds.ts delete mode 100644 front/src/modules/companies/states/contexts/BoardContext.ts delete mode 100644 front/src/modules/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext.ts create mode 100644 front/src/modules/object-record/hooks/useObjectRecordBoard.ts create mode 100644 front/src/modules/ui/object/record-board/components/RecordBoardEffect.tsx create mode 100644 front/src/modules/ui/object/record-board/components/RecordBoardInternalEffect.tsx delete mode 100644 front/src/modules/ui/object/record-board/contexts/BoardOptionsContext.ts rename front/src/modules/{companies/hooks => ui/object/record-board/hooks/internal}/useCreateOpportunity.ts (71%) rename front/src/modules/ui/object/record-board/hooks/{useCurrentCardSelected.ts => internal/useCurrentRecordBoardCardSelectedInternal.ts} (64%) rename front/src/modules/ui/object/record-board/hooks/{useDeleteSelectedBoardCards.ts => internal/useDeleteSelectedRecordBoardCardsInternal.ts} (65%) rename front/src/modules/ui/object/record-board/hooks/{useBoardActionBarEntries.tsx => internal/useRecordBoardActionBarEntriesInternal.ts} (69%) create mode 100644 front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardCardFieldsInternal.ts rename front/src/modules/ui/object/record-board/hooks/{useBoardColumns.ts => internal/useRecordBoardColumnsInternal.ts} (82%) rename front/src/modules/ui/object/record-board/hooks/{useBoardContextMenuEntries.tsx => internal/useRecordBoardContextMenuEntriesInternal.ts} (69%) create mode 100644 front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardScopedStates.ts rename front/src/modules/ui/object/record-board/hooks/{useRemoveCardIds.ts => internal/useRemoveRecordBoardCardIdsInternal.ts} (51%) rename front/src/modules/ui/object/record-board/hooks/{useSetCardSelected.ts => internal/useSetRecordBoardCardSelectedInternal.ts} (52%) create mode 100644 front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardCardIdsInternal.ts rename front/src/modules/{companies/hooks/useUpdateCompanyBoardColumns.ts => ui/object/record-board/hooks/internal/useUpdateCompanyBoardColumnsInternal.ts} (83%) rename front/src/modules/ui/object/record-board/hooks/{useUpdateBoardCardIds.ts => internal/useUpdateRecordBoardCardIdsInternal.ts} (59%) delete mode 100644 front/src/modules/ui/object/record-board/hooks/useBoardCardFields.ts delete mode 100644 front/src/modules/ui/object/record-board/hooks/useBoardContext.ts create mode 100644 front/src/modules/ui/object/record-board/hooks/useRecordBoard.ts rename front/src/modules/ui/object/record-board/options/components/{BoardOptionsDropdown.tsx => RecordBoardOptionsDropdown.tsx} (55%) rename front/src/modules/ui/object/record-board/options/components/{BoardOptionsDropdownButton.tsx => RecordBoardOptionsDropdownButton.tsx} (89%) rename front/src/modules/ui/object/record-board/options/components/{BoardOptionsDropdownContent.tsx => RecordBoardOptionsDropdownContent.tsx} (86%) create mode 100644 front/src/modules/ui/object/record-board/scopes/RecordBoardScope.tsx create mode 100644 front/src/modules/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts delete mode 100644 front/src/modules/ui/object/record-board/states/activeCardIdsState.ts create mode 100644 front/src/modules/ui/object/record-board/states/activeRecordBoardCardIdsScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/boardCardFieldsScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/boardColumnsState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/isBoardLoadedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/isCardInCompactViewState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/isCardSelectedFamilyState.ts create mode 100644 front/src/modules/ui/object/record-board/states/isCompactViewEnabledScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/isCompactViewEnabledState.ts create mode 100644 front/src/modules/ui/object/record-board/states/isRecordBoardCardInCompactViewFamilyState.ts create mode 100644 front/src/modules/ui/object/record-board/states/isRecordBoardCardSelectedFamilyState.ts create mode 100644 front/src/modules/ui/object/record-board/states/isRecordBoardLoadedScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/onFieldsChangeScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext.ts rename front/src/modules/ui/object/record-board/states/{availableBoardCardFieldsScopedState.ts => recordBoardCardFieldsScopedState.ts} (72%) create mode 100644 front/src/modules/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState.ts create mode 100644 front/src/modules/ui/object/record-board/states/recordBoardColumnsScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/recordBoardFiltersScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/recordBoardSortsScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/savedBoardCardFieldsFamilyState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/savedBoardColumnsState.ts create mode 100644 front/src/modules/ui/object/record-board/states/savedOpportunitiesScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/savedPipelineStepsScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/savedRecordBoardCardFieldsScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/savedRecordBoardColumnsScopedState.ts create mode 100644 front/src/modules/ui/object/record-board/states/savedRecordsScopedState.ts delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/canPersistBoardCardFieldsScopedFamilySelector.ts delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/canPersistBoardColumnsSelector.ts delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts create mode 100644 front/src/modules/ui/object/record-board/states/selectors/hiddenRecordBoardCardFieldsScopedSelector.ts rename front/src/modules/ui/object/record-board/states/selectors/{boardCardFieldsByKeyScopedSelector.ts => recordBoardCardFieldsByKeyScopedSelector.ts} (57%) rename front/src/modules/ui/object/record-board/states/selectors/{boardColumnTotalsFamilySelector.ts => recordBoardColumnTotalsFamilySelector.ts} (69%) delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/selectedCardIdsSelector.ts create mode 100644 front/src/modules/ui/object/record-board/states/selectors/selectedRecordBoardCardIdsScopedSelector.ts delete mode 100644 front/src/modules/ui/object/record-board/states/selectors/visibleBoardCardFieldsScopedSelector.ts create mode 100644 front/src/modules/ui/object/record-board/states/selectors/visibleRecordBoardCardFieldsScopedSelector.ts create mode 100644 front/src/modules/ui/object/record-board/utils/getRecordBoardScopedStates.ts diff --git a/front/src/modules/companies/__stories__/Board.stories.tsx b/front/src/modules/companies/__stories__/Board.stories.tsx index f264ef39f..0159b5cd6 100644 --- a/front/src/modules/companies/__stories__/Board.stories.tsx +++ b/front/src/modules/companies/__stories__/Board.stories.tsx @@ -5,17 +5,12 @@ import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; import { CompanyBoard } from '../board/components/CompanyBoard'; -import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; const meta: Meta = { title: 'Modules/Companies/Board', component: CompanyBoard, decorators: [ - (Story) => ( - - - - ), + (Story) => , ComponentWithRouterDecorator, SnackBarDecorator, ], diff --git a/front/src/modules/companies/board/components/CompanyBoard.tsx b/front/src/modules/companies/board/components/CompanyBoard.tsx index 845729d78..a1cd01747 100644 --- a/front/src/modules/companies/board/components/CompanyBoard.tsx +++ b/front/src/modules/companies/board/components/CompanyBoard.tsx @@ -1,21 +1,17 @@ import styled from '@emotion/styled'; -import { BoardContext } from '@/companies/states/contexts/BoardContext'; import { mapBoardFieldDefinitionsToViewFields } from '@/companies/utils/mapBoardFieldDefinitionsToViewFields'; -import { RecordBoardActionBar } from '@/ui/object/record-board/action-bar/components/RecordBoardActionBar'; -import { BoardOptionsDropdownId } from '@/ui/object/record-board/components/constants/BoardOptionsDropdownId'; import { RecordBoard, RecordBoardProps, } from '@/ui/object/record-board/components/RecordBoard'; -import { RecordBoardContextMenu } from '@/ui/object/record-board/context-menu/components/RecordBoardContextMenu'; -import { BoardOptionsDropdown } from '@/ui/object/record-board/options/components/BoardOptionsDropdown'; +import { RecordBoardEffect } from '@/ui/object/record-board/components/RecordBoardEffect'; +import { RecordBoardOptionsDropdown } from '@/ui/object/record-board/options/components/RecordBoardOptionsDropdown'; import { ViewBar } from '@/views/components/ViewBar'; import { useViewFields } from '@/views/hooks/internal/useViewFields'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; import { HooksCompanyBoardEffect } from '../../components/HooksCompanyBoardEffect'; -import { CompanyBoardRecoilScopeContext } from '../../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; const StyledContainer = styled.div` display: flex; @@ -36,34 +32,38 @@ export const CompanyBoard = ({ onEditColumnTitle, }: CompanyBoardProps) => { const viewBarId = 'company-board-view'; + const recordBoardId = 'company-board'; const { persistViewFields } = useViewFields(viewBarId); return ( - { - persistViewFields(mapBoardFieldDefinitionsToViewFields(fields)); - }, + + } + optionsDropdownScopeId={recordBoardId} + /> + + + { + persistViewFields(mapBoardFieldDefinitionsToViewFields(fields)); }} - > - } - optionsDropdownScopeId={BoardOptionsDropdownId} - /> - - - - - + /> + + ); }; diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index 042a5090a..72bff6c56 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -1,6 +1,6 @@ import { ReactNode, useContext } from 'react'; import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { EntityChipVariant } from '@/ui/display/chip/components/EntityChip'; @@ -9,15 +9,12 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox'; import { FieldContext } from '@/ui/object/field/contexts/FieldContext'; import { BoardCardIdContext } from '@/ui/object/record-board/contexts/BoardCardIdContext'; -import { useBoardContext } from '@/ui/object/record-board/hooks/useBoardContext'; -import { useCurrentCardSelected } from '@/ui/object/record-board/hooks/useCurrentCardSelected'; -import { isCardInCompactViewState } from '@/ui/object/record-board/states/isCardInCompactViewState'; -import { isCompactViewEnabledState } from '@/ui/object/record-board/states/isCompactViewEnabledState'; -import { visibleBoardCardFieldsScopedSelector } from '@/ui/object/record-board/states/selectors/visibleBoardCardFieldsScopedSelector'; +import { useCurrentRecordBoardCardSelectedInternal } from '@/ui/object/record-board/hooks/internal/useCurrentRecordBoardCardSelectedInternal'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { isRecordBoardCardInCompactViewFamilyState } from '@/ui/object/record-board/states/isRecordBoardCardInCompactViewFamilyState'; import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/RecordInlineCell'; import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut'; -import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { getLogoUrlFromDomainName } from '~/utils'; import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState'; @@ -125,30 +122,28 @@ const StyledCompactIconContainer = styled.div` `; export const CompanyBoardCard = () => { - const { BoardRecoilScopeContext } = useBoardContext(); - const { isCurrentCardSelected, setCurrentCardSelected } = - useCurrentCardSelected(); + useCurrentRecordBoardCardSelectedInternal(); const boardCardId = useContext(BoardCardIdContext); const [companyProgress] = useRecoilState( companyProgressesFamilyState(boardCardId ?? ''), ); + const { isCompactViewEnabledState, visibleBoardCardFieldsSelector } = + useRecordBoardScopedStates(); + const [isCompactViewEnabled] = useRecoilState(isCompactViewEnabledState); const [isCardInCompactView, setIsCardInCompactView] = useRecoilState( - isCardInCompactViewState(boardCardId ?? ''), + isRecordBoardCardInCompactViewFamilyState(boardCardId ?? ''), ); const showCompactView = isCompactViewEnabled && isCardInCompactView; const { opportunity, company } = companyProgress ?? {}; - const visibleBoardCardFields = useRecoilScopedValue( - visibleBoardCardFieldsScopedSelector, - BoardRecoilScopeContext, - ); + const visibleBoardCardFields = useRecoilValue(visibleBoardCardFieldsSelector); const useUpdateOneRecordMutation: () => [(params: any) => any, any] = () => { const { updateOneRecord: updateOneOpportunity } = useUpdateOneRecord({ diff --git a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx index b29e2962d..a8277fd3a 100644 --- a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx +++ b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx @@ -1,64 +1,36 @@ -import { useCallback, useEffect, useState } from 'react'; -import { useRecoilState, useRecoilValue } from 'recoil'; +import { useEffect } from 'react'; +import { useRecoilValue } from 'recoil'; -import { Company } from '@/companies/types/Company'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { PaginatedRecordTypeResults } from '@/object-record/types/PaginatedRecordTypeResults'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; -import { Opportunity } from '@/pipeline/types/Opportunity'; -import { PipelineStep } from '@/pipeline/types/PipelineStep'; -import { turnFiltersIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClause'; -import { turnSortsIntoOrderBy } from '@/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderBy'; -import { useBoardActionBarEntries } from '@/ui/object/record-board/hooks/useBoardActionBarEntries'; -import { useBoardContext } from '@/ui/object/record-board/hooks/useBoardContext'; -import { useBoardContextMenuEntries } from '@/ui/object/record-board/hooks/useBoardContextMenuEntries'; -import { availableBoardCardFieldsScopedState } from '@/ui/object/record-board/states/availableBoardCardFieldsScopedState'; -import { boardCardFieldsScopedState } from '@/ui/object/record-board/states/boardCardFieldsScopedState'; -import { isBoardLoadedState } from '@/ui/object/record-board/states/isBoardLoadedState'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { availableRecordBoardCardFieldsScopedState } from '@/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState'; +import { recordBoardCardFieldsScopedState } from '@/ui/object/record-board/states/recordBoardCardFieldsScopedState'; +import { recordBoardFiltersScopedState } from '@/ui/object/record-board/states/recordBoardFiltersScopedState'; +import { recordBoardSortsScopedState } from '@/ui/object/record-board/states/recordBoardSortsScopedState'; import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewBar } from '@/views/hooks/useViewBar'; import { ViewType } from '@/views/types/ViewType'; import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions'; -import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; -import { isDefined } from '~/utils/isDefined'; - -import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds'; -import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns'; type HooksCompanyBoardEffectProps = { viewBarId: string; + recordBoardId: string; }; export const HooksCompanyBoardEffect = ({ viewBarId, + recordBoardId, }: HooksCompanyBoardEffectProps) => { const { setAvailableFilterDefinitions, setAvailableSortDefinitions, setAvailableFieldDefinitions, - setEntityCountInCurrentView, setViewObjectMetadataId, setViewType, - } = useViewBar({ viewBarId: viewBarId }); - - const { - currentViewFieldsState, - currentViewFiltersState, - currentViewSortsState, - } = useViewScopedStates({ viewScopeId: viewBarId }); - - const [pipelineSteps, setPipelineSteps] = useState([]); - const [opportunities, setOpportunities] = useState([]); - const [companies, setCompanies] = useState([]); - - const currentViewFields = useRecoilValue(currentViewFieldsState); - const currentViewFilters = useRecoilValue(currentViewFiltersState); - const currentViewSorts = useRecoilValue(currentViewSortsState); + } = useViewBar({ viewBarId }); const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular: 'opportunity', @@ -67,88 +39,11 @@ export const HooksCompanyBoardEffect = ({ const { columnDefinitions, filterDefinitions, sortDefinitions } = useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - const [, setIsBoardLoaded] = useRecoilState(isBoardLoadedState); - - const { BoardRecoilScopeContext } = useBoardContext(); - - const [, setBoardCardFields] = useRecoilScopedState( - boardCardFieldsScopedState, - BoardRecoilScopeContext, - ); - - const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds(); - const updateCompanyBoard = useUpdateCompanyBoard(); - const setAvailableBoardCardFields = useSetRecoilScopedStateV2( - availableBoardCardFieldsScopedState, + availableRecordBoardCardFieldsScopedState, 'company-board-view', ); - useFindManyRecords({ - objectNameSingular: 'pipelineStep', - filter: {}, - onCompleted: useCallback( - (data: PaginatedRecordTypeResults) => { - setPipelineSteps(data.edges.map((edge) => edge.node)); - }, - [], - ), - }); - - const filter = turnFiltersIntoWhereClause( - mapViewFiltersToFilters(currentViewFilters), - objectMetadataItem?.fields ?? [], - ); - - const orderBy = turnSortsIntoOrderBy( - mapViewSortsToSorts(currentViewSorts), - objectMetadataItem?.fields ?? [], - ); - - const { fetchMoreRecords: fetchMoreOpportunities } = useFindManyRecords({ - skip: !pipelineSteps.length, - objectNameSingular: 'opportunity', - filter: filter, - orderBy: orderBy, - onCompleted: useCallback( - (data: PaginatedRecordTypeResults) => { - const pipelineProgresses: Array = data.edges.map( - (edge) => edge.node, - ); - - updateCompanyBoardCardIds(pipelineProgresses); - - setOpportunities(pipelineProgresses); - setIsBoardLoaded(true); - }, - [setIsBoardLoaded, updateCompanyBoardCardIds], - ), - }); - useEffect(() => { - if (isDefined(fetchMoreOpportunities)) { - fetchMoreOpportunities(); - } - }, [fetchMoreOpportunities]); - - const { fetchMoreRecords: fetchMoreCompanies } = useFindManyRecords({ - skip: !opportunities.length, - objectNameSingular: 'company', - filter: { - id: { - in: opportunities.map((opportunity) => opportunity.companyId || ''), - }, - }, - onCompleted: useCallback((data: PaginatedRecordTypeResults) => { - setCompanies(data.edges.map((edge) => edge.node)); - }, []), - }); - - useEffect(() => { - if (isDefined(fetchMoreCompanies)) { - fetchMoreCompanies(); - } - }, [fetchMoreCompanies]); - useEffect(() => { if (!objectMetadataItem) { return; @@ -182,26 +77,30 @@ export const HooksCompanyBoardEffect = ({ setViewType?.(ViewType.Kanban); }, [objectMetadataItem, setViewObjectMetadataId, setViewType]); - const { setActionBarEntries } = useBoardActionBarEntries(); - const { setContextMenuEntries } = useBoardContextMenuEntries(); + const { + currentViewFieldsState, + currentViewFiltersState, + currentViewSortsState, + } = useViewScopedStates({ viewScopeId: viewBarId }); - useEffect(() => { - if (opportunities && companies) { - setActionBarEntries(); - setContextMenuEntries(); + const currentViewFields = useRecoilValue(currentViewFieldsState); + const currentViewFilters = useRecoilValue(currentViewFiltersState); + const currentViewSorts = useRecoilValue(currentViewSortsState); - updateCompanyBoard(pipelineSteps, opportunities, companies); - setEntityCountInCurrentView(opportunities.length); - } - }, [ - companies, - opportunities, - pipelineSteps, - setActionBarEntries, - setContextMenuEntries, - setEntityCountInCurrentView, - updateCompanyBoard, - ]); + //TODO: Modify to use scopeId + const setBoardCardFields = useSetRecoilScopedStateV2( + recordBoardCardFieldsScopedState, + 'company-board', + ); + const setBoardCardFilters = useSetRecoilScopedStateV2( + recordBoardFiltersScopedState, + 'company-board', + ); + + const setBoardCardSorts = useSetRecoilScopedStateV2( + recordBoardSortsScopedState, + 'company-board', + ); useEffect(() => { if (currentViewFields) { @@ -214,5 +113,29 @@ export const HooksCompanyBoardEffect = ({ } }, [columnDefinitions, currentViewFields, setBoardCardFields]); + useEffect(() => { + if (currentViewFilters) { + setBoardCardFilters(currentViewFilters); + } + }, [currentViewFilters, setBoardCardFilters]); + + useEffect(() => { + if (currentViewSorts) { + setBoardCardSorts(currentViewSorts); + } + }, [currentViewSorts, setBoardCardSorts]); + + const { setEntityCountInCurrentView } = useViewBar({ viewBarId }); + + const { savedOpportunitiesState } = useRecordBoardScopedStates({ + recordBoardScopeId: recordBoardId, + }); + + const savedOpportunities = useRecoilValue(savedOpportunitiesState); + + useEffect(() => { + setEntityCountInCurrentView(savedOpportunities.length); + }, [savedOpportunities.length, setEntityCountInCurrentView]); + return <>; }; diff --git a/front/src/modules/companies/components/NewOpportunityButton.tsx b/front/src/modules/companies/components/NewOpportunityButton.tsx index 69a6b2e96..a1f54e93e 100644 --- a/front/src/modules/companies/components/NewOpportunityButton.tsx +++ b/front/src/modules/companies/components/NewOpportunityButton.tsx @@ -1,7 +1,6 @@ import { useCallback, useContext, useState } from 'react'; import { useQuery } from '@apollo/client'; -import { useCreateOpportunity } from '@/companies/hooks/useCreateOpportunity'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; @@ -11,6 +10,7 @@ import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picke import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { NewButton } from '@/ui/object/record-board/components/NewButton'; import { BoardColumnContext } from '@/ui/object/record-board/contexts/BoardColumnContext'; +import { useCreateOpportunity } from '@/ui/object/record-board/hooks/internal/useCreateOpportunity'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; @@ -21,7 +21,7 @@ export const NewOpportunityButton = () => { const pipelineStepId = column?.columnDefinition.id || ''; const { enqueueSnackBar } = useSnackBar(); - const { createOpportunity } = useCreateOpportunity(); + const createOpportunity = useCreateOpportunity(); const { goBackToPreviousHotkeyScope, diff --git a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts b/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts deleted file mode 100644 index 7939f3df5..000000000 --- a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { useRecoilCallback } from 'recoil'; - -import { Opportunity } from '@/pipeline/types/Opportunity'; -import { boardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState'; -import { boardColumnsState } from '@/ui/object/record-board/states/boardColumnsState'; - -export const useUpdateCompanyBoardCardIds = () => - useRecoilCallback( - ({ snapshot, set }) => - (pipelineProgresses: Pick[]) => { - const boardColumns = snapshot - .getLoadable(boardColumnsState) - .valueOrThrow(); - - for (const boardColumn of boardColumns) { - const boardCardIds = pipelineProgresses - .filter( - (pipelineProgressToFilter) => - pipelineProgressToFilter.pipelineStepId === boardColumn.id, - ) - .map((pipelineProgress) => pipelineProgress.id); - - set(boardCardIdsByColumnIdFamilyState(boardColumn.id), boardCardIds); - } - }, - [], - ); diff --git a/front/src/modules/companies/states/contexts/BoardContext.ts b/front/src/modules/companies/states/contexts/BoardContext.ts deleted file mode 100644 index b13b67213..000000000 --- a/front/src/modules/companies/states/contexts/BoardContext.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext } from 'react'; - -import { RecoilScopeContext } from '@/types/RecoilScopeContext'; -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { BoardFieldDefinition } from '@/ui/object/record-board/types/BoardFieldDefinition'; - -export const BoardContext = createContext<{ - BoardRecoilScopeContext: RecoilScopeContext; - onFieldsChange: (fields: BoardFieldDefinition[]) => void; -}>({ - BoardRecoilScopeContext: createContext(null), - onFieldsChange: () => {}, -}); diff --git a/front/src/modules/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext.ts b/front/src/modules/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext.ts deleted file mode 100644 index 34cf8c703..000000000 --- a/front/src/modules/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -export const CompanyBoardRecoilScopeContext = createContext( - null, -); diff --git a/front/src/modules/object-record/hooks/useObjectRecordBoard.ts b/front/src/modules/object-record/hooks/useObjectRecordBoard.ts new file mode 100644 index 000000000..22274111c --- /dev/null +++ b/front/src/modules/object-record/hooks/useObjectRecordBoard.ts @@ -0,0 +1,118 @@ +import { useCallback } from 'react'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; + +import { Company } from '@/companies/types/Company'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { PaginatedRecordTypeResults } from '@/object-record/types/PaginatedRecordTypeResults'; +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; +import { turnFiltersIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClause'; +import { turnSortsIntoOrderBy } from '@/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderBy'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { useUpdateCompanyBoardCardIdsInternal } from '@/ui/object/record-board/hooks/internal/useUpdateCompanyBoardCardIdsInternal'; + +import { useFindManyRecords } from './useFindManyRecords'; + +export const useObjectRecordBoard = () => { + const objectNameSingular = 'opportunity'; + const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIdsInternal(); + + const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem( + { + objectNameSingular, + }, + ); + + const { + isBoardLoadedState, + boardFiltersState, + boardSortsState, + savedCompaniesState, + savedOpportunitiesState, + savedPipelineStepsState, + } = useRecordBoardScopedStates(); + + const setIsBoardLoaded = useSetRecoilState(isBoardLoadedState); + + const boardFilters = useRecoilValue(boardFiltersState); + const boardSorts = useRecoilValue(boardSortsState); + + const setSavedCompanies = useSetRecoilState(savedCompaniesState); + + const [savedOpportunities, setSavedOpportunities] = useRecoilState( + savedOpportunitiesState, + ); + + const [savedPipelineSteps, setSavedPipelineSteps] = useRecoilState( + savedPipelineStepsState, + ); + + const filter = turnFiltersIntoWhereClause( + boardFilters, + foundObjectMetadataItem?.fields ?? [], + ); + const orderBy = turnSortsIntoOrderBy( + boardSorts, + foundObjectMetadataItem?.fields ?? [], + ); + + useFindManyRecords({ + objectNameSingular: 'pipelineStep', + filter: {}, + onCompleted: useCallback( + (data: PaginatedRecordTypeResults) => { + setSavedPipelineSteps(data.edges.map((edge) => edge.node)); + }, + [setSavedPipelineSteps], + ), + }); + + const { + records: opportunities, + loading, + fetchMoreRecords: fetchMoreOpportunities, + } = useFindManyRecords({ + skip: !savedPipelineSteps.length, + objectNameSingular: 'opportunity', + filter: filter, + orderBy: orderBy, + onCompleted: useCallback( + (data: PaginatedRecordTypeResults) => { + const pipelineProgresses: Array = data.edges.map( + (edge) => edge.node, + ); + + updateCompanyBoardCardIds(pipelineProgresses); + + setSavedOpportunities(pipelineProgresses); + setIsBoardLoaded(true); + }, + [setIsBoardLoaded, setSavedOpportunities, updateCompanyBoardCardIds], + ), + }); + + const { fetchMoreRecords: fetchMoreCompanies } = useFindManyRecords({ + skip: !savedOpportunities.length, + objectNameSingular: 'company', + filter: { + id: { + in: savedOpportunities.map( + (opportunity) => opportunity.companyId || '', + ), + }, + }, + onCompleted: useCallback( + (data: PaginatedRecordTypeResults) => { + setSavedCompanies(data.edges.map((edge) => edge.node)); + }, + [setSavedCompanies], + ), + }); + + return { + opportunities, + loading, + fetchMoreOpportunities, + fetchMoreCompanies, + }; +}; diff --git a/front/src/modules/pipeline/components/PipelineAddButton.tsx b/front/src/modules/pipeline/components/PipelineAddButton.tsx index db310b101..10ce43797 100644 --- a/front/src/modules/pipeline/components/PipelineAddButton.tsx +++ b/front/src/modules/pipeline/components/PipelineAddButton.tsx @@ -1,5 +1,4 @@ import { OpportunityPicker } from '@/companies/components/OpportunityPicker'; -import { useCreateOpportunity } from '@/companies/hooks/useCreateOpportunity'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { IconPlus } from '@/ui/display/icon/index'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; @@ -9,6 +8,7 @@ import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/Rela import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; +import { useCreateOpportunity } from '@/ui/object/record-board/hooks/internal/useCreateOpportunity'; import { logError } from '~/utils/logError'; export const PipelineAddButton = () => { @@ -18,7 +18,7 @@ export const PipelineAddButton = () => { dropdownScopeId: 'add-pipeline-progress', }); - const { createOpportunity } = useCreateOpportunity(); + const createOpportunity = useCreateOpportunity(); const handleCompanySelected = ( selectedCompany: EntityForSelect | null, diff --git a/front/src/modules/ui/input/relation-picker/hooks/useEntitySelectSearch.ts b/front/src/modules/ui/input/relation-picker/hooks/useEntitySelectSearch.ts index 551b9e7d8..134423996 100644 --- a/front/src/modules/ui/input/relation-picker/hooks/useEntitySelectSearch.ts +++ b/front/src/modules/ui/input/relation-picker/hooks/useEntitySelectSearch.ts @@ -13,7 +13,10 @@ export const useEntitySelectSearch = () => { ); const [relationPickerSearchFilter, setRelationPickerSearchFilter] = - useRecoilScopedState(relationPickerSearchFilterScopedState); + useRecoilScopedState( + relationPickerSearchFilterScopedState, + RelationPickerRecoilScopeContext, + ); const debouncedSetSearchFilter = debounce( setRelationPickerSearchFilter, diff --git a/front/src/modules/ui/object/record-board/action-bar/components/RecordBoardActionBar.tsx b/front/src/modules/ui/object/record-board/action-bar/components/RecordBoardActionBar.tsx index de16d7f02..d531f8eea 100644 --- a/front/src/modules/ui/object/record-board/action-bar/components/RecordBoardActionBar.tsx +++ b/front/src/modules/ui/object/record-board/action-bar/components/RecordBoardActionBar.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; import { ActionBar } from '@/ui/navigation/action-bar/components/ActionBar'; - -import { selectedCardIdsSelector } from '../../states/selectors/selectedCardIdsSelector'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; export const RecordBoardActionBar = () => { + const { selectedCardIdsSelector } = useRecordBoardScopedStates(); const selectedCardIds = useRecoilValue(selectedCardIdsSelector); return ; }; diff --git a/front/src/modules/ui/object/record-board/components/RecordBoard.tsx b/front/src/modules/ui/object/record-board/components/RecordBoard.tsx index 657729240..a24c47b1e 100644 --- a/front/src/modules/ui/object/record-board/components/RecordBoard.tsx +++ b/front/src/modules/ui/object/record-board/components/RecordBoard.tsx @@ -6,24 +6,26 @@ import { useRecoilValue } from 'recoil'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { Opportunity } from '@/pipeline/types/Opportunity'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; -import { BoardColumnContext } from '@/ui/object/record-board/contexts/BoardColumnContext'; -import { useSetCardSelected } from '@/ui/object/record-board/hooks/useSetCardSelected'; -import { useUpdateBoardCardIds } from '@/ui/object/record-board/hooks/useUpdateBoardCardIds'; -import { boardColumnsState } from '@/ui/object/record-board/states/boardColumnsState'; +import { RecordBoardActionBar } from '@/ui/object/record-board/action-bar/components/RecordBoardActionBar'; +import { RecordBoardInternalEffect } from '@/ui/object/record-board/components/RecordBoardInternalEffect'; +import { RecordBoardContextMenu } from '@/ui/object/record-board/context-menu/components/RecordBoardContextMenu'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { useSetRecordBoardCardSelectedInternal } from '@/ui/object/record-board/hooks/internal/useSetRecordBoardCardSelectedInternal'; +import { useUpdateRecordBoardCardIdsInternal } from '@/ui/object/record-board/hooks/internal/useUpdateRecordBoardCardIdsInternal'; +import { RecordBoardScope } from '@/ui/object/record-board/scopes/RecordBoardScope'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutsideByClassName } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { logError } from '~/utils/logError'; -import { BoardColumnRecoilScopeContext } from '../states/recoil-scope-contexts/BoardColumnRecoilScopeContext'; import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; import { BoardOptions } from '../types/BoardOptions'; import { RecordBoardColumn } from './RecordBoardColumn'; export type RecordBoardProps = { + recordBoardId: string; boardOptions: BoardOptions; onColumnAdd?: (boardColumn: BoardColumnDefinition) => void; onColumnDelete?: (boardColumnId: string) => void; @@ -54,10 +56,16 @@ const StyledBoardHeader = styled.div` `; export const RecordBoard = ({ + recordBoardId, boardOptions, onColumnDelete, onEditColumnTitle, }: RecordBoardProps) => { + const recordBoardScopeId = recordBoardId; + + const { boardColumnsState } = useRecordBoardScopedStates({ + recordBoardScopeId, + }); const boardColumns = useRecoilValue(boardColumnsState); const { updateOneRecord: updateOneOpportunity } = @@ -65,7 +73,8 @@ export const RecordBoard = ({ objectNameSingular: 'opportunity', }); - const { unselectAllActiveCards, setCardSelected } = useSetCardSelected(); + const { unselectAllActiveCards, setCardSelected } = + useSetRecordBoardCardSelectedInternal({ recordBoardScopeId }); const updatePipelineProgressStageInDB = useCallback( async (pipelineProgressId: string, pipelineStepId: string) => { @@ -85,7 +94,9 @@ export const RecordBoard = ({ callback: unselectAllActiveCards, }); - const updateBoardCardIds = useUpdateBoardCardIds(); + const updateBoardCardIds = useUpdateRecordBoardCardIdsInternal({ + recordBoardScopeId, + }); const onDragEnd: OnDragEndResponder = useCallback( async (result) => { @@ -128,41 +139,35 @@ export const RecordBoard = ({ ); return ( - - - - - - {sortedBoardColumns.map((column) => ( - - + + + + + + + + + + {sortedBoardColumns.map((column) => ( + - - - - ))} - - - - - + recordBoardColumnId={column.id} + columnDefinition={column} + recordBoardColumnTotal={sortedBoardColumns.length} + recordBoardOptions={boardOptions} + onDelete={onColumnDelete} + onTitleEdit={onEditColumnTitle} + /> + ))} + + + + + + ); }; diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardCard.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardCard.tsx index 8c99659bf..e77aa9918 100644 --- a/front/src/modules/ui/object/record-board/components/RecordBoardCard.tsx +++ b/front/src/modules/ui/object/record-board/components/RecordBoardCard.tsx @@ -4,22 +4,23 @@ import { useSetRecoilState } from 'recoil'; import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/contextMenuIsOpenState'; import { contextMenuPositionState } from '@/ui/navigation/context-menu/states/contextMenuPositionState'; -import { useCurrentCardSelected } from '../hooks/useCurrentCardSelected'; +import { useCurrentRecordBoardCardSelectedInternal } from '../hooks/internal/useCurrentRecordBoardCardSelectedInternal'; import { BoardOptions } from '../types/BoardOptions'; export const RecordBoardCard = ({ - boardOptions, + recordBoardOptions, cardId, index, }: { - boardOptions: BoardOptions; + recordBoardOptions: BoardOptions; cardId: string; index: number; }) => { const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); - const { setCurrentCardSelected } = useCurrentCardSelected(); + const { setCurrentCardSelected } = + useCurrentRecordBoardCardSelectedInternal(); const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault(); @@ -45,7 +46,7 @@ export const RecordBoardCard = ({ data-select-disable onContextMenu={handleContextMenu} > - {} + {} )} diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardColumn.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardColumn.tsx index 47c894b95..d8378dfb3 100644 --- a/front/src/modules/ui/object/record-board/components/RecordBoardColumn.tsx +++ b/front/src/modules/ui/object/record-board/components/RecordBoardColumn.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useState } from 'react'; import styled from '@emotion/styled'; import { Draggable, Droppable, DroppableProvided } from '@hello-pangea/dnd'; import { useRecoilValue } from 'recoil'; @@ -8,12 +8,12 @@ import { Tag } from '@/ui/display/tag/components/Tag'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { RecordBoardCard } from '@/ui/object/record-board/components/RecordBoardCard'; import { BoardCardIdContext } from '@/ui/object/record-board/contexts/BoardCardIdContext'; +import { BoardColumnDefinition } from '@/ui/object/record-board/types/BoardColumnDefinition'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { BoardColumnContext } from '../contexts/BoardColumnContext'; -import { boardCardIdsByColumnIdFamilyState } from '../states/boardCardIdsByColumnIdFamilyState'; -import { boardColumnTotalsFamilySelector } from '../states/selectors/boardColumnTotalsFamilySelector'; +import { recordBoardCardIdsByColumnIdFamilyState } from '../states/recordBoardCardIdsByColumnIdFamilyState'; +import { recordBoardColumnTotalsFamilySelector } from '../states/selectors/recordBoardColumnTotalsFamilySelector'; import { BoardColumnHotkeyScope } from '../types/BoardColumnHotkeyScope'; import { BoardOptions } from '../types/BoardOptions'; @@ -87,7 +87,10 @@ type BoardColumnCardsContainerProps = { }; type RecordBoardColumnProps = { - boardOptions: BoardOptions; + recordBoardColumnId: string; + columnDefinition: BoardColumnDefinition; + recordBoardOptions: BoardOptions; + recordBoardColumnTotal: number; onDelete?: (columnId: string) => void; onTitleEdit: (columnId: string, title: string, color: string) => void; }; @@ -109,12 +112,13 @@ const BoardColumnCardsContainer = ({ }; export const RecordBoardColumn = ({ - boardOptions, + recordBoardColumnId, + columnDefinition, + recordBoardOptions, + recordBoardColumnTotal, onDelete, onTitleEdit, }: RecordBoardColumnProps) => { - const column = useContext(BoardColumnContext); - const [isBoardColumnMenuOpen, setIsBoardColumnMenuOpen] = useState(false); const [isHeaderHovered, setIsHeaderHovered] = useState(false); @@ -135,96 +139,110 @@ export const RecordBoardColumn = ({ setIsBoardColumnMenuOpen(false); }; - const boardColumnId = column?.id || ''; - const boardColumnTotal = useRecoilValue( - boardColumnTotalsFamilySelector(boardColumnId), + recordBoardColumnTotalsFamilySelector(recordBoardColumnId), ); const cardIds = useRecoilValue( - boardCardIdsByColumnIdFamilyState(boardColumnId), + recordBoardCardIdsByColumnIdFamilyState(recordBoardColumnId), ); const handleTitleEdit = (title: string, color: string) => { - onTitleEdit(boardColumnId, title, color); + onTitleEdit(recordBoardColumnId, title, color); }; - if (!column) return <>; - - const { isFirstColumn, columnDefinition } = column; + const isFirstColumn = columnDefinition.position === 0; return ( - - {(droppableProvided) => ( - - setIsHeaderHovered(true)} - onMouseLeave={() => setIsHeaderHovered(false)} - > - - {!!boardColumnTotal && ( - ${boardColumnTotal} - )} - {!isHeaderHovered && ( - {cardIds.length} - )} - {isHeaderHovered && ( - - - {/* + + {(droppableProvided) => ( + + setIsHeaderHovered(true)} + onMouseLeave={() => setIsHeaderHovered(false)} + > + + {!!boardColumnTotal && ( + ${boardColumnTotal} + )} + {!isHeaderHovered && ( + {cardIds.length} + )} + {isHeaderHovered && ( + + + {/* {}} /> */} - - )} - - {isBoardColumnMenuOpen && ( - - )} - - {cardIds.map((cardId, index) => ( - - - - ))} - - {(draggableProvided) => ( -
- - {boardOptions.newCardComponent} - -
+
)} - - -
- )} -
+ + {isBoardColumnMenuOpen && ( + + )} + + {isBoardColumnMenuOpen && ( + + )} + + {cardIds.map((cardId, index) => ( + + + + ))} + + {(draggableProvided) => ( +
+ + {recordBoardOptions.newCardComponent} + +
+ )} +
+
+ + )} + + ); }; diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardColumnDropdownMenu.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardColumnDropdownMenu.tsx index b463fc715..1920b3359 100644 --- a/front/src/modules/ui/object/record-board/components/RecordBoardColumnDropdownMenu.tsx +++ b/front/src/modules/ui/object/record-board/components/RecordBoardColumnDropdownMenu.tsx @@ -12,7 +12,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { BoardColumnContext } from '../contexts/BoardColumnContext'; -import { useBoardColumns } from '../hooks/useBoardColumns'; +import { useBoardColumnsInternal } from '../hooks/internal/useRecordBoardColumnsInternal'; import { BoardColumnHotkeyScope } from '../types/BoardColumnHotkeyScope'; import { RecordBoardColumnEditTitleMenu } from './RecordBoardColumnEditTitleMenu'; @@ -43,7 +43,7 @@ export const RecordBoardColumnDropdownMenu = ({ const boardColumnMenuRef = useRef(null); - const { handleMoveBoardColumn } = useBoardColumns(); + const { handleMoveBoardColumn } = useBoardColumnsInternal(); const { setHotkeyScopeAndMemorizePreviousScope, diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardColumnEditTitleMenu.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardColumnEditTitleMenu.tsx index 7ba9aa065..3ca7f5b66 100644 --- a/front/src/modules/ui/object/record-board/components/RecordBoardColumnEditTitleMenu.tsx +++ b/front/src/modules/ui/object/record-board/components/RecordBoardColumnEditTitleMenu.tsx @@ -1,18 +1,16 @@ import { ChangeEvent, useCallback, useState } from 'react'; import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; import { IconTrash } from '@/ui/display/icon'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemSelectColor } from '@/ui/navigation/menu-item/components/MenuItemSelectColor'; +import { useRecordBoard } from '@/ui/object/record-board/hooks/useRecordBoard'; import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors'; import { textInputStyle } from '@/ui/theme/constants/effects'; import { debounce } from '~/utils/debounce'; -import { boardColumnsState } from '../states/boardColumnsState'; - const StyledEditTitleContainer = styled.div` --vertical-padding: ${({ theme }) => theme.spacing(1)}; @@ -58,7 +56,9 @@ export const RecordBoardColumnEditTitleMenu = ({ color, }: RecordBoardColumnEditTitleMenuProps) => { const [internalValue, setInternalValue] = useState(title); - const [, setBoardColumns] = useRecoilState(boardColumnsState); + + const { setBoardColumns } = useRecordBoard(); + const debouncedOnUpdateTitle = debounce( (newTitle) => onTitleEdit(newTitle, color), 200, diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardEffect.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardEffect.tsx new file mode 100644 index 000000000..1bc1995b9 --- /dev/null +++ b/front/src/modules/ui/object/record-board/components/RecordBoardEffect.tsx @@ -0,0 +1,25 @@ +import { useEffect } from 'react'; + +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { useRecordBoard } from '@/ui/object/record-board/hooks/useRecordBoard'; +import { BoardFieldDefinition } from '@/ui/object/record-board/types/BoardFieldDefinition'; + +type RecordBoardEffectProps = { + recordBoardId: string; + onFieldsChange: (fields: BoardFieldDefinition[]) => void; +}; + +export const RecordBoardEffect = ({ + recordBoardId, + onFieldsChange, +}: RecordBoardEffectProps) => { + const { setOnFieldsChange } = useRecordBoard({ + recordBoardScopeId: recordBoardId, + }); + + useEffect(() => { + setOnFieldsChange(() => onFieldsChange); + }, [onFieldsChange, setOnFieldsChange]); + + return <>; +}; diff --git a/front/src/modules/ui/object/record-board/components/RecordBoardInternalEffect.tsx b/front/src/modules/ui/object/record-board/components/RecordBoardInternalEffect.tsx new file mode 100644 index 000000000..7cbaf6c98 --- /dev/null +++ b/front/src/modules/ui/object/record-board/components/RecordBoardInternalEffect.tsx @@ -0,0 +1,66 @@ +import { useEffect } from 'react'; +import { useRecoilValue } from 'recoil'; + +import { useObjectRecordBoard } from '@/object-record/hooks/useObjectRecordBoard'; +import { useRecordBoardActionBarEntriesInternal } from '@/ui/object/record-board/hooks/internal/useRecordBoardActionBarEntriesInternal'; +import { useRecordBoardContextMenuEntriesInternal } from '@/ui/object/record-board/hooks/internal/useRecordBoardContextMenuEntriesInternal'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { useUpdateCompanyBoardColumnsInternal } from '@/ui/object/record-board/hooks/internal/useUpdateCompanyBoardColumnsInternal'; +import { isDefined } from '~/utils/isDefined'; + +export type RecordBoardInternalEffectProps = { + onFieldsChange: (fields: any) => void; +}; + +export const RecordBoardInternalEffect = ({}) => { + const updateCompanyColumnsBoardInternal = + useUpdateCompanyBoardColumnsInternal(); + const { setActionBarEntries } = useRecordBoardActionBarEntriesInternal(); + const { setContextMenuEntries } = useRecordBoardContextMenuEntriesInternal(); + + const { fetchMoreOpportunities, fetchMoreCompanies } = useObjectRecordBoard(); + + useEffect(() => { + if (isDefined(fetchMoreOpportunities)) { + fetchMoreOpportunities(); + } + }, [fetchMoreOpportunities]); + + useEffect(() => { + if (isDefined(fetchMoreCompanies)) { + fetchMoreCompanies(); + } + }, [fetchMoreCompanies]); + + const { + savedPipelineStepsState, + savedOpportunitiesState, + savedCompaniesState, + } = useRecordBoardScopedStates(); + + const savedPipelineSteps = useRecoilValue(savedPipelineStepsState); + const savedOpportunities = useRecoilValue(savedOpportunitiesState); + const savedCompanies = useRecoilValue(savedCompaniesState); + + useEffect(() => { + if (savedOpportunities && savedCompanies) { + setActionBarEntries(); + setContextMenuEntries(); + + updateCompanyColumnsBoardInternal( + savedPipelineSteps, + savedOpportunities, + savedCompanies, + ); + } + }, [ + savedCompanies, + savedOpportunities, + savedPipelineSteps, + setActionBarEntries, + setContextMenuEntries, + updateCompanyColumnsBoardInternal, + ]); + + return <>; +}; diff --git a/front/src/modules/ui/object/record-board/context-menu/components/RecordBoardContextMenu.tsx b/front/src/modules/ui/object/record-board/context-menu/components/RecordBoardContextMenu.tsx index ce2200618..6388e7013 100644 --- a/front/src/modules/ui/object/record-board/context-menu/components/RecordBoardContextMenu.tsx +++ b/front/src/modules/ui/object/record-board/context-menu/components/RecordBoardContextMenu.tsx @@ -1,11 +1,10 @@ -import React from 'react'; import { useRecoilValue } from 'recoil'; import { ContextMenu } from '@/ui/navigation/context-menu/components/ContextMenu'; - -import { selectedCardIdsSelector } from '../../states/selectors/selectedCardIdsSelector'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; export const RecordBoardContextMenu = () => { + const { selectedCardIdsSelector } = useRecordBoardScopedStates(); const selectedCardIds = useRecoilValue(selectedCardIdsSelector); return ; }; diff --git a/front/src/modules/ui/object/record-board/contexts/BoardOptionsContext.ts b/front/src/modules/ui/object/record-board/contexts/BoardOptionsContext.ts deleted file mode 100644 index 6b87907fe..000000000 --- a/front/src/modules/ui/object/record-board/contexts/BoardOptionsContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -import { BoardOptions } from '@/ui/object/record-board/types/BoardOptions'; - -export const BoardOptionsContext = createContext(null); diff --git a/front/src/modules/companies/hooks/useCreateOpportunity.ts b/front/src/modules/ui/object/record-board/hooks/internal/useCreateOpportunity.ts similarity index 71% rename from front/src/modules/companies/hooks/useCreateOpportunity.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useCreateOpportunity.ts index 03d64dbbf..c9f5b2662 100644 --- a/front/src/modules/companies/hooks/useCreateOpportunity.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useCreateOpportunity.ts @@ -3,7 +3,7 @@ import { v4 } from 'uuid'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { Opportunity } from '@/pipeline/types/Opportunity'; -import { boardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState'; +import { recordBoardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState'; export const useCreateOpportunity = () => { const { createOneRecord: createOneOpportunity } = @@ -16,10 +16,10 @@ export const useCreateOpportunity = () => { async (companyId: string, pipelineStepId: string) => { const newUuid = v4(); - set(boardCardIdsByColumnIdFamilyState(pipelineStepId), (oldValue) => [ - ...oldValue, - newUuid, - ]); + set( + recordBoardCardIdsByColumnIdFamilyState(pipelineStepId), + (oldValue) => [...oldValue, newUuid], + ); await createOneOpportunity?.({ id: newUuid, @@ -30,5 +30,5 @@ export const useCreateOpportunity = () => { [createOneOpportunity], ); - return { createOpportunity }; + return createOpportunity; }; diff --git a/front/src/modules/ui/object/record-board/hooks/useCurrentCardSelected.ts b/front/src/modules/ui/object/record-board/hooks/internal/useCurrentRecordBoardCardSelectedInternal.ts similarity index 64% rename from front/src/modules/ui/object/record-board/hooks/useCurrentCardSelected.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useCurrentRecordBoardCardSelectedInternal.ts index f6ed25afe..ed2749288 100644 --- a/front/src/modules/ui/object/record-board/hooks/useCurrentCardSelected.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useCurrentRecordBoardCardSelectedInternal.ts @@ -2,18 +2,20 @@ import { useContext } from 'react'; import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; import { actionBarOpenState } from '@/ui/navigation/action-bar/states/actionBarIsOpenState'; -import { activeCardIdsState } from '@/ui/object/record-board/states/activeCardIdsState'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; -import { BoardCardIdContext } from '../contexts/BoardCardIdContext'; -import { isCardSelectedFamilyState } from '../states/isCardSelectedFamilyState'; +import { BoardCardIdContext } from '../../contexts/BoardCardIdContext'; +import { isRecordBoardCardSelectedFamilyState } from '../../states/isRecordBoardCardSelectedFamilyState'; -export const useCurrentCardSelected = () => { +export const useCurrentRecordBoardCardSelectedInternal = () => { const currentCardId = useContext(BoardCardIdContext); const isCurrentCardSelected = useRecoilValue( - isCardSelectedFamilyState(currentCardId ?? ''), + isRecordBoardCardSelectedFamilyState(currentCardId ?? ''), ); + const { activeCardIdsState } = useRecordBoardScopedStates(); + const setActiveCardIds = useSetRecoilState(activeCardIdsState); const setCurrentCardSelected = useRecoilCallback( @@ -21,7 +23,7 @@ export const useCurrentCardSelected = () => { (selected: boolean) => { if (!currentCardId) return; - set(isCardSelectedFamilyState(currentCardId), selected); + set(isRecordBoardCardSelectedFamilyState(currentCardId), selected); set(actionBarOpenState, selected); if (selected) { diff --git a/front/src/modules/ui/object/record-board/hooks/useDeleteSelectedBoardCards.ts b/front/src/modules/ui/object/record-board/hooks/internal/useDeleteSelectedRecordBoardCardsInternal.ts similarity index 65% rename from front/src/modules/ui/object/record-board/hooks/useDeleteSelectedBoardCards.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useDeleteSelectedRecordBoardCardsInternal.ts index 59313c3de..d62cf1455 100644 --- a/front/src/modules/ui/object/record-board/hooks/useDeleteSelectedBoardCards.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useDeleteSelectedRecordBoardCardsInternal.ts @@ -3,13 +3,12 @@ import { useRecoilCallback } from 'recoil'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { Opportunity } from '@/pipeline/types/Opportunity'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; -import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector'; +import { useRemoveRecordBoardCardIdsInternal } from './useRemoveRecordBoardCardIdsInternal'; -import { useRemoveCardIds } from './useRemoveCardIds'; - -export const useDeleteSelectedBoardCards = () => { - const removeCardIds = useRemoveCardIds(); +export const useDeleteSelectedRecordBoardCardsInternal = () => { + const removeCardIds = useRemoveRecordBoardCardIdsInternal(); const apolloClient = useApolloClient(); const { deleteOneRecord: deleteOneOpportunity } = @@ -17,6 +16,8 @@ export const useDeleteSelectedBoardCards = () => { objectNameSingular: 'opportunity', }); + const { selectedCardIdsSelector } = useRecordBoardScopedStates(); + const deleteSelectedBoardCards = useRecoilCallback( ({ snapshot }) => async () => { @@ -34,7 +35,12 @@ export const useDeleteSelectedBoardCards = () => { apolloClient.cache.evict({ id: `Opportunity:${id}` }); }); }, - [apolloClient.cache, removeCardIds, deleteOneOpportunity], + [ + selectedCardIdsSelector, + removeCardIds, + deleteOneOpportunity, + apolloClient.cache, + ], ); return deleteSelectedBoardCards; diff --git a/front/src/modules/ui/object/record-board/hooks/useBoardActionBarEntries.tsx b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardActionBarEntriesInternal.ts similarity index 69% rename from front/src/modules/ui/object/record-board/hooks/useBoardActionBarEntries.tsx rename to front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardActionBarEntriesInternal.ts index 9f44688f3..45d50f560 100644 --- a/front/src/modules/ui/object/record-board/hooks/useBoardActionBarEntries.tsx +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardActionBarEntriesInternal.ts @@ -3,12 +3,12 @@ import { useSetRecoilState } from 'recoil'; import { IconTrash } from '@/ui/display/icon'; import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; -import { useDeleteSelectedBoardCards } from '@/ui/object/record-board/hooks/useDeleteSelectedBoardCards'; +import { useDeleteSelectedRecordBoardCardsInternal } from '@/ui/object/record-board/hooks/internal/useDeleteSelectedRecordBoardCardsInternal'; -export const useBoardActionBarEntries = () => { +export const useRecordBoardActionBarEntriesInternal = () => { const setActionBarEntriesRecoil = useSetRecoilState(actionBarEntriesState); - const deleteSelectedBoardCards = useDeleteSelectedBoardCards(); + const deleteSelectedBoardCards = useDeleteSelectedRecordBoardCardsInternal(); const setActionBarEntries = useCallback(() => { setActionBarEntriesRecoil([ diff --git a/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardCardFieldsInternal.ts b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardCardFieldsInternal.ts new file mode 100644 index 000000000..d40461434 --- /dev/null +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardCardFieldsInternal.ts @@ -0,0 +1,73 @@ +import { useCallback } from 'react'; +import { useRecoilCallback, useSetRecoilState } from 'recoil'; + +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; +import { onFieldsChangeScopedState } from '@/ui/object/record-board/states/onFieldsChangeScopedState'; +import { recordBoardCardFieldsScopedState } from '@/ui/object/record-board/states/recordBoardCardFieldsScopedState'; +import { savedRecordBoardCardFieldsScopedState } from '@/ui/object/record-board/states/savedRecordBoardCardFieldsScopedState'; +import { BoardFieldDefinition } from '@/ui/object/record-board/types/BoardFieldDefinition'; +import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; + +type useRecordBoardCardFieldsInternalProps = { + recordBoardScopeId?: string; +}; + +export const useRecordBoardCardFieldsInternal = ( + props?: useRecordBoardCardFieldsInternalProps, +) => { + const scopeId = useAvailableScopeIdOrThrow( + RecordBoardScopeInternalContext, + props?.recordBoardScopeId, + ); + + const setBoardCardFields = useSetRecoilState( + recordBoardCardFieldsScopedState({ scopeId }), + ); + + const setSavedBoardCardFields = useSetRecoilState( + savedRecordBoardCardFieldsScopedState({ scopeId }), + ); + + const handleFieldVisibilityChange = ( + field: Omit, 'size' | 'position'>, + ) => { + setBoardCardFields((previousFields) => + previousFields.map((previousField) => + previousField.fieldMetadataId === field.fieldMetadataId + ? { ...previousField, isVisible: !field.isVisible } + : previousField, + ), + ); + }; + + const handleFieldsChange = useRecoilCallback( + ({ snapshot }) => + async (fields: BoardFieldDefinition[]) => { + setSavedBoardCardFields(fields); + setBoardCardFields(fields); + + const onFieldsChange = snapshot + .getLoadable(onFieldsChangeScopedState({ scopeId })) + .getValue(); + + await onFieldsChange?.(fields); + }, + [scopeId, setBoardCardFields, setSavedBoardCardFields], + ); + + const handleFieldsReorder = useCallback( + async (fields: BoardFieldDefinition[]) => { + const updatedFields = fields.map((column, index) => ({ + ...column, + position: index, + })); + + await handleFieldsChange(updatedFields); + }, + [handleFieldsChange], + ); + + return { handleFieldVisibilityChange, handleFieldsReorder }; +}; diff --git a/front/src/modules/ui/object/record-board/hooks/useBoardColumns.ts b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardColumnsInternal.ts similarity index 82% rename from front/src/modules/ui/object/record-board/hooks/useBoardColumns.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardColumnsInternal.ts index 91a91f9ff..45961e6e5 100644 --- a/front/src/modules/ui/object/record-board/hooks/useBoardColumns.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardColumnsInternal.ts @@ -2,12 +2,13 @@ import { useRecoilState } from 'recoil'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { PipelineStep } from '@/pipeline/types/PipelineStep'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns'; -import { boardColumnsState } from '../states/boardColumnsState'; -import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; +import { BoardColumnDefinition } from '../../types/BoardColumnDefinition'; -export const useBoardColumns = () => { +export const useBoardColumnsInternal = () => { + const { boardColumnsState } = useRecordBoardScopedStates(); const [boardColumns, setBoardColumns] = useRecoilState(boardColumnsState); const { handleColumnMove } = useMoveViewColumns(); diff --git a/front/src/modules/ui/object/record-board/hooks/useBoardContextMenuEntries.tsx b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardContextMenuEntriesInternal.ts similarity index 69% rename from front/src/modules/ui/object/record-board/hooks/useBoardContextMenuEntries.tsx rename to front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardContextMenuEntriesInternal.ts index e0fc6a8c6..2ac5c8341 100644 --- a/front/src/modules/ui/object/record-board/hooks/useBoardContextMenuEntries.tsx +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardContextMenuEntriesInternal.ts @@ -3,14 +3,14 @@ import { useSetRecoilState } from 'recoil'; import { IconTrash } from '@/ui/display/icon'; import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; -import { useDeleteSelectedBoardCards } from '@/ui/object/record-board/hooks/useDeleteSelectedBoardCards'; +import { useDeleteSelectedRecordBoardCardsInternal } from '@/ui/object/record-board/hooks/internal/useDeleteSelectedRecordBoardCardsInternal'; -export const useBoardContextMenuEntries = () => { +export const useRecordBoardContextMenuEntriesInternal = () => { const setContextMenuEntriesRecoil = useSetRecoilState( contextMenuEntriesState, ); - const deleteSelectedBoardCards = useDeleteSelectedBoardCards(); + const deleteSelectedBoardCards = useDeleteSelectedRecordBoardCardsInternal(); const setContextMenuEntries = useCallback(() => { setContextMenuEntriesRecoil([ diff --git a/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardScopedStates.ts b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardScopedStates.ts new file mode 100644 index 000000000..5939cce41 --- /dev/null +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRecordBoardScopedStates.ts @@ -0,0 +1,59 @@ +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; +import { getRecordBoardScopedStates } from '@/ui/object/record-board/utils/getRecordBoardScopedStates'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; + +type useRecordBoardScopedStates = { + recordBoardScopeId?: string; +}; + +export const useRecordBoardScopedStates = ( + args?: useRecordBoardScopedStates, +) => { + const { recordBoardScopeId } = args ?? {}; + + const scopeId = useAvailableScopeIdOrThrow( + RecordBoardScopeInternalContext, + recordBoardScopeId, + ); + + const { + activeCardIdsState, + availableBoardCardFieldsState, + boardColumnsState, + isBoardLoadedState, + isCompactViewEnabledState, + savedBoardColumnsState, + boardFiltersState, + boardSortsState, + onFieldsChangeState, + boardCardFieldsByKeySelector, + hiddenBoardCardFieldsSelector, + selectedCardIdsSelector, + visibleBoardCardFieldsSelector, + savedCompaniesState, + savedOpportunitiesState, + savedPipelineStepsState, + } = getRecordBoardScopedStates({ + recordBoardScopeId: scopeId, + }); + + return { + scopeId, + activeCardIdsState, + availableBoardCardFieldsState, + boardColumnsState, + isBoardLoadedState, + isCompactViewEnabledState, + savedBoardColumnsState, + boardFiltersState, + boardSortsState, + onFieldsChangeState, + boardCardFieldsByKeySelector, + hiddenBoardCardFieldsSelector, + selectedCardIdsSelector, + visibleBoardCardFieldsSelector, + savedCompaniesState, + savedOpportunitiesState, + savedPipelineStepsState, + }; +}; diff --git a/front/src/modules/ui/object/record-board/hooks/useRemoveCardIds.ts b/front/src/modules/ui/object/record-board/hooks/internal/useRemoveRecordBoardCardIdsInternal.ts similarity index 51% rename from front/src/modules/ui/object/record-board/hooks/useRemoveCardIds.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useRemoveRecordBoardCardIdsInternal.ts index 739b5ab4e..ac3113d6c 100644 --- a/front/src/modules/ui/object/record-board/hooks/useRemoveCardIds.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useRemoveRecordBoardCardIdsInternal.ts @@ -1,11 +1,14 @@ // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350 import { useRecoilCallback } from 'recoil'; -import { boardCardIdsByColumnIdFamilyState } from '../states/boardCardIdsByColumnIdFamilyState'; -import { boardColumnsState } from '../states/boardColumnsState'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; -export const useRemoveCardIds = () => - useRecoilCallback( +import { recordBoardCardIdsByColumnIdFamilyState } from '../../states/recordBoardCardIdsByColumnIdFamilyState'; + +export const useRemoveRecordBoardCardIdsInternal = () => { + const { boardColumnsState } = useRecordBoardScopedStates(); + + return useRecoilCallback( ({ snapshot, set }) => (cardIdToRemove: string[]) => { const boardColumns = snapshot @@ -14,13 +17,16 @@ export const useRemoveCardIds = () => boardColumns.forEach((boardColumn) => { const columnCardIds = snapshot - .getLoadable(boardCardIdsByColumnIdFamilyState(boardColumn.id)) + .getLoadable( + recordBoardCardIdsByColumnIdFamilyState(boardColumn.id), + ) .valueOrThrow(); set( - boardCardIdsByColumnIdFamilyState(boardColumn.id), + recordBoardCardIdsByColumnIdFamilyState(boardColumn.id), columnCardIds.filter((cardId) => !cardIdToRemove.includes(cardId)), ); }); }, - [], + [boardColumnsState], ); +}; diff --git a/front/src/modules/ui/object/record-board/hooks/useSetCardSelected.ts b/front/src/modules/ui/object/record-board/hooks/internal/useSetRecordBoardCardSelectedInternal.ts similarity index 52% rename from front/src/modules/ui/object/record-board/hooks/useSetCardSelected.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useSetRecordBoardCardSelectedInternal.ts index 45344e708..7224da20c 100644 --- a/front/src/modules/ui/object/record-board/hooks/useSetCardSelected.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useSetRecordBoardCardSelectedInternal.ts @@ -1,17 +1,27 @@ import { useRecoilCallback } from 'recoil'; import { actionBarOpenState } from '@/ui/navigation/action-bar/states/actionBarIsOpenState'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { activeCardIdsState } from '../states/activeCardIdsState'; -import { isCardSelectedFamilyState } from '../states/isCardSelectedFamilyState'; +import { isRecordBoardCardSelectedFamilyState } from '../../states/isRecordBoardCardSelectedFamilyState'; + +export const useSetRecordBoardCardSelectedInternal = (props: any) => { + const scopeId = useAvailableScopeIdOrThrow( + RecordBoardScopeInternalContext, + props?.recordBoardScopeId, + ); + const { activeCardIdsState } = useRecordBoardScopedStates({ + recordBoardScopeId: scopeId, + }); -export const useSetCardSelected = () => { const setCardSelected = useRecoilCallback( ({ set, snapshot }) => (cardId: string, selected: boolean) => { const activeCardIds = snapshot.getLoadable(activeCardIdsState).contents; - set(isCardSelectedFamilyState(cardId), selected); + set(isRecordBoardCardSelectedFamilyState(cardId), selected); set(actionBarOpenState, selected || activeCardIds.length > 0); if (selected) { @@ -23,6 +33,7 @@ export const useSetCardSelected = () => { ); } }, + [activeCardIdsState], ); const unselectAllActiveCards = useRecoilCallback( @@ -31,13 +42,13 @@ export const useSetCardSelected = () => { const activeCardIds = snapshot.getLoadable(activeCardIdsState).contents; activeCardIds.forEach((cardId: string) => { - set(isCardSelectedFamilyState(cardId), false); + set(isRecordBoardCardSelectedFamilyState(cardId), false); }); set(activeCardIdsState, []); set(actionBarOpenState, false); }, - [], + [activeCardIdsState], ); return { diff --git a/front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardCardIdsInternal.ts b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardCardIdsInternal.ts new file mode 100644 index 000000000..bbe4bf101 --- /dev/null +++ b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardCardIdsInternal.ts @@ -0,0 +1,32 @@ +import { useRecoilCallback } from 'recoil'; + +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { recordBoardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState'; + +export const useUpdateCompanyBoardCardIdsInternal = () => { + const { boardColumnsState } = useRecordBoardScopedStates(); + + return useRecoilCallback( + ({ snapshot, set }) => + (pipelineProgresses: Pick[]) => { + const boardColumns = snapshot + .getLoadable(boardColumnsState) + .valueOrThrow(); + + for (const boardColumn of boardColumns) { + const boardCardIds = pipelineProgresses + .filter((pipelineProgressToFilter) => { + return pipelineProgressToFilter.pipelineStepId === boardColumn.id; + }) + .map((pipelineProgress) => pipelineProgress.id); + + set( + recordBoardCardIdsByColumnIdFamilyState(boardColumn.id), + boardCardIds, + ); + } + }, + [boardColumnsState], + ); +}; diff --git a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardColumnsInternal.ts similarity index 83% rename from front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardColumnsInternal.ts index 523ff946c..0b605b538 100644 --- a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateCompanyBoardColumnsInternal.ts @@ -4,19 +4,24 @@ import { currentPipelineStepsState } from '@/pipeline/states/currentPipelineStep import { Opportunity } from '@/pipeline/types/Opportunity'; import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; -import { boardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState'; -import { boardColumnsState } from '@/ui/object/record-board/states/boardColumnsState'; -import { savedBoardColumnsState } from '@/ui/object/record-board/states/savedBoardColumnsState'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { recordBoardCardIdsByColumnIdFamilyState } from '@/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState'; import { BoardColumnDefinition } from '@/ui/object/record-board/types/BoardColumnDefinition'; import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { logError } from '~/utils/logError'; -import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState'; -import { CompanyForBoard, CompanyProgressDict } from '../types/CompanyProgress'; +import { companyProgressesFamilyState } from '../../../../../companies/states/companyProgressesFamilyState'; +import { + CompanyForBoard, + CompanyProgressDict, +} from '../../../../../companies/types/CompanyProgress'; -export const useUpdateCompanyBoard = () => - useRecoilCallback( +export const useUpdateCompanyBoardColumnsInternal = () => { + const { boardColumnsState, savedBoardColumnsState } = + useRecordBoardScopedStates(); + + return useRecoilCallback( ({ set, snapshot }) => ( pipelineSteps: PipelineStep[], @@ -125,16 +130,19 @@ export const useUpdateCompanyBoard = () => .map((opportunity) => opportunity.id); const currentBoardCardIds = snapshot - .getLoadable(boardCardIdsByColumnIdFamilyState(boardColumn.id)) + .getLoadable( + recordBoardCardIdsByColumnIdFamilyState(boardColumn.id), + ) .valueOrThrow(); if (!isDeeplyEqual(currentBoardCardIds, boardCardIds)) { set( - boardCardIdsByColumnIdFamilyState(boardColumn.id), + recordBoardCardIdsByColumnIdFamilyState(boardColumn.id), boardCardIds, ); } } }, - [], + [boardColumnsState, savedBoardColumnsState], ); +}; diff --git a/front/src/modules/ui/object/record-board/hooks/useUpdateBoardCardIds.ts b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateRecordBoardCardIdsInternal.ts similarity index 59% rename from front/src/modules/ui/object/record-board/hooks/useUpdateBoardCardIds.ts rename to front/src/modules/ui/object/record-board/hooks/internal/useUpdateRecordBoardCardIdsInternal.ts index 3051f2715..6979cd403 100644 --- a/front/src/modules/ui/object/record-board/hooks/useUpdateBoardCardIds.ts +++ b/front/src/modules/ui/object/record-board/hooks/internal/useUpdateRecordBoardCardIdsInternal.ts @@ -1,12 +1,30 @@ import { DropResult } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350 import { useRecoilCallback } from 'recoil'; -import { boardCardIdsByColumnIdFamilyState } from '../states/boardCardIdsByColumnIdFamilyState'; -import { boardColumnsState } from '../states/boardColumnsState'; -import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -export const useUpdateBoardCardIds = () => - useRecoilCallback( +import { recordBoardCardIdsByColumnIdFamilyState } from '../../states/recordBoardCardIdsByColumnIdFamilyState'; +import { BoardColumnDefinition } from '../../types/BoardColumnDefinition'; + +type useUpdateRecordBoardCardIdsInternalProps = { + recordBoardScopeId?: string; +}; + +export const useUpdateRecordBoardCardIdsInternal = ( + props: useUpdateRecordBoardCardIdsInternalProps, +) => { + const scopeId = useAvailableScopeIdOrThrow( + RecordBoardScopeInternalContext, + props?.recordBoardScopeId, + ); + + const { boardColumnsState } = useRecordBoardScopedStates({ + recordBoardScopeId: scopeId, + }); + + return useRecoilCallback( ({ snapshot, set }) => (result: DropResult) => { const currentBoardColumns = snapshot @@ -37,14 +55,16 @@ export const useUpdateBoardCardIds = () => const sourceCardIds = [ ...snapshot - .getLoadable(boardCardIdsByColumnIdFamilyState(sourceColumn.id)) + .getLoadable( + recordBoardCardIdsByColumnIdFamilyState(sourceColumn.id), + ) .valueOrThrow(), ]; const destinationCardIds = [ ...snapshot .getLoadable( - boardCardIdsByColumnIdFamilyState(destinationColumn.id), + recordBoardCardIdsByColumnIdFamilyState(destinationColumn.id), ) .valueOrThrow(), ]; @@ -60,7 +80,7 @@ export const useUpdateBoardCardIds = () => sourceCardIds.splice(destinationIndex, 0, deletedCardId); set( - boardCardIdsByColumnIdFamilyState(sourceColumn.id), + recordBoardCardIdsByColumnIdFamilyState(sourceColumn.id), sourceCardIds, ); } else { @@ -69,17 +89,18 @@ export const useUpdateBoardCardIds = () => destinationCardIds.splice(destinationIndex, 0, removedCardId); set( - boardCardIdsByColumnIdFamilyState(sourceColumn.id), + recordBoardCardIdsByColumnIdFamilyState(sourceColumn.id), sourceCardIds, ); set( - boardCardIdsByColumnIdFamilyState(destinationColumn.id), + recordBoardCardIdsByColumnIdFamilyState(destinationColumn.id), destinationCardIds, ); } return newBoardColumns; }, - [], + [boardColumnsState], ); +}; diff --git a/front/src/modules/ui/object/record-board/hooks/useBoardCardFields.ts b/front/src/modules/ui/object/record-board/hooks/useBoardCardFields.ts deleted file mode 100644 index 5b0a43846..000000000 --- a/front/src/modules/ui/object/record-board/hooks/useBoardCardFields.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { useCallback } from 'react'; - -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; -import { savedBoardCardFieldsFamilyState } from '@/ui/object/record-board/states/savedBoardCardFieldsFamilyState'; -import { BoardFieldDefinition } from '@/ui/object/record-board/types/BoardFieldDefinition'; -import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition'; -import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; - -import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState'; - -import { useBoardContext } from './useBoardContext'; - -export const useBoardCardFields = () => { - const { BoardRecoilScopeContext, onFieldsChange } = useBoardContext(); - - const [, setBoardCardFields] = useRecoilScopedState( - boardCardFieldsScopedState, - BoardRecoilScopeContext, - ); - - const [, setSavedBoardCardFields] = useRecoilScopedState( - savedBoardCardFieldsFamilyState, - BoardRecoilScopeContext, - ); - - const handleFieldVisibilityChange = ( - field: Omit, 'size' | 'position'>, - ) => { - setBoardCardFields((previousFields) => - previousFields.map((previousField) => - previousField.fieldMetadataId === field.fieldMetadataId - ? { ...previousField, isVisible: !field.isVisible } - : previousField, - ), - ); - }; - - const handleFieldsChange = useCallback( - async (fields: BoardFieldDefinition[]) => { - setSavedBoardCardFields(fields); - setBoardCardFields(fields); - - await onFieldsChange?.(fields); - }, - [setBoardCardFields, setSavedBoardCardFields, onFieldsChange], - ); - - const handleFieldsReorder = useCallback( - async (fields: BoardFieldDefinition[]) => { - const updatedFields = fields.map((column, index) => ({ - ...column, - position: index, - })); - - await handleFieldsChange(updatedFields); - }, - [handleFieldsChange], - ); - - return { handleFieldVisibilityChange, handleFieldsReorder }; -}; diff --git a/front/src/modules/ui/object/record-board/hooks/useBoardContext.ts b/front/src/modules/ui/object/record-board/hooks/useBoardContext.ts deleted file mode 100644 index 4c3b158e1..000000000 --- a/front/src/modules/ui/object/record-board/hooks/useBoardContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useContext } from 'react'; - -import { BoardContext } from '@/companies/states/contexts/BoardContext'; - -export const useBoardContext = () => { - return useContext(BoardContext); -}; diff --git a/front/src/modules/ui/object/record-board/hooks/useRecordBoard.ts b/front/src/modules/ui/object/record-board/hooks/useRecordBoard.ts new file mode 100644 index 000000000..3d794cc0c --- /dev/null +++ b/front/src/modules/ui/object/record-board/hooks/useRecordBoard.ts @@ -0,0 +1,37 @@ +import { useSetRecoilState } from 'recoil'; + +import { useCreateOpportunity } from '@/ui/object/record-board/hooks/internal/useCreateOpportunity'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; + +type useRecordBoardProps = { + recordBoardScopeId?: string; +}; + +export const useRecordBoard = (props?: useRecordBoardProps) => { + const scopeId = useAvailableScopeIdOrThrow( + RecordBoardScopeInternalContext, + props?.recordBoardScopeId, + ); + + const { isBoardLoadedState, boardColumnsState, onFieldsChangeState } = + useRecordBoardScopedStates({ + recordBoardScopeId: scopeId, + }); + const setIsBoardLoaded = useSetRecoilState(isBoardLoadedState); + + const setBoardColumns = useSetRecoilState(boardColumnsState); + + const createOpportunity = useCreateOpportunity(); + + const setOnFieldsChange = useSetRecoilState(onFieldsChangeState); + + return { + scopeId, + setIsBoardLoaded, + setBoardColumns, + createOpportunity, + setOnFieldsChange, + }; +}; diff --git a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdown.tsx b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdown.tsx similarity index 55% rename from front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdown.tsx rename to front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdown.tsx index 40be878b0..35ff237a2 100644 --- a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdown.tsx +++ b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdown.tsx @@ -5,28 +5,32 @@ import { DropdownScope } from '../../../../layout/dropdown/scopes/DropdownScope' import { BoardOptionsDropdownId } from '../../components/constants/BoardOptionsDropdownId'; import { BoardOptionsHotkeyScope } from '../../types/BoardOptionsHotkeyScope'; -import { BoardOptionsDropdownButton } from './BoardOptionsDropdownButton'; +import { RecordBoardOptionsDropdownButton } from './RecordBoardOptionsDropdownButton'; import { - BoardOptionsDropdownContent, - BoardOptionsDropdownContentProps, -} from './BoardOptionsDropdownContent'; + RecordBoardOptionsDropdownContent, + RecordBoardOptionsDropdownContentProps, +} from './RecordBoardOptionsDropdownContent'; -type BoardOptionsDropdownProps = Pick< - BoardOptionsDropdownContentProps, - 'onStageAdd' +type RecordBoardOptionsDropdownProps = Pick< + RecordBoardOptionsDropdownContentProps, + 'onStageAdd' | 'recordBoardId' >; -export const BoardOptionsDropdown = ({ +export const RecordBoardOptionsDropdown = ({ onStageAdd, -}: BoardOptionsDropdownProps) => { + recordBoardId, +}: RecordBoardOptionsDropdownProps) => { const { setViewEditMode } = useViewBar(); return ( } + clickableComponent={} dropdownComponents={ - + } dropdownHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }} onClickOutside={() => setViewEditMode('none')} diff --git a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownButton.tsx b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownButton.tsx similarity index 89% rename from front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownButton.tsx rename to front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownButton.tsx index d578ec5da..6325b4a6b 100644 --- a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownButton.tsx +++ b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownButton.tsx @@ -1,7 +1,7 @@ import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; -export const BoardOptionsDropdownButton = () => { +export const RecordBoardOptionsDropdownButton = () => { const { isDropdownOpen, toggleDropdown } = useDropdown(); const handleClick = () => { diff --git a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownContent.tsx b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownContent.tsx similarity index 86% rename from front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownContent.tsx rename to front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownContent.tsx index e25fc4367..02d49c80f 100644 --- a/front/src/modules/ui/object/record-board/options/components/BoardOptionsDropdownContent.tsx +++ b/front/src/modules/ui/object/record-board/options/components/RecordBoardOptionsDropdownContent.tsx @@ -1,10 +1,9 @@ -import { useCallback, useContext, useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { OnDragEndResponder } from '@hello-pangea/dnd'; import { useRecoilState, useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { v4 } from 'uuid'; -import { BoardContext } from '@/companies/states/contexts/BoardContext'; import { IconBaselineDensitySmall, IconChevronLeft, @@ -21,23 +20,20 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemNavigate } from '@/ui/navigation/menu-item/components/MenuItemNavigate'; import { MenuItemToggle } from '@/ui/navigation/menu-item/components/MenuItemToggle'; +import { useRecordBoardScopedStates } from '@/ui/object/record-board/hooks/internal/useRecordBoardScopedStates'; import { ThemeColor } from '@/ui/theme/constants/colors'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewBar } from '@/views/hooks/useViewBar'; -import { useBoardCardFields } from '../../hooks/useBoardCardFields'; -import { boardColumnsState } from '../../states/boardColumnsState'; -import { isCompactViewEnabledState } from '../../states/isCompactViewEnabledState'; -import { hiddenBoardCardFieldsScopedSelector } from '../../states/selectors/hiddenBoardCardFieldsScopedSelector'; -import { visibleBoardCardFieldsScopedSelector } from '../../states/selectors/visibleBoardCardFieldsScopedSelector'; +import { useRecordBoardCardFieldsInternal } from '../../hooks/internal/useRecordBoardCardFieldsInternal'; import { BoardColumnDefinition } from '../../types/BoardColumnDefinition'; import { BoardOptionsHotkeyScope } from '../../types/BoardOptionsHotkeyScope'; -export type BoardOptionsDropdownContentProps = { +export type RecordBoardOptionsDropdownContentProps = { onStageAdd?: (boardColumn: BoardColumnDefinition) => void; + recordBoardId: string; }; type BoardOptionsMenu = 'fields' | 'stage-creation' | 'stages'; @@ -49,12 +45,12 @@ type ColumnForCreate = { title: string; }; -export const BoardOptionsDropdownContent = ({ +export const RecordBoardOptionsDropdownContent = ({ onStageAdd, -}: BoardOptionsDropdownContentProps) => { + recordBoardId, +}: RecordBoardOptionsDropdownContentProps) => { const { setViewEditMode, handleViewNameSubmit } = useViewBar(); const { viewEditModeState, currentViewSelector } = useViewScopedStates(); - const { BoardRecoilScopeContext } = useContext(BoardContext); const viewEditMode = useRecoilValue(viewEditModeState); const currentView = useRecoilValue(currentViewSelector); @@ -66,21 +62,22 @@ export const BoardOptionsDropdownContent = ({ BoardOptionsMenu | undefined >(); + const { + boardColumnsState, + isCompactViewEnabledState, + hiddenBoardCardFieldsSelector, + visibleBoardCardFieldsSelector, + } = useRecordBoardScopedStates({ recordBoardScopeId: recordBoardId }); + const [boardColumns, setBoardColumns] = useRecoilState(boardColumnsState); const [isCompactViewEnabled, setIsCompactViewEnabled] = useRecoilState( isCompactViewEnabledState, ); - const hiddenBoardCardFields = useRecoilScopedValue( - hiddenBoardCardFieldsScopedSelector, - BoardRecoilScopeContext, - ); - + const hiddenBoardCardFields = useRecoilValue(hiddenBoardCardFieldsSelector); const hasHiddenFields = hiddenBoardCardFields.length > 0; - const visibleBoardCardFields = useRecoilScopedValue( - visibleBoardCardFieldsScopedSelector, - BoardRecoilScopeContext, - ); + + const visibleBoardCardFields = useRecoilValue(visibleBoardCardFieldsSelector); const hasVisibleFields = visibleBoardCardFields.length > 0; const handleStageSubmit = () => { @@ -109,7 +106,9 @@ export const BoardOptionsDropdownContent = ({ }; const { handleFieldVisibilityChange, handleFieldsReorder } = - useBoardCardFields(); + useRecordBoardCardFieldsInternal({ + recordBoardScopeId: recordBoardId, + }); const { closeDropdown } = useDropdown(); diff --git a/front/src/modules/ui/object/record-board/scopes/RecordBoardScope.tsx b/front/src/modules/ui/object/record-board/scopes/RecordBoardScope.tsx new file mode 100644 index 000000000..586433fb3 --- /dev/null +++ b/front/src/modules/ui/object/record-board/scopes/RecordBoardScope.tsx @@ -0,0 +1,23 @@ +import { ReactNode } from 'react'; + +import { RecordBoardScopeInternalContext } from '@/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; + +type RecordBoardScopeProps = { + children: ReactNode; + recordBoardScopeId: string; +}; + +export const RecordBoardScope = ({ + children, + recordBoardScopeId, +}: RecordBoardScopeProps) => { + return ( + + {children} + + ); +}; diff --git a/front/src/modules/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts b/front/src/modules/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts new file mode 100644 index 000000000..a2d9a3999 --- /dev/null +++ b/front/src/modules/ui/object/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts @@ -0,0 +1,7 @@ +import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey'; +import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; + +type RecordBoardScopeInternalContext = ScopedStateKey; + +export const RecordBoardScopeInternalContext = + createScopeInternalContext(); diff --git a/front/src/modules/ui/object/record-board/states/activeCardIdsState.ts b/front/src/modules/ui/object/record-board/states/activeCardIdsState.ts deleted file mode 100644 index 2221ab10c..000000000 --- a/front/src/modules/ui/object/record-board/states/activeCardIdsState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil'; - -export const activeCardIdsState = atom({ - key: 'activeCardIdsState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/activeRecordBoardCardIdsScopedState.ts b/front/src/modules/ui/object/record-board/states/activeRecordBoardCardIdsScopedState.ts new file mode 100644 index 000000000..a0e788c6e --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/activeRecordBoardCardIdsScopedState.ts @@ -0,0 +1,6 @@ +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const activeRecordBoardCardIdsScopedState = createScopedState({ + key: 'activeRecordBoardCardIdsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState.ts b/front/src/modules/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState.ts new file mode 100644 index 000000000..e39361146 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState.ts @@ -0,0 +1,11 @@ +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +import { BoardFieldDefinition } from '../types/BoardFieldDefinition'; + +export const availableRecordBoardCardFieldsScopedState = createScopedState< + BoardFieldDefinition[] +>({ + key: 'availableRecordBoardCardFieldsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/boardCardFieldsScopedState.ts b/front/src/modules/ui/object/record-board/states/boardCardFieldsScopedState.ts deleted file mode 100644 index 7fbeecd43..000000000 --- a/front/src/modules/ui/object/record-board/states/boardCardFieldsScopedState.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { atomFamily } from 'recoil'; - -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; - -import { BoardFieldDefinition } from '../types/BoardFieldDefinition'; - -export const boardCardFieldsScopedState = atomFamily< - BoardFieldDefinition[], - string ->({ - key: 'boardCardFieldsScopedState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState.ts b/front/src/modules/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState.ts deleted file mode 100644 index 57253e89f..000000000 --- a/front/src/modules/ui/object/record-board/states/boardCardIdsByColumnIdFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const boardCardIdsByColumnIdFamilyState = atomFamily({ - key: 'boardCardIdsByColumnIdFamilyState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/boardColumnsState.ts b/front/src/modules/ui/object/record-board/states/boardColumnsState.ts deleted file mode 100644 index 18bfef93b..000000000 --- a/front/src/modules/ui/object/record-board/states/boardColumnsState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { atom } from 'recoil'; - -import { BoardColumnDefinition } from '@/ui/object/record-board/types/BoardColumnDefinition'; - -export const boardColumnsState = atom({ - key: 'boardColumnsState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/isBoardLoadedState.ts b/front/src/modules/ui/object/record-board/states/isBoardLoadedState.ts deleted file mode 100644 index 541c5e90e..000000000 --- a/front/src/modules/ui/object/record-board/states/isBoardLoadedState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil'; - -export const isBoardLoadedState = atom({ - key: 'isBoardLoadedState', - default: false, -}); diff --git a/front/src/modules/ui/object/record-board/states/isCardInCompactViewState.ts b/front/src/modules/ui/object/record-board/states/isCardInCompactViewState.ts deleted file mode 100644 index 58542815a..000000000 --- a/front/src/modules/ui/object/record-board/states/isCardInCompactViewState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const isCardInCompactViewState = atomFamily({ - key: 'isCardInCompactViewState', - default: true, -}); diff --git a/front/src/modules/ui/object/record-board/states/isCardSelectedFamilyState.ts b/front/src/modules/ui/object/record-board/states/isCardSelectedFamilyState.ts deleted file mode 100644 index a6402a88e..000000000 --- a/front/src/modules/ui/object/record-board/states/isCardSelectedFamilyState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atomFamily } from 'recoil'; - -export const isCardSelectedFamilyState = atomFamily({ - key: 'isCardSelectedFamilyState', - default: false, -}); diff --git a/front/src/modules/ui/object/record-board/states/isCompactViewEnabledScopedState.ts b/front/src/modules/ui/object/record-board/states/isCompactViewEnabledScopedState.ts new file mode 100644 index 000000000..4a9ab49a3 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/isCompactViewEnabledScopedState.ts @@ -0,0 +1,6 @@ +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const isCompactViewEnabledScopedState = createScopedState({ + key: 'isCompactViewEnabledScopedState', + defaultValue: false, +}); diff --git a/front/src/modules/ui/object/record-board/states/isCompactViewEnabledState.ts b/front/src/modules/ui/object/record-board/states/isCompactViewEnabledState.ts deleted file mode 100644 index 7fb7793c9..000000000 --- a/front/src/modules/ui/object/record-board/states/isCompactViewEnabledState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil'; - -export const isCompactViewEnabledState = atom({ - key: 'isCompactViewEnabledState', - default: false, -}); diff --git a/front/src/modules/ui/object/record-board/states/isRecordBoardCardInCompactViewFamilyState.ts b/front/src/modules/ui/object/record-board/states/isRecordBoardCardInCompactViewFamilyState.ts new file mode 100644 index 000000000..c19ef2b5c --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/isRecordBoardCardInCompactViewFamilyState.ts @@ -0,0 +1,9 @@ +import { atomFamily } from 'recoil'; + +export const isRecordBoardCardInCompactViewFamilyState = atomFamily< + boolean, + string +>({ + key: 'isRecordBoardCardInCompactViewFamilyState', + default: true, +}); diff --git a/front/src/modules/ui/object/record-board/states/isRecordBoardCardSelectedFamilyState.ts b/front/src/modules/ui/object/record-board/states/isRecordBoardCardSelectedFamilyState.ts new file mode 100644 index 000000000..a4d1e5536 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/isRecordBoardCardSelectedFamilyState.ts @@ -0,0 +1,8 @@ +import { atomFamily } from 'recoil'; + +export const isRecordBoardCardSelectedFamilyState = atomFamily( + { + key: 'isRecordBoardCardSelectedFamilyState', + default: false, + }, +); diff --git a/front/src/modules/ui/object/record-board/states/isRecordBoardLoadedScopedState.ts b/front/src/modules/ui/object/record-board/states/isRecordBoardLoadedScopedState.ts new file mode 100644 index 000000000..7c201cb1c --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/isRecordBoardLoadedScopedState.ts @@ -0,0 +1,6 @@ +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const isRecordBoardLoadedScopedState = createScopedState({ + key: 'isRecordBoardLoadedScopedState', + defaultValue: false, +}); diff --git a/front/src/modules/ui/object/record-board/states/onFieldsChangeScopedState.ts b/front/src/modules/ui/object/record-board/states/onFieldsChangeScopedState.ts new file mode 100644 index 000000000..de02a46d6 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/onFieldsChangeScopedState.ts @@ -0,0 +1,10 @@ +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { BoardFieldDefinition } from '@/ui/object/record-board/types/BoardFieldDefinition'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const onFieldsChangeScopedState = createScopedState< + (fields: BoardFieldDefinition[]) => void +>({ + key: 'onFieldsChangeScopedState', + defaultValue: () => {}, +}); diff --git a/front/src/modules/ui/object/record-board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext.ts b/front/src/modules/ui/object/record-board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext.ts deleted file mode 100644 index 90bfd27cb..000000000 --- a/front/src/modules/ui/object/record-board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createContext } from 'react'; - -export const BoardColumnRecoilScopeContext = createContext(null); diff --git a/front/src/modules/ui/object/record-board/states/availableBoardCardFieldsScopedState.ts b/front/src/modules/ui/object/record-board/states/recordBoardCardFieldsScopedState.ts similarity index 72% rename from front/src/modules/ui/object/record-board/states/availableBoardCardFieldsScopedState.ts rename to front/src/modules/ui/object/record-board/states/recordBoardCardFieldsScopedState.ts index 86205c5ce..94ca2d2c6 100644 --- a/front/src/modules/ui/object/record-board/states/availableBoardCardFieldsScopedState.ts +++ b/front/src/modules/ui/object/record-board/states/recordBoardCardFieldsScopedState.ts @@ -3,9 +3,9 @@ import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScope import { BoardFieldDefinition } from '../types/BoardFieldDefinition'; -export const availableBoardCardFieldsScopedState = createScopedState< +export const recordBoardCardFieldsScopedState = createScopedState< BoardFieldDefinition[] >({ - key: 'availableBoardCardFieldsScopedState', + key: 'recordBoardCardFieldsScopedState', defaultValue: [], }); diff --git a/front/src/modules/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState.ts b/front/src/modules/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState.ts new file mode 100644 index 000000000..0c462a3e6 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/recordBoardCardIdsByColumnIdFamilyState.ts @@ -0,0 +1,9 @@ +import { atomFamily } from 'recoil'; + +export const recordBoardCardIdsByColumnIdFamilyState = atomFamily< + string[], + string +>({ + key: 'recordBoardCardIdsByColumnIdFamilyState', + default: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/recordBoardColumnsScopedState.ts b/front/src/modules/ui/object/record-board/states/recordBoardColumnsScopedState.ts new file mode 100644 index 000000000..d191dd9f0 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/recordBoardColumnsScopedState.ts @@ -0,0 +1,9 @@ +import { BoardColumnDefinition } from '@/ui/object/record-board/types/BoardColumnDefinition'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const recordBoardColumnsScopedState = createScopedState< + BoardColumnDefinition[] +>({ + key: 'recordBoardColumnsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/recordBoardFiltersScopedState.ts b/front/src/modules/ui/object/record-board/states/recordBoardFiltersScopedState.ts new file mode 100644 index 000000000..d87eb4633 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/recordBoardFiltersScopedState.ts @@ -0,0 +1,7 @@ +import { Filter } from '@/ui/object/object-filter-dropdown/types/Filter'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const recordBoardFiltersScopedState = createScopedState({ + key: 'recordBoardFiltersScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/recordBoardSortsScopedState.ts b/front/src/modules/ui/object/record-board/states/recordBoardSortsScopedState.ts new file mode 100644 index 000000000..28ee2daa9 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/recordBoardSortsScopedState.ts @@ -0,0 +1,8 @@ +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +import { Sort } from '../../object-sort-dropdown/types/Sort'; + +export const recordBoardSortsScopedState = createScopedState({ + key: 'recordBoardSortsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/savedBoardCardFieldsFamilyState.ts b/front/src/modules/ui/object/record-board/states/savedBoardCardFieldsFamilyState.ts deleted file mode 100644 index 9e0656f3e..000000000 --- a/front/src/modules/ui/object/record-board/states/savedBoardCardFieldsFamilyState.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { atomFamily } from 'recoil'; - -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; - -import { BoardFieldDefinition } from '../types/BoardFieldDefinition'; - -export const savedBoardCardFieldsFamilyState = atomFamily< - BoardFieldDefinition[], - string | undefined ->({ - key: 'savedBoardCardFieldsFamilyState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/savedBoardColumnsState.ts b/front/src/modules/ui/object/record-board/states/savedBoardColumnsState.ts deleted file mode 100644 index df5f50fb8..000000000 --- a/front/src/modules/ui/object/record-board/states/savedBoardColumnsState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { atom } from 'recoil'; - -import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; - -export const savedBoardColumnsState = atom({ - key: 'savedBoardColumnsState', - default: [], -}); diff --git a/front/src/modules/ui/object/record-board/states/savedOpportunitiesScopedState.ts b/front/src/modules/ui/object/record-board/states/savedOpportunitiesScopedState.ts new file mode 100644 index 000000000..b3da8ff9d --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/savedOpportunitiesScopedState.ts @@ -0,0 +1,7 @@ +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const savedOpportunitiesScopedState = createScopedState({ + key: 'savedOpportunitiesScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/savedPipelineStepsScopedState.ts b/front/src/modules/ui/object/record-board/states/savedPipelineStepsScopedState.ts new file mode 100644 index 000000000..b9f651ed6 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/savedPipelineStepsScopedState.ts @@ -0,0 +1,7 @@ +import { PipelineStep } from '@/pipeline/types/PipelineStep'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const savedPipelineStepsScopedState = createScopedState({ + key: 'savedPipelineStepsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/savedRecordBoardCardFieldsScopedState.ts b/front/src/modules/ui/object/record-board/states/savedRecordBoardCardFieldsScopedState.ts new file mode 100644 index 000000000..ddbfe7763 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/savedRecordBoardCardFieldsScopedState.ts @@ -0,0 +1,11 @@ +import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +import { BoardFieldDefinition } from '../types/BoardFieldDefinition'; + +export const savedRecordBoardCardFieldsScopedState = createScopedState< + BoardFieldDefinition[] +>({ + key: 'savedRecordBoardCardFieldsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/savedRecordBoardColumnsScopedState.ts b/front/src/modules/ui/object/record-board/states/savedRecordBoardColumnsScopedState.ts new file mode 100644 index 000000000..e285bc94e --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/savedRecordBoardColumnsScopedState.ts @@ -0,0 +1,10 @@ +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; + +export const savedRecordBoardColumnsScopedState = createScopedState< + BoardColumnDefinition[] +>({ + key: 'savedRecordBoardColumnsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/savedRecordsScopedState.ts b/front/src/modules/ui/object/record-board/states/savedRecordsScopedState.ts new file mode 100644 index 000000000..5b6c01039 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/savedRecordsScopedState.ts @@ -0,0 +1,7 @@ +import { Company } from '@/companies/types/Company'; +import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; + +export const savedRecordsScopedState = createScopedState({ + key: 'savedRecordsScopedState', + defaultValue: [], +}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardCardFieldsScopedFamilySelector.ts b/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardCardFieldsScopedFamilySelector.ts deleted file mode 100644 index 8bfd159f5..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardCardFieldsScopedFamilySelector.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; - -import { boardCardFieldsScopedState } from '../boardCardFieldsScopedState'; -import { savedBoardCardFieldsFamilyState } from '../savedBoardCardFieldsFamilyState'; - -export const canPersistBoardCardFieldsScopedFamilySelector = selectorFamily({ - key: 'canPersistBoardCardFieldsScopedFamilySelector', - get: - ({ - recoilScopeId, - viewId, - }: { - recoilScopeId: string; - viewId: string | undefined; - }) => - ({ get }) => - !isDeeplyEqual( - get(savedBoardCardFieldsFamilyState(viewId)), - get(boardCardFieldsScopedState(recoilScopeId)), - ), -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardColumnsSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardColumnsSelector.ts deleted file mode 100644 index af24d48a2..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/canPersistBoardColumnsSelector.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { selector } from 'recoil'; - -import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; - -import { boardColumnsState } from '../boardColumnsState'; -import { savedBoardColumnsState } from '../savedBoardColumnsState'; - -export const canPersistBoardColumnsSelector = selector({ - key: 'canPersistBoardCardFieldsScopedFamilySelector', - get: ({ get }) => - !isDeeplyEqual(get(boardColumnsState), get(savedBoardColumnsState)), -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts deleted file mode 100644 index 3dae2d8e2..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { availableBoardCardFieldsScopedState } from '../availableBoardCardFieldsScopedState'; -import { boardCardFieldsScopedState } from '../boardCardFieldsScopedState'; - -export const hiddenBoardCardFieldsScopedSelector = selectorFamily({ - key: 'hiddenBoardCardFieldsScopedSelector', - get: - (scopeId: string) => - ({ get }) => { - const fields = get(boardCardFieldsScopedState(scopeId)); - const fieldKeys = fields.map(({ fieldMetadataId }) => fieldMetadataId); - const otherAvailableKeys = get( - availableBoardCardFieldsScopedState({ scopeId }), - ).filter(({ fieldMetadataId }) => !fieldKeys.includes(fieldMetadataId)); - - return [ - ...fields.filter((field) => !field.isVisible), - ...otherAvailableKeys, - ]; - }, -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/hiddenRecordBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/hiddenRecordBoardCardFieldsScopedSelector.ts new file mode 100644 index 000000000..f3c7bba35 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/selectors/hiddenRecordBoardCardFieldsScopedSelector.ts @@ -0,0 +1,22 @@ +import { createScopedSelector } from '@/ui/utilities/recoil-scope/utils/createScopedSelector'; + +import { availableRecordBoardCardFieldsScopedState } from '../availableRecordBoardCardFieldsScopedState'; +import { recordBoardCardFieldsScopedState } from '../recordBoardCardFieldsScopedState'; + +export const hiddenRecordBoardCardFieldsScopedSelector = createScopedSelector({ + key: 'hiddenRecordBoardCardFieldsScopedSelector', + get: + ({ scopeId }) => + ({ get }) => { + const fields = get(recordBoardCardFieldsScopedState({ scopeId })); + const fieldKeys = fields.map(({ fieldMetadataId }) => fieldMetadataId); + const otherAvailableKeys = get( + availableRecordBoardCardFieldsScopedState({ scopeId }), + ).filter(({ fieldMetadataId }) => !fieldKeys.includes(fieldMetadataId)); + + return [ + ...fields.filter((field) => !field.isVisible), + ...otherAvailableKeys, + ]; + }, +}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/boardCardFieldsByKeyScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/recordBoardCardFieldsByKeyScopedSelector.ts similarity index 57% rename from front/src/modules/ui/object/record-board/states/selectors/boardCardFieldsByKeyScopedSelector.ts rename to front/src/modules/ui/object/record-board/states/selectors/recordBoardCardFieldsByKeyScopedSelector.ts index cebd20e36..74ccbaaad 100644 --- a/front/src/modules/ui/object/record-board/states/selectors/boardCardFieldsByKeyScopedSelector.ts +++ b/front/src/modules/ui/object/record-board/states/selectors/recordBoardCardFieldsByKeyScopedSelector.ts @@ -3,14 +3,14 @@ import { selectorFamily } from 'recoil'; import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; import { BoardFieldDefinition } from '../../types/BoardFieldDefinition'; -import { boardCardFieldsScopedState } from '../boardCardFieldsScopedState'; +import { recordBoardCardFieldsScopedState } from '../recordBoardCardFieldsScopedState'; -export const boardCardFieldsByKeyScopedSelector = selectorFamily({ - key: 'boardCardFieldsByKeyScopedSelector', +export const recordBoardCardFieldsByKeyScopedSelector = selectorFamily({ + key: 'recordBoardCardFieldsByKeyScopedSelector', get: (scopeId: string) => ({ get }) => - get(boardCardFieldsScopedState(scopeId)).reduce< + get(recordBoardCardFieldsScopedState({ scopeId })).reduce< Record> >((result, field) => ({ ...result, [field.fieldMetadataId]: field }), {}), }); diff --git a/front/src/modules/ui/object/record-board/states/selectors/boardColumnTotalsFamilySelector.ts b/front/src/modules/ui/object/record-board/states/selectors/recordBoardColumnTotalsFamilySelector.ts similarity index 69% rename from front/src/modules/ui/object/record-board/states/selectors/boardColumnTotalsFamilySelector.ts rename to front/src/modules/ui/object/record-board/states/selectors/recordBoardColumnTotalsFamilySelector.ts index 77aca5f72..656c1f6b4 100644 --- a/front/src/modules/ui/object/record-board/states/selectors/boardColumnTotalsFamilySelector.ts +++ b/front/src/modules/ui/object/record-board/states/selectors/recordBoardColumnTotalsFamilySelector.ts @@ -2,16 +2,18 @@ import { selectorFamily } from 'recoil'; import { companyProgressesFamilyState } from '@/companies/states/companyProgressesFamilyState'; -import { boardCardIdsByColumnIdFamilyState } from '../boardCardIdsByColumnIdFamilyState'; +import { recordBoardCardIdsByColumnIdFamilyState } from '../recordBoardCardIdsByColumnIdFamilyState'; // TODO: this state should be computed during the synchronization web-hook and put in a generic // boardColumnTotalsFamilyState indexed by columnId. -export const boardColumnTotalsFamilySelector = selectorFamily({ - key: 'boardColumnTotalsFamilySelector', +export const recordBoardColumnTotalsFamilySelector = selectorFamily({ + key: 'recordBoardColumnTotalsFamilySelector', get: (pipelineStepId: string) => ({ get }) => { - const cardIds = get(boardCardIdsByColumnIdFamilyState(pipelineStepId)); + const cardIds = get( + recordBoardCardIdsByColumnIdFamilyState(pipelineStepId), + ); const opportunities = cardIds.map((opportunityId: string) => get(companyProgressesFamilyState(opportunityId)), diff --git a/front/src/modules/ui/object/record-board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts b/front/src/modules/ui/object/record-board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts deleted file mode 100644 index 891ed831f..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; - -import { BoardFieldDefinition } from '../../types/BoardFieldDefinition'; -import { savedBoardCardFieldsFamilyState } from '../savedBoardCardFieldsFamilyState'; - -export const savedBoardCardFieldsByKeyFamilySelector = selectorFamily({ - key: 'savedBoardCardFieldsByKeyFamilySelector', - get: - (viewId: string | undefined) => - ({ get }) => - get(savedBoardCardFieldsFamilyState(viewId)).reduce< - Record> - >((result, field) => ({ ...result, [field.fieldMetadataId]: field }), {}), -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/selectedCardIdsSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/selectedCardIdsSelector.ts deleted file mode 100644 index 8ea5e1c1c..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/selectedCardIdsSelector.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { selector } from 'recoil'; - -import { boardCardIdsByColumnIdFamilyState } from '../boardCardIdsByColumnIdFamilyState'; -import { boardColumnsState } from '../boardColumnsState'; -import { isCardSelectedFamilyState } from '../isCardSelectedFamilyState'; - -export const selectedCardIdsSelector = selector({ - key: 'selectedCardIdsSelector', - get: ({ get }) => { - const boardColumns = get(boardColumnsState); - - const cardIds = boardColumns.flatMap((boardColumn) => - get(boardCardIdsByColumnIdFamilyState(boardColumn.id)), - ); - - const selectedCardIds = cardIds.filter( - (cardId) => get(isCardSelectedFamilyState(cardId)) === true, - ); - - return selectedCardIds; - }, -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/selectedRecordBoardCardIdsScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/selectedRecordBoardCardIdsScopedSelector.ts new file mode 100644 index 000000000..a93e65544 --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/selectors/selectedRecordBoardCardIdsScopedSelector.ts @@ -0,0 +1,26 @@ +import { createScopedSelector } from '@/ui/utilities/recoil-scope/utils/createScopedSelector'; + +import { isRecordBoardCardSelectedFamilyState } from '../isRecordBoardCardSelectedFamilyState'; +import { recordBoardCardIdsByColumnIdFamilyState } from '../recordBoardCardIdsByColumnIdFamilyState'; +import { recordBoardColumnsScopedState } from '../recordBoardColumnsScopedState'; + +export const selectedRecordBoardCardIdsScopedSelector = createScopedSelector< + string[] +>({ + key: 'selectedRecordBoardCardIdsScopedSelector', + get: + ({ scopeId }) => + ({ get }) => { + const boardColumns = get(recordBoardColumnsScopedState({ scopeId })); + + const cardIds = boardColumns.flatMap((boardColumn) => + get(recordBoardCardIdsByColumnIdFamilyState(boardColumn.id)), + ); + + const selectedCardIds = cardIds.filter( + (cardId) => get(isRecordBoardCardSelectedFamilyState(cardId)) === true, + ); + + return selectedCardIds; + }, +}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/visibleBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/visibleBoardCardFieldsScopedSelector.ts deleted file mode 100644 index 669c2ba22..000000000 --- a/front/src/modules/ui/object/record-board/states/selectors/visibleBoardCardFieldsScopedSelector.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { boardCardFieldsScopedState } from '../boardCardFieldsScopedState'; - -export const visibleBoardCardFieldsScopedSelector = selectorFamily({ - key: 'visibleBoardCardFieldsScopedSelector', - get: - (scopeId: string) => - ({ get }) => - get(boardCardFieldsScopedState(scopeId)) - .filter((field) => field.isVisible) - .sort((a, b) => a.position - b.position), -}); diff --git a/front/src/modules/ui/object/record-board/states/selectors/visibleRecordBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/object/record-board/states/selectors/visibleRecordBoardCardFieldsScopedSelector.ts new file mode 100644 index 000000000..47ee4ac2d --- /dev/null +++ b/front/src/modules/ui/object/record-board/states/selectors/visibleRecordBoardCardFieldsScopedSelector.ts @@ -0,0 +1,13 @@ +import { createScopedSelector } from '@/ui/utilities/recoil-scope/utils/createScopedSelector'; + +import { recordBoardCardFieldsScopedState } from '../recordBoardCardFieldsScopedState'; + +export const visibleRecordBoardCardFieldsScopedSelector = createScopedSelector({ + key: 'visibleRecordBoardCardFieldsScopedSelector', + get: + ({ scopeId }) => + ({ get }) => + get(recordBoardCardFieldsScopedState({ scopeId })) + .filter((field) => field.isVisible) + .sort((a, b) => a.position - b.position), +}); diff --git a/front/src/modules/ui/object/record-board/utils/getRecordBoardScopedStates.ts b/front/src/modules/ui/object/record-board/utils/getRecordBoardScopedStates.ts new file mode 100644 index 000000000..f5617a8cc --- /dev/null +++ b/front/src/modules/ui/object/record-board/utils/getRecordBoardScopedStates.ts @@ -0,0 +1,120 @@ +import { activeRecordBoardCardIdsScopedState } from '@/ui/object/record-board/states/activeRecordBoardCardIdsScopedState'; +import { availableRecordBoardCardFieldsScopedState } from '@/ui/object/record-board/states/availableRecordBoardCardFieldsScopedState'; +import { isCompactViewEnabledScopedState } from '@/ui/object/record-board/states/isCompactViewEnabledScopedState'; +import { isRecordBoardLoadedScopedState } from '@/ui/object/record-board/states/isRecordBoardLoadedScopedState'; +import { onFieldsChangeScopedState } from '@/ui/object/record-board/states/onFieldsChangeScopedState'; +import { recordBoardColumnsScopedState } from '@/ui/object/record-board/states/recordBoardColumnsScopedState'; +import { recordBoardFiltersScopedState } from '@/ui/object/record-board/states/recordBoardFiltersScopedState'; +import { recordBoardSortsScopedState } from '@/ui/object/record-board/states/recordBoardSortsScopedState'; +import { savedOpportunitiesScopedState } from '@/ui/object/record-board/states/savedOpportunitiesScopedState'; +import { savedPipelineStepsScopedState } from '@/ui/object/record-board/states/savedPipelineStepsScopedState'; +import { savedRecordBoardColumnsScopedState } from '@/ui/object/record-board/states/savedRecordBoardColumnsScopedState'; +import { savedRecordsScopedState } from '@/ui/object/record-board/states/savedRecordsScopedState'; +import { hiddenRecordBoardCardFieldsScopedSelector } from '@/ui/object/record-board/states/selectors/hiddenRecordBoardCardFieldsScopedSelector'; +import { recordBoardCardFieldsByKeyScopedSelector } from '@/ui/object/record-board/states/selectors/recordBoardCardFieldsByKeyScopedSelector'; +import { selectedRecordBoardCardIdsScopedSelector } from '@/ui/object/record-board/states/selectors/selectedRecordBoardCardIdsScopedSelector'; +import { visibleRecordBoardCardFieldsScopedSelector } from '@/ui/object/record-board/states/selectors/visibleRecordBoardCardFieldsScopedSelector'; +import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState'; + +export const getRecordBoardScopedStates = ({ + recordBoardScopeId, +}: { + recordBoardScopeId: string; +}) => { + const activeCardIdsState = getScopedState( + activeRecordBoardCardIdsScopedState, + recordBoardScopeId, + ); + + const availableBoardCardFieldsState = getScopedState( + availableRecordBoardCardFieldsScopedState, + recordBoardScopeId, + ); + + const boardColumnsState = getScopedState( + recordBoardColumnsScopedState, + recordBoardScopeId, + ); + + const isBoardLoadedState = getScopedState( + isRecordBoardLoadedScopedState, + recordBoardScopeId, + ); + + const isCompactViewEnabledState = getScopedState( + isCompactViewEnabledScopedState, + recordBoardScopeId, + ); + + const savedBoardColumnsState = getScopedState( + savedRecordBoardColumnsScopedState, + recordBoardScopeId, + ); + + const boardFiltersState = getScopedState( + recordBoardFiltersScopedState, + recordBoardScopeId, + ); + + const boardSortsState = getScopedState( + recordBoardSortsScopedState, + recordBoardScopeId, + ); + + const savedCompaniesState = getScopedState( + savedRecordsScopedState, + recordBoardScopeId, + ); + + const savedOpportunitiesState = getScopedState( + savedOpportunitiesScopedState, + recordBoardScopeId, + ); + + const savedPipelineStepsState = getScopedState( + savedPipelineStepsScopedState, + recordBoardScopeId, + ); + + const onFieldsChangeState = getScopedState( + onFieldsChangeScopedState, + recordBoardScopeId, + ); + + // TODO: Family scoped selector + const boardCardFieldsByKeySelector = + recordBoardCardFieldsByKeyScopedSelector(recordBoardScopeId); + + const hiddenBoardCardFieldsSelector = + hiddenRecordBoardCardFieldsScopedSelector({ + scopeId: recordBoardScopeId, + }); + + const selectedCardIdsSelector = selectedRecordBoardCardIdsScopedSelector({ + scopeId: recordBoardScopeId, + }); + + const visibleBoardCardFieldsSelector = + visibleRecordBoardCardFieldsScopedSelector({ + scopeId: recordBoardScopeId, + }); + + return { + activeCardIdsState, + availableBoardCardFieldsState, + boardColumnsState, + isBoardLoadedState, + isCompactViewEnabledState, + savedBoardColumnsState, + boardFiltersState, + boardSortsState, + onFieldsChangeState, + boardCardFieldsByKeySelector, + hiddenBoardCardFieldsSelector, + selectedCardIdsSelector, + visibleBoardCardFieldsSelector, + savedCompaniesState, + savedOpportunitiesState, + savedPipelineStepsState, + }; +}; diff --git a/front/src/pages/opportunities/Opportunities.tsx b/front/src/pages/opportunities/Opportunities.tsx index 99d224f2a..0a4146a8c 100644 --- a/front/src/pages/opportunities/Opportunities.tsx +++ b/front/src/pages/opportunities/Opportunities.tsx @@ -1,7 +1,6 @@ import styled from '@emotion/styled'; import { CompanyBoard } from '@/companies/board/components/CompanyBoard'; -import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton'; import { usePipelineSteps } from '@/pipeline/hooks/usePipelineSteps'; @@ -10,9 +9,6 @@ import { IconTargetArrow } from '@/ui/display/icon'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; import { PageHeader } from '@/ui/layout/page/PageHeader'; -import { BoardOptionsContext } from '@/ui/object/record-board/contexts/BoardOptionsContext'; -import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; const StyledBoardContainer = styled.div` display: flex; @@ -45,24 +41,18 @@ export const Opportunities = () => { return ( - - - - - - - - - - - - - - + + + + + + + + ); }; diff --git a/front/src/pages/opportunities/opportunitiesBoardOptions.tsx b/front/src/pages/opportunities/opportunitiesBoardOptions.tsx index 9457b8c58..759175b11 100644 --- a/front/src/pages/opportunities/opportunitiesBoardOptions.tsx +++ b/front/src/pages/opportunities/opportunitiesBoardOptions.tsx @@ -1,8 +1,13 @@ import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard'; import { NewOpportunityButton } from '@/companies/components/NewOpportunityButton'; import { BoardOptions } from '@/ui/object/record-board/types/BoardOptions'; +import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; export const opportunitiesBoardOptions: BoardOptions = { - newCardComponent: , + newCardComponent: ( + + + + ), CardComponent: CompanyBoardCard, };