diff --git a/src/todo.rs b/src/todo.rs index 738faac..b3ea4a7 100644 --- a/src/todo.rs +++ b/src/todo.rs @@ -1,6 +1,7 @@ use iced::{event, keyboard, widget, Center, Element, Event, Length, Subscription, Task, Theme}; use iced::keyboard::key; use iced::widget::{button, center, checkbox, column, row, scrollable, text_input, Space, Text}; +use iced::widget::text::danger; use rusqlite::Connection; use crate::db; @@ -12,12 +13,13 @@ pub struct TaskColumn { } pub struct TaskData { - id: usize, + db_id: usize, checked: bool, value: String, edit: bool, can_update: bool, can_delete: bool, + already_exists: bool, } pub(crate) struct Todo { @@ -75,17 +77,21 @@ impl Todo { match message { Message::ContentUpdated(new, value) => { if new { - self.new_task = value + self.new_task = String::from(&value); } else { - self.updated_task = value + self.updated_task = String::from(&value) } - + + for task in &mut self.tasks { + task.already_exists = task.value == value.to_string(); + } + Task::none() } Message::AddTask => { if self.new_task.is_empty() { return Task::none(); } - - + if self.duplicate_exists(None) { return Task::none(); } + let result = db::insert_task(&self.conn, TaskColumn { id: 0, checked: false, @@ -95,12 +101,13 @@ impl Todo { match result { Ok(t) => { let data = TaskData { - id: t as usize, + db_id: t as usize, checked: false, value: self.new_task.to_string(), edit: false, can_update: true, can_delete: true, + already_exists: false, }; self.tasks.push(data); }, @@ -116,7 +123,7 @@ impl Todo { self.completed_tasks -= 1; } - if let Err(e) = db::delete_tasks(&self.conn, Some(self.tasks[index].id)) { + if let Err(e) = db::delete_tasks(&self.conn, Some(self.tasks[index].db_id)) { eprintln!("[ERROR] Failed to delete task '{}':\n{e}", self.tasks[index].value); } @@ -130,7 +137,7 @@ impl Todo { self.tasks[id].checked = choice; let result = db::update_task(&self.conn, TaskColumn { - id: self.tasks[id].id, + id: self.tasks[id].db_id, checked: self.tasks[id].checked, value: self.tasks[id].value.to_string(), }, ChangeType::Checked); @@ -141,36 +148,41 @@ impl Todo { Task::none() }, - Message::EditTask(id) => { + Message::EditTask(index) => { let set_update; - if self.tasks[id].edit { - if self.updated_task.is_empty() { - return Task::none(); - } + if self.tasks[index].edit { + if self.updated_task.is_empty() { return Task::none(); } + if self.duplicate_exists(Some(&self.tasks[index].value)) { return Task::none(); } - self.tasks[id].value = self.updated_task.clone(); + self.tasks[index].value = self.updated_task.clone(); let result = db::update_task(&self.conn, TaskColumn { - id: self.tasks[id].id, - checked: self.tasks[id].checked, - value: self.tasks[id].value.to_string(), + id: self.tasks[index].db_id, + checked: self.tasks[index].checked, + value: self.tasks[index].value.to_string(), }, ChangeType::Value); if let Err(e) = result { - eprintln!("[ERROR] Failed to update task '{}' in local storage:\n{e}", self.tasks[id].value); + eprintln!("[ERROR] Failed to update task '{}' in local storage:\n{e}", self.tasks[index].value); } set_update = true; self.updated_task = String::new(); + + for item in &mut self.tasks { + if item.already_exists { + item.already_exists = false; + } + } } else { set_update = false; } - self.tasks[id].edit = !self.tasks[id].edit; - self.set_other_update(id, set_update); + self.tasks[index].edit = !self.tasks[index].edit; + self.set_other_update(index, set_update); widget::focus_previous() - }, + } Message::DeleteAll => { if let Err(e) = db::delete_tasks(&self.conn, None) { eprintln!("[ERROR] Failed to delete all tasks:\n{e}") @@ -280,7 +292,10 @@ impl Todo { for (i, task) in self.tasks.iter().enumerate() { let chk = checkbox("", task.checked).size(25).on_toggle(move |b| Message::CheckTask(b, i)); - let label = Text::new(&task.value).width(200); + let mut label = Text::new(&task.value).width(200); + if task.already_exists { + label = label.style(danger); + } let input = text_input("Enter new name", &self.updated_task) .width(200) .on_input(|str| Message::ContentUpdated(false, str)) @@ -333,12 +348,13 @@ impl Todo { if let Ok(t) = db::get_tasks(&self.conn) { for item in t { let data = TaskData { - id: item.id, + db_id: item.id, checked: item.checked, value: item.value, edit: false, can_update: true, can_delete: true, + already_exists: false, }; if item.checked { @@ -349,4 +365,20 @@ impl Todo { } } } + + fn duplicate_exists(&self, task_name: Option<&String>) -> bool { + for task in &self.tasks { + if task.already_exists { + match task_name { + Some(t) => { + if task.value != *t { return true; } + }, + None => return true, + } + + } + } + + false + } } \ No newline at end of file