Add task search (vibe-kanban) (#48)

* Perfect! I've successfully added search functionality to the TaskKanbanBoard component. The implementation includes:

1. **Search input field** at the top of the kanban board
2. **Real-time filtering** that searches both task titles and descriptions
3. **Case-insensitive search** for better user experience
4. **Clean integration** with the existing kanban board structure

The search functionality works by filtering tasks before they're grouped by status, so only matching tasks will appear on the board across all columns.

* Perfect! I've successfully moved the search input to the header, positioning it to the left of the "Add Task" button. The improvements include:

1. **Better positioning**: Search input is now in the header alongside the "Add Task" button
2. **Improved layout**: The search input has a fixed width (w-64) and is properly spaced
3. **Clean integration**: The search functionality is maintained while improving the visual hierarchy
4. **Responsive design**: The search input is grouped with the "Add Task" button for better visual balance

The search functionality remains the same - it filters tasks by title and description in real-time as you type.

* Prettier
This commit is contained in:
Louis Knight-Webb
2025-07-02 12:09:09 +01:00
committed by GitHub
parent 26032c11cd
commit d2e3cbd4f6
2 changed files with 34 additions and 5 deletions

View File

@@ -12,6 +12,7 @@ type Task = TaskWithAttemptStatus;
interface TaskKanbanBoardProps {
tasks: Task[];
searchQuery?: string;
onDragEnd: (event: DragEndEvent) => void;
onEditTask: (task: Task) => void;
onDeleteTask: (taskId: string) => void;
@@ -44,11 +45,25 @@ const statusBoardColors: Record<TaskStatus, string> = {
export function TaskKanbanBoard({
tasks,
searchQuery = '',
onDragEnd,
onEditTask,
onDeleteTask,
onViewTaskDetails,
}: TaskKanbanBoardProps) {
const filterTasks = (tasks: Task[]) => {
if (!searchQuery.trim()) {
return tasks;
}
const query = searchQuery.toLowerCase();
return tasks.filter(
(task) =>
task.title.toLowerCase().includes(query) ||
(task.description && task.description.toLowerCase().includes(query))
);
};
const groupTasksByStatus = () => {
const groups: Record<TaskStatus, Task[]> = {} as Record<TaskStatus, Task[]>;
@@ -57,7 +72,9 @@ export function TaskKanbanBoard({
groups[status] = [];
});
tasks.forEach((task) => {
const filteredTasks = filterTasks(tasks);
filteredTasks.forEach((task) => {
// Convert old capitalized status to lowercase if needed
const normalizedStatus = task.status.toLowerCase() as TaskStatus;
if (groups[normalizedStatus]) {

View File

@@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Plus, Settings, FolderOpen } from 'lucide-react';
import { makeRequest } from '@/lib/api';
import { TaskFormDialog } from '@/components/tasks/TaskFormDialog';
@@ -44,6 +45,7 @@ export function ProjectTasks() {
const [isTaskDialogOpen, setIsTaskDialogOpen] = useState(false);
const [editingTask, setEditingTask] = useState<Task | null>(null);
const [isProjectSettingsOpen, setIsProjectSettingsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
// Panel state
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
@@ -402,10 +404,19 @@ export function ProjectTasks() {
<Settings className="h-4 w-4" />
</Button>
</div>
<Button onClick={handleCreateNewTask}>
<Plus className="h-4 w-4 mr-2" />
Add Task
</Button>
<div className="flex items-center gap-3">
<Input
type="text"
placeholder="Search tasks..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-64"
/>
<Button onClick={handleCreateNewTask}>
<Plus className="h-4 w-4 mr-2" />
Add Task
</Button>
</div>
</div>
{/* Tasks View */}
@@ -428,6 +439,7 @@ export function ProjectTasks() {
<div className="min-w-[900px] max-w-[2000px] relative py-1">
<TaskKanbanBoard
tasks={tasks}
searchQuery={searchQuery}
onDragEnd={handleDragEnd}
onEditTask={handleEditTask}
onDeleteTask={handleDeleteTask}