Created
October 28, 2019 15:55
-
-
Save rethna2/83afd1671ef7932e898d02f67f545e6e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useCallback, useRef } from "react"; | |
import { DndProvider, useDrag, useDrop } from "react-dnd"; | |
import HTML5Backend from "react-dnd-html5-backend"; | |
import update from "immutability-helper"; | |
const tasksList = [ | |
{ _id: 1, title: "First Task", status: "backlog" }, | |
{ _id: 2, title: "Second Task", status: "backlog" }, | |
{ _id: 3, title: "Third Task", status: "backlog" }, | |
{ _id: 4, title: "Fourth Task", status: "new" }, | |
{ _id: 5, title: "Fifth Task", status: "new" }, | |
{ _id: 6, title: "Sixth Task", status: "wip" }, | |
{ _id: 7, title: "Seventh Task", status: "review" }, | |
{ _id: 8, title: "Eighth Task", status: "review" }, | |
{ _id: 9, title: "Ninth Task", status: "done" }, | |
{ _id: 10, title: "Tenth Task", status: "done" } | |
]; | |
const channels = ["backlog", "new", "wip", "review", "done"]; | |
const labelsMap = { | |
backlog: "Backlog", | |
new: "To Do", | |
wip: "In Progress", | |
review: "Review", | |
done: "Done" | |
}; | |
const classes = { | |
board: { | |
display: "flex", | |
margin: "0 auto", | |
width: "90vw", | |
fontFamily: 'Arial, "Helvetica Neue", sans-serif' | |
}, | |
column: { | |
minWidth: 200, | |
width: "18vw", | |
height: "80vh", | |
margin: "0 auto", | |
backgroundColor: "#FCC8B2" | |
}, | |
columnHead: { | |
textAlign: "center", | |
padding: 10, | |
fontSize: "1.2em", | |
backgroundColor: "#C6D8AF" | |
}, | |
item: { | |
padding: 10, | |
margin: 10, | |
fontSize: "0.8em", | |
cursor: "pointer", | |
backgroundColor: "white" | |
} | |
}; | |
const Kanban = () => { | |
const [tasks, setTaskStatus] = useState(tasksList); | |
const changeTaskStatus = useCallback( | |
(id, status) => { | |
let task = tasks.find(task => task._id === id); | |
const taskIndex = tasks.indexOf(task); | |
task = { ...task, status }; | |
let newTasks = update(tasks, { | |
[taskIndex]: { $set: task } | |
}); | |
setTaskStatus(newTasks); | |
}, | |
[tasks] | |
); | |
return ( | |
<main> | |
<header> Kanban Board </header> | |
<DndProvider backend={HTML5Backend}> | |
<section style={classes.board}> | |
{channels.map(channel => ( | |
<KanbanColumn | |
key={channel} | |
status={channel} | |
changeTaskStatus={changeTaskStatus} | |
> | |
<div style={classes.column}> | |
<div style={classes.columnHead}>{labelsMap[channel]}</div> | |
<div> | |
{tasks | |
.filter(item => item.status === channel) | |
.map(item => ( | |
<KanbanItem key={item._id} id={item._id}> | |
<div style={classes.item}>{item.title}</div> | |
</KanbanItem> | |
))} | |
</div> | |
</div> | |
</KanbanColumn> | |
))} | |
</section> | |
</DndProvider> | |
</main> | |
); | |
}; | |
export default Kanban; | |
const KanbanColumn = ({ status, changeTaskStatus, children }) => { | |
const ref = useRef(null); | |
const [, drop] = useDrop({ | |
accept: "card", | |
drop(item) { | |
changeTaskStatus(item.id, status); | |
} | |
}); | |
drop(ref); | |
return <div ref={ref}> {children}</div>; | |
}; | |
const KanbanItem = ({ id, children }) => { | |
const ref = useRef(null); | |
const [{ isDragging }, drag] = useDrag({ | |
item: { type: "card", id }, | |
collect: monitor => ({ | |
isDragging: monitor.isDragging() | |
}) | |
}); | |
const opacity = isDragging ? 0 : 1; | |
drag(ref); | |
return ( | |
<div ref={ref} style={{ opacity }}> | |
{children} | |
</div> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment