From f00e0720e17b4ef0870eabd1ab654272ef86d464 Mon Sep 17 00:00:00 2001 From: Hammer Date: Thu, 29 Jan 2026 08:03:47 +0000 Subject: [PATCH] feat: enhanced create modal, project/assignee badges, status filter, keyboard shortcuts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CreateTaskModal: project selector, due date picker, source in 'more options' - TaskCard: project name badge (๐Ÿ“) and assignee badge (๐Ÿ‘ค) - QueuePage: status filter dropdown, clear filters button, filter count indicator - QueuePage: Ctrl+N keyboard shortcut to create task - DashboardPage: project/assignee badges on active task cards - Search now also matches assignee name --- frontend/src/components/CreateTaskModal.tsx | 211 +++++++++++++---- frontend/src/components/TaskCard.tsx | 14 ++ frontend/src/lib/api.ts | 2 +- frontend/src/pages/DashboardPage.tsx | 22 +- frontend/src/pages/QueuePage.tsx | 244 ++++++++++++++------ 5 files changed, 368 insertions(+), 125 deletions(-) diff --git a/frontend/src/components/CreateTaskModal.tsx b/frontend/src/components/CreateTaskModal.tsx index 034252a..2175069 100644 --- a/frontend/src/components/CreateTaskModal.tsx +++ b/frontend/src/components/CreateTaskModal.tsx @@ -1,4 +1,6 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; +import { fetchProjects } from "../lib/api"; +import type { Project } from "../lib/types"; interface CreateTaskModalProps { open: boolean; @@ -8,6 +10,8 @@ interface CreateTaskModalProps { description?: string; source?: string; priority?: string; + projectId?: string; + dueDate?: string; }) => void; } @@ -16,6 +20,26 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp const [description, setDescription] = useState(""); const [source, setSource] = useState("donovan"); const [priority, setPriority] = useState("medium"); + const [projectId, setProjectId] = useState(""); + const [dueDate, setDueDate] = useState(""); + const [projects, setProjects] = useState([]); + const [showAdvanced, setShowAdvanced] = useState(false); + + useEffect(() => { + if (open) { + fetchProjects().then(setProjects).catch(() => {}); + } + }, [open]); + + // Keyboard shortcut: Escape to close + useEffect(() => { + if (!open) return; + const handleKey = (e: KeyboardEvent) => { + if (e.key === "Escape") onClose(); + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, [open, onClose]); if (!open) return null; @@ -27,75 +51,166 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp description: description.trim() || undefined, source, priority, + projectId: projectId || undefined, + dueDate: dueDate ? new Date(dueDate).toISOString() : undefined, }); + // Reset form setTitle(""); setDescription(""); setSource("donovan"); setPriority("medium"); + setProjectId(""); + setDueDate(""); + setShowAdvanced(false); onClose(); }; return ( -
-
-

New Task

-
- setTitle(e.target.value)} - className="w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-amber-400" - autoFocus - /> -