diff --git a/routers/focus.py b/routers/focus.py index 56545d0..316b062 100644 --- a/routers/focus.py +++ b/routers/focus.py @@ -39,7 +39,11 @@ async def focus_view( t.project_id, t.due_date, t.estimated_minutes, COALESCE(p.name, lp.name) as project_name, COALESCE(t.project_id, l.project_id) as effective_project_id, - d.name as domain_name, d.color as domain_color, + COALESCE(d.name, ld.name) as domain_name, + COALESCE(d.color, ld.color) as domain_color, + COALESCE(d.id, ld.id) as effective_domain_id, + COALESCE(a.name, la.name) as area_name, + COALESCE(a.id, la.id) as effective_area_id, li.content as list_item_content, li.list_id as list_item_list_id, li.completed as list_item_completed, l.name as list_name @@ -47,24 +51,50 @@ async def focus_view( LEFT JOIN tasks t ON df.task_id = t.id LEFT JOIN projects p ON t.project_id = p.id LEFT JOIN domains d ON t.domain_id = d.id + LEFT JOIN areas a ON t.area_id = a.id LEFT JOIN list_items li ON df.list_item_id = li.id LEFT JOIN lists l ON li.list_id = l.id LEFT JOIN projects lp ON l.project_id = lp.id + LEFT JOIN domains ld ON l.domain_id = ld.id + LEFT JOIN areas la ON l.area_id = la.id WHERE df.focus_date = :target_date AND df.is_deleted = false ORDER BY df.sort_order, df.created_at """), {"target_date": target_date}) items = [dict(r._mapping) for r in result] - # Group items by project for template rendering + # Build Domain > Area > Project hierarchy from collections import OrderedDict - _groups = OrderedDict() + domain_map = OrderedDict() for item in items: - key = item.get("effective_project_id") or "__general__" - label = item.get("project_name") or "General" - if key not in _groups: - _groups[key] = {"label": label, "rows": []} - _groups[key]["rows"].append(item) - grouped_items = list(_groups.values()) + dk = item.get("effective_domain_id") or "__none__" + dl = item.get("domain_name") or "General" + dc = item.get("domain_color") or "" + if dk not in domain_map: + domain_map[dk] = {"label": dl, "color": dc, "areas": OrderedDict()} + + ak = item.get("effective_area_id") or "__none__" + al = item.get("area_name") or "" + area_map = domain_map[dk]["areas"] + if ak not in area_map: + area_map[ak] = {"label": al, "projects": OrderedDict()} + + pk = item.get("effective_project_id") or "__none__" + pl = item.get("project_name") or "" + proj_map = area_map[ak]["projects"] + if pk not in proj_map: + proj_map[pk] = {"label": pl, "rows": []} + proj_map[pk]["rows"].append(item) + + # Convert to nested lists for Jinja + hierarchy = [] + for dk, dv in domain_map.items(): + domain_group = {"label": dv["label"], "color": dv["color"], "areas": []} + for ak, av in dv["areas"].items(): + area_group = {"label": av["label"], "projects": []} + for pk, pv in av["projects"].items(): + area_group["projects"].append({"label": pv["label"], "rows": pv["rows"]}) + domain_group["areas"].append(area_group) + hierarchy.append(domain_group) # --- Available tasks --- available_tasks = [] @@ -152,7 +182,7 @@ async def focus_view( return templates.TemplateResponse("focus.html", { "request": request, "sidebar": sidebar, - "items": items, "grouped_items": grouped_items, + "items": items, "hierarchy": hierarchy, "available_tasks": available_tasks, "available_list_items": available_list_items, "focus_date": target_date, diff --git a/templates/focus.html b/templates/focus.html index e14b69c..f704420 100644 --- a/templates/focus.html +++ b/templates/focus.html @@ -12,15 +12,31 @@ {{ focus_date }} - + {% if items %} -{% for group in grouped_items %} -
-
-

{{ group.label }}

+{% for domain in hierarchy %} +
+ +
+ + {{ domain.label }}
- {% for item in group.rows %} -
+ {% for area in domain.areas %} + {% if area.label %} + +
+ {{ area.label }} +
+ {% endif %} + {% for project in area.projects %} + {% if project.label %} + +
+ {{ project.label }} +
+ {% endif %} + {% for item in project.rows %} +
{% with reorder_url="/focus/reorder", item_id=item.id, extra_fields={"focus_date": focus_date|string} %} {% include 'partials/reorder_arrows.html' %} {% endwith %} @@ -53,6 +69,8 @@
{% endfor %} + {% endfor %} + {% endfor %}
{% endfor %} {% else %} @@ -60,11 +78,11 @@ {% endif %} -