R1 foundation - Phase 1 live build
This commit is contained in:
72
core/sidebar.py
Normal file
72
core/sidebar.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
Sidebar navigation data builder.
|
||||
Loads domains > areas > projects hierarchy for the sidebar tree.
|
||||
"""
|
||||
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
|
||||
async def get_sidebar_data(db: AsyncSession) -> dict:
|
||||
"""Build full sidebar navigation data."""
|
||||
|
||||
# Domains
|
||||
result = await db.execute(text("""
|
||||
SELECT id, name, color FROM domains
|
||||
WHERE is_deleted = false ORDER BY sort_order, name
|
||||
"""))
|
||||
domains = [dict(r._mapping) for r in result]
|
||||
|
||||
# Areas grouped by domain
|
||||
result = await db.execute(text("""
|
||||
SELECT id, domain_id, name FROM areas
|
||||
WHERE is_deleted = false ORDER BY sort_order, name
|
||||
"""))
|
||||
areas = [dict(r._mapping) for r in result]
|
||||
|
||||
# Projects grouped by domain/area
|
||||
result = await db.execute(text("""
|
||||
SELECT id, domain_id, area_id, name, status FROM projects
|
||||
WHERE is_deleted = false AND status != 'archived'
|
||||
ORDER BY sort_order, name
|
||||
"""))
|
||||
projects = [dict(r._mapping) for r in result]
|
||||
|
||||
# Counts for badges
|
||||
result = await db.execute(text("""
|
||||
SELECT count(*) FROM capture WHERE is_deleted = false AND processed = false
|
||||
"""))
|
||||
capture_count = result.scalar() or 0
|
||||
|
||||
result = await db.execute(text("""
|
||||
SELECT count(*) FROM daily_focus
|
||||
WHERE is_deleted = false AND focus_date = CURRENT_DATE AND completed = false
|
||||
"""))
|
||||
focus_count = result.scalar() or 0
|
||||
|
||||
# Build tree structure
|
||||
domain_tree = []
|
||||
for d in domains:
|
||||
d_areas = [a for a in areas if str(a["domain_id"]) == str(d["id"])]
|
||||
d_projects = [p for p in projects if str(p["domain_id"]) == str(d["id"])]
|
||||
|
||||
# Projects under areas
|
||||
for a in d_areas:
|
||||
a["projects"] = [p for p in d_projects if str(p.get("area_id", "")) == str(a["id"])]
|
||||
|
||||
# Projects directly under domain (no area)
|
||||
standalone_projects = [p for p in d_projects if p.get("area_id") is None]
|
||||
|
||||
domain_tree.append({
|
||||
"id": d["id"],
|
||||
"name": d["name"],
|
||||
"color": d.get("color", "#4F6EF7"),
|
||||
"areas": d_areas,
|
||||
"standalone_projects": standalone_projects,
|
||||
})
|
||||
|
||||
return {
|
||||
"domain_tree": domain_tree,
|
||||
"capture_count": capture_count,
|
||||
"focus_count": focus_count,
|
||||
}
|
||||
Reference in New Issue
Block a user