diff --git a/src/dashboard/routes/tasks.py b/src/dashboard/routes/tasks.py
index 69f2fc72..f6d1ffee 100644
--- a/src/dashboard/routes/tasks.py
+++ b/src/dashboard/routes/tasks.py
@@ -143,64 +143,49 @@ async def tasks_page(request: Request):
# ---------------------------------------------------------------------------
+def _render_task_list(request: Request, query: str, empty_msg: str) -> HTMLResponse:
+ """Fetch tasks by query and render as HTMX task-card partials."""
+ with _get_db() as db:
+ rows = db.execute(query).fetchall()
+ parts = [
+ templates.TemplateResponse(
+ request, "partials/task_card.html", {"task": _TaskView(_row_to_dict(r))}
+ ).body.decode()
+ for r in rows
+ ]
+ if not parts:
+ return HTMLResponse(f'
{empty_msg}
')
+ return HTMLResponse("".join(parts))
+
+
@router.get("/tasks/pending", response_class=HTMLResponse)
async def tasks_pending(request: Request):
"""Return HTMX partial for pending approval tasks."""
- with _get_db() as db:
- rows = db.execute(
- "SELECT * FROM tasks WHERE status='pending_approval' ORDER BY created_at DESC"
- ).fetchall()
- tasks = [_TaskView(_row_to_dict(r)) for r in rows]
- parts = []
- for task in tasks:
- parts.append(
- templates.TemplateResponse(
- request, "partials/task_card.html", {"task": task}
- ).body.decode()
- )
- if not parts:
- return HTMLResponse('No pending tasks
')
- return HTMLResponse("".join(parts))
+ return _render_task_list(
+ request,
+ "SELECT * FROM tasks WHERE status='pending_approval' ORDER BY created_at DESC",
+ "No pending tasks",
+ )
@router.get("/tasks/active", response_class=HTMLResponse)
async def tasks_active(request: Request):
"""Return HTMX partial for active (approved/running/paused) tasks."""
- with _get_db() as db:
- rows = db.execute(
- "SELECT * FROM tasks WHERE status IN ('approved','running','paused') ORDER BY created_at DESC"
- ).fetchall()
- tasks = [_TaskView(_row_to_dict(r)) for r in rows]
- parts = []
- for task in tasks:
- parts.append(
- templates.TemplateResponse(
- request, "partials/task_card.html", {"task": task}
- ).body.decode()
- )
- if not parts:
- return HTMLResponse('No active tasks
')
- return HTMLResponse("".join(parts))
+ return _render_task_list(
+ request,
+ "SELECT * FROM tasks WHERE status IN ('approved','running','paused') ORDER BY created_at DESC",
+ "No active tasks",
+ )
@router.get("/tasks/completed", response_class=HTMLResponse)
async def tasks_completed(request: Request):
"""Return HTMX partial for completed/vetoed/failed tasks (last 50)."""
- with _get_db() as db:
- rows = db.execute(
- "SELECT * FROM tasks WHERE status IN ('completed','vetoed','failed') ORDER BY completed_at DESC LIMIT 50"
- ).fetchall()
- tasks = [_TaskView(_row_to_dict(r)) for r in rows]
- parts = []
- for task in tasks:
- parts.append(
- templates.TemplateResponse(
- request, "partials/task_card.html", {"task": task}
- ).body.decode()
- )
- if not parts:
- return HTMLResponse('No completed tasks yet
')
- return HTMLResponse("".join(parts))
+ return _render_task_list(
+ request,
+ "SELECT * FROM tasks WHERE status IN ('completed','vetoed','failed') ORDER BY completed_at DESC LIMIT 50",
+ "No completed tasks yet",
+ )
# ---------------------------------------------------------------------------