From 951e71e184476df2d0a35ec9a523653df60efa92 Mon Sep 17 00:00:00 2001 From: malkoe Date: Wed, 17 May 2023 09:22:23 +0800 Subject: [PATCH] First Attempt --- db.json | 35 ++++++++++-- src/App.tsx | 97 +++++++++++++++++++++++++++------ src/api/index.tsx | 23 +++++++- src/components/KanbanColumn.tsx | 3 +- 4 files changed, 130 insertions(+), 28 deletions(-) diff --git a/db.json b/db.json index aababa0..70c3093 100644 --- a/db.json +++ b/db.json @@ -1,11 +1,34 @@ { "tasks": { "Backlog": [ - { "id": "task1", "name": "Write specs" }, - { "id": "task2", "name": "Design mockups" } + { + "id": "task1", + "name": "Write specs" + }, + { + "id": "task2", + "name": "Design mockups" + } ], - "In Progress": [{ "id": "task3", "name": "Develop features" }], - "In Review": [{ "id": "task4", "name": "Test application" }], - "Done": [{ "id": "task5", "name": "Deploy application" }] + "In Progress": [ + { + "id": "task4", + "name": "Test application", + "isDragging": false + } + ], + "In Review": [], + "Done": [ + { + "id": "task5", + "name": "Deploy application", + "isDragging": false + }, + { + "id": "task3", + "name": "Develop features", + "isDragging": false + } + ] } -} +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 9f58580..4b80244 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import "./App.css"; import KanbanColumn from "./components/KanbanColumn"; import { Column, DraggableTask, DraggedTaskInfo, Task } from "./types"; +import { fetchKanbanTasks, updateKanbanTasks } from "./api"; export default function App() { const [kanbanColumns, setKanbanColumns] = useState>({ @@ -11,41 +12,101 @@ export default function App() { Done: [], }); - // Fetch Tasks useEffect(() => { - // TODO: Pull state from json-server - // Hint: You may want to use the fetchTasks function from api/index.tsx + fetchKanbanTasks() + .then((tasks) => { + const columns: Record = { + Backlog: [], + "In Progress": [], + "In Review": [], + Done: [], + }; + Object.entries(tasks).forEach(([status, tasks]) => { + columns[status as Column] = tasks as DraggableTask[]; + }); + setKanbanColumns(columns); + }) + .catch((error) => { + console.error(error); + }); }, []); - // Hint: You will need these states for dragging and dropping tasks const [draggedTaskInfo, setDraggedTaskInfo] = useState(null); const [hoveredColumn, setHoveredColumn] = useState(null); const handleTaskDragStart = (task: Task, column: Column) => { - // TODO: Implement functionality for when the drag starts - }; + setDraggedTaskInfo({ task: task, column: column }) + setHoveredColumn(column) + } const handleTaskDragOver = (e: React.DragEvent, column: Column) => { e.preventDefault(); - // TODO: Implement functionality for when an item is being dragged over a column - // Hint: Remember to check if the item is being dragged over a new column + if (hoveredColumn !== column) { + setHoveredColumn(column); + } + if (draggedTaskInfo && hoveredColumn) { + const { task, column: fromColumn } = draggedTaskInfo; + const newColumns = { ...kanbanColumns }; + for (const col in newColumns) { + if (col !== column && col !== fromColumn) { + newColumns[col] = newColumns[col].filter((t) => t.id !== task.id); + } + } + if (!newColumns[hoveredColumn].some((t) => t.id === task.id)) { + newColumns[hoveredColumn] = [ + ...newColumns[hoveredColumn], + { ...task, isDragging: true }, + ]; + } + setKanbanColumns(newColumns); + } }; + const handleTaskDrop = (column: Column) => { - // TODO: Implement functionality for when the item is dropped - // Hint: Make sure to handle the cases when the item is dropped in the same column or in a new column - }; + if (draggedTaskInfo) { + const { task, column: fromColumn } = draggedTaskInfo + const newColumns = { ...kanbanColumns } + + newColumns[column] = newColumns[column].filter((t) => t.id !== task.id) + newColumns[fromColumn] = newColumns[fromColumn].filter( + (t) => t.id !== task.id + ) + + newColumns[column].push({ ...task, isDragging: false }) + + setKanbanColumns(newColumns) + updateKanbanTasks(newColumns) + + setDraggedTaskInfo(null) + setHoveredColumn(null) + } + } const getTasksForColumn = (column: Column): DraggableTask[] => { - // TODO: Handle the bug where card dragged over itself shows duplicate - // Hint: Consider how you can use the dragInfo and overColumn states to prevent this - return [{ id: "1", name: "Task 1", isDragging: false }]; - }; + return kanbanColumns[column] + } const handleTaskDragEnd = () => { - // TODO: Implement functionality for when the drag ends - // Hint: Remember to handle the case when the item is released back to its current column - }; + if (draggedTaskInfo) { + const { task, column: fromColumn } = draggedTaskInfo + const newColumns = { ...kanbanColumns } + + for (const col in newColumns) { + if (col != fromColumn) { + const index = newColumns[col].findIndex((t) => t.id === task.id) + if (index !== -1) { + newColumns[col].splice(index, 1) + } + } + } + + setKanbanColumns(newColumns) + + setDraggedTaskInfo(null) + setHoveredColumn(null) + } + } return (
diff --git a/src/api/index.tsx b/src/api/index.tsx index 17d63ea..7ab468e 100644 --- a/src/api/index.tsx +++ b/src/api/index.tsx @@ -1,10 +1,27 @@ const apiUrl = "http://localhost:3001"; export const fetchKanbanTasks = async () => { - // TODO: Implement functionality to fetch tasks from the server + const response = await fetch(`${apiUrl}/tasks`); + if (response.ok) { + const tasks = await response.json(); + return tasks; + } else { + throw new Error(response.statusText); + } }; export const updateKanbanTasks = async (tasks: any) => { - // TODO: Save the new order of the items when tasks are modified to the server - // Hint: You may want to use the fetch API with a "PUT" method + try { + const response = await fetch(`${apiUrl}/tasks`, { + method: "PUT", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(tasks) + }) + const data = await response.json() + console.log(data) + } catch (error) { + console.error(error) + } }; diff --git a/src/components/KanbanColumn.tsx b/src/components/KanbanColumn.tsx index 6fd89ba..a7ce75a 100644 --- a/src/components/KanbanColumn.tsx +++ b/src/components/KanbanColumn.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import { Column, DraggableTask, Task } from "../types"; interface KanbanColumnProps { @@ -18,6 +18,7 @@ export default function KanbanColumn({ onTaskDrop, onTaskDragEnd, }: KanbanColumnProps) { + return (