From 07f8ef7791a9b375af114bbec4501df07b0a7e91 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 21 Jan 2026 00:39:26 +0000
Subject: [PATCH 1/3] Initial plan
From 21c7cba215ec50314ae2f24f669cb0cadaee5d89 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 21 Jan 2026 00:48:22 +0000
Subject: [PATCH 2/3] feat: Add search functionality to task list (TF-13)
Co-authored-by: BitoviAI <226138784+BitoviAI@users.noreply.github.com>
---
components/task-list.tsx | 29 +++++-
jest.config.cjs | 3 +-
package-lock.json | 35 +++----
tests/__mocks__/nextFontMock.js | 9 ++
tests/e2e/kanban.spec.ts | 2 +-
tests/unit/task-list-search.test.tsx | 144 +++++++++++++++++++++++++++
6 files changed, 196 insertions(+), 26 deletions(-)
create mode 100644 tests/__mocks__/nextFontMock.js
create mode 100644 tests/unit/task-list-search.test.tsx
diff --git a/components/task-list.tsx b/components/task-list.tsx
index 5bb18ab..c4d6a7a 100644
--- a/components/task-list.tsx
+++ b/components/task-list.tsx
@@ -8,7 +8,8 @@ import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Checkbox } from "@/components/ui/checkbox"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
-import { MoreHorizontal, Clock, Edit, Trash2 } from "lucide-react"
+import { Input } from "@/components/ui/input"
+import { MoreHorizontal, Clock, Edit, Trash2, Search } from "lucide-react"
import { deleteTask, updateTaskStatus } from "@/app/(dashboard)/tasks/actions"
import { formatDateForDisplay } from "@/lib/date-utils"
import { EditTaskForm } from "./edit-task-form"
@@ -22,6 +23,7 @@ type TaskWithProfile = PrismaTask & {
export function TaskList({ initialTasks }: { initialTasks: TaskWithProfile[]; }) {
const [tasks, setTasks] = useState(initialTasks)
+ const [searchTerm, setSearchTerm] = useState("")
const [optimisticTasks, setOptimisticTasks] = useOptimistic(
tasks,
(state, { action, task }: { action: "delete" | "toggle"; task: TaskWithProfile | { id: number } }) => {
@@ -75,9 +77,32 @@ export function TaskList({ initialTasks }: { initialTasks: TaskWithProfile[]; })
.toUpperCase()
}
+ // Filter tasks based on search term
+ const filteredTasks = optimisticTasks.filter((task) => {
+ if (!searchTerm) return true
+ const lowerSearchTerm = searchTerm.toLowerCase()
+ return (
+ task.name.toLowerCase().includes(lowerSearchTerm) ||
+ (task.description && task.description.toLowerCase().includes(lowerSearchTerm))
+ )
+ })
+
return (
- {optimisticTasks.map((task) => (
+ {/* Search Input */}
+
+
+ setSearchTerm(e.target.value)}
+ className="pl-10"
+ />
+
+
+ {/* Task List */}
+ {filteredTasks.map((task) => (