diff --git a/client/src/components/board/KanbanColumn.jsx b/client/src/components/board/KanbanColumn.jsx index bbef9ee..0e8b481 100644 --- a/client/src/components/board/KanbanColumn.jsx +++ b/client/src/components/board/KanbanColumn.jsx @@ -99,7 +99,7 @@ const KanbanColumn = ({ > {/* Create Task Form */} {showCreateForm && ( -
+
setShowCreateForm(false)} diff --git a/client/src/components/board/TaskCard.jsx b/client/src/components/board/TaskCard.jsx index 3d84ee3..37da507 100644 --- a/client/src/components/board/TaskCard.jsx +++ b/client/src/components/board/TaskCard.jsx @@ -12,10 +12,12 @@ import { } from 'lucide-react'; import { Avatar } from '../common'; import TaskEditModal from '../common/TaskEditModal'; +import ConfirmDialog from '../common/ConfirmDialog'; const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { const [showMenu, setShowMenu] = useState(false); const [showEditModal, setShowEditModal] = useState(false); + const [showConfirmDialog, setShowConfirmDialog] = useState(false); const menuRef = useRef(null); // Close menu when clicking outside @@ -48,13 +50,21 @@ const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { } }; - const formatDate = (date) => { + const formatDate = (date, taskStatus) => { if (!date) return null; const taskDate = new Date(date); const today = new Date(); const diffTime = taskDate - today; const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + // Don't show overdue messages for completed tasks + if (taskStatus === 'completed') { + return { + text: `Completed ${taskDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}`, + color: 'text-green-600' + }; + } + if (diffDays < 0) { return { text: `${Math.abs(diffDays)}d overdue`, color: 'text-red-600' }; } else if (diffDays === 0) { @@ -71,7 +81,7 @@ const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { } }; - const dueDateInfo = formatDate(task.dueDate); + const dueDateInfo = formatDate(task.dueDate, task.status); const handleEdit = () => { setShowEditModal(true); @@ -79,12 +89,19 @@ const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { }; const handleDelete = () => { - if (window.confirm('Are you sure you want to delete this task?')) { - onDelete(task._id); - } + setShowConfirmDialog(true); setShowMenu(false); }; + const confirmDelete = () => { + onDelete(task._id); + setShowConfirmDialog(false); + }; + + const cancelDelete = () => { + setShowConfirmDialog(false); + }; + const handleSaveEdit = async (updatedData) => { try { await onUpdate(task._id, updatedData); @@ -171,58 +188,66 @@ const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { )} {/* Metadata */} -
-
- {/* Priority */} - {task.priority && ( - - - {task.priority} - - )} - - {/* Due Date */} - {dueDateInfo && ( - - - {dueDateInfo.text} - - )} -
+
+ {/* Priority and Due Date Row */} +
+
+ {/* Priority */} + {task.priority && ( + + + {task.priority} + + )} -
- {/* Comments Count */} - {task.commentsCount > 0 && ( - - - {task.commentsCount} - - )} - - {/* Attachments Count */} - {task.attachmentsCount > 0 && ( - - - {task.attachmentsCount} - - )} + {/* Due Date */} + {dueDateInfo && ( + + + {dueDateInfo.text} + + )} +
{/* Assignee Avatar */} - {task.assignedTo && ( - - )} - {!task.assignedTo && task.assignee && ( - - )} +
+ {task.assignedTo && ( + + )} + {!task.assignedTo && task.assignee && ( + + )} +
+ + {/* Comments and Attachments Row */} + {(task.commentsCount > 0 || task.attachmentsCount > 0) && ( +
+ {/* Comments Count */} + {task.commentsCount > 0 && ( + + + {task.commentsCount} + + )} + + {/* Attachments Count */} + {task.attachmentsCount > 0 && ( + + + {task.attachmentsCount} + + )} +
+ )}
{/* Edit Modal */} @@ -232,6 +257,17 @@ const TaskCard = ({ task, onUpdate, onDelete, isDragging }) => { task={task} onSave={handleSaveEdit} /> + + {/* Delete Confirmation Dialog */} +
); }; diff --git a/client/src/components/board/TaskCreateForm.jsx b/client/src/components/board/TaskCreateForm.jsx index ec8283e..856a0e3 100644 --- a/client/src/components/board/TaskCreateForm.jsx +++ b/client/src/components/board/TaskCreateForm.jsx @@ -81,102 +81,119 @@ const TaskCreateForm = ({ onSubmit, onCancel }) => { }; return ( -
-
- {/* Title */} - handleChange('title', e.target.value)} - autoFocus - required - className="border-0 shadow-none p-0 text-sm font-medium placeholder-gray-400 focus:ring-0" - /> - - {/* Description */} -