diff --git a/README.md b/README.md index 7d04d80..5d93bb4 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A simple Todo API application built with FastAPI and SQLite. This RESTful API pr - Priority levels (low, medium, high) - Due dates for task deadlines - Task completion tracking with completion timestamps +- Search functionality to find todos by title or description content - Advanced filtering capabilities: - Filter by category - Filter by priority @@ -52,6 +53,7 @@ simpletodoapplication/ ### Todo Operations - **GET /api/v1/todos/** - Get all todos with filtering options - **POST /api/v1/todos/** - Create a new todo +- **GET /api/v1/todos/search** - Search todos by title or description content - **GET /api/v1/todos/{todo_id}** - Get a specific todo - **PUT /api/v1/todos/{todo_id}** - Update a todo - **DELETE /api/v1/todos/{todo_id}** - Delete a todo @@ -68,6 +70,7 @@ simpletodoapplication/ The GET /api/v1/todos/ endpoint supports the following query parameters: +- **search** - Search within title and description fields - **category** - Filter todos by category - **priority** - Filter by priority level (low, medium, high) - **completed** - Filter by completion status (true/false) @@ -78,6 +81,10 @@ The GET /api/v1/todos/ endpoint supports the following query parameters: - **skip** - Number of records to skip (for pagination) - **limit** - Maximum number of records to return (for pagination) +The GET /api/v1/todos/search endpoint requires the following parameter: + +- **q** - Search query string (required) - searches in both title and description fields + ## Setup and Running 1. Install dependencies: diff --git a/app/api/routes/todos.py b/app/api/routes/todos.py index 9f0896c..b236b03 100644 --- a/app/api/routes/todos.py +++ b/app/api/routes/todos.py @@ -20,6 +20,7 @@ def read_todos( completed: Optional[bool] = None, due_before: Optional[datetime] = None, due_after: Optional[datetime] = None, + search: Optional[str] = None, sort_by: str = "created_at", sort_desc: bool = True, db: Session = Depends(get_db) @@ -30,6 +31,7 @@ def read_todos( - Filter by priority level - Filter by completion status - Filter by due date (before/after) + - Search in title and description - Sort by any field - Pagination """ @@ -42,6 +44,7 @@ def read_todos( completed=completed, due_before=due_before, due_after=due_after, + search=search, sort_by=sort_by, sort_desc=sort_desc ) @@ -54,6 +57,30 @@ def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): return crud.create_todo(db=db, todo=todo) +@router.get("/search", response_model=List[Todo]) +def search_todos( + q: str = Query(..., min_length=1, description="Search query for title or description"), + skip: int = 0, + limit: int = 100, + sort_by: str = "created_at", + sort_desc: bool = True, + db: Session = Depends(get_db) +): + """ + Search todos by title or description content + Returns todos where the title or description contains the search query + """ + todos = crud.get_todos( + db=db, + skip=skip, + limit=limit, + search=q, + sort_by=sort_by, + sort_desc=sort_desc + ) + return todos + + @router.get("/stats", response_model=Dict[str, Any]) def get_todo_stats(db: Session = Depends(get_db)): """Get statistics about todos including: diff --git a/app/crud/todo.py b/app/crud/todo.py index 181a399..07cb6f0 100644 --- a/app/crud/todo.py +++ b/app/crud/todo.py @@ -20,6 +20,7 @@ def get_todos( completed: Optional[bool] = None, due_before: Optional[datetime] = None, due_after: Optional[datetime] = None, + search: Optional[str] = None, sort_by: str = "created_at", sort_desc: bool = True ) -> List[Todo]: @@ -45,6 +46,14 @@ def get_todos( if due_after: query = query.filter(Todo.due_date >= due_after) + # Apply text search if provided + if search: + search_term = f"%{search}%" + query = query.filter( + (Todo.title.ilike(search_term)) | + (Todo.description.ilike(search_term)) + ) + # Apply sorting if hasattr(Todo, sort_by): sort_column = getattr(Todo, sort_by) @@ -133,14 +142,14 @@ def get_todo_stats(db: Session) -> Dict[str, Any]: ).count() # Get completed todos in last 24 hours - yesterday = now - datetime.timedelta(days=1) + yesterday = now - timedelta(days=1) completed_last_24h = db.query(Todo).filter( Todo.completion_date > yesterday, Todo.completed == True ).count() # Get completed todos in last 7 days - last_week = now - datetime.timedelta(days=7) + last_week = now - timedelta(days=7) completed_last_week = db.query(Todo).filter( Todo.completion_date > last_week, Todo.completed == True