diff --git a/src/dashboard/routes/calm.py b/src/dashboard/routes/calm.py index 3482608..045bc29 100644 --- a/src/dashboard/routes/calm.py +++ b/src/dashboard/routes/calm.py @@ -19,14 +19,17 @@ router = APIRouter(tags=["calm"]) # Helper functions for state machine logic def get_now_task(db: Session) -> Task | None: + """Return the single active NOW task, or None.""" return db.query(Task).filter(Task.state == TaskState.NOW).first() def get_next_task(db: Session) -> Task | None: + """Return the single queued NEXT task, or None.""" return db.query(Task).filter(Task.state == TaskState.NEXT).first() def get_later_tasks(db: Session) -> list[Task]: + """Return all LATER tasks ordered by MIT flag then sort_order.""" return ( db.query(Task) .filter(Task.state == TaskState.LATER) @@ -36,6 +39,12 @@ def get_later_tasks(db: Session) -> list[Task]: def promote_tasks(db: Session): + """Enforce the NOW/NEXT/LATER state machine invariants. + + - At most one NOW task (extras demoted to NEXT). + - If no NOW, promote NEXT -> NOW. + - If no NEXT, promote highest-priority LATER -> NEXT. + """ # Ensure only one NOW task exists. If multiple, demote extras to NEXT. now_tasks = db.query(Task).filter(Task.state == TaskState.NOW).all() if len(now_tasks) > 1: @@ -74,6 +83,7 @@ def promote_tasks(db: Session): # Endpoints @router.get("/calm", response_class=HTMLResponse) async def get_calm_view(request: Request, db: Session = Depends(get_db)): + """Render the main CALM dashboard with NOW/NEXT/LATER counts.""" now_task = get_now_task(db) next_task = get_next_task(db) later_tasks_count = len(get_later_tasks(db)) @@ -90,6 +100,7 @@ async def get_calm_view(request: Request, db: Session = Depends(get_db)): @router.get("/calm/ritual/morning", response_class=HTMLResponse) async def get_morning_ritual_form(request: Request): + """Render the morning ritual intake form.""" return templates.TemplateResponse(request, "calm/morning_ritual_form.html", {}) @@ -102,6 +113,7 @@ async def post_morning_ritual( mit3_title: str = Form(None), other_tasks: str = Form(""), ): + """Process morning ritual: create MITs, other tasks, and set initial states.""" # Create Journal Entry mit_task_ids = [] journal_entry = JournalEntry(entry_date=date.today()) @@ -173,6 +185,7 @@ async def post_morning_ritual( @router.get("/calm/ritual/evening", response_class=HTMLResponse) async def get_evening_ritual_form(request: Request, db: Session = Depends(get_db)): + """Render the evening ritual form for today's journal entry.""" journal_entry = db.query(JournalEntry).filter(JournalEntry.entry_date == date.today()).first() if not journal_entry: raise HTTPException(status_code=404, detail="No journal entry for today") @@ -189,6 +202,7 @@ async def post_evening_ritual( gratitude: str = Form(None), energy_level: int = Form(None), ): + """Process evening ritual: save reflection/gratitude, archive active tasks.""" journal_entry = db.query(JournalEntry).filter(JournalEntry.entry_date == date.today()).first() if not journal_entry: raise HTTPException(status_code=404, detail="No journal entry for today") @@ -223,6 +237,7 @@ async def create_new_task( is_mit: bool = Form(False), certainty: TaskCertainty = Form(TaskCertainty.SOFT), ): + """Create a new task in LATER state and return updated count.""" task = Task( title=title, description=description, @@ -247,6 +262,7 @@ async def start_task( task_id: int, db: Session = Depends(get_db), ): + """Move a task to NOW state, demoting the current NOW to NEXT.""" current_now_task = get_now_task(db) if current_now_task and current_now_task.id != task_id: current_now_task.state = TaskState.NEXT # Demote current NOW to NEXT @@ -281,6 +297,7 @@ async def complete_task( task_id: int, db: Session = Depends(get_db), ): + """Mark a task as DONE and trigger state promotion.""" task = db.query(Task).filter(Task.id == task_id).first() if not task: raise HTTPException(status_code=404, detail="Task not found") @@ -309,6 +326,7 @@ async def defer_task( task_id: int, db: Session = Depends(get_db), ): + """Defer a task and trigger state promotion.""" task = db.query(Task).filter(Task.id == task_id).first() if not task: raise HTTPException(status_code=404, detail="Task not found") @@ -333,6 +351,7 @@ async def defer_task( @router.get("/calm/partials/later_tasks_list", response_class=HTMLResponse) async def get_later_tasks_list(request: Request, db: Session = Depends(get_db)): + """Render the expandable list of LATER tasks.""" later_tasks = get_later_tasks(db) return templates.TemplateResponse( "calm/partials/later_tasks_list.html", @@ -348,6 +367,7 @@ async def reorder_tasks( later_task_ids: str = Form(""), next_task_id: int | None = Form(None), ): + """Reorder LATER tasks and optionally promote one to NEXT.""" # Reorder LATER tasks if later_task_ids: ids_in_order = [int(x.strip()) for x in later_task_ids.split(",") if x.strip()]