158 lines
3.7 KiB
Python

from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from pydantic import BaseModel
from app.crud import todo
from app.db.session import get_db
from app.schemas.todo import TodoCreate, TodoResponse, TodoUpdate
router = APIRouter()
class BulkCompleteRequest(BaseModel):
todo_ids: List[int]
@router.get("/", response_model=List[TodoResponse])
def read_todos(
skip: int = 0,
limit: int = 100,
category: Optional[str] = Query(None, description="Filter by category"),
completed: Optional[bool] = Query(None, description="Filter by completion status"),
overdue_only: bool = Query(False, description="Show only overdue todos"),
db: Session = Depends(get_db),
):
"""
Retrieve todos with pagination and filtering.
"""
todos = todo.get_multi(
db,
skip=skip,
limit=limit,
category=category,
completed=completed,
overdue_only=overdue_only,
)
return todos
@router.get("/categories/{category}", response_model=List[TodoResponse])
def read_todos_by_category(
*,
db: Session = Depends(get_db),
category: str,
):
"""
Get all todos by category.
"""
return todo.get_by_category(db=db, category=category)
@router.get("/overdue", response_model=List[TodoResponse])
def read_overdue_todos(
db: Session = Depends(get_db),
):
"""
Get all overdue todos.
"""
return todo.get_overdue(db=db)
@router.post("/", response_model=TodoResponse, status_code=status.HTTP_201_CREATED)
def create_todo(
*,
db: Session = Depends(get_db),
todo_in: TodoCreate,
):
"""
Create new todo.
"""
return todo.create(db=db, obj_in=todo_in)
@router.get("/{todo_id}", response_model=TodoResponse)
def read_todo(
*,
db: Session = Depends(get_db),
todo_id: int,
):
"""
Get todo by ID.
"""
todo_obj = todo.get(db=db, todo_id=todo_id)
if not todo_obj:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Todo not found"
)
return todo_obj
@router.put("/{todo_id}", response_model=TodoResponse)
def update_todo(
*,
db: Session = Depends(get_db),
todo_id: int,
todo_in: TodoUpdate,
):
"""
Update a todo.
"""
todo_obj = todo.get(db=db, todo_id=todo_id)
if not todo_obj:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Todo not found"
)
return todo.update(db=db, db_obj=todo_obj, obj_in=todo_in)
@router.delete("/{todo_id}", response_model=TodoResponse)
def delete_todo(
*,
db: Session = Depends(get_db),
todo_id: int,
):
"""
Delete a todo.
"""
todo_obj = todo.remove(db=db, todo_id=todo_id)
if not todo_obj:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Todo not found"
)
return todo_obj
@router.post("/bulk-complete", response_model=List[TodoResponse])
def bulk_complete_todos(
*,
db: Session = Depends(get_db),
request: BulkCompleteRequest,
):
"""
Mark multiple todos as completed.
"""
completed_todos = []
not_found_ids = []
for todo_id in request.todo_ids:
todo_obj = todo.get(db=db, todo_id=todo_id)
if todo_obj:
updated_todo = todo.update(
db=db,
db_obj=todo_obj,
obj_in={"completed": True}
)
completed_todos.append(updated_todo)
else:
not_found_ids.append(todo_id)
if not_found_ids:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Todos not found: {not_found_ids}"
)
return completed_todos