feat: toast notifications, delete task, due date badges on cards, keyboard shortcuts
This commit is contained in:
@@ -123,6 +123,37 @@ export function TaskCard({
|
||||
{task.description && (
|
||||
<p className="text-xs sm:text-sm text-gray-500 line-clamp-1">{task.description}</p>
|
||||
)}
|
||||
|
||||
{/* Due date and subtask badges */}
|
||||
<div className="flex items-center gap-2 mt-1.5 flex-wrap">
|
||||
{task.dueDate && (() => {
|
||||
const due = new Date(task.dueDate);
|
||||
const diffMs = due.getTime() - Date.now();
|
||||
const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24));
|
||||
const isOverdue = diffMs < 0;
|
||||
const isDueSoon = diffDays <= 2 && !isOverdue;
|
||||
return (
|
||||
<span className={`text-[10px] sm:text-xs px-1.5 py-0.5 rounded-full font-medium inline-flex items-center gap-0.5 ${
|
||||
isOverdue ? "bg-red-100 text-red-700" : isDueSoon ? "bg-amber-100 text-amber-700" : "bg-gray-100 text-gray-500"
|
||||
}`}>
|
||||
📅 {isOverdue ? `${Math.abs(diffDays)}d overdue` : diffDays === 0 ? "today" : diffDays === 1 ? "tomorrow" : `${diffDays}d`}
|
||||
</span>
|
||||
);
|
||||
})()}
|
||||
{task.subtasks?.length > 0 && (() => {
|
||||
const done = task.subtasks.filter(s => s.completed).length;
|
||||
const total = task.subtasks.length;
|
||||
const pct = Math.round((done / total) * 100);
|
||||
return (
|
||||
<span className="text-[10px] sm:text-xs text-gray-400 inline-flex items-center gap-1.5">
|
||||
<span className="inline-block w-12 h-1 bg-gray-200 rounded-full overflow-hidden">
|
||||
<span className={`block h-full rounded-full ${pct === 100 ? "bg-green-500" : "bg-amber-400"}`} style={{ width: `${pct}%` }} />
|
||||
</span>
|
||||
{done}/{total}
|
||||
</span>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Expand chevron - always visible */}
|
||||
|
||||
Reference in New Issue
Block a user