Fix Style of Kanban

This commit is contained in:
sosokker 2023-11-17 03:04:42 +07:00
parent 438d9b74b5
commit 297529472d
5 changed files with 81 additions and 85 deletions

View File

@ -1,6 +1,6 @@
import { SortableContext, useSortable } from "@dnd-kit/sortable"; import { SortableContext, useSortable } from "@dnd-kit/sortable";
import { BsFillTrashFill } from "react-icons/bs" import { BsFillTrashFill } from "react-icons/bs";
import { AiOutlinePlusCircle } from "react-icons/ai" import { AiOutlinePlusCircle } from "react-icons/ai";
import { CSS } from "@dnd-kit/utilities"; import { CSS } from "@dnd-kit/utilities";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import TaskCard from "./taskCard"; import TaskCard from "./taskCard";
@ -32,13 +32,11 @@ function ColumnContainer({ column, deleteColumn, updateColumn, createTask, tasks
ref={setNodeRef} ref={setNodeRef}
style={style} style={style}
className=" className="
bg-columnBackgroundColor
opacity-40 opacity-40
border-2 border-2
border-pink-500 border-blue-500
w-[350px] w-[350px]
h-[500px] max-h-[400px]
max-h-[500px]
rounded-md rounded-md
flex flex
flex-col flex-col
@ -51,10 +49,9 @@ function ColumnContainer({ column, deleteColumn, updateColumn, createTask, tasks
ref={setNodeRef} ref={setNodeRef}
style={style} style={style}
className=" className="
bg-columnBackgroundColor bg-[#f1f2f4]
w-[350px] w-[280px]
h-[500px] max-h-[400px]
max-h-[500px]
rounded-md rounded-md
flex flex
flex-col flex-col
@ -82,23 +79,10 @@ function ColumnContainer({ column, deleteColumn, updateColumn, createTask, tasks
justify-between justify-between
"> ">
<div className="flex gap-2"> <div className="flex gap-2">
<div
className="
flex
justify-center
items-center
bg-columnBackgroundColor
px-2
py-1
text-sm
rounded-full
">
0
</div>
{!editMode && column.title} {!editMode && column.title}
{editMode && ( {editMode && (
<input <input
className="bg-black focus:border-rose-500 border rounded outline-none px-2" className="bg-gray-200 focus:border-blue-500 border rounded-md outline-none px-2"
value={column.title} value={column.title}
onChange={e => updateColumn(column.id, e.target.value)} onChange={e => updateColumn(column.id, e.target.value)}
autoFocus autoFocus
@ -138,7 +122,7 @@ function ColumnContainer({ column, deleteColumn, updateColumn, createTask, tasks
</div> </div>
{/* Column footer */} {/* Column footer */}
<button <button
className="flex gap-2 items-center border-columnBackgroundColor border-2 rounded-md p-4 border-x-columnBackgroundColor hover:bg-mainBackgroundColor hover:text-rose-500 active:bg-black" className="flex gap-2 items-center rounded-md p-2 my-2 hover:bg-zinc-200 active:bg-zinc-400"
onClick={() => { onClick={() => {
createTask(column.id); createTask(column.id);
}}> }}>

View File

@ -0,0 +1,19 @@
import ColumnContainer from "./columnContainer";
function ColumnContainerCard({ column, deleteColumn, updateColumn, createTask, tasks, deleteTask, updateTask }) {
return (
<div className="card bg-[#f1f2f4] shadow p-4 my-2 border-2">
<ColumnContainer
column={column}
deleteColumn={deleteColumn}
updateColumn={updateColumn}
createTask={createTask}
tasks={tasks}
deleteTask={deleteTask}
updateTask={updateTask}
/>
</div>
);
}
export default ColumnContainerCard;

View File

@ -1,5 +1,5 @@
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import ColumnContainer from "./columnContainer"; import ColumnContainerCard from "./columnContainerWrapper";
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"; import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import { SortableContext, arrayMove } from "@dnd-kit/sortable"; import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
@ -124,7 +124,7 @@ function KanbanBoard() {
<div className="flex gap-4"> <div className="flex gap-4">
<SortableContext items={columnsId}> <SortableContext items={columnsId}>
{columns.map(col => ( {columns.map(col => (
<ColumnContainer <ColumnContainerCard
key={col.id} key={col.id}
column={col} column={col}
deleteColumn={deleteColumn} deleteColumn={deleteColumn}
@ -164,7 +164,7 @@ function KanbanBoard() {
{createPortal( {createPortal(
<DragOverlay> <DragOverlay>
{activeColumn && ( {activeColumn && (
<ColumnContainer <ColumnContainerCard
column={activeColumn} column={activeColumn}
deleteColumn={deleteColumn} deleteColumn={deleteColumn}
updateColumn={updateColumn} updateColumn={updateColumn}

View File

@ -1,11 +1,11 @@
import { useState } from "react"; import { useState } from "react";
import { BsFillTrashFill } from "react-icons/bs" import { BsFillTrashFill } from "react-icons/bs";
import { useSortable } from "@dnd-kit/sortable"; import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities"; import { CSS } from "@dnd-kit/utilities";
import TaskDetailModal from "./taskDetailModal";
function TaskCard({ task, deleteTask, updateTask }) { function TaskCard({ task, deleteTask, updateTask }) {
const [mouseIsOver, setMouseIsOver] = useState(false); const [mouseIsOver, setMouseIsOver] = useState(false);
const [editMode, setEditMode] = useState(true);
const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({ const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
id: task.id, id: task.id,
@ -13,7 +13,6 @@ function TaskCard({ task, deleteTask, updateTask }) {
type: "Task", type: "Task",
task, task,
}, },
disabled: editMode,
}); });
const style = { const style = {
@ -21,11 +20,9 @@ function TaskCard({ task, deleteTask, updateTask }) {
transform: CSS.Transform.toString(transform), transform: CSS.Transform.toString(transform),
}; };
const toggleEditMode = () => { {
setEditMode(prev => !prev); /* If card is dragged */
setMouseIsOver(false); }
};
if (isDragging) { if (isDragging) {
return ( return (
<div <div
@ -33,65 +30,44 @@ function TaskCard({ task, deleteTask, updateTask }) {
style={style} style={style}
className=" className="
opacity-30 opacity-30
bg-mainBackgroundColor p-2.5 h-[100px] min-h-[100px] items-center flex text-left rounded-xl border-2 border-gray-400 cursor-grab relative bg-mainBackgroundColor p-2.5 items-center flex text-left rounded-xl border-2 border-gray-400 cursor-grab relative
" "
/> />
); );
} }
if (editMode) { return (
return ( <div>
<TaskDetailModal />
<div <div
ref={setNodeRef} ref={setNodeRef}
style={style}
{...attributes} {...attributes}
{...listeners} {...listeners}
className="bg-mainBackgroundColor p-2.5 h-[100px] min-h-[100px] items-center flex text-left rounded-xl hover:ring-2 hover:ring-inset bg-zinc-400 ring-zinc-950 cursor-grab relative"> onClick={() => document.getElementById("task_detail_modal").showModal()}
<textarea style={style}
className=" className="justify-center items-center flex text-left rounded-xl cursor-grab relative hover:border-2 hover:border-blue-400 shadow bg-white"
h-[90%] onMouseEnter={() => {
w-full resize-none border-none rounded bg-transparent focus:outline-none setMouseIsOver(true);
" }}
value={task.content} onMouseLeave={() => {
autoFocus setMouseIsOver(false);
placeholder="Task content here" }}>
onBlur={toggleEditMode} <p
onKeyDown={e => { className="p-2.5 my-auto w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-xl shadow bg-white"
if (e.key === "Enter" && e.shiftKey) { onClick={() => document.getElementById("task_detail_modal").showModal()}>
toggleEditMode(); {task.content}
} </p>
}}
onChange={e => updateTask(task.id, e.target.value)} {mouseIsOver && (
/> <button
onClick={() => {
deleteTask(task.id);
}}
className="stroke-white absolute right-0 top-1/2 rounded-full bg-white -translate-y-1/2 bg-columnBackgroundColor p-2 hover:opacity-100 ">
<BsFillTrashFill />
</button>
)}
</div> </div>
);
}
return (
<div
ref={setNodeRef}
style={style}
{...attributes}
{...listeners}
onClick={toggleEditMode}
className="p-1 justify-center h-[100px] min-h-[100px] items-center flex text-left rounded-xl hover:ring-2 hover:ring-gray-950 hover:bg-zinc-400 cursor-grab relative task"
onMouseEnter={() => {
setMouseIsOver(true);
}}
onMouseLeave={() => {
setMouseIsOver(false);
}}>
<p className="p-2.5 my-auto h-[100px] min-h-[100px] w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-xl ring-2 ring-gray-950 bg-zinc-100">{task.content}</p>
{mouseIsOver && (
<button
onClick={() => {
deleteTask(task.id);
}}
className="stroke-white absolute right-4 top-1/2 -translate-y-1/2 bg-columnBackgroundColor p-2 rounded opacity-60 hover:opacity-100 ">
<BsFillTrashFill />
</button>
)}
</div> </div>
); );
} }

View File

@ -0,0 +1,17 @@
import React from "react";
function TaskDetailModal() {
return (
<dialog id="task_detail_modal" className="modal">
<div className="modal-box">
<form method="dialog">
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
</form>
<h3 className="font-bold text-lg">Hello!</h3>
<p className="py-4">Press ESC key or click on button to close</p>
</div>
</dialog>
);
}
export default TaskDetailModal;