diff --git a/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.css b/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.css new file mode 100644 index 00000000..9822e0a0 --- /dev/null +++ b/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.css @@ -0,0 +1,19 @@ +.priority-dropdown .ant-dropdown-menu { + padding: 0 !important; + margin-top: 8px !important; + overflow: hidden; +} + +.priority-dropdown .ant-dropdown-menu-item { + padding: 0 !important; +} + +.priority-dropdown-card .ant-card-body { + padding: 0 !important; +} + +.priority-menu .ant-menu-item { + display: flex; + align-items: center; + height: 32px; +} diff --git a/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.tsx b/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.tsx new file mode 100644 index 00000000..3deceb7a --- /dev/null +++ b/worklenz-frontend/src/components/board/taskCard/priority-section/priority-section.tsx @@ -0,0 +1,66 @@ +import { Flex, Typography } from 'antd'; +import './priority-section.css'; +import { useAppSelector } from '@/hooks/useAppSelector'; +import { useState, useEffect, useMemo } from 'react'; +import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; +import { ITaskPriority } from '@/types/tasks/taskPriority.types'; +import { DoubleLeftOutlined, MinusOutlined, PauseOutlined } from '@ant-design/icons'; + +type PrioritySectionProps = { + task: IProjectTask; +}; + +const PrioritySection = ({ task }: PrioritySectionProps) => { + const [selectedPriority, setSelectedPriority] = useState(undefined); + const priorityList = useAppSelector(state => state.priorityReducer.priorities); + const themeMode = useAppSelector(state => state.themeReducer.mode); + + // Update selectedPriority whenever task.priority or priorityList changes + useEffect(() => { + if (!task.priority || !priorityList.length) { + setSelectedPriority(undefined); + return; + } + + const foundPriority = priorityList.find(priority => priority.id === task.priority); + setSelectedPriority(foundPriority); + }, [task.priority, priorityList]); + + const priorityIcon = useMemo(() => { + if (!selectedPriority) return null; + + const iconProps = { + style: { + color: themeMode === 'dark' ? selectedPriority.color_code_dark : selectedPriority.color_code, + marginRight: '0.25rem', + }, + }; + + switch (selectedPriority.name) { + case 'Low': + return ; + case 'Medium': + return ; + case 'High': + return ; + default: + return null; + } + }, [selectedPriority, themeMode]); + + if (!task.priority || !selectedPriority) return null; + + return ( + + {priorityIcon} + + {task.name} + + + ); +}; + +export default PrioritySection; diff --git a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-container.tsx b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-container.tsx index 8b0fce41..83ee7c05 100644 --- a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-container.tsx +++ b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-section-container.tsx @@ -3,7 +3,7 @@ import { SortableContext, horizontalListSortingStrategy } from '@dnd-kit/sortabl import BoardSectionCard from './board-section-card/board-section-card'; import BoardCreateSectionCard from './board-section-card/board-create-section-card'; import { ITaskListGroup } from '@/types/tasks/taskList.types'; -import { useEffect } from 'react'; +import React, { useEffect } from 'react'; import { setTaskAssignee, setTaskEndDate } from '@/features/task-drawer/task-drawer.slice'; import { fetchTaskAssignees } from '@/features/taskAttributes/taskMemberSlice'; import { SocketEvents } from '@/shared/socket-events'; @@ -113,4 +113,4 @@ const BoardSectionCardContainer = ({ ); }; -export default BoardSectionCardContainer; +export default React.memo(BoardSectionCardContainer); diff --git a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-task-card/board-view-task-card.tsx b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-task-card/board-view-task-card.tsx index 1ebbd37b..8faa1fe5 100644 --- a/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-task-card/board-view-task-card.tsx +++ b/worklenz-frontend/src/pages/projects/projectView/board/board-section/board-task-card/board-view-task-card.tsx @@ -55,6 +55,8 @@ import { evt_project_task_list_context_menu_delete, } from '@/shared/worklenz-analytics-events'; import logger from '@/utils/errorLogger'; +import { useAuthService } from '@/hooks/useAuth'; +import PrioritySection from '@/components/board/taskCard/priority-section/priority-section'; interface IBoardViewTaskCardProps { task: IProjectTask; @@ -65,7 +67,7 @@ const BoardViewTaskCard = ({ task, sectionId }: IBoardViewTaskCardProps) => { const dispatch = useAppDispatch(); const { t } = useTranslation('kanban-board'); const { trackMixpanelEvent } = useMixpanelTracking(); - + const currentSession = useAuthService().getCurrentSession(); const themeMode = useAppSelector(state => state.themeReducer.mode); const projectId = useAppSelector(state => state.projectReducer.projectId); const [isSubTaskShow, setIsSubTaskShow] = useState(false); @@ -234,42 +236,11 @@ const BoardViewTaskCard = ({ task, sectionId }: IBoardViewTaskCardProps) => { }, ], [t, handleAssignToMe, handleArchive, handleDelete, updatingAssignToMe]); - const priorityIcon = useMemo(() => { - if (task.priority_value === 0) { - return ( - - ); - } else if (task.priority_value === 1) { - return ( - - ); - } else { - return ( - - ); - } - }, [task.priority_value]); + const renderLabels = useMemo(() => { if (!task?.labels?.length) return null; - + return ( <> {task.labels.slice(0, 2).map((label: any) => ( @@ -313,20 +284,12 @@ const BoardViewTaskCard = ({ task, sectionId }: IBoardViewTaskCardProps) => { - = 100 ? 9 : 7} /> + = 100 ? 9 : 7} /> {/* Action Icons */} - - {priorityIcon} - - {task.name} - - + { )} - + {!task.sub_tasks_loading && task?.sub_tasks && task?.sub_tasks.map((subtask: any) => (