Initial commit

This commit is contained in:
2026-03-03 00:44:33 +00:00
commit 5297da485f
126 changed files with 54767 additions and 0 deletions

72
core/sidebar.py Normal file
View 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,
}