From b847dbca69bca63575b65f3e7b8e8dcfc3b6940a Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 19 Jul 2026 11:39:31 +0330 Subject: [PATCH] update column name --- src/langs/fa.json | 2 + src/pages/taskmanager/components/Column.tsx | 93 +++++++++++++++++-- .../taskmanager/components/ColumnMenu.tsx | 56 +++++++---- .../components/HeaderWorkspace.tsx | 15 ++- .../task-phase/types/TaskPhaseTypes.ts | 3 +- src/pages/taskmanager/workspace.tsx | 5 + 6 files changed, 135 insertions(+), 39 deletions(-) diff --git a/src/langs/fa.json b/src/langs/fa.json index 3f438bf..803742a 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -1023,8 +1023,10 @@ "add_column": "اضافه کردن", "column_name": "نام ستون", "delete_column": "حذف ستون", + "edit_column": "ویرایش نام", "delete_column_confirm": "آیا از حذف این ستون اطمینان دارید؟", "column_deleted": "ستون با موفقیت حذف شد", + "column_updated": "ستون با موفقیت ویرایش شد", "add_new_task": "اضافه کردن تسک", "add_task": "اضافه کردن", "task_title": "عنوان تسک", diff --git a/src/pages/taskmanager/components/Column.tsx b/src/pages/taskmanager/components/Column.tsx index ed61a4c..2501729 100644 --- a/src/pages/taskmanager/components/Column.tsx +++ b/src/pages/taskmanager/components/Column.tsx @@ -8,7 +8,7 @@ import { ErrorType } from "../../../helpers/types"; import { useCreateTask, useGetTasksByTaskPhase } from "../task/hooks/useTaskData"; import type { TaskItemType } from "../task/types/TaskTypes"; import { mapTaskItemToTask } from "../task/utils/mapTaskItemToTask"; -import { useDeleteTaskPhase } from "../task-phase/hooks/useTaskPhaseData"; +import { useDeleteTaskPhase, useUpdateTaskPhase } from "../task-phase/hooks/useTaskPhaseData"; import type { Column as ColumnType, Task as TaskType } from "../types"; import ColumnMenu from "./ColumnMenu"; import Task from "./Task"; @@ -22,6 +22,7 @@ type Props = { onColumnDrop: (overColumnId: string) => void; onTaskClick?: (task: TaskType) => void; onColumnDeleted?: (columnId: string) => void; + onColumnTitleUpdated?: (columnId: string, title: string) => void; }; const Column: FC = ({ @@ -33,9 +34,11 @@ const Column: FC = ({ onColumnDrop, onTaskClick, onColumnDeleted, + onColumnTitleUpdated, }) => { const { t } = useTranslation("global"); const deleteTaskPhase = useDeleteTaskPhase(); + const updateTaskPhase = useUpdateTaskPhase(); const createTask = useCreateTask(); const { data: tasksData, @@ -55,10 +58,13 @@ const Column: FC = ({ const [isAdding, setIsAdding] = useState(false); const [title, setTitle] = useState(""); + const [isEditingTitle, setIsEditingTitle] = useState(false); + const [editTitle, setEditTitle] = useState(column.title); const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false); const [isColumnDragOver, setIsColumnDragOver] = useState(false); const columnRef = useRef(null); const dragImageRef = useRef(null); + const isCancellingTitleEdit = useRef(false); const isDraggingColumn = draggedColumnId === column.id; const handleTasksScroll = (event: React.UIEvent) => { @@ -167,6 +173,50 @@ const Column: FC = ({ ); }; + const startEditingTitle = () => { + isCancellingTitleEdit.current = false; + setEditTitle(column.title); + setIsEditingTitle(true); + }; + + const cancelEditingTitle = () => { + isCancellingTitleEdit.current = true; + setEditTitle(column.title); + setIsEditingTitle(false); + }; + + const handleSaveTitle = () => { + if (isCancellingTitleEdit.current) { + isCancellingTitleEdit.current = false; + return; + } + + const trimmedTitle = editTitle.trim(); + if (!trimmedTitle || trimmedTitle === column.title) { + setIsEditingTitle(false); + setEditTitle(column.title); + return; + } + + const previousTitle = column.title; + onColumnTitleUpdated?.(column.id, trimmedTitle); + setIsEditingTitle(false); + + updateTaskPhase.mutate( + { id: column.id, params: { name: trimmedTitle }, projectId }, + { + onSuccess: () => { + toast.success(t("taskmanager.column_updated")); + }, + onError: (error: ErrorType) => { + onColumnTitleUpdated?.(column.id, previousTitle); + setEditTitle(previousTitle); + toast.error(error.response?.data?.error.message[0]); + }, + }, + ); + }; + return (
= ({ onDrop={handleColumnDrop} >
-
- {column.title} -
- setIsDeleteConfirmOpen(true)} /> + {isEditingTitle ? ( + setEditTitle(e.target.value)} + onBlur={handleSaveTitle} + onKeyDown={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + handleSaveTitle(); + } + if (e.key === "Escape") { + e.preventDefault(); + cancelEditingTitle(); + } + }} + disabled={updateTaskPhase.isPending} + className="flex-1 min-w-0 font-bold text-sm bg-white rounded-lg px-2 py-1 outline-none" + autoFocus + /> + ) : ( +
+ {column.title} +
+ )} + setIsDeleteConfirmOpen(true)} />
void; onDelete: () => void; }; -const ColumnMenu: FC = ({ onDelete }) => { +const ColumnMenu: FC = ({ onEdit, onDelete }) => { const { t } = useTranslation("global"); return ( - e.stopPropagation()} - > - - + {({ close }) => ( + <> + e.stopPropagation()} + > + + - - - + + + + + + )} ); }; diff --git a/src/pages/taskmanager/components/HeaderWorkspace.tsx b/src/pages/taskmanager/components/HeaderWorkspace.tsx index 9c18090..c090a31 100644 --- a/src/pages/taskmanager/components/HeaderWorkspace.tsx +++ b/src/pages/taskmanager/components/HeaderWorkspace.tsx @@ -1,7 +1,6 @@ -import { InfoCircle, Setting2, UserAdd } from "iconsax-react"; +import { ArrowRight, InfoCircle, Setting2 } from "iconsax-react"; import type { FC } from "react"; import { useNavigate } from "react-router-dom"; -import Button from "../../../components/Button"; type HeaderWorkspaceProps = { projectName: string; @@ -21,17 +20,15 @@ const HeaderWorkspace: FC = ({ projectName }) => {
-