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}