From 46ac8ca0ca64e2135af17ed5916e42e4587f8849 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Tue, 14 Jul 2026 14:57:43 +0330 Subject: [PATCH] change priority --- .../taskmanager/task/hooks/useTaskData.ts | 19 ++++++++ .../taskmanager/task/service/TaskService.ts | 5 ++ .../utils/getPriorityDestinationTaskId.ts | 24 ++++++++++ src/pages/taskmanager/workspace.tsx | 47 ++++++++++++++++++- 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/pages/taskmanager/utils/getPriorityDestinationTaskId.ts diff --git a/src/pages/taskmanager/task/hooks/useTaskData.ts b/src/pages/taskmanager/task/hooks/useTaskData.ts index e73fcf7..2d1598e 100644 --- a/src/pages/taskmanager/task/hooks/useTaskData.ts +++ b/src/pages/taskmanager/task/hooks/useTaskData.ts @@ -72,6 +72,25 @@ export const useChangeTaskPhase = () => { }); }; +export const useChangeTaskPriority = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({ + srcId, + destId, + }: { + srcId: string; + destId: string; + taskPhaseId: string; + projectId: string; + }) => api.changeTaskPriority(srcId, destId), + onSuccess: (_data, variables) => { + queryClient.invalidateQueries({ queryKey: ["tasks-by-task-phase", variables.taskPhaseId] }); + }, + }); +}; + export const useDeleteTask = () => { const queryClient = useQueryClient(); diff --git a/src/pages/taskmanager/task/service/TaskService.ts b/src/pages/taskmanager/task/service/TaskService.ts index c89f215..6dbfad1 100644 --- a/src/pages/taskmanager/task/service/TaskService.ts +++ b/src/pages/taskmanager/task/service/TaskService.ts @@ -48,6 +48,11 @@ export const changeTaskPhase = async (id: string, params: ChangeTaskPhaseType) = return data; }; +export const changeTaskPriority = async (srcId: string, destId: string) => { + const { data } = await axios.patch(`/task-manager/tasks/change-priority/${srcId}/${destId}`); + return data; +}; + export const deleteTask = async (id: string) => { const { data } = await axios.delete(`/task-manager/tasks/${id}`); return data; diff --git a/src/pages/taskmanager/utils/getPriorityDestinationTaskId.ts b/src/pages/taskmanager/utils/getPriorityDestinationTaskId.ts new file mode 100644 index 0000000..b03783a --- /dev/null +++ b/src/pages/taskmanager/utils/getPriorityDestinationTaskId.ts @@ -0,0 +1,24 @@ +import type { TaskItemType } from "../task/types/TaskTypes"; + +const getTaskSortOrder = (task: TaskItemType) => task.order ?? task.priority ?? 0; + +export const getPriorityDestinationTaskId = ( + items: TaskItemType[], + sourceId: string, + destIndex: number, + removeSource = true, +): string | null => { + const sorted = [...items].sort((a, b) => getTaskSortOrder(a) - getTaskSortOrder(b)); + const sourceIndex = sorted.findIndex((item) => item.id === sourceId); + + if (removeSource && sourceIndex === destIndex) return null; + + const list = removeSource ? sorted.filter((item) => item.id !== sourceId) : sorted; + if (list.length === 0) return null; + + if (destIndex >= list.length) { + return list[list.length - 1].id; + } + + return list[destIndex].id; +}; diff --git a/src/pages/taskmanager/workspace.tsx b/src/pages/taskmanager/workspace.tsx index 19305b0..d7059c9 100644 --- a/src/pages/taskmanager/workspace.tsx +++ b/src/pages/taskmanager/workspace.tsx @@ -10,12 +10,14 @@ import HeaderWorkspace from "./components/HeaderWorkspace"; import TaskDetailModal from "./components/task-detail/TaskDetailModal"; import { useGetProject } from "./project/hooks/useProjectData"; import { useUpdateTaskPhase } from "./task-phase/hooks/useTaskPhaseData"; -import { useChangeTaskPhase } from "./task/hooks/useTaskData"; +import { useChangeTaskPhase, useChangeTaskPriority } from "./task/hooks/useTaskData"; import type { TaskPhaseItemType } from "./task-phase/types/TaskPhaseTypes"; import type { Column as ColumnType, Task } from "./types"; +import { getPriorityDestinationTaskId } from "./utils/getPriorityDestinationTaskId"; import { reorderColumns } from "./utils/reorderColumns"; import { reorderTaskItems } from "./utils/reorderTaskItems"; import { + getTaskPhaseItems, insertTaskPhaseItem, type TasksByTaskPhaseInfiniteData, updateTaskPhaseItems, @@ -26,6 +28,7 @@ const Workspace: FC = () => { const { slug: projectId = "" } = useParams<{ slug: string }>(); const { data: project, isPending } = useGetProject(projectId); const changeTaskPhase = useChangeTaskPhase(); + const changeTaskPriority = useChangeTaskPriority(); const updateTaskPhase = useUpdateTaskPhase(); const [columns, setColumns] = useState([]); const [draggedTask, setDraggedTask] = useState(null); @@ -65,9 +68,30 @@ const Workspace: FC = () => { setDraggedTask(null); if (!columnChanged) { + const previousData = queryClient.getQueryData([ + "tasks-by-task-phase", + columnId, + ]); + const currentItems = getTaskPhaseItems(previousData); + const destTaskId = getPriorityDestinationTaskId(currentItems, activeTask.id, index); + + if (!destTaskId) return; + queryClient.setQueryData(["tasks-by-task-phase", columnId], (current) => updateTaskPhaseItems(current, (items) => reorderTaskItems(items, activeTask.id, index)), ); + + changeTaskPriority.mutate( + { srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId }, + { + onError: (error: ErrorType) => { + if (previousData) { + queryClient.setQueryData(["tasks-by-task-phase", columnId], previousData); + } + toast.error(error.response?.data?.error.message[0]); + }, + }, + ); return; } @@ -100,6 +124,13 @@ const Workspace: FC = () => { }, index), ); + const destTaskId = getPriorityDestinationTaskId( + getTaskPhaseItems(previousDest), + activeTask.id, + index, + false, + ); + if (selectedTask?.id === activeTask.id) { setSelectedTask({ ...activeTask, columnId }); } @@ -108,6 +139,20 @@ const Workspace: FC = () => { { id: activeTask.id, params: { taskPhaseId: columnId }, projectId }, { onSuccess: () => { + if (destTaskId) { + changeTaskPriority.mutate( + { srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId }, + { + onError: (error: ErrorType) => { + queryClient.invalidateQueries({ queryKey: ["tasks-by-task-phase", sourceColumnId] }); + queryClient.invalidateQueries({ queryKey: ["tasks-by-task-phase", columnId] }); + toast.error(error.response?.data?.error.message[0]); + }, + }, + ); + return; + } + queryClient.invalidateQueries({ queryKey: ["tasks-by-task-phase", sourceColumnId] }); queryClient.invalidateQueries({ queryKey: ["tasks-by-task-phase", columnId] }); },