diff --git a/frontend/src/components/kanbanBoard/columnContainer.jsx b/frontend/src/components/kanbanBoard/columnContainer.jsx
index 5b9648e..d6f4565 100644
--- a/frontend/src/components/kanbanBoard/columnContainer.jsx
+++ b/frontend/src/components/kanbanBoard/columnContainer.jsx
@@ -4,28 +4,13 @@ import { useMemo } from "react";
import { TaskCard } from "./taskCard";
export function ColumnContainer({ column, createTask, tasks, deleteTask, updateTask }) {
+ // Memoize task IDs to prevent unnecessary recalculations
const tasksIds = useMemo(() => {
return tasks.map((task) => task.id);
}, [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 (
+ {/* Provide a SortableContext for the tasks within the column */}
+ {/* Render TaskCard for each task in the column */}
{tasks.map((task) => (
useSortable({ ...props, disabled: false })}
/>
))}
diff --git a/frontend/src/components/kanbanBoard/kanbanBoard.jsx b/frontend/src/components/kanbanBoard/kanbanBoard.jsx
index 69cf2f4..ca393c5 100644
--- a/frontend/src/components/kanbanBoard/kanbanBoard.jsx
+++ b/frontend/src/components/kanbanBoard/kanbanBoard.jsx
@@ -8,14 +8,13 @@ import { axiosInstance } from "src/api/AxiosConfig";
export function KanbanBoard() {
const [columns, setColumns] = useState([]);
- const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
const [boardId, setBoardData] = useState();
const [isLoading, setLoading] = useState(false);
const [tasks, setTasks] = useState([]);
-
- const [activeColumn, setActiveColumn] = useState(null);
-
const [activeTask, setActiveTask] = useState(null);
+ const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
+
+ // ---------------- END STATE INITIATE ----------------
const sensors = useSensors(
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(() => {
const fetchData = async () => {
try {
@@ -88,6 +157,8 @@ export function KanbanBoard() {
fetchBoardData();
}, []);
+ // ---------------- END Fetch Data ----------------
+
return (
- {activeColumn && (
- task.columnId === activeColumn.id)}
- />
- )}
{activeTask && }
,
document.body
@@ -140,97 +202,31 @@ export function KanbanBoard() {
);
- function createTask(columnId, setTasks) {
- 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);
- }
-
+ // Handle the start of a drag event
function onDragStart(event) {
- if (event.active.data.current?.type === "Column") {
- setActiveColumn(event.active.data.current.column);
- return;
- }
-
+ // Check if the dragged item is a Task
if (event.active.data.current?.type === "Task") {
setActiveTask(event.active.data.current.task);
return;
}
}
+ // Handle the end of a drag event
function onDragEnd(event) {
- setActiveColumn(null);
+ // Reset active column and task after the drag ends
setActiveTask(null);
const { active, over } = event;
- if (!over) return;
+ if (!over) return; // If not dropped over anything, exit
const activeId = active.id;
const overId = over.id;
- const isActiveAColumn = active.data.current?.type === "Column";
const isActiveATask = active.data.current?.type === "Task";
const isOverAColumn = over.data.current?.type === "Column";
const isOverATask = over.data.current?.type === "Task";
- // Reorder columns if the dragged item is a 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
+ // Reorder logic for Tasks within the same column
if (isActiveATask && isOverATask) {
setTasks((tasks) => {
const activeIndex = tasks.findIndex((t) => t.id === activeId);
@@ -249,6 +245,7 @@ export function KanbanBoard() {
tasks[activeIndex].columnId = overId;
+ // API call to update task's columnId
axiosInstance
.put(`todo/change_task_list_board/`, { todo_id: activeId, new_list_board_id: overId, new_index: 0 })
.then((response) => {})
@@ -261,25 +258,28 @@ export function KanbanBoard() {
}
}
+ // Handle the drag-over event
function onDragOver(event) {
const { active, over } = event;
- if (!over) return;
+ if (!over) return; // If not over anything, exit
const activeId = active.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 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) {
setTasks((tasks) => {
const activeIndex = tasks.findIndex((t) => t.id === activeId);
const overIndex = tasks.findIndex((t) => t.id === overId);
+ // If moving to a different column, update columnId
if (tasks[activeIndex].columnId !== tasks[overIndex].columnId) {
tasks[activeIndex].columnId = tasks[overIndex].columnId;
return arrayMove(tasks, activeIndex, overIndex - 1);
@@ -291,6 +291,7 @@ export function KanbanBoard() {
const isOverAColumn = over.data.current?.type === "Column";
+ // Move the Task to a different column and update columnId
if (isActiveATask && isOverAColumn) {
setTasks((tasks) => {
const activeIndex = tasks.findIndex((t) => t.id === activeId);