rtd_tutorial/
service.rs

1use crate::{
2    model::Item,
3    storage::{self, get_item_by_id, get_max_id, update_item, StorageError},
4};
5use chrono::Local;
6use std::{error::Error, fmt::Display};
7
8pub fn add_item(name: &str) -> Result<String> {
9    let max_id = get_max_id()?;
10    let item = Item::new(
11        max_id + 1,
12        name,
13        false,
14        false,
15        Some(Local::now().timestamp()),
16        None,
17        None,
18    );
19    storage::add_item(item.clone())?;
20    Ok(format!("Added [{}]: {}\n", item.id, item.name))
21}
22
23pub fn complete_item(id: u32) -> Result<String> {
24    let item = get_item_by_id(id)?;
25    update_item(Item {
26        completed: true,
27        completed_at: Some(Local::now().timestamp()),
28        ..item.clone()
29    })?;
30    Ok(format!("Completed [{}]: {}\n", item.id, item.name))
31}
32
33pub fn uncomplete_item(id: u32) -> Result<String> {
34    let item = get_item_by_id(id)?;
35    update_item(Item {
36        completed: false,
37        completed_at: None,
38        ..item.clone()
39    })?;
40    Ok(format!("Uncompleted [{}]: {}\n", item.id, item.name))
41}
42
43pub fn delete_item(id: u32) -> Result<String> {
44    let item = get_item_by_id(id)?;
45    update_item(Item {
46        deleted: true,
47        deleted_at: Some(Local::now().timestamp()),
48        ..item.clone()
49    })?;
50    Ok(format!("Deleted [{}]: {}\n", item.id, item.name))
51}
52
53pub fn restore_item(id: u32) -> Result<String> {
54    let item = get_item_by_id(id)?;
55    update_item(Item {
56        deleted: false,
57        deleted_at: None,
58        ..item.clone()
59    })?;
60    Ok(format!("Restored [{}]: {}\n", item.id, item.name))
61}
62
63pub fn destroy_deleted() -> Result<String> {
64    let items = storage::get_all()?
65        .into_iter()
66        .filter(|item| item.deleted)
67        .collect::<Vec<_>>();
68    if items.is_empty() {
69        return Ok("Nothing to destory.".to_string());
70    }
71    let mut result_string = String::new();
72    for item in items {
73        result_string += &destroy_item(item.id)?
74    }
75    result_string += "All deleted todos were destroyed.\n";
76    Ok(result_string)
77}
78
79pub fn destroy_item(id: u32) -> Result<String> {
80    storage::delete_item(id)?;
81    Ok(format!("Destroyed [{}]\n", id))
82}
83
84pub fn clear() -> Result<String> {
85    let items = storage::get_all()?;
86    if items.is_empty() {
87        return Ok("Nothing to clear.".to_string());
88    }
89    let mut result_string = String::new();
90    for item in items {
91        result_string += &destroy_item(item.id)?
92    }
93    Ok("All todos were destroyed.\n".to_string())
94}
95
96pub fn list_uncompleted() -> Result<String> {
97    let items = storage::get_all()?
98        .into_iter()
99        .filter(|item| !item.deleted && !item.completed)
100        .collect::<Vec<_>>();
101    if items.is_empty() {
102        return Ok("Nothing need to do.".to_string());
103    }
104    let mut result = "Uncompleted todos:\n\n".to_string();
105    for item in items {
106        result += &item.to_prettier_string();
107        result += "\n";
108    }
109    Ok(result)
110}
111
112pub fn list_completed() -> Result<String> {
113    let items = storage::get_all()?
114        .into_iter()
115        .filter(|item| !item.deleted && item.completed)
116        .collect::<Vec<_>>();
117    if items.is_empty() {
118        return Ok("Nothing completed.".to_string());
119    }
120    let mut result = "Completed todos:\n\n".to_string();
121    for item in items {
122        result += &item.to_prettier_string();
123        result += "\n";
124    }
125    Ok(result)
126}
127
128pub fn list_deleted() -> Result<String> {
129    let items = storage::get_all()?
130        .into_iter()
131        .filter(|item| item.deleted)
132        .collect::<Vec<_>>();
133    if items.is_empty() {
134        return Ok("Nothing deleted.".to_string());
135    }
136    let mut result = "Deleted todos:\n\n".to_string();
137    for item in items {
138        result += &item.to_prettier_string();
139        result += "\n";
140    }
141    Ok(result)
142}
143
144pub fn list_all() -> Result<String> {
145    let items = storage::get_all()?;
146    if items.is_empty() {
147        return Ok("Nothing need to do.".to_string());
148    }
149    let mut result = "All todos:\n\n".to_string();
150    for item in items {
151        result += &item.to_prettier_string();
152        result += "\n";
153    }
154    Ok(result)
155}
156
157type Result<T> = std::result::Result<T, ServiceError>;
158
159#[derive(Debug)]
160pub enum ServiceError {
161    Storage(StorageError),
162}
163
164impl Error for ServiceError {}
165
166impl Display for ServiceError {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        use ServiceError::*;
169        match self {
170            Storage(e) => writeln!(f, "Rtd service storage error: {}", e),
171        }
172    }
173}
174
175impl From<StorageError> for ServiceError {
176    fn from(value: StorageError) -> Self {
177        Self::Storage(value)
178    }
179}