Files
lifeos-prod/routers/areas.py
2026-03-03 00:44:33 +00:00

123 lines
3.9 KiB
Python

"""Areas: grouping within domains."""
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="/areas", tags=["areas"])
templates = Jinja2Templates(directory="templates")
@router.get("/")
async def list_areas(
request: Request,
domain_id: Optional[str] = None,
db: AsyncSession = Depends(get_db),
):
repo = BaseRepository("areas", db)
sidebar = await get_sidebar_data(db)
filters = {}
if domain_id:
filters["domain_id"] = domain_id
result = await db.execute(text("""
SELECT a.*, d.name as domain_name, d.color as domain_color
FROM areas a
JOIN domains d ON a.domain_id = d.id
WHERE a.is_deleted = false
ORDER BY d.sort_order, d.name, a.sort_order, a.name
"""))
items = [dict(r._mapping) for r in result]
if domain_id:
items = [i for i in items if str(i["domain_id"]) == domain_id]
# Get domains for filter/form
domains_repo = BaseRepository("domains", db)
domains = await domains_repo.list()
return templates.TemplateResponse("areas.html", {
"request": request, "sidebar": sidebar, "items": items,
"domains": domains, "current_domain_id": domain_id or "",
"page_title": "Areas", "active_nav": "areas",
})
@router.get("/create")
async def create_form(
request: Request,
domain_id: Optional[str] = None,
db: AsyncSession = Depends(get_db),
):
sidebar = await get_sidebar_data(db)
domains_repo = BaseRepository("domains", db)
domains = await domains_repo.list()
return templates.TemplateResponse("area_form.html", {
"request": request, "sidebar": sidebar, "domains": domains,
"page_title": "New Area", "active_nav": "areas",
"item": None, "prefill_domain_id": domain_id or "",
})
@router.post("/create")
async def create_area(
request: Request,
name: str = Form(...),
domain_id: str = Form(...),
description: Optional[str] = Form(None),
status: str = Form("active"),
db: AsyncSession = Depends(get_db),
):
repo = BaseRepository("areas", db)
await repo.create({
"name": name, "domain_id": domain_id,
"description": description, "status": status,
})
return RedirectResponse(url="/areas", status_code=303)
@router.get("/{area_id}/edit")
async def edit_form(area_id: str, request: Request, db: AsyncSession = Depends(get_db)):
repo = BaseRepository("areas", db)
sidebar = await get_sidebar_data(db)
item = await repo.get(area_id)
if not item:
return RedirectResponse(url="/areas", status_code=303)
domains_repo = BaseRepository("domains", db)
domains = await domains_repo.list()
return templates.TemplateResponse("area_form.html", {
"request": request, "sidebar": sidebar, "domains": domains,
"page_title": f"Edit {item['name']}", "active_nav": "areas",
"item": item, "prefill_domain_id": "",
})
@router.post("/{area_id}/edit")
async def update_area(
area_id: str,
name: str = Form(...),
domain_id: str = Form(...),
description: Optional[str] = Form(None),
status: str = Form("active"),
db: AsyncSession = Depends(get_db),
):
repo = BaseRepository("areas", db)
await repo.update(area_id, {
"name": name, "domain_id": domain_id,
"description": description, "status": status,
})
return RedirectResponse(url="/areas", status_code=303)
@router.post("/{area_id}/delete")
async def delete_area(area_id: str, db: AsyncSession = Depends(get_db)):
repo = BaseRepository("areas", db)
await repo.soft_delete(area_id)
return RedirectResponse(url="/areas", status_code=303)