|
|
"""Task API routes.""" |
|
|
from typing import Optional |
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Query |
|
|
from sqlmodel import Session |
|
|
from src.api.deps import get_db, get_current_user |
|
|
from src.schemas.task import TaskCreate, TaskUpdate, TaskPatch, TaskResponse, TaskListResponse |
|
|
from src.services.task_service import TaskService |
|
|
|
|
|
router = APIRouter(prefix="/api/tasks", tags=["tasks"]) |
|
|
|
|
|
|
|
|
@router.get("", response_model=TaskListResponse) |
|
|
def get_tasks( |
|
|
completed: Optional[bool] = Query(None, description="Filter by completion status"), |
|
|
sort: str = Query("created_at", description="Sort field (created_at or updated_at)"), |
|
|
order: str = Query("desc", description="Sort order (asc or desc)"), |
|
|
limit: Optional[int] = Query(None, description="Maximum number of tasks to return"), |
|
|
offset: int = Query(0, description="Number of tasks to skip"), |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Get tasks for the current user with filtering and sorting. |
|
|
|
|
|
Query Parameters: |
|
|
- completed: Filter by completion status (true/false/null for all) |
|
|
- sort: Sort field (created_at or updated_at) |
|
|
- order: Sort order (asc or desc) |
|
|
- limit: Maximum number of tasks to return |
|
|
- offset: Number of tasks to skip |
|
|
|
|
|
Returns: |
|
|
TaskListResponse: List of tasks with total count |
|
|
""" |
|
|
service = TaskService(db) |
|
|
tasks = service.get_tasks( |
|
|
user_id=current_user_id, |
|
|
completed=completed, |
|
|
sort=sort, |
|
|
order=order, |
|
|
limit=limit, |
|
|
offset=offset |
|
|
) |
|
|
return TaskListResponse(tasks=tasks, total=len(tasks)) |
|
|
|
|
|
|
|
|
@router.post("", response_model=TaskResponse, status_code=status.HTTP_201_CREATED) |
|
|
def create_task( |
|
|
task_data: TaskCreate, |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Create a new task for the current user. |
|
|
|
|
|
Args: |
|
|
task_data: Task creation data |
|
|
|
|
|
Returns: |
|
|
TaskResponse: Created task |
|
|
""" |
|
|
service = TaskService(db) |
|
|
task = service.create_task(user_id=current_user_id, task_data=task_data) |
|
|
return task |
|
|
|
|
|
|
|
|
@router.get("/{task_id}", response_model=TaskResponse) |
|
|
def get_task( |
|
|
task_id: int, |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Get a single task by ID. |
|
|
|
|
|
Args: |
|
|
task_id: ID of the task |
|
|
|
|
|
Returns: |
|
|
TaskResponse: Task details |
|
|
|
|
|
Raises: |
|
|
HTTPException: 404 if task not found or doesn't belong to user |
|
|
""" |
|
|
service = TaskService(db) |
|
|
task = service.get_task(task_id=task_id, user_id=current_user_id) |
|
|
if not task: |
|
|
raise HTTPException( |
|
|
status_code=status.HTTP_404_NOT_FOUND, |
|
|
detail="Task not found" |
|
|
) |
|
|
return task |
|
|
|
|
|
|
|
|
@router.put("/{task_id}", response_model=TaskResponse) |
|
|
def update_task( |
|
|
task_id: int, |
|
|
task_data: TaskUpdate, |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Update a task (PUT - replaces all fields). |
|
|
|
|
|
Args: |
|
|
task_id: ID of the task |
|
|
task_data: Task update data |
|
|
|
|
|
Returns: |
|
|
TaskResponse: Updated task |
|
|
|
|
|
Raises: |
|
|
HTTPException: 404 if task not found or doesn't belong to user |
|
|
""" |
|
|
service = TaskService(db) |
|
|
task = service.update_task(task_id=task_id, user_id=current_user_id, task_data=task_data) |
|
|
if not task: |
|
|
raise HTTPException( |
|
|
status_code=status.HTTP_404_NOT_FOUND, |
|
|
detail="Task not found" |
|
|
) |
|
|
return task |
|
|
|
|
|
|
|
|
@router.patch("/{task_id}", response_model=TaskResponse) |
|
|
def patch_task( |
|
|
task_id: int, |
|
|
task_data: TaskPatch, |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Partially update a task (PATCH - updates only provided fields). |
|
|
|
|
|
Args: |
|
|
task_id: ID of the task |
|
|
task_data: Task patch data |
|
|
|
|
|
Returns: |
|
|
TaskResponse: Updated task |
|
|
|
|
|
Raises: |
|
|
HTTPException: 404 if task not found or doesn't belong to user |
|
|
""" |
|
|
service = TaskService(db) |
|
|
task = service.patch_task(task_id=task_id, user_id=current_user_id, task_data=task_data) |
|
|
if not task: |
|
|
raise HTTPException( |
|
|
status_code=status.HTTP_404_NOT_FOUND, |
|
|
detail="Task not found" |
|
|
) |
|
|
return task |
|
|
|
|
|
|
|
|
@router.delete("/{task_id}", status_code=status.HTTP_204_NO_CONTENT) |
|
|
def delete_task( |
|
|
task_id: int, |
|
|
db: Session = Depends(get_db), |
|
|
current_user_id: int = Depends(get_current_user) |
|
|
): |
|
|
""" |
|
|
Delete a task. |
|
|
|
|
|
Args: |
|
|
task_id: ID of the task |
|
|
|
|
|
Returns: |
|
|
No content (204) |
|
|
|
|
|
Raises: |
|
|
HTTPException: 404 if task not found or doesn't belong to user |
|
|
""" |
|
|
service = TaskService(db) |
|
|
deleted = service.delete_task(task_id=task_id, user_id=current_user_id) |
|
|
if not deleted: |
|
|
raise HTTPException( |
|
|
status_code=status.HTTP_404_NOT_FOUND, |
|
|
detail="Task not found" |
|
|
) |
|
|
|