Create opportunity from board column menu (#1323)

- create opportunity from column menu
This commit is contained in:
brendanlaschke
2023-08-28 18:23:28 +02:00
committed by GitHub
parent 6e201ba3a6
commit 0d7b869274
3 changed files with 83 additions and 5 deletions

View File

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

View File

@ -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({
<StyledDropdownMenu>
{openMenu === 'actions' && (
<StyledDropdownMenuItemsContainer>
<DropdownMenuSelectableItem onClick={() => setOpenMenu('title')}>
<DropdownMenuSelectableItem onClick={() => setMenu('title')}>
<IconPencil size={icon.size.md} stroke={icon.stroke.sm} />
Rename
</DropdownMenuSelectableItem>
<DropdownMenuSelectableItem onClick={() => setMenu('add')}>
<IconPlus size={icon.size.md} stroke={icon.stroke.sm} />
New opportunity
</DropdownMenuSelectableItem>
</StyledDropdownMenuItemsContainer>
)}
{openMenu === 'title' && (
<BoardColumnEditTitleMenu
color={color}
onClose={onClose}
onClose={closeMenu}
onTitleEdit={onTitleEdit}
title={title}
/>
)}
{openMenu === 'add' && (
<SingleEntitySelect
onEntitySelected={(value) => handleCompanySelected(value)}
onCancel={closeMenu}
entities={{
entitiesToSelect: companies.entitiesToSelect,
selectedEntity: companies.selectedEntities[0],
loading: companies.loading,
}}
disableBackgroundBlur={true}
/>
)}
</StyledDropdownMenu>
</StyledMenuContainer>
);

View File

@ -80,6 +80,7 @@ export function EntityBoardColumn({
totalAmount={boardColumnTotal}
isFirstColumn={column.index === 0}
numChildren={cardIds.length}
stageId={column.id}
>
<BoardColumnCardsContainer droppableProvided={droppableProvided}>
{cardIds.map((cardId, index) => (