import { useContext, useRef, useState } from 'react'; import { useRecoilCallback, useRecoilState, useRecoilValue, useResetRecoilState, } from 'recoil'; import { Key } from 'ts-key-enum'; import { v4 } from 'uuid'; import { BoardContext } from '@/companies/states/contexts/BoardContext'; import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader'; import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput'; import { DropdownMenuInputContainer } from '@/ui/dropdown/components/DropdownMenuInputContainer'; import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput'; import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu'; import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator'; import { useDropdown } from '@/ui/dropdown/hooks/useDropdown'; import { IconChevronLeft, IconLayoutKanban, IconPlus, IconTag, } from '@/ui/icon'; import { MenuItem } from '@/ui/menu-item/components/MenuItem'; import { MenuItemNavigate } from '@/ui/menu-item/components/MenuItemNavigate'; import { ThemeColor } from '@/ui/theme/constants/colors'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId'; import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection'; import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView'; import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector'; import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector'; import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState'; import { useBoardCardFields } from '../hooks/useBoardCardFields'; import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState'; import { boardColumnsState } from '../states/boardColumnsState'; import { savedBoardCardFieldsFamilyState } from '../states/savedBoardCardFieldsFamilyState'; import { hiddenBoardCardFieldsScopedSelector } from '../states/selectors/hiddenBoardCardFieldsScopedSelector'; import { visibleBoardCardFieldsScopedSelector } from '../states/selectors/visibleBoardCardFieldsScopedSelector'; import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; export type BoardOptionsDropdownContentProps = { customHotkeyScope: HotkeyScope; onStageAdd?: (boardColumn: BoardColumnDefinition) => void; }; type BoardOptionsMenu = 'fields' | 'stage-creation' | 'stages'; type ColumnForCreate = { id: string; colorCode: ThemeColor; index: number; title: string; }; export const BoardOptionsDropdownContent = ({ customHotkeyScope, onStageAdd, }: BoardOptionsDropdownContentProps) => { const { BoardRecoilScopeContext } = useContext(BoardContext); const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext); const stageInputRef = useRef(null); const viewEditInputRef = useRef(null); const [currentMenu, setCurrentMenu] = useState< BoardOptionsMenu | undefined >(); const [boardColumns, setBoardColumns] = useRecoilState(boardColumnsState); const hiddenBoardCardFields = useRecoilScopedValue( hiddenBoardCardFieldsScopedSelector, BoardRecoilScopeContext, ); const hasHiddenFields = hiddenBoardCardFields.length > 0; const visibleBoardCardFields = useRecoilScopedValue( visibleBoardCardFieldsScopedSelector, BoardRecoilScopeContext, ); const hasVisibleFields = visibleBoardCardFields.length > 0; const viewsById = useRecoilScopedValue( viewsByIdScopedSelector, BoardRecoilScopeContext, // TODO: replace with ViewBarRecoilScopeContext ); const currentView = useRecoilScopedValue( currentViewScopedSelector, BoardRecoilScopeContext, ); const viewEditMode = useRecoilValue(viewEditModeState); const resetViewEditMode = useResetRecoilState(viewEditModeState); const handleStageSubmit = () => { if (currentMenu !== 'stage-creation' || !stageInputRef?.current?.value) return; const columnToCreate: ColumnForCreate = { id: v4(), colorCode: 'gray', index: boardColumns.length, title: stageInputRef.current.value, }; setBoardColumns((previousBoardColumns) => [ ...previousBoardColumns, columnToCreate, ]); onStageAdd?.(columnToCreate); }; const { upsertView } = useUpsertView(); const handleViewNameSubmit = useRecoilCallback( ({ set, snapshot }) => async () => { const boardCardFields = await snapshot.getPromise( boardCardFieldsScopedState(boardRecoilScopeId), ); const isCreateMode = viewEditMode.mode === 'create'; const name = viewEditInputRef.current?.value; const view = await upsertView(name); if (view && isCreateMode) { set(savedBoardCardFieldsFamilyState(view.id), boardCardFields); } }, [boardRecoilScopeId, upsertView, viewEditMode.mode], ); const resetMenu = () => setCurrentMenu(undefined); const handleMenuNavigate = (menu: BoardOptionsMenu) => { handleViewNameSubmit(); setCurrentMenu(menu); }; const { handleFieldVisibilityChange } = useBoardCardFields(); const { closeDropdown } = useDropdown(); useScopedHotkeys( Key.Escape, () => { resetViewEditMode(); closeDropdown(); }, customHotkeyScope.scope, ); useScopedHotkeys( Key.Enter, () => { handleStageSubmit(); handleViewNameSubmit(); resetViewEditMode(); closeDropdown(); }, customHotkeyScope.scope, ); return ( {!currentMenu && ( <> handleMenuNavigate('fields')} LeftIcon={IconTag} text="Fields" /> handleMenuNavigate('stages')} LeftIcon={IconLayoutKanban} text="Stages" /> )} {currentMenu === 'stages' && ( <> Stages setCurrentMenu('stage-creation')} LeftIcon={IconPlus} text="Add stage" /> )} {currentMenu === 'stage-creation' && ( )} {currentMenu === 'fields' && ( <> Fields {hasVisibleFields && ( )} {hasVisibleFields && hasHiddenFields && ( )} {hasHiddenFields && ( )} )} ); };