"""Capture: quick text capture queue with conversion.""" from fastapi import APIRouter, Request, Form, Depends from fastapi.templating import Jinja2Templates from fastapi.responses import RedirectResponse from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import text from typing import Optional from core.database import get_db from core.base_repository import BaseRepository from core.sidebar import get_sidebar_data router = APIRouter(prefix="/capture", tags=["capture"]) templates = Jinja2Templates(directory="templates") @router.get("/") async def list_capture(request: Request, show: str = "unprocessed", db: AsyncSession = Depends(get_db)): sidebar = await get_sidebar_data(db) if show == "all": filters = {} else: filters = {"processed": False} result = await db.execute(text(""" SELECT * FROM capture WHERE is_deleted = false AND (:show_all OR processed = false) ORDER BY created_at DESC """), {"show_all": show == "all"}) items = [dict(r._mapping) for r in result] return templates.TemplateResponse("capture.html", { "request": request, "sidebar": sidebar, "items": items, "show": show, "page_title": "Capture", "active_nav": "capture", }) @router.post("/add") async def add_capture( request: Request, raw_text: str = Form(...), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("capture", db) # Multi-line: split into individual items lines = [l.strip() for l in raw_text.strip().split("\n") if l.strip()] for line in lines: await repo.create({"raw_text": line, "processed": False}) return RedirectResponse(url="/capture", status_code=303) @router.post("/{capture_id}/to-task") async def convert_to_task( capture_id: str, request: Request, domain_id: str = Form(...), project_id: Optional[str] = Form(None), db: AsyncSession = Depends(get_db), ): capture_repo = BaseRepository("capture", db) item = await capture_repo.get(capture_id) if not item: return RedirectResponse(url="/capture", status_code=303) task_repo = BaseRepository("tasks", db) data = {"title": item["raw_text"], "domain_id": domain_id, "status": "open", "priority": 3} if project_id and project_id.strip(): data["project_id"] = project_id task = await task_repo.create(data) await capture_repo.update(capture_id, { "processed": True, "converted_to_type": "task", "converted_to_id": str(task["id"]), }) return RedirectResponse(url="/capture", status_code=303) @router.post("/{capture_id}/dismiss") async def dismiss_capture(capture_id: str, db: AsyncSession = Depends(get_db)): repo = BaseRepository("capture", db) await repo.update(capture_id, {"processed": True}) return RedirectResponse(url="/capture", status_code=303) @router.post("/{capture_id}/delete") async def delete_capture(capture_id: str, db: AsyncSession = Depends(get_db)): repo = BaseRepository("capture", db) await repo.soft_delete(capture_id) return RedirectResponse(url="/capture", status_code=303)