Compare commits

...

4 Commits

Author SHA1 Message Date
hamid zarghami 89d9ad7557 grediend in workspace
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-19 11:49:38 +03:30
hamid zarghami 3eae768d5a fix build 2026-07-19 11:43:35 +03:30
hamid zarghami b847dbca69 update column name 2026-07-19 11:39:31 +03:30
hamid zarghami 44fd61c039 update sidebar 2026-07-19 11:32:33 +03:30
12 changed files with 231 additions and 94 deletions
+4
View File
@@ -43,6 +43,10 @@ export const getSubMenuNameFromPath = (pathname: string): string => {
return "customers"; return "customers";
} }
if (pathname.startsWith("/workspace") || pathname.startsWith("/project") || pathname.startsWith("/taskmanager")) {
return "other";
}
const segment = pathname.split("/")[1] ?? ""; const segment = pathname.split("/")[1] ?? "";
return pathSegmentToSubMenu[segment] ?? ""; return pathSegmentToSubMenu[segment] ?? "";
}; };
+2
View File
@@ -1023,8 +1023,10 @@
"add_column": "اضافه کردن", "add_column": "اضافه کردن",
"column_name": "نام ستون", "column_name": "نام ستون",
"delete_column": "حذف ستون", "delete_column": "حذف ستون",
"edit_column": "ویرایش نام",
"delete_column_confirm": "آیا از حذف این ستون اطمینان دارید؟", "delete_column_confirm": "آیا از حذف این ستون اطمینان دارید؟",
"column_deleted": "ستون با موفقیت حذف شد", "column_deleted": "ستون با موفقیت حذف شد",
"column_updated": "ستون با موفقیت ویرایش شد",
"add_new_task": "اضافه کردن تسک", "add_new_task": "اضافه کردن تسک",
"add_task": "اضافه کردن", "add_task": "اضافه کردن",
"task_title": "عنوان تسک", "task_title": "عنوان تسک",
+75 -2
View File
@@ -8,7 +8,7 @@ import { ErrorType } from "../../../helpers/types";
import { useCreateTask, useGetTasksByTaskPhase } from "../task/hooks/useTaskData"; import { useCreateTask, useGetTasksByTaskPhase } from "../task/hooks/useTaskData";
import type { TaskItemType } from "../task/types/TaskTypes"; import type { TaskItemType } from "../task/types/TaskTypes";
import { mapTaskItemToTask } from "../task/utils/mapTaskItemToTask"; 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 type { Column as ColumnType, Task as TaskType } from "../types";
import ColumnMenu from "./ColumnMenu"; import ColumnMenu from "./ColumnMenu";
import Task from "./Task"; import Task from "./Task";
@@ -22,6 +22,7 @@ type Props = {
onColumnDrop: (overColumnId: string) => void; onColumnDrop: (overColumnId: string) => void;
onTaskClick?: (task: TaskType) => void; onTaskClick?: (task: TaskType) => void;
onColumnDeleted?: (columnId: string) => void; onColumnDeleted?: (columnId: string) => void;
onColumnTitleUpdated?: (columnId: string, title: string) => void;
}; };
const Column: FC<Props> = ({ const Column: FC<Props> = ({
@@ -33,9 +34,11 @@ const Column: FC<Props> = ({
onColumnDrop, onColumnDrop,
onTaskClick, onTaskClick,
onColumnDeleted, onColumnDeleted,
onColumnTitleUpdated,
}) => { }) => {
const { t } = useTranslation("global"); const { t } = useTranslation("global");
const deleteTaskPhase = useDeleteTaskPhase(); const deleteTaskPhase = useDeleteTaskPhase();
const updateTaskPhase = useUpdateTaskPhase();
const createTask = useCreateTask(); const createTask = useCreateTask();
const { const {
data: tasksData, data: tasksData,
@@ -55,10 +58,13 @@ const Column: FC<Props> = ({
const [isAdding, setIsAdding] = useState(false); const [isAdding, setIsAdding] = useState(false);
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [isEditingTitle, setIsEditingTitle] = useState(false);
const [editTitle, setEditTitle] = useState(column.title);
const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false); const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false);
const [isColumnDragOver, setIsColumnDragOver] = useState(false); const [isColumnDragOver, setIsColumnDragOver] = useState(false);
const columnRef = useRef<HTMLDivElement>(null); const columnRef = useRef<HTMLDivElement>(null);
const dragImageRef = useRef<HTMLElement | null>(null); const dragImageRef = useRef<HTMLElement | null>(null);
const isCancellingTitleEdit = useRef(false);
const isDraggingColumn = draggedColumnId === column.id; const isDraggingColumn = draggedColumnId === column.id;
const handleTasksScroll = (event: React.UIEvent<HTMLDivElement>) => { const handleTasksScroll = (event: React.UIEvent<HTMLDivElement>) => {
@@ -167,6 +173,50 @@ const Column: FC<Props> = ({
); );
}; };
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 ( return (
<div <div
ref={columnRef} ref={columnRef}
@@ -178,15 +228,38 @@ const Column: FC<Props> = ({
onDrop={handleColumnDrop} onDrop={handleColumnDrop}
> >
<div className="flex justify-between items-center shrink-0 gap-2"> <div className="flex justify-between items-center shrink-0 gap-2">
{isEditingTitle ? (
<input
type="text"
value={editTitle}
onChange={(e) => 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
/>
) : (
<div <div
draggable draggable
onDragStart={handleColumnDragStart} onDragStart={handleColumnDragStart}
onDragEnd={handleColumnDragEnd} onDragEnd={handleColumnDragEnd}
onDoubleClick={startEditingTitle}
className="flex-1 min-w-0 font-bold text-sm truncate cursor-grab active:cursor-grabbing" className="flex-1 min-w-0 font-bold text-sm truncate cursor-grab active:cursor-grabbing"
> >
{column.title} {column.title}
</div> </div>
<ColumnMenu onDelete={() => setIsDeleteConfirmOpen(true)} /> )}
<ColumnMenu onEdit={startEditingTitle} onDelete={() => setIsDeleteConfirmOpen(true)} />
</div> </div>
<ModalConfrim <ModalConfrim
@@ -4,14 +4,17 @@ import { FC } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
type Props = { type Props = {
onEdit: () => void;
onDelete: () => void; onDelete: () => void;
}; };
const ColumnMenu: FC<Props> = ({ onDelete }) => { const ColumnMenu: FC<Props> = ({ onEdit, onDelete }) => {
const { t } = useTranslation("global"); const { t } = useTranslation("global");
return ( return (
<Popover className="relative"> <Popover className="relative">
{({ close }) => (
<>
<PopoverButton <PopoverButton
className="flex items-center justify-center size-8 rounded-lg hover:bg-black/5 transition-colors outline-none shrink-0" className="flex items-center justify-center size-8 rounded-lg hover:bg-black/5 transition-colors outline-none shrink-0"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
@@ -25,12 +28,27 @@ const ColumnMenu: FC<Props> = ({ onDelete }) => {
> >
<button <button
type="button" type="button"
onClick={onDelete} onClick={() => {
close();
onEdit();
}}
className="w-full px-4 py-2.5 text-right hover:bg-black/5 transition-colors"
>
{t("taskmanager.edit_column")}
</button>
<button
type="button"
onClick={() => {
close();
onDelete();
}}
className="w-full px-4 py-2.5 text-right text-red-500 hover:bg-red-50 transition-colors" className="w-full px-4 py-2.5 text-right text-red-500 hover:bg-red-50 transition-colors"
> >
{t("taskmanager.delete_column")} {t("taskmanager.delete_column")}
</button> </button>
</PopoverPanel> </PopoverPanel>
</>
)}
</Popover> </Popover>
); );
}; };
@@ -1,7 +1,6 @@
import { InfoCircle, Setting2, UserAdd } from "iconsax-react"; import { ArrowRight, Setting2 } from "iconsax-react";
import type { FC } from "react"; import type { FC } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Button from "../../../components/Button";
type HeaderWorkspaceProps = { type HeaderWorkspaceProps = {
projectName: string; projectName: string;
@@ -11,27 +10,25 @@ const HeaderWorkspace: FC<HeaderWorkspaceProps> = ({ projectName }) => {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<div className="flex justify-between items-center bg-primary h-14 sm:h-16 xl:h-[102px] px-3 sm:px-6 xl:px-8 shrink-0 gap-3"> <div className="flex justify-between items-center bg-primary h-14 sm:h-16 xl:h-[80px] px-3 sm:px-6 xl:px-8 shrink-0 gap-3">
<div className="flex gap-2 sm:gap-4 items-center min-w-0"> <div className="flex gap-2 sm:gap-4 items-center min-w-0">
<div className="text-white text-base sm:text-lg xl:text-xl truncate">{projectName}</div> <div className="text-white text-base sm:text-lg xl:text-xl truncate">{projectName}</div>
<InfoCircle {/* <InfoCircle
size={18} size={18}
color="white" color="white"
/> /> */}
</div> </div>
<div className="flex gap-2 sm:gap-4 items-center shrink-0"> <div className="flex gap-2 sm:gap-4 items-center shrink-0">
<Button <div
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
label="برگشت" className="flex gap-1 items-center px-2 sm:px-3 rounded-lg bg-white h-8"
/> >
<ArrowRight
<div className="flex gap-1 items-center px-2 sm:px-3 rounded-lg bg-white h-8">
<UserAdd
size={18} size={18}
color="black" color="black"
/> />
<div className="text-black text-xs hidden sm:block whitespace-nowrap">اشتراک گذاری</div> <div className="text-black text-xs hidden sm:block whitespace-nowrap">برگشت</div>
</div> </div>
<Setting2 <Setting2
@@ -1,7 +1,8 @@
import { CSSProperties, FC } from "react"; import { FC } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { Pages } from "../../../../config/Pages"; import { Pages } from "../../../../config/Pages";
import type { ProjectItem } from "../types/ProjectTypes"; import type { ProjectItem } from "../types/ProjectTypes";
import { getProjectBackgroundStyle } from "../utils/getProjectBackgroundStyle";
import ProjectCardMenu from "./ProjectCardMenu"; import ProjectCardMenu from "./ProjectCardMenu";
type Props = { type Props = {
@@ -9,30 +10,6 @@ type Props = {
onDelete: (id: string) => void; onDelete: (id: string) => void;
}; };
const hexToRgba = (hex: string, alpha: number) => {
const normalized = hex.replace("#", "");
const r = parseInt(normalized.slice(0, 2), 16);
const g = parseInt(normalized.slice(2, 4), 16);
const b = parseInt(normalized.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
const getCardBackgroundStyle = (project: ProjectItem): CSSProperties => {
if (project.backgroundPicture) {
return {
backgroundImage: `url(${project.backgroundPicture})`,
backgroundSize: "cover",
backgroundPosition: "center",
};
}
const color = project.backgroundColor ?? "#A8E6CF";
return {
background: `linear-gradient(135deg, ${color}, ${hexToRgba(color, 0.5)})`,
};
};
const ProjectCard: FC<Props> = ({ project, onDelete }) => { const ProjectCard: FC<Props> = ({ project, onDelete }) => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -43,7 +20,7 @@ const ProjectCard: FC<Props> = ({ project, onDelete }) => {
return ( return (
<div className="bg-white rounded-[20px] overflow-hidden shadow-sm border border-border/40 p-3"> <div className="bg-white rounded-[20px] overflow-hidden shadow-sm border border-border/40 p-3">
<Link to={Pages.taskmanager.workspace + project.id}> <Link to={Pages.taskmanager.workspace + project.id}>
<div className="h-[84px] w-full rounded-[16px]" style={getCardBackgroundStyle(project)} /> <div className="h-[84px] w-full rounded-[16px]" style={getProjectBackgroundStyle(project)} />
</Link> </Link>
<div className="flex items-center justify-between mt-3.5"> <div className="flex items-center justify-between mt-3.5">
@@ -1,7 +1,7 @@
import { Add, Setting2 } from "iconsax-react"; import { Add, ArrowRight } from "iconsax-react";
import { FC } from "react"; import { FC } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import Button from "../../../../components/Button"; import Button from "../../../../components/Button";
import { Pages } from "../../../../config/Pages"; import { Pages } from "../../../../config/Pages";
@@ -13,23 +13,33 @@ type Props = {
const ProjectListHeader: FC<Props> = ({ title, workspaceId, onSettingsClick }) => { const ProjectListHeader: FC<Props> = ({ title, workspaceId, onSettingsClick }) => {
const { t } = useTranslation("global"); const { t } = useTranslation("global");
const createProjectLink = workspaceId const createProjectLink = workspaceId ? `${Pages.taskmanager.createProject}?workspaceId=${workspaceId}` : Pages.taskmanager.createProject;
? `${Pages.taskmanager.createProject}?workspaceId=${workspaceId}` const navigate = useNavigate();
: Pages.taskmanager.createProject;
return ( return (
<div className="flex w-full justify-between items-center"> <div className="flex w-full justify-between items-center">
<h1>{title}</h1> <h1>{title}</h1>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Button onClick={onSettingsClick} className="flex items-center gap-2 bg-[#C3C7DD] text-black whitespace-nowrap px-4"> <Button
<Setting2 size={18} color="black" /> onClick={() => navigate(-1)}
<span>{t("sidebar.setting")}</span> className="flex items-center gap-2 bg-[#C3C7DD] text-black whitespace-nowrap px-4"
>
<ArrowRight
size={18}
color="black"
/>
<span>برگشت</span>
</Button> </Button>
<Link to={createProjectLink}> <Link to={createProjectLink}>
<Button onClick={onSettingsClick} className="flex items-center gap-2 whitespace-nowrap px-4"> <Button
<Add size={18} color="white" /> onClick={onSettingsClick}
className="flex items-center gap-2 whitespace-nowrap px-4"
>
<Add
size={18}
color="white"
/>
<span>{t("taskmanager.new_project")}</span> <span>{t("taskmanager.new_project")}</span>
</Button> </Button>
</Link> </Link>
@@ -0,0 +1,30 @@
import type { CSSProperties } from "react";
type ProjectBackground = {
backgroundColor?: string;
backgroundPicture?: string;
};
const hexToRgba = (hex: string, alpha: number) => {
const normalized = hex.replace("#", "");
const r = parseInt(normalized.slice(0, 2), 16);
const g = parseInt(normalized.slice(2, 4), 16);
const b = parseInt(normalized.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
export const getProjectBackgroundStyle = (project: ProjectBackground): CSSProperties => {
if (project.backgroundPicture) {
return {
backgroundImage: `url(${project.backgroundPicture})`,
backgroundSize: "cover",
backgroundPosition: "center",
};
}
const color = project.backgroundColor ?? "#A8E6CF";
return {
background: `linear-gradient(135deg, ${color}, ${hexToRgba(color, 0.5)})`,
};
};
@@ -6,7 +6,8 @@ export type CreateTaskPhaseType = {
}; };
export type UpdateTaskPhaseType = { export type UpdateTaskPhaseType = {
order: number; order?: number;
name?: string;
}; };
export type TaskPhaseItemType = { export type TaskPhaseItemType = {
+25 -9
View File
@@ -9,7 +9,9 @@ import AddNewColumn from "./components/AddNewColumn";
import Column from "./components/Column"; import Column from "./components/Column";
import HeaderWorkspace from "./components/HeaderWorkspace"; import HeaderWorkspace from "./components/HeaderWorkspace";
import TaskDetailModal from "./components/task-detail/TaskDetailModal"; import TaskDetailModal from "./components/task-detail/TaskDetailModal";
import { useGetProject } from "./project/hooks/useProjectData"; import { useGetProject, useGetProjectDetail } from "./project/hooks/useProjectData";
import type { ProjectDetailType } from "./project/types/ProjectTypes";
import { getProjectBackgroundStyle } from "./project/utils/getProjectBackgroundStyle";
import { useUpdateTaskPhase } from "./task-phase/hooks/useTaskPhaseData"; import { useUpdateTaskPhase } from "./task-phase/hooks/useTaskPhaseData";
import type { TaskPhaseItemType } from "./task-phase/types/TaskPhaseTypes"; import type { TaskPhaseItemType } from "./task-phase/types/TaskPhaseTypes";
import { useChangeTaskPhase, useChangeTaskPriority } from "./task/hooks/useTaskData"; import { useChangeTaskPhase, useChangeTaskPriority } from "./task/hooks/useTaskData";
@@ -25,9 +27,12 @@ const Workspace: FC = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { slug: projectId = "" } = useParams<{ slug: string }>(); const { slug: projectId = "" } = useParams<{ slug: string }>();
const { data: project, isPending } = useGetProject(projectId); const { data: project, isPending } = useGetProject(projectId);
const changeTaskPhase = useChangeTaskPhase(); const { data: projectDetailData } = useGetProjectDetail(projectId);
const changeTaskPriority = useChangeTaskPriority(); const projectDetail: ProjectDetailType | undefined =
const updateTaskPhase = useUpdateTaskPhase(); projectDetailData?.data?.project ?? projectDetailData?.data;
const { mutate: changeTaskPhase } = useChangeTaskPhase();
const { mutate: changeTaskPriority } = useChangeTaskPriority();
const { mutate: updateTaskPhase } = useUpdateTaskPhase();
const [columns, setColumns] = useState<ColumnType[]>([]); const [columns, setColumns] = useState<ColumnType[]>([]);
const [draggedTask, setDraggedTask] = useState<Task | null>(null); const [draggedTask, setDraggedTask] = useState<Task | null>(null);
const [draggedColumnId, setDraggedColumnId] = useState<string | null>(null); const [draggedColumnId, setDraggedColumnId] = useState<string | null>(null);
@@ -75,7 +80,7 @@ const Workspace: FC = () => {
updateTaskPhaseItems(current, (items) => reorderTaskItems(items, activeTask.id, index)), updateTaskPhaseItems(current, (items) => reorderTaskItems(items, activeTask.id, index)),
); );
changeTaskPriority.mutate( changeTaskPriority(
{ srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId }, { srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId },
{ {
onError: (error: ErrorType) => { onError: (error: ErrorType) => {
@@ -122,12 +127,12 @@ const Workspace: FC = () => {
setSelectedTask({ ...activeTask, columnId }); setSelectedTask({ ...activeTask, columnId });
} }
changeTaskPhase.mutate( changeTaskPhase(
{ id: activeTask.id, params: { taskPhaseId: columnId }, projectId }, { id: activeTask.id, params: { taskPhaseId: columnId }, projectId },
{ {
onSuccess: () => { onSuccess: () => {
if (destTaskId) { if (destTaskId) {
changeTaskPriority.mutate( changeTaskPriority(
{ srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId }, { srcId: activeTask.id, destId: destTaskId, taskPhaseId: columnId, projectId },
{ {
onError: (error: ErrorType) => { onError: (error: ErrorType) => {
@@ -202,7 +207,7 @@ const Workspace: FC = () => {
if (!movedColumn?.order) return; if (!movedColumn?.order) return;
updateTaskPhase.mutate( updateTaskPhase(
{ id: draggedColumnId, params: { order: movedColumn.order }, projectId }, { id: draggedColumnId, params: { order: movedColumn.order }, projectId },
{ {
onError: (error: ErrorType) => { onError: (error: ErrorType) => {
@@ -227,12 +232,22 @@ const Workspace: FC = () => {
} }
}; };
const handleColumnTitleUpdated = (columnId: string, title: string) => {
setColumns((prev) => prev.map((column) => (column.id === columnId ? { ...column, title } : column)));
};
if (isPending) { if (isPending) {
return <PageLoading />; return <PageLoading />;
} }
return ( return (
<div className="bg-[#01347A] h-full min-h-0 rounded-none xl:rounded-[32px] overflow-hidden flex flex-col"> <div
className="h-full min-h-0 rounded-none xl:rounded-[32px] overflow-hidden flex flex-col"
style={getProjectBackgroundStyle({
backgroundColor: projectDetail?.backgroundColor,
backgroundPicture: projectDetail?.backgroundPicture,
})}
>
<HeaderWorkspace projectName={project?.data?.name ?? ""} /> <HeaderWorkspace projectName={project?.data?.name ?? ""} />
<div className="flex-1 min-h-0 flex flex-col px-3 sm:px-4 xl:px-8 py-4 xl:py-6"> <div className="flex-1 min-h-0 flex flex-col px-3 sm:px-4 xl:px-8 py-4 xl:py-6">
<DragDropContext onDragStart={handleTaskDragStart} onDragEnd={handleTaskDragEnd}> <DragDropContext onDragStart={handleTaskDragStart} onDragEnd={handleTaskDragEnd}>
@@ -249,6 +264,7 @@ const Workspace: FC = () => {
onColumnDrop={handleColumnDrop} onColumnDrop={handleColumnDrop}
onTaskClick={setSelectedTask} onTaskClick={setSelectedTask}
onColumnDeleted={handleColumnDeleted} onColumnDeleted={handleColumnDeleted}
onColumnTitleUpdated={handleColumnTitleUpdated}
/> />
))} ))}
-5
View File
@@ -73,12 +73,7 @@ const WorkspaceList: FC = () => {
className="size-4 rounded-full shrink-0" className="size-4 rounded-full shrink-0"
style={{ backgroundColor: item.color }} style={{ backgroundColor: item.color }}
/> />
<Link
to={Pages.taskmanager.workspace + item.id}
className="text-[#0047FF] hover:opacity-70 transition-opacity"
>
{item.name} {item.name}
</Link>
</div> </div>
</Td> </Td>
<Td text={item.description ?? ""} /> <Td text={item.description ?? ""} />
+14
View File
@@ -12,6 +12,15 @@ const OtherSubMenu: FC = () => {
const isActive = (name: string) => location.pathname.includes(name); const isActive = (name: string) => location.pathname.includes(name);
const isTaskManagerActive =
location.pathname.startsWith(Pages.taskmanager.workspace) ||
location.pathname === Pages.taskmanager.workspaceList ||
location.pathname.startsWith(Pages.taskmanager.updateWorkspace) ||
location.pathname === Pages.taskmanager.createWorkspace ||
location.pathname === Pages.taskmanager.createProject ||
location.pathname.startsWith(Pages.taskmanager.updateProject) ||
location.pathname.startsWith(Pages.taskmanager.projectList);
return ( return (
<div className="py-12"> <div className="py-12">
<div className="flex gap-3 items-center border-b pb-10 px-6"> <div className="flex gap-3 items-center border-b pb-10 px-6">
@@ -70,6 +79,11 @@ const OtherSubMenu: FC = () => {
link={Pages.messages.list} link={Pages.messages.list}
activeName="contacts_us" activeName="contacts_us"
/> />
<SubMenuItem
title={t("sidebar.taskmanager")}
isActive={isTaskManagerActive}
link={Pages.taskmanager.workspaceList}
/>
</div> </div>
</div> </div>
); );