Skip to main content

track/models/
todo_action.rs

1use super::{Todo, TodoStatus};
2use crate::utils::TrackError;
3use serde::Serialize;
4
5/// Intent-based operations on a TODO item.
6///
7/// Handlers map CLI/WebUI input to these actions instead of writing status strings directly.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
9#[serde(rename_all = "snake_case")]
10pub enum TodoAction {
11    Complete,
12    Cancel,
13    MakeNext,
14}
15
16impl TodoAction {
17    /// Parses a `track todo update` status argument.
18    pub fn from_cli_update_status(status: &str) -> Result<Self, TrackError> {
19        match status {
20            TodoStatus::CANCELLED => Ok(Self::Cancel),
21            TodoStatus::DONE => Err(TrackError::TodoCompleteRequiresDoneCommand),
22            TodoStatus::PENDING => Err(TrackError::InvalidStatus(
23                "pending (reopen is not allowed; add a new TODO instead)".to_string(),
24            )),
25            other => Err(TrackError::InvalidStatus(other.to_string())),
26        }
27    }
28
29    /// Parses a WebUI route segment such as `/api/todo/1/done`.
30    pub fn from_web_route(status: &str) -> Result<Self, TrackError> {
31        match status {
32            TodoStatus::DONE => Ok(Self::Complete),
33            TodoStatus::CANCELLED => Ok(Self::Cancel),
34            TodoStatus::PENDING => Err(TrackError::InvalidStatus(
35                "pending (reopen is not allowed)".to_string(),
36            )),
37            other => Err(TrackError::InvalidStatus(other.to_string())),
38        }
39    }
40
41    /// Returns actions the caller may invoke for this TODO.
42    pub fn allowed_for(todo: &Todo) -> Vec<Self> {
43        match todo.status {
44            TodoStatus::Pending => vec![Self::MakeNext, Self::Complete, Self::Cancel],
45            TodoStatus::Done | TodoStatus::Cancelled => Vec::new(),
46        }
47    }
48
49    pub fn as_str(&self) -> &'static str {
50        match self {
51            Self::Complete => "complete",
52            Self::Cancel => "cancel",
53            Self::MakeNext => "make_next",
54        }
55    }
56}