diff --git a/core/sidebar.py b/core/sidebar.py index 70fc445..5b10f29 100644 --- a/core/sidebar.py +++ b/core/sidebar.py @@ -40,7 +40,7 @@ async def get_sidebar_data(db: AsyncSession) -> dict: result = await db.execute(text(""" SELECT count(*) FROM daily_focus - WHERE is_deleted = false AND focus_date = CURRENT_DATE AND completed = false + WHERE is_deleted = false AND completed = false """)) focus_count = result.scalar() or 0 diff --git a/routers/focus.py b/routers/focus.py index 867970d..4b4a088 100644 --- a/routers/focus.py +++ b/routers/focus.py @@ -1,4 +1,4 @@ -"""Daily Focus: date-scoped task/list-item commitment list.""" +"""Focus: persistent commitment list — items stay until removed.""" from fastapi import APIRouter, Request, Form, Depends from fastapi.templating import Jinja2Templates @@ -21,7 +21,6 @@ templates.env.filters["autolink"] = autolink @router.get("/") async def focus_view( request: Request, - focus_date: Optional[str] = None, domain_id: Optional[str] = None, area_id: Optional[str] = None, project_id: Optional[str] = None, @@ -30,11 +29,10 @@ async def focus_view( db: AsyncSession = Depends(get_db), ): sidebar = await get_sidebar_data(db) - target_date = date.fromisoformat(focus_date) if focus_date else date.today() if not source_type: source_type = "tasks" - # --- Focus items (both tasks and list items) --- + # --- All active focus items --- result = await db.execute(text(""" SELECT df.*, t.title as title, t.priority, t.status as task_status, @@ -60,11 +58,11 @@ async def focus_view( 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 + WHERE df.is_deleted = false AND (t.id IS NULL OR t.is_deleted = false) AND (li.id IS NULL OR li.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 domain only — area/project shown as inline columns @@ -86,9 +84,9 @@ async def focus_view( avail_where = [ "t.is_deleted = false", "t.status NOT IN ('done', 'cancelled')", - "t.id NOT IN (SELECT task_id FROM daily_focus WHERE focus_date = :target_date AND is_deleted = false AND task_id IS NOT NULL)", + "t.id NOT IN (SELECT task_id FROM daily_focus WHERE is_deleted = false AND task_id IS NOT NULL)", ] - avail_params = {"target_date": target_date} + avail_params = {} if search: avail_where.append("t.title ILIKE :search") @@ -123,9 +121,9 @@ async def focus_view( "li.is_deleted = false", "li.completed = false", "l.is_deleted = false", - "li.id NOT IN (SELECT list_item_id FROM daily_focus WHERE focus_date = :target_date AND is_deleted = false AND list_item_id IS NOT NULL)", + "li.id NOT IN (SELECT list_item_id FROM daily_focus WHERE is_deleted = false AND list_item_id IS NOT NULL)", ] - li_params = {"target_date": target_date} + li_params = {} if search: li_where.append("li.content ILIKE :search") @@ -169,7 +167,6 @@ async def focus_view( "items": items, "hierarchy": hierarchy, "available_tasks": available_tasks, "available_list_items": available_list_items, - "focus_date": target_date, "total_estimated": total_est, "domains": domains, "areas": areas, "projects": projects, "current_domain_id": domain_id or "", @@ -177,29 +174,27 @@ async def focus_view( "current_project_id": project_id or "", "current_search": search or "", "current_source_type": source_type, - "page_title": "Daily Focus", "active_nav": "focus", + "page_title": "Focus", "active_nav": "focus", }) @router.post("/add") async def add_to_focus( request: Request, - focus_date: str = Form(...), task_id: Optional[str] = Form(None), list_item_id: Optional[str] = Form(None), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("daily_focus", db) - parsed_date = date.fromisoformat(focus_date) # Get next sort order result = await db.execute(text(""" SELECT COALESCE(MAX(sort_order), 0) + 10 FROM daily_focus - WHERE focus_date = :fd AND is_deleted = false - """), {"fd": parsed_date}) + WHERE is_deleted = false + """)) next_order = result.scalar() data = { - "focus_date": parsed_date, + "focus_date": date.today(), "sort_order": next_order, "completed": False, } @@ -209,7 +204,7 @@ async def add_to_focus( data["list_item_id"] = list_item_id await repo.create(data) - return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303) + return RedirectResponse(url="/focus", status_code=303) @router.post("/reorder") @@ -217,27 +212,24 @@ async def reorder_focus( request: Request, item_id: str = Form(...), direction: str = Form(...), - focus_date: str = Form(...), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("daily_focus", db) - parsed_date = date.fromisoformat(focus_date) - await repo.move_in_order(item_id, direction, filters={"focus_date": parsed_date}) - return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303) + await repo.move_in_order(item_id, direction) + return RedirectResponse(url="/focus", status_code=303) @router.post("/reorder-all") async def reorder_all_focus( request: Request, item_ids: str = Form(...), - focus_date: str = Form(...), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("daily_focus", db) ids = [i.strip() for i in item_ids.split(",") if i.strip()] if ids: await repo.reorder(ids) - return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303) + return RedirectResponse(url="/focus", status_code=303) @router.post("/{focus_id}/toggle") @@ -265,14 +257,11 @@ async def toggle_focus(focus_id: str, request: Request, db: AsyncSession = Depen "UPDATE list_items SET completed = false, completed_at = NULL, updated_at = :now WHERE id = :id" ), {"id": item["list_item_id"], "now": now}) await db.commit() - focus_date = item["focus_date"] if item else date.today() - return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303) + return RedirectResponse(url="/focus", status_code=303) @router.post("/{focus_id}/remove") async def remove_from_focus(focus_id: str, request: Request, db: AsyncSession = Depends(get_db)): repo = BaseRepository("daily_focus", db) - item = await repo.get(focus_id) await repo.soft_delete(focus_id) - focus_date = item["focus_date"] if item else date.today() - return RedirectResponse(url=f"/focus?focus_date={focus_date}", status_code=303) + return RedirectResponse(url="/focus", status_code=303) diff --git a/templates/focus.html b/templates/focus.html index 68e798f..669b02e 100644 --- a/templates/focus.html +++ b/templates/focus.html @@ -1,17 +1,12 @@ {% extends "base.html" %} {% block content %}