From 7369b303174f56b5fd5f360e56d355c1d004ee0b Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 3 May 2023 20:13:10 -0700 Subject: [PATCH] finished tasks --- .gitignore | 1 + src/App.tsx | 132 ++++++++++++++++++++++++-------- src/api/index.tsx | 31 ++++++-- src/components/KanbanColumn.tsx | 24 +++--- 4 files changed, 139 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 76a7616..a9fbbe2 100644 --- a/.gitignore +++ b/.gitignore @@ -296,3 +296,4 @@ $RECYCLE.BIN/ cat_files.sh contents.txt +db.backup.json diff --git a/src/App.tsx b/src/App.tsx index 9f58580..1cf2ff5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,55 +1,123 @@ -import React, { useEffect, useState } from "react"; -import "./App.css"; -import KanbanColumn from "./components/KanbanColumn"; -import { Column, DraggableTask, DraggedTaskInfo, Task } from "./types"; +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>({ - Backlog: [], + //prettier-ignore + const [kanbanColumns, setKanbanColumns] = useState< + Record + >({ + "Backlog": [], "In Progress": [], "In Review": [], - Done: [], - }); + "Done": [] + }) // Fetch Tasks useEffect(() => { - // TODO: Pull state from json-server - // Hint: You may want to use the fetchTasks function from api/index.tsx - }, []); + async function getTasks() { + try { + const tasks = await fetchKanbanTasks() + setKanbanColumns(tasks) + } catch (error) { + console.error("Error fetching tasks:", error) + } + } + getTasks() + }, []) - // Hint: You will need these states for dragging and dropping tasks - const [draggedTaskInfo, setDraggedTaskInfo] = useState(null); - const [hoveredColumn, setHoveredColumn] = useState(null); + 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 - }; + e.preventDefault() + + if (hoveredColumn !== column) { + setHoveredColumn(column) + } + + const { task, column: fromColumn } = draggedTaskInfo + const newColumns = { ...kanbanColumns } + + // remove task from old column + for (const col in newColumns) { + if (col !== column && col != fromColumn) { + const index = newColumns[col].findIndex((t) => t.id === task.id) + if (index !== -1) { + newColumns[col].splice(index, 1) + } + } + } + + // add task to new column + const index = newColumns[hoveredColumn].findIndex((t) => t.id === task.id) + if (index === -1) { + newColumns[hoveredColumn].push({ + ...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 - }; + const { task, column: fromColumn } = draggedTaskInfo + const newColumns = { ...kanbanColumns } + + // remove task from old columns + 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 - }; + // for dragging off the board + const { task, column: fromColumn } = draggedTaskInfo + const newColumns = { ...kanbanColumns } + + // remove task from old columns + 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 (
-

Codebase Mentor Kanban Board

+

+ Codebase Mentor Kanban Board +

- ); + ) } diff --git a/src/api/index.tsx b/src/api/index.tsx index 17d63ea..6189871 100644 --- a/src/api/index.tsx +++ b/src/api/index.tsx @@ -1,10 +1,29 @@ -const apiUrl = "http://localhost:3001"; +const apiUrl = "http://localhost:3001" export const fetchKanbanTasks = async () => { - // TODO: Implement functionality to fetch tasks from the server -}; + try { + const response = await fetch(`${apiUrl}/tasks`) + const tasks = await response.json() + return tasks + } catch (error) { + console.error("Error fetching tasks:", error) + throw error + } +} 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 updatedTasks = await response.json() + return updatedTasks + } catch (error) { + console.error("Error updating tasks:", error) + throw error + } +} diff --git a/src/components/KanbanColumn.tsx b/src/components/KanbanColumn.tsx index 6fd89ba..28c2772 100644 --- a/src/components/KanbanColumn.tsx +++ b/src/components/KanbanColumn.tsx @@ -1,13 +1,13 @@ -import React from "react"; -import { Column, DraggableTask, Task } from "../types"; +import React from "react" +import { Column, DraggableTask, Task } from "../types" interface KanbanColumnProps { - title: Column; - tasks: DraggableTask[]; - onTaskDragStart: (task: Task, column: Column) => void; - onTaskDragOver: (e: React.DragEvent, column: Column) => void; - onTaskDrop: (column: Column) => void; - onTaskDragEnd: () => void; + title: Column + tasks: DraggableTask[] + onTaskDragStart: (task: Task, column: Column) => void + onTaskDragOver: (e: React.DragEvent, column: Column) => void + onTaskDrop: (column: Column) => void + onTaskDragEnd: () => void } export default function KanbanColumn({ @@ -16,7 +16,7 @@ export default function KanbanColumn({ onTaskDragStart, onTaskDragOver, onTaskDrop, - onTaskDragEnd, + onTaskDragEnd }: KanbanColumnProps) { return (
(
  • onTaskDragStart(task, title)} onDragEnd={onTaskDragEnd} @@ -39,5 +41,5 @@ export default function KanbanColumn({ ))}
  • - ); + ) }