import { ArrowLeftOutlined, BellFilled, BellOutlined, CalendarOutlined, DownOutlined, EditOutlined, ImportOutlined, SaveOutlined, SettingOutlined, SyncOutlined, UsergroupAddOutlined, } from '@ant-design/icons'; import { PageHeader } from '@ant-design/pro-components'; import { Button, Dropdown, Flex, Tag, Tooltip, Typography } from 'antd'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { colors } from '@/styles/colors'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { useAppSelector } from '@/hooks/useAppSelector'; import { SocketEvents } from '@/shared/socket-events'; import { useAuthService } from '@/hooks/useAuth'; import { useSocket } from '@/socket/socketContext'; import { setProject, setImportTaskTemplateDrawerOpen, setRefreshTimestamp, } from '@features/project/project.slice'; import { addTask, fetchTaskGroups, fetchTaskListColumns, IGroupBy, } from '@features/tasks/tasks.slice'; import ProjectStatusIcon from '@/components/common/project-status-icon/project-status-icon'; import { formatDate } from '@/utils/timeUtils'; import { toggleSaveAsTemplateDrawer } from '@/features/projects/projectsSlice'; import SaveProjectAsTemplate from '@/components/save-project-as-template/save-project-as-template'; import { fetchProjectData, toggleProjectDrawer, setProjectId, } from '@/features/project/project-drawer.slice'; import { setSelectedTaskId, setShowTaskDrawer } from '@/features/task-drawer/task-drawer.slice'; import { useState } from 'react'; import { ITaskCreateRequest } from '@/types/tasks/task-create-request.types'; import { DEFAULT_TASK_NAME, UNMAPPED } from '@/shared/constants'; import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import { getGroupIdByGroupedColumn } from '@/services/task-list/taskList.service'; import logger from '@/utils/errorLogger'; import { createPortal } from 'react-dom'; import ImportTaskTemplate from '@/components/task-templates/import-task-template'; import ProjectDrawer from '@/components/projects/project-drawer/project-drawer'; import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice'; import useIsProjectManager from '@/hooks/useIsProjectManager'; import useTabSearchParam from '@/hooks/useTabSearchParam'; import { addTaskCardToTheTop, fetchBoardTaskGroups } from '@/features/board/board-slice'; import { fetchPhasesByProjectId } from '@/features/projects/singleProject/phase/phases.slice'; import { evt_project_task_create, evt_project_refresh_click, evt_project_settings_click, evt_project_import_tasks_click, } from '@/shared/worklenz-analytics-events'; import { useMixpanelTracking } from '@/hooks/useMixpanelTracking'; const ProjectViewHeader = () => { const navigate = useNavigate(); const { t } = useTranslation('project-view/project-view-header'); const dispatch = useAppDispatch(); const currentSession = useAuthService().getCurrentSession(); const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin(); const isProjectManager = useIsProjectManager(); const { trackMixpanelEvent } = useMixpanelTracking(); const { tab } = useTabSearchParam(); const { socket } = useSocket(); const { project: selectedProject, projectId } = useAppSelector(state => state.projectReducer); const { loadingGroups, groupBy } = useAppSelector(state => state.taskReducer); const [creatingTask, setCreatingTask] = useState(false); const handleRefresh = () => { if (!projectId) return; trackMixpanelEvent(evt_project_refresh_click, { project_id: projectId, tab: tab, project_name: selectedProject?.name, }); switch (tab) { case 'tasks-list': dispatch(fetchTaskListColumns(projectId)); dispatch(fetchPhasesByProjectId(projectId)); dispatch(fetchTaskGroups(projectId)); break; case 'board': dispatch(fetchBoardTaskGroups(projectId)); break; case 'project-insights-member-overview': dispatch(setRefreshTimestamp()); break; case 'all-attachments': dispatch(setRefreshTimestamp()); break; case 'members': dispatch(setRefreshTimestamp()); break; case 'updates': dispatch(setRefreshTimestamp()); break; default: break; } }; const handleSubscribe = () => { if (selectedProject?.id) { const newSubscriptionState = !selectedProject.subscribed; dispatch(setProject({ ...selectedProject, subscribed: newSubscriptionState })); socket?.emit(SocketEvents.PROJECT_SUBSCRIBERS_CHANGE.toString(), { project_id: selectedProject.id, user_id: currentSession?.id, team_member_id: currentSession?.team_member_id, mode: newSubscriptionState ? 1 : 0, }); } }; const handleSettingsClick = () => { if (selectedProject?.id) { trackMixpanelEvent(evt_project_settings_click, { project_id: selectedProject.id, project_name: selectedProject.name, }); dispatch(setProjectId(selectedProject.id)); dispatch(fetchProjectData(selectedProject.id)); dispatch(toggleProjectDrawer()); } }; const handleCreateTask = () => { try { setCreatingTask(true); trackMixpanelEvent(evt_project_task_create, { project_id: selectedProject?.id, project_name: selectedProject?.name, reporter_id: currentSession?.id, team_id: currentSession?.team_id, creation_method: 'quick_create', }); const body: ITaskCreateRequest = { name: DEFAULT_TASK_NAME, project_id: selectedProject?.id, reporter_id: currentSession?.id, team_id: currentSession?.team_id, }; socket?.once(SocketEvents.QUICK_TASK.toString(), (task: IProjectTask) => { if (task.id) { dispatch(setSelectedTaskId(task.id)); dispatch(setShowTaskDrawer(true)); const groupId = groupBy === IGroupBy.PHASE ? UNMAPPED : getGroupIdByGroupedColumn(task); if (groupId) { if (tab === 'board') { dispatch(addTaskCardToTheTop({ sectionId: groupId, task })); } else { dispatch(addTask({ task, groupId })); } socket?.emit(SocketEvents.GET_TASK_PROGRESS.toString(), task.id); } } }); socket?.emit(SocketEvents.QUICK_TASK.toString(), JSON.stringify(body)); } catch (error) { logger.error('Error creating task', error); } finally { setCreatingTask(false); } }; const handleImportTaskTemplate = () => { trackMixpanelEvent(evt_project_import_tasks_click, { project_id: selectedProject?.id, project_name: selectedProject?.name, }); dispatch(setImportTaskTemplateDrawerOpen(true)); }; const dropdownItems = [ { key: 'import', label: (