From 0d7b869274a8bf8035f263b44a729932c5415fcb Mon Sep 17 00:00:00 2001 From: brendanlaschke Date: Mon, 28 Aug 2023 18:23:28 +0200 Subject: [PATCH] Create opportunity from board column menu (#1323) - create opportunity from column menu --- .../ui/board/components/BoardColumn.tsx | 3 + .../ui/board/components/BoardColumnMenu.tsx | 84 +++++++++++++++++-- .../ui/board/components/EntityBoardColumn.tsx | 1 + 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/front/src/modules/ui/board/components/BoardColumn.tsx b/front/src/modules/ui/board/components/BoardColumn.tsx index baaffe636..17412fead 100644 --- a/front/src/modules/ui/board/components/BoardColumn.tsx +++ b/front/src/modules/ui/board/components/BoardColumn.tsx @@ -59,6 +59,7 @@ export type BoardColumnProps = { children: React.ReactNode; isFirstColumn: boolean; numChildren: number; + stageId: string; }; export function BoardColumn({ @@ -69,6 +70,7 @@ export function BoardColumn({ children, isFirstColumn, numChildren, + stageId, }: BoardColumnProps) { const [isBoardColumnMenuOpen, setIsBoardColumnMenuOpen] = React.useState(false); @@ -103,6 +105,7 @@ export function BoardColumn({ onTitleEdit={onTitleEdit} title={title} color={color} + stageId={stageId} /> )} {children} diff --git a/front/src/modules/ui/board/components/BoardColumnMenu.tsx b/front/src/modules/ui/board/components/BoardColumnMenu.tsx index 679ab1df4..3745d408e 100644 --- a/front/src/modules/ui/board/components/BoardColumnMenu.tsx +++ b/front/src/modules/ui/board/components/BoardColumnMenu.tsx @@ -1,14 +1,23 @@ import { useRef, useState } from 'react'; import styled from '@emotion/styled'; -import { IconPencil } from '@tabler/icons-react'; import { Key } from 'ts-key-enum'; +import { useCreateCompanyProgress } from '@/companies/hooks/useCreateCompanyProgress'; +import { useFilteredSearchCompanyQuery } from '@/companies/hooks/useFilteredSearchCompanyQuery'; import { DropdownMenuSelectableItem } from '@/ui/dropdown/components/DropdownMenuSelectableItem'; import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu'; import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer'; +import { IconPencil, IconPlus } from '@/ui/icon'; +import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect'; +import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState'; +import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; +import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; +import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar'; import { icon } from '@/ui/theme/constants/icon'; +import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; +import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { BoardColumnHotkeyScope } from '../types/BoardColumnHotkeyScope'; @@ -25,6 +34,7 @@ type OwnProps = { title: string; color: string; onTitleEdit: (title: string, color: string) => void; + stageId: string; }; export function BoardColumnMenu({ @@ -32,18 +42,65 @@ export function BoardColumnMenu({ onTitleEdit, title, color, + stageId, }: OwnProps) { const [openMenu, setOpenMenu] = useState('actions'); const boardColumnMenuRef = useRef(null); + const { enqueueSnackBar } = useSnackBar(); + const createCompanyProgress = useCreateCompanyProgress(); + + function handleCompanySelected( + selectedCompany: EntityForSelect | null | undefined, + ) { + if (!selectedCompany?.id) { + enqueueSnackBar( + 'There was a problem with the company selection, please retry.', + { + variant: 'error', + }, + ); + + console.error( + 'There was a problem with the company selection, please retry.', + ); + return; + } + + createCompanyProgress(selectedCompany.id, stageId); + closeMenu(); + } + + function closeMenu() { + goBackToPreviousHotkeyScope(); + onClose(); + } + + const { + setHotkeyScopeAndMemorizePreviousScope, + goBackToPreviousHotkeyScope, + } = usePreviousHotkeyScope(); + + function setMenu(menu: string) { + if (menu === 'add') { + setHotkeyScopeAndMemorizePreviousScope( + RelationPickerHotkeyScope.RelationPicker, + ); + } + setOpenMenu(menu); + } + const [searchFilter] = useRecoilScopedState( + relationPickerSearchFilterScopedState, + ); + const companies = useFilteredSearchCompanyQuery({ searchFilter }); useListenClickOutside({ refs: [boardColumnMenuRef], - callback: onClose, + callback: closeMenu, }); useScopedHotkeys( [Key.Escape, Key.Enter], - onClose, + closeMenu, BoardColumnHotkeyScope.BoardColumn, [], ); @@ -53,20 +110,37 @@ export function BoardColumnMenu({ {openMenu === 'actions' && ( - setOpenMenu('title')}> + setMenu('title')}> Rename + setMenu('add')}> + + New opportunity + )} {openMenu === 'title' && ( )} + + {openMenu === 'add' && ( + handleCompanySelected(value)} + onCancel={closeMenu} + entities={{ + entitiesToSelect: companies.entitiesToSelect, + selectedEntity: companies.selectedEntities[0], + loading: companies.loading, + }} + disableBackgroundBlur={true} + /> + )} ); diff --git a/front/src/modules/ui/board/components/EntityBoardColumn.tsx b/front/src/modules/ui/board/components/EntityBoardColumn.tsx index 2af7dfcab..a39f96540 100644 --- a/front/src/modules/ui/board/components/EntityBoardColumn.tsx +++ b/front/src/modules/ui/board/components/EntityBoardColumn.tsx @@ -80,6 +80,7 @@ export function EntityBoardColumn({ totalAmount={boardColumnTotal} isFirstColumn={column.index === 0} numChildren={cardIds.length} + stageId={column.id} > {cardIds.map((cardId, index) => (