diff --git a/src/dashboard/routes/calm.py b/src/dashboard/routes/calm.py index 045bc293..49098cae 100644 --- a/src/dashboard/routes/calm.py +++ b/src/dashboard/routes/calm.py @@ -38,6 +38,56 @@ def get_later_tasks(db: Session) -> list[Task]: ) +def _create_mit_tasks(db: Session, titles: list[str | None]) -> list[int]: + """Create MIT tasks from a list of titles, return their IDs.""" + task_ids: list[int] = [] + for title in titles: + if title: + task = Task( + title=title, + is_mit=True, + state=TaskState.LATER, + certainty=TaskCertainty.SOFT, + ) + db.add(task) + db.commit() + db.refresh(task) + task_ids.append(task.id) + return task_ids + + +def _create_other_tasks(db: Session, other_tasks: str): + """Create non-MIT tasks from newline-separated text.""" + for line in other_tasks.split("\n"): + line = line.strip() + if line: + task = Task( + title=line, + state=TaskState.LATER, + certainty=TaskCertainty.FUZZY, + ) + db.add(task) + + +def _seed_now_next(db: Session): + """Set initial NOW/NEXT states when both slots are empty.""" + if get_now_task(db) or get_next_task(db): + return + later_tasks = ( + db.query(Task) + .filter(Task.state == TaskState.LATER) + .order_by(Task.is_mit.desc(), Task.sort_order) + .all() + ) + if later_tasks: + later_tasks[0].state = TaskState.NOW + db.add(later_tasks[0]) + db.flush() + if len(later_tasks) > 1: + later_tasks[1].state = TaskState.NEXT + db.add(later_tasks[1]) + + def promote_tasks(db: Session): """Enforce the NOW/NEXT/LATER state machine invariants. @@ -114,63 +164,19 @@ async def post_morning_ritual( 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()) db.add(journal_entry) db.commit() db.refresh(journal_entry) - # Create MIT tasks - for mit_title in [mit1_title, mit2_title, mit3_title]: - if mit_title: - task = Task( - title=mit_title, - is_mit=True, - state=TaskState.LATER, # Initially LATER, will be promoted - certainty=TaskCertainty.SOFT, - ) - db.add(task) - db.commit() - db.refresh(task) - mit_task_ids.append(task.id) - - journal_entry.mit_task_ids = mit_task_ids + journal_entry.mit_task_ids = _create_mit_tasks(db, [mit1_title, mit2_title, mit3_title]) db.add(journal_entry) - # Create other tasks - for task_title in other_tasks.split("\n"): - task_title = task_title.strip() - if task_title: - task = Task( - title=task_title, - state=TaskState.LATER, - certainty=TaskCertainty.FUZZY, - ) - db.add(task) - + _create_other_tasks(db, other_tasks) db.commit() - # Set initial NOW/NEXT states - # Set initial NOW/NEXT states after all tasks are created - if not get_now_task(db) and not get_next_task(db): - later_tasks = ( - db.query(Task) - .filter(Task.state == TaskState.LATER) - .order_by(Task.is_mit.desc(), Task.sort_order) - .all() - ) - if later_tasks: - # Set the highest priority LATER task to NOW - later_tasks[0].state = TaskState.NOW - db.add(later_tasks[0]) - db.flush() # Flush to make the change visible for the next query - - # Set the next highest priority LATER task to NEXT - if len(later_tasks) > 1: - later_tasks[1].state = TaskState.NEXT - db.add(later_tasks[1]) - db.commit() # Commit changes after initial NOW/NEXT setup + _seed_now_next(db) + db.commit() return templates.TemplateResponse( request,