import React, { useMemo, useCallback, useState, useRef, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { Button, Typography, Dropdown, Popconfirm, Tooltip, Space, Badge, Divider, type InputRef, message } from '@/shared/antd-imports'; import type { CheckboxChangeEvent } from 'antd/es/checkbox'; import { DeleteOutlined, CloseOutlined, MoreOutlined, SyncOutlined, UserOutlined, BellOutlined, TagOutlined, UsergroupAddOutlined, CheckOutlined, EditOutlined, FileOutlined, ImportOutlined, CalendarOutlined, BarChartOutlined, SettingOutlined } from '@/shared/antd-imports'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { RootState } from '@/app/store'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useMixpanelTracking } from '@/hooks/useMixpanelTracking'; import { clearSelection } from '@/features/task-management/selection.slice'; import { fetchTasksV3 } from '@/features/task-management/task-management.slice'; import { taskListBulkActionsApiService } from '@/api/tasks/task-list-bulk-actions.api.service'; import { evt_project_task_list_bulk_archive, evt_project_task_list_bulk_assign_me, evt_project_task_list_bulk_assign_members, evt_project_task_list_bulk_change_phase, evt_project_task_list_bulk_change_priority, evt_project_task_list_bulk_change_status, evt_project_task_list_bulk_delete, evt_project_task_list_bulk_update_labels, } from '@/shared/worklenz-analytics-events'; import { IBulkTasksLabelsRequest, IBulkTasksPhaseChangeRequest, IBulkTasksPriorityChangeRequest, IBulkTasksStatusChangeRequest, } from '@/types/tasks/bulk-action-bar.types'; import { ITaskStatus } from '@/types/tasks/taskStatus.types'; import { ITaskPriority } from '@/types/tasks/taskPriority.types'; import { ITaskPhase } from '@/types/tasks/taskPhase.types'; import { ITaskLabel } from '@/types/tasks/taskLabel.types'; import { ITeamMemberViewModel } from '@/types/teamMembers/teamMembersGetResponse.types'; import { ITeamMembersViewModel } from '@/types/teamMembers/teamMembersViewModel.types'; import { ITaskAssignee } from '@/types/tasks/task.types'; import { createPortal as createReactPortal } from 'react-dom'; import TaskTemplateDrawer from '@/components/task-templates/task-template-drawer'; import AssigneesDropdown from '@/components/taskListCommon/task-list-bulk-actions-bar/components/AssigneesDropdown'; import LabelsDropdown from '@/components/taskListCommon/task-list-bulk-actions-bar/components/LabelsDropdown'; import { sortTeamMembers } from '@/utils/sort-team-members'; import { fetchLabels } from '@/features/taskAttributes/taskLabelSlice'; import { useAuthService } from '@/hooks/useAuth'; import { checkTaskDependencyStatus } from '@/utils/check-task-dependency-status'; import alertService from '@/services/alerts/alertService'; import logger from '@/utils/errorLogger'; const { Text } = Typography; interface OptimizedBulkActionBarProps { selectedTaskIds: string[]; totalSelected: number; projectId: string; onClearSelection?: () => void; } // Performance-optimized memoized action button component const ActionButton = React.memo<{ icon: React.ReactNode; tooltip: string; onClick?: () => void; loading?: boolean; danger?: boolean; disabled?: boolean; isDarkMode: boolean; badge?: number; }>(({ icon, tooltip, onClick, loading = false, danger = false, disabled = false, isDarkMode, badge }) => { const buttonClasses = useMemo(() => { const baseClasses = [ 'flex items-center justify-center', 'h-8 w-8 p-1.5', 'text-sm rounded-md', 'transition-all duration-150 ease-out', 'border-none bg-transparent', 'hover:scale-105 focus:outline-none focus:ring-2 focus:ring-offset-2', disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', ]; if (danger) { baseClasses.push( isDarkMode ? 'text-red-400 hover:bg-red-400/10 focus:ring-red-400/20' : 'text-red-500 hover:bg-red-500/10 focus:ring-red-500/20' ); } else { baseClasses.push( isDarkMode ? 'text-gray-300 hover:bg-white/10 focus:ring-gray-400/20' : 'text-gray-600 hover:bg-black/5 focus:ring-gray-400/20' ); } return baseClasses.join(' '); }, [isDarkMode, danger, disabled]); const ButtonComponent = (