Files
danak-admin/src/pages/taskmanager/workspace.tsx
T
2026-07-11 11:06:43 +03:30

126 lines
4.2 KiB
TypeScript

import { useMemo, useState, type FC } from "react";
import { useParams } from "react-router-dom";
import AddNewColumn from "./components/AddNewColumn";
import Column from "./components/Column";
import HeaderWorkspace from "./components/HeaderWorkspace";
import TaskDetailModal from "./components/task-detail/TaskDetailModal";
import tasksData from "./data/tasks.json";
import type { TaskPhaseItemType } from "./task-phase/types/TaskPhaseTypes";
import type { Task, WorkspaceData } from "./types";
import { reorderColumns } from "./utils/reorderColumns";
import { reorderTasks } from "./utils/reorderTasks";
const Workspace: FC = () => {
const { slug: projectId = "" } = useParams<{ slug: string }>();
const [columns, setColumns] = useState(
(tasksData as WorkspaceData).columns,
);
const [tasks, setTasks] = useState<Task[]>(tasksData.tasks as Task[]);
const [draggedTaskId, setDraggedTaskId] = useState<string | null>(null);
const [draggedColumnId, setDraggedColumnId] = useState<string | null>(null);
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
const tasksByColumn = useMemo(() => {
return columns.reduce<Record<string, Task[]>>((acc, column) => {
acc[column.id] = tasks
.filter((task) => task.columnId === column.id)
.sort((a, b) => a.order - b.order);
return acc;
}, {});
}, [columns, tasks]);
const handleDragStart = (taskId: string) => {
setDraggedTaskId(taskId);
};
const handleDragEnd = () => {
setDraggedTaskId(null);
};
const handleDrop = (columnId: string, index: number) => {
if (!draggedTaskId) return;
setTasks((prev) => reorderTasks(prev, draggedTaskId, columnId, index));
setDraggedTaskId(null);
};
const handleColumnDragStart = (columnId: string) => {
setDraggedColumnId(columnId);
};
const handleColumnDragEnd = () => {
setDraggedColumnId(null);
};
const handleColumnDrop = (overColumnId: string) => {
if (!draggedColumnId || draggedColumnId === overColumnId) return;
setColumns((prev) => reorderColumns(prev, draggedColumnId, overColumnId));
setDraggedColumnId(null);
};
const handleColumnCreated = (phase: TaskPhaseItemType) => {
setColumns((prev) => [
...prev,
{
id: phase.id,
title: phase.name,
color: phase.color,
order: phase.order,
},
]);
};
const handleColumnDeleted = (columnId: string) => {
setColumns((prev) => prev.filter((column) => column.id !== columnId));
setTasks((prev) => prev.filter((task) => task.columnId !== columnId));
if (selectedTask?.columnId === columnId) {
setSelectedTask(null);
}
};
const selectedTaskColumn = selectedTask
? columns.find((column) => column.id === selectedTask.columnId)
: null;
return (
<div className="bg-[#01347A] h-full rounded-none xl:rounded-[32px] overflow-hidden flex flex-col">
<HeaderWorkspace />
<div className="flex-1 min-h-0 overflow-x-auto overflow-y-hidden overscroll-x-contain">
<div className="flex gap-3 sm:gap-4 xl:gap-7 px-3 sm:px-4 xl:px-8 pt-4 xl:pt-6 pb-4 xl:pb-6 h-full items-start w-max min-w-full">
{columns.map((column) => (
<Column
key={column.id}
column={column}
tasks={tasksByColumn[column.id] ?? []}
draggedTaskId={draggedTaskId}
draggedColumnId={draggedColumnId}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDrop={handleDrop}
onColumnDragStart={handleColumnDragStart}
onColumnDragEnd={handleColumnDragEnd}
onColumnDrop={handleColumnDrop}
onTaskClick={setSelectedTask}
onColumnDeleted={handleColumnDeleted}
/>
))}
<AddNewColumn
projectId={projectId}
nextOrder={columns.length}
onColumnCreated={handleColumnCreated}
/>
</div>
</div>
<TaskDetailModal
open={selectedTask !== null}
task={selectedTask}
statusLabel={selectedTaskColumn?.title ?? ""}
onClose={() => setSelectedTask(null)}
/>
</div>
);
};
export default Workspace;