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:
committed by
GitHub
parent
26032c11cd
commit
d2e3cbd4f6
@@ -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]) {
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user