feat: toast notifications, delete task, due date badges on cards, keyboard shortcuts

This commit is contained in:
2026-01-29 07:33:05 +00:00
parent e874cafbec
commit 578b092a78
6 changed files with 234 additions and 8 deletions

View File

@@ -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 */}