This commit is contained in:
Martin Vrhovšek 2025-02-02 14:35:43 +01:00
parent 339cf9d119
commit 33207c2620

View File

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