mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-20 06:24:07 +01:00
Completely remove drag functionality of column
This commit is contained in:
parent
5051f1f460
commit
fd052fb613
@ -4,28 +4,13 @@ import { useMemo } from "react";
|
|||||||
import { TaskCard } from "./taskCard";
|
import { TaskCard } from "./taskCard";
|
||||||
|
|
||||||
export function ColumnContainer({ column, createTask, tasks, deleteTask, updateTask }) {
|
export function ColumnContainer({ column, createTask, tasks, deleteTask, updateTask }) {
|
||||||
|
// Memoize task IDs to prevent unnecessary recalculations
|
||||||
const tasksIds = useMemo(() => {
|
const tasksIds = useMemo(() => {
|
||||||
return tasks.map((task) => task.id);
|
return tasks.map((task) => task.id);
|
||||||
}, [tasks]);
|
}, [tasks]);
|
||||||
|
|
||||||
const {
|
|
||||||
setNodeRef: columnNodeRef,
|
|
||||||
attributes: columnAttributes,
|
|
||||||
listeners: columnListeners,
|
|
||||||
} = useSortable({
|
|
||||||
id: column.id,
|
|
||||||
data: {
|
|
||||||
type: "Column",
|
|
||||||
column,
|
|
||||||
},
|
|
||||||
disabled: true, // Disable drag for the entire column
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={columnNodeRef}
|
|
||||||
{...columnAttributes}
|
|
||||||
{...columnListeners}
|
|
||||||
className="
|
className="
|
||||||
bg-[#f1f2f4]
|
bg-[#f1f2f4]
|
||||||
w-[280px]
|
w-[280px]
|
||||||
@ -49,14 +34,16 @@ export function ColumnContainer({ column, createTask, tasks, deleteTask, updateT
|
|||||||
|
|
||||||
{/* Column task container */}
|
{/* Column task container */}
|
||||||
<div className="flex flex-grow flex-col gap-2 p-1 overflow-x-hidden overflow-y-auto">
|
<div className="flex flex-grow flex-col gap-2 p-1 overflow-x-hidden overflow-y-auto">
|
||||||
|
{/* Provide a SortableContext for the tasks within the column */}
|
||||||
<SortableContext items={tasksIds}>
|
<SortableContext items={tasksIds}>
|
||||||
|
{/* Render TaskCard for each task in the column */}
|
||||||
{tasks.map((task) => (
|
{tasks.map((task) => (
|
||||||
<TaskCard
|
<TaskCard
|
||||||
key={task.id}
|
key={task.id}
|
||||||
task={task}
|
task={task}
|
||||||
deleteTask={deleteTask}
|
deleteTask={deleteTask}
|
||||||
updateTask={updateTask}
|
updateTask={updateTask}
|
||||||
// Adjust the useSortable hook for tasks
|
// Adjust the useSortable hook for tasks to enable dragging
|
||||||
useSortable={(props) => useSortable({ ...props, disabled: false })}
|
useSortable={(props) => useSortable({ ...props, disabled: false })}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -8,14 +8,13 @@ import { axiosInstance } from "src/api/AxiosConfig";
|
|||||||
|
|
||||||
export function KanbanBoard() {
|
export function KanbanBoard() {
|
||||||
const [columns, setColumns] = useState([]);
|
const [columns, setColumns] = useState([]);
|
||||||
const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
|
|
||||||
const [boardId, setBoardData] = useState();
|
const [boardId, setBoardData] = useState();
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
const [tasks, setTasks] = useState([]);
|
const [tasks, setTasks] = useState([]);
|
||||||
|
|
||||||
const [activeColumn, setActiveColumn] = useState(null);
|
|
||||||
|
|
||||||
const [activeTask, setActiveTask] = useState(null);
|
const [activeTask, setActiveTask] = useState(null);
|
||||||
|
const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
|
||||||
|
|
||||||
|
// ---------------- END STATE INITIATE ----------------
|
||||||
|
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor, {
|
useSensor(PointerSensor, {
|
||||||
@ -25,6 +24,76 @@ export function KanbanBoard() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ---------------- Task Handlers ----------------
|
||||||
|
const handleTaskUpdate = (tasks, setTasks, updatedTask) => {
|
||||||
|
const updatedTasks = tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task));
|
||||||
|
setTasks(updatedTasks);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleApiError = (error, action) => {
|
||||||
|
console.error(`Error ${action}:`, error);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createTask = async (columnId, setTasks) => {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.post("todo/", {
|
||||||
|
title: `Task ${tasks.length + 1}`,
|
||||||
|
importance: 1,
|
||||||
|
difficulty: 1,
|
||||||
|
challenge: false,
|
||||||
|
fromSystem: false,
|
||||||
|
is_active: false,
|
||||||
|
is_full_day_event: false,
|
||||||
|
completed: false,
|
||||||
|
priority: 1,
|
||||||
|
list_board: columnId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const newTask = {
|
||||||
|
id: response.data.id,
|
||||||
|
columnId,
|
||||||
|
content: response.data.title,
|
||||||
|
};
|
||||||
|
|
||||||
|
setTasks((tasks) => [...tasks, newTask]);
|
||||||
|
} catch (error) {
|
||||||
|
handleApiError(error, "creating task");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTask = async (id, tasks, setTasks) => {
|
||||||
|
try {
|
||||||
|
await axiosInstance.delete(`todo/${id}/`);
|
||||||
|
const newTasks = tasks.filter((task) => task.id !== id);
|
||||||
|
setTasks(newTasks);
|
||||||
|
} catch (error) {
|
||||||
|
handleApiError(error, "deleting task");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateTask = async (id, content, tasks, setTasks) => {
|
||||||
|
try {
|
||||||
|
if (content === "") {
|
||||||
|
await deleteTask(id, tasks, setTasks);
|
||||||
|
} else {
|
||||||
|
const response = await axiosInstance.put(`todo/${id}/`, { content });
|
||||||
|
|
||||||
|
const updatedTask = {
|
||||||
|
id,
|
||||||
|
columnId: response.data.list_board,
|
||||||
|
content: response.data.title,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleTaskUpdate(tasks, setTasks, updatedTask);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
handleApiError(error, "updating task");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------- END Task Handlers ----------------
|
||||||
|
|
||||||
|
// ---------------- Fetch Data ----------------
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
@ -88,6 +157,8 @@ export function KanbanBoard() {
|
|||||||
fetchBoardData();
|
fetchBoardData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// ---------------- END Fetch Data ----------------
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="
|
className="
|
||||||
@ -123,15 +194,6 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
{createPortal(
|
{createPortal(
|
||||||
<DragOverlay className="bg-white" dropAnimation={null} zIndex={20}>
|
<DragOverlay className="bg-white" dropAnimation={null} zIndex={20}>
|
||||||
{activeColumn && (
|
|
||||||
<ColumnContainerCard
|
|
||||||
column={activeColumn}
|
|
||||||
createTask={createTask}
|
|
||||||
deleteTask={deleteTask}
|
|
||||||
updateTask={updateTask}
|
|
||||||
tasks={tasks.filter((task) => task.columnId === activeColumn.id)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{activeTask && <TaskCard task={activeTask} deleteTask={deleteTask} updateTask={updateTask} />}
|
{activeTask && <TaskCard task={activeTask} deleteTask={deleteTask} updateTask={updateTask} />}
|
||||||
</DragOverlay>,
|
</DragOverlay>,
|
||||||
document.body
|
document.body
|
||||||
@ -140,97 +202,31 @@ export function KanbanBoard() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
function createTask(columnId, setTasks) {
|
// Handle the start of a drag event
|
||||||
const newTaskData = {
|
|
||||||
title: `Task ${tasks.length + 1}`,
|
|
||||||
importance: 1,
|
|
||||||
difficulty: 1,
|
|
||||||
challenge: false,
|
|
||||||
fromSystem: false,
|
|
||||||
is_active: false,
|
|
||||||
is_full_day_event: false,
|
|
||||||
completed: false,
|
|
||||||
priority: 1,
|
|
||||||
list_board: columnId,
|
|
||||||
};
|
|
||||||
|
|
||||||
axiosInstance
|
|
||||||
.post("todo/", newTaskData)
|
|
||||||
.then((response) => {
|
|
||||||
const newTask = {
|
|
||||||
id: response.data.id,
|
|
||||||
columnId,
|
|
||||||
content: response.data.title,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error creating task:", error);
|
|
||||||
});
|
|
||||||
setTasks((tasks) => [...tasks, newTask]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteTask(id) {
|
|
||||||
const newTasks = tasks.filter((task) => task.id !== id);
|
|
||||||
axiosInstance
|
|
||||||
.delete(`todo/${id}/`)
|
|
||||||
.then((response) => {
|
|
||||||
setTasks(newTasks);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error deleting Task:", error);
|
|
||||||
});
|
|
||||||
setTasks(newTasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTask(id, content) {
|
|
||||||
const newTasks = tasks.map((task) => {
|
|
||||||
if (task.id !== id) return task;
|
|
||||||
return { ...task, content };
|
|
||||||
});
|
|
||||||
if (content === "") return deleteTask(id);
|
|
||||||
setTasks(newTasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDragStart(event) {
|
function onDragStart(event) {
|
||||||
if (event.active.data.current?.type === "Column") {
|
// Check if the dragged item is a Task
|
||||||
setActiveColumn(event.active.data.current.column);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.active.data.current?.type === "Task") {
|
if (event.active.data.current?.type === "Task") {
|
||||||
setActiveTask(event.active.data.current.task);
|
setActiveTask(event.active.data.current.task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the end of a drag event
|
||||||
function onDragEnd(event) {
|
function onDragEnd(event) {
|
||||||
setActiveColumn(null);
|
// Reset active column and task after the drag ends
|
||||||
setActiveTask(null);
|
setActiveTask(null);
|
||||||
|
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
if (!over) return;
|
if (!over) return; // If not dropped over anything, exit
|
||||||
|
|
||||||
const activeId = active.id;
|
const activeId = active.id;
|
||||||
const overId = over.id;
|
const overId = over.id;
|
||||||
|
|
||||||
const isActiveAColumn = active.data.current?.type === "Column";
|
|
||||||
const isActiveATask = active.data.current?.type === "Task";
|
const isActiveATask = active.data.current?.type === "Task";
|
||||||
const isOverAColumn = over.data.current?.type === "Column";
|
const isOverAColumn = over.data.current?.type === "Column";
|
||||||
const isOverATask = over.data.current?.type === "Task";
|
const isOverATask = over.data.current?.type === "Task";
|
||||||
|
|
||||||
// Reorder columns if the dragged item is a column
|
// Reorder logic for Tasks within the same column
|
||||||
if (isActiveAColumn && isOverAColumn) {
|
|
||||||
setColumns((columns) => {
|
|
||||||
const activeColumnIndex = columns.findIndex((col) => col.id === activeId);
|
|
||||||
const overColumnIndex = columns.findIndex((col) => col.id === overId);
|
|
||||||
|
|
||||||
const reorderedColumns = arrayMove(columns, activeColumnIndex, overColumnIndex);
|
|
||||||
|
|
||||||
return reorderedColumns;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reorder tasks within the same column
|
|
||||||
if (isActiveATask && isOverATask) {
|
if (isActiveATask && isOverATask) {
|
||||||
setTasks((tasks) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||||
@ -249,6 +245,7 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
tasks[activeIndex].columnId = overId;
|
tasks[activeIndex].columnId = overId;
|
||||||
|
|
||||||
|
// API call to update task's columnId
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.put(`todo/change_task_list_board/`, { todo_id: activeId, new_list_board_id: overId, new_index: 0 })
|
.put(`todo/change_task_list_board/`, { todo_id: activeId, new_list_board_id: overId, new_index: 0 })
|
||||||
.then((response) => {})
|
.then((response) => {})
|
||||||
@ -261,25 +258,28 @@ export function KanbanBoard() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the drag-over event
|
||||||
function onDragOver(event) {
|
function onDragOver(event) {
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
if (!over) return;
|
if (!over) return; // If not over anything, exit
|
||||||
|
|
||||||
const activeId = active.id;
|
const activeId = active.id;
|
||||||
const overId = over.id;
|
const overId = over.id;
|
||||||
|
|
||||||
if (activeId === overId) return;
|
if (activeId === overId) return; // If over the same element, exit
|
||||||
|
|
||||||
const isActiveATask = active.data.current?.type === "Task";
|
const isActiveATask = active.data.current?.type === "Task";
|
||||||
const isOverATask = over.data.current?.type === "Task";
|
const isOverATask = over.data.current?.type === "Task";
|
||||||
|
|
||||||
if (!isActiveATask) return;
|
if (!isActiveATask) return; // If not dragging a Task, exit
|
||||||
|
|
||||||
|
// Reorder logic for Tasks within the same column
|
||||||
if (isActiveATask && isOverATask) {
|
if (isActiveATask && isOverATask) {
|
||||||
setTasks((tasks) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||||
const overIndex = tasks.findIndex((t) => t.id === overId);
|
const overIndex = tasks.findIndex((t) => t.id === overId);
|
||||||
|
|
||||||
|
// If moving to a different column, update columnId
|
||||||
if (tasks[activeIndex].columnId !== tasks[overIndex].columnId) {
|
if (tasks[activeIndex].columnId !== tasks[overIndex].columnId) {
|
||||||
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
||||||
return arrayMove(tasks, activeIndex, overIndex - 1);
|
return arrayMove(tasks, activeIndex, overIndex - 1);
|
||||||
@ -291,6 +291,7 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
const isOverAColumn = over.data.current?.type === "Column";
|
const isOverAColumn = over.data.current?.type === "Column";
|
||||||
|
|
||||||
|
// Move the Task to a different column and update columnId
|
||||||
if (isActiveATask && isOverAColumn) {
|
if (isActiveATask && isOverAColumn) {
|
||||||
setTasks((tasks) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user