local storage - fin
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,3 @@
 | 
				
			|||||||
/target
 | 
					/target
 | 
				
			||||||
/.idea
 | 
					/.idea
 | 
				
			||||||
/todo-db.db3
 | 
					/todolist-db.db3
 | 
				
			||||||
							
								
								
									
										74
									
								
								src/db.rs
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								src/db.rs
									
									
									
									
									
								
							@@ -1,10 +1,8 @@
 | 
				
			|||||||
 | 
					use crate::todo::{ChangeType, TaskColumn};
 | 
				
			||||||
 | 
					use rusqlite::{params, Connection, Error, Result};
 | 
				
			||||||
use std::path::Path;
 | 
					use std::path::Path;
 | 
				
			||||||
use rusqlite::{params, Connection, Result};
 | 
					 | 
				
			||||||
use crate::def;
 | 
					 | 
				
			||||||
use crate::def::Task;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) fn startup(path: &Path) -> Result<(Connection)> {
 | 
					pub(crate) fn startup(path: &Path) -> Result<(Connection)> {
 | 
				
			||||||
    // let conn = Connection::open_in_memory()?;
 | 
					 | 
				
			||||||
    let conn = Connection::open(path)?;
 | 
					    let conn = Connection::open(path)?;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    conn.execute(
 | 
					    conn.execute(
 | 
				
			||||||
@@ -16,32 +14,74 @@ pub(crate) fn startup(path: &Path) -> Result<(Connection)> {
 | 
				
			|||||||
        ()
 | 
					        ()
 | 
				
			||||||
    )?;
 | 
					    )?;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // todo
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Ok(conn)
 | 
					    Ok(conn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) fn get_tasks(conn: &Connection) -> Result<()> {
 | 
					pub(crate) fn get_tasks(conn: &Connection) -> std::result::Result<Vec<TaskColumn>, Error> {
 | 
				
			||||||
    let mut stmt = conn.prepare("SELECT checked, value FROM tasks")?;
 | 
					    let mut stmt = conn.prepare("SELECT id, checked, value FROM tasks")?;
 | 
				
			||||||
    let task_iter = stmt.query_map([], |row| {
 | 
					    let tasks_iter = stmt.query_map([], |row| {
 | 
				
			||||||
        Ok(Task {
 | 
					        Ok(TaskColumn {
 | 
				
			||||||
            checked: row.get(0)?,
 | 
					            id: row.get(0)?,
 | 
				
			||||||
            value: row.get(1)?,
 | 
					            checked: row.get(1)?,
 | 
				
			||||||
 | 
					            value: row.get(2)?,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    })?;
 | 
					    })?;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for task in task_iter {
 | 
					    let mut tasks = Vec::new();
 | 
				
			||||||
        println!("{:?}", task);
 | 
					    for task in tasks_iter {
 | 
				
			||||||
 | 
					        tasks.push(task?);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(tasks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) fn insert_task(task: Task, conn: &Connection) -> Result<()> {
 | 
					pub(crate) fn insert_task(conn: &Connection, task: TaskColumn) -> Result<i64> {
 | 
				
			||||||
    conn.execute(
 | 
					    conn.execute(
 | 
				
			||||||
        "INSERT INTO tasks (checked, value) VALUES (?1, ?2)",
 | 
					        "INSERT INTO tasks (checked, value) VALUES (?1, ?2)",
 | 
				
			||||||
        (&task.checked, &task.value),
 | 
					        (&task.checked, &task.value),
 | 
				
			||||||
    )?;
 | 
					    )?;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    Ok(conn.last_insert_rowid())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// happens if we un/select task or we rename the task
 | 
				
			||||||
 | 
					pub(crate) fn update_task(conn: &Connection, task: TaskColumn, change: ChangeType) -> Result<()> {
 | 
				
			||||||
 | 
					    let (query, params) = match change {
 | 
				
			||||||
 | 
					        ChangeType::Checked => (
 | 
				
			||||||
 | 
					            "UPDATE tasks SET checked = ?1 WHERE id = ?2",
 | 
				
			||||||
 | 
					            params![&task.checked, &task.id]
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        ChangeType::Value => (
 | 
				
			||||||
 | 
					            "UPDATE tasks SET value = ?1 WHERE id = ?2",
 | 
				
			||||||
 | 
					            params![&task.value, &task.id]
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conn.execute(query, params)?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) fn update_unselect_tasks(conn: &Connection, checked: bool) -> Result<()> {
 | 
				
			||||||
 | 
					    conn.execute(
 | 
				
			||||||
 | 
					        "UPDATE tasks SET checked = ?1",
 | 
				
			||||||
 | 
					        (&checked,)
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) fn delete_tasks(conn: &Connection, id: Option<usize>) -> Result<()> {
 | 
				
			||||||
 | 
					    let (query, params) = match id { 
 | 
				
			||||||
 | 
					        Some(t) => (
 | 
				
			||||||
 | 
					            "DELETE FROM tasks WHERE id = ?1",
 | 
				
			||||||
 | 
					            params![t.clone()]
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        None => (
 | 
				
			||||||
 | 
					            "DELETE FROM tasks",
 | 
				
			||||||
 | 
					            params![]
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conn.execute(query, params)?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/def.rs
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/def.rs
									
									
									
									
									
								
							@@ -1,35 +0,0 @@
 | 
				
			|||||||
use iced::Event;
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub struct Task {
 | 
					 | 
				
			||||||
    pub(crate) checked: bool,
 | 
					 | 
				
			||||||
    pub(crate) value: String,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct TaskData {
 | 
					 | 
				
			||||||
    pub(crate) checked: bool,
 | 
					 | 
				
			||||||
    pub(crate) value: String,
 | 
					 | 
				
			||||||
    pub(crate) edit: bool,
 | 
					 | 
				
			||||||
    pub(crate) can_update: bool,
 | 
					 | 
				
			||||||
    pub(crate) can_delete: bool,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct Todo {
 | 
					 | 
				
			||||||
    pub(crate) new_task: String,
 | 
					 | 
				
			||||||
    pub(crate) updated_task: String,
 | 
					 | 
				
			||||||
    pub(crate) tasks: Vec<TaskData>,
 | 
					 | 
				
			||||||
    pub(crate) completed_tasks: usize,
 | 
					 | 
				
			||||||
    pub(crate) local_storage: bool,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					 | 
				
			||||||
pub enum Message {
 | 
					 | 
				
			||||||
    AddTask,
 | 
					 | 
				
			||||||
    CheckTask(bool, usize),
 | 
					 | 
				
			||||||
    EditTask(usize),
 | 
					 | 
				
			||||||
    DeleteTask(usize),
 | 
					 | 
				
			||||||
    DeleteAll,
 | 
					 | 
				
			||||||
    ContentUpdated(bool, String),
 | 
					 | 
				
			||||||
    Event(Event),
 | 
					 | 
				
			||||||
    TaskPush(Option<usize>),
 | 
					 | 
				
			||||||
    StorageToggle(bool),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										26
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,18 +1,14 @@
 | 
				
			|||||||
use std::path::Path;
 | 
					 | 
				
			||||||
use iced::window::Settings;
 | 
					use iced::window::Settings;
 | 
				
			||||||
use iced::Size;
 | 
					use iced::Size;
 | 
				
			||||||
use def::Todo;
 | 
					use todo::Todo;
 | 
				
			||||||
use crate::db::startup;
 | 
					 | 
				
			||||||
use crate::def::Task;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod todo;
 | 
					mod todo;
 | 
				
			||||||
mod def;
 | 
					 | 
				
			||||||
mod db;
 | 
					mod db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*fn main() -> iced::Result {
 | 
					fn main() -> iced::Result {
 | 
				
			||||||
    let settings = Settings {
 | 
					    let settings = Settings {
 | 
				
			||||||
        size: Size::new(500.0, 600.0),
 | 
					        size: Size::new(500.0, 600.0),
 | 
				
			||||||
        resizable: false,
 | 
					        //resizable: false,
 | 
				
			||||||
        ..Settings::default()
 | 
					        ..Settings::default()
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -21,18 +17,20 @@ mod db;
 | 
				
			|||||||
        .theme(Todo::theme)
 | 
					        .theme(Todo::theme)
 | 
				
			||||||
        .window(settings)
 | 
					        .window(settings)
 | 
				
			||||||
        .run()
 | 
					        .run()
 | 
				
			||||||
}*/
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					/*fn main() {
 | 
				
			||||||
    let path: &Path = Path::new("./todo-db.db3");
 | 
					    let path: &Path = Path::new("./todolist-db.db3");
 | 
				
			||||||
    let conn = startup(path);
 | 
					    let conn = startup(path);
 | 
				
			||||||
    let t = Task {
 | 
					    let t = Task {
 | 
				
			||||||
        checked: true,
 | 
					        checked: true,
 | 
				
			||||||
        value: String::from("Troll Ink"),
 | 
					        value: String::from("JJ"),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    let c = conn.unwrap();
 | 
					    let c = conn.unwrap();
 | 
				
			||||||
    /*let r = db::insert_task(t, &c);
 | 
					    let r = db::insert_task(t, &c);
 | 
				
			||||||
    println!("{:?}", r);*/
 | 
					    println!("{:?}", r);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    let rr = db::get_tasks(&c);
 | 
					    let rr = db::get_tasks(&c);
 | 
				
			||||||
}
 | 
					    
 | 
				
			||||||
 | 
					    let x = c.close();
 | 
				
			||||||
 | 
					}*/
 | 
				
			||||||
							
								
								
									
										179
									
								
								src/todo.rs
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								src/todo.rs
									
									
									
									
									
								
							@@ -1,26 +1,77 @@
 | 
				
			|||||||
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 crate::def::{Message, TaskData, Todo};
 | 
					use rusqlite::Connection;
 | 
				
			||||||
 | 
					use crate::db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct TaskColumn {
 | 
				
			||||||
 | 
					     pub(crate) id: usize,
 | 
				
			||||||
 | 
					     pub(crate) checked: bool,
 | 
				
			||||||
 | 
					     pub(crate) value: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct TaskData {
 | 
				
			||||||
 | 
					     id: usize,
 | 
				
			||||||
 | 
					     checked: bool,
 | 
				
			||||||
 | 
					     value: String,
 | 
				
			||||||
 | 
					     edit: bool,
 | 
				
			||||||
 | 
					     can_update: bool,
 | 
				
			||||||
 | 
					     can_delete: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) struct Todo {
 | 
				
			||||||
 | 
					     new_task: String,
 | 
				
			||||||
 | 
					     updated_task: String,
 | 
				
			||||||
 | 
					     tasks: Vec<TaskData>,
 | 
				
			||||||
 | 
					     completed_tasks: usize,
 | 
				
			||||||
 | 
					     local_storage: bool,
 | 
				
			||||||
 | 
					     conn: Connection,
 | 
				
			||||||
 | 
					     select_all: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub enum Message {
 | 
				
			||||||
 | 
					    AddTask,
 | 
				
			||||||
 | 
					    CheckTask(bool, usize),
 | 
				
			||||||
 | 
					    EditTask(usize),
 | 
				
			||||||
 | 
					    DeleteTask(usize),
 | 
				
			||||||
 | 
					    DeleteAll,
 | 
				
			||||||
 | 
					    ContentUpdated(bool, String),
 | 
				
			||||||
 | 
					    Event(Event),
 | 
				
			||||||
 | 
					    TaskPush(Option<usize>),
 | 
				
			||||||
 | 
					    StorageToggle(bool),
 | 
				
			||||||
 | 
					    ToggleUnselect(bool),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum ChangeType {
 | 
				
			||||||
 | 
					    Checked,
 | 
				
			||||||
 | 
					    Value,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for Todo {
 | 
					impl Default for Todo {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        Todo::new()
 | 
					        Todo::new()
 | 
				
			||||||
        // startup checks
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Todo {
 | 
					impl Todo {
 | 
				
			||||||
    fn new() -> Self {
 | 
					    fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        let mut init = Self {
 | 
				
			||||||
            new_task: String::new(),
 | 
					            new_task: String::new(),
 | 
				
			||||||
            updated_task: String::new(),
 | 
					            updated_task: String::new(),
 | 
				
			||||||
            tasks: Vec::new(),
 | 
					            tasks: Vec::new(),
 | 
				
			||||||
            completed_tasks: 0,
 | 
					            completed_tasks: 0,
 | 
				
			||||||
            local_storage: true,
 | 
					            local_storage: true, // todo eventually get this info from db - if no db set it to true
 | 
				
			||||||
        }
 | 
					            conn: db::startup("./todolist-db.db3".as_ref()).expect("[ERROR] Failed to access the local storage"),
 | 
				
			||||||
 | 
					            select_all: false,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        Self::load_data_from_db(&mut init);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        init
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
 | 
					     pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
 | 
				
			||||||
        match message {
 | 
					        match message {
 | 
				
			||||||
            Message::ContentUpdated(new, value) => {
 | 
					            Message::ContentUpdated(new, value) => {
 | 
				
			||||||
                if new {
 | 
					                if new {
 | 
				
			||||||
@@ -34,31 +85,60 @@ impl Todo {
 | 
				
			|||||||
            Message::AddTask => {
 | 
					            Message::AddTask => {
 | 
				
			||||||
                if self.new_task.is_empty() { return Task::none(); }
 | 
					                if self.new_task.is_empty() { return Task::none(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let data = TaskData {
 | 
					
 | 
				
			||||||
 | 
					                let result = db::insert_task(&self.conn, TaskColumn {
 | 
				
			||||||
 | 
					                    id: 0,
 | 
				
			||||||
                    checked: false,
 | 
					                    checked: false,
 | 
				
			||||||
                    value: self.new_task.to_string(),
 | 
					                    value: self.new_task.to_string(),
 | 
				
			||||||
                    edit: false,
 | 
					                });
 | 
				
			||||||
                    can_update: true,
 | 
					
 | 
				
			||||||
                    can_delete: true,
 | 
					                match result {
 | 
				
			||||||
                };
 | 
					                    Ok(t) => {
 | 
				
			||||||
 | 
					                        let data = TaskData {
 | 
				
			||||||
 | 
					                            id: t as usize,
 | 
				
			||||||
 | 
					                            checked: false,
 | 
				
			||||||
 | 
					                            value: self.new_task.to_string(),
 | 
				
			||||||
 | 
					                            edit: false,
 | 
				
			||||||
 | 
					                            can_update: true,
 | 
				
			||||||
 | 
					                            can_delete: true,
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        self.tasks.push(data);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    Err(e) => eprintln!("[ERROR] Failed to insert new task into DB:\n{e}"),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                self.tasks.push(data);
 | 
					 | 
				
			||||||
                self.new_task = String::new();
 | 
					                self.new_task = String::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Task::none()
 | 
					                Task::none()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Message::DeleteTask(id) => {
 | 
					            Message::DeleteTask(index) => {
 | 
				
			||||||
                if self.tasks[id].checked {
 | 
					                if self.tasks[index].checked {
 | 
				
			||||||
                    self.completed_tasks -= 1;
 | 
					                    self.completed_tasks -= 1;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                self.tasks.remove(id);
 | 
					                
 | 
				
			||||||
 | 
					                if let Err(e) = db::delete_tasks(&self.conn, Some(self.tasks[index].id)) {
 | 
				
			||||||
 | 
					                    eprintln!("[ERROR] Failed to delete task '{}':\n{e}", self.tasks[index].value);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                self.tasks.remove(index);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Task::none()
 | 
					                Task::none()
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
            Message::CheckTask(choice, id) => {
 | 
					            Message::CheckTask(choice, id) => {
 | 
				
			||||||
                self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 };
 | 
					                self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 };
 | 
				
			||||||
                self.tasks[id].checked = choice;
 | 
					                self.tasks[id].checked = choice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                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(),
 | 
				
			||||||
 | 
					                }, ChangeType::Checked);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if let Err(e) = result {
 | 
				
			||||||
 | 
					                    eprintln!("[ERROR] Failed to update checkbox in local storage:\n{e}");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Task::none()
 | 
					                Task::none()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Message::EditTask(id) => {
 | 
					            Message::EditTask(id) => {
 | 
				
			||||||
@@ -70,6 +150,16 @@ impl Todo {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    self.tasks[id].value = self.updated_task.clone();
 | 
					                    self.tasks[id].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(),
 | 
				
			||||||
 | 
					                    }, ChangeType::Value);
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if let Err(e) = result {
 | 
				
			||||||
 | 
					                        eprintln!("[ERROR] Failed to update task '{}' in local storage:\n{e}", self.tasks[id].value);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                    set_update = true;
 | 
					                    set_update = true;
 | 
				
			||||||
                    self.updated_task = String::new();
 | 
					                    self.updated_task = String::new();
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
@@ -82,6 +172,10 @@ impl Todo {
 | 
				
			|||||||
                widget::focus_previous()
 | 
					                widget::focus_previous()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Message::DeleteAll => {
 | 
					            Message::DeleteAll => {
 | 
				
			||||||
 | 
					                if let Err(e) = db::delete_tasks(&self.conn, None) {
 | 
				
			||||||
 | 
					                    eprintln!("[ERROR] Failed to delete all tasks:\n{e}")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                self.new_task = String::from("");
 | 
					                self.new_task = String::from("");
 | 
				
			||||||
                self.updated_task = String::from("");
 | 
					                self.updated_task = String::from("");
 | 
				
			||||||
                self.tasks.clear();
 | 
					                self.tasks.clear();
 | 
				
			||||||
@@ -121,20 +215,41 @@ impl Todo {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Message::StorageToggle(toggle) => {
 | 
					            Message::StorageToggle(toggle) => {
 | 
				
			||||||
                self.local_storage = toggle;
 | 
					                // todo must be enabled eventually
 | 
				
			||||||
 | 
					                //self.local_storage = toggle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /*
 | 
					                /*
 | 
				
			||||||
                todo
 | 
					                todo
 | 
				
			||||||
                here we only call for storage change not implement the whole system
 | 
					                here we only call for storage change not implement the whole system
 | 
				
			||||||
                as the system should be running since the program startup
 | 
					                as the system should be running since the program startup
 | 
				
			||||||
                */
 | 
					                */
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                // also how do we even implement that
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Task::none()
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            Message::ToggleUnselect(toggle) => {
 | 
				
			||||||
 | 
					                self.select_all = toggle;
 | 
				
			||||||
 | 
					                for task in &mut self.tasks {
 | 
				
			||||||
 | 
					                    task.checked = toggle;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if toggle {
 | 
				
			||||||
 | 
					                    self.completed_tasks = self.tasks.len();
 | 
				
			||||||
 | 
					                } else { 
 | 
				
			||||||
 | 
					                    self.completed_tasks = 0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if let Err(e) = db::update_unselect_tasks(&self.conn, toggle) {
 | 
				
			||||||
 | 
					                    eprintln!("[ERROR] Failed to update un/select all operation in database:\n{e}");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                Task::none()
 | 
					                Task::none()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn view(&self) -> Element<Message> {
 | 
					     pub(crate) fn view(&self) -> Element<Message> {
 | 
				
			||||||
        let input = text_input("Enter new task", &self.new_task)
 | 
					        let input = text_input("Enter new task", &self.new_task)
 | 
				
			||||||
            .width(300)
 | 
					            .width(300)
 | 
				
			||||||
            .size(25)
 | 
					            .size(25)
 | 
				
			||||||
@@ -186,8 +301,9 @@ impl Todo {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let status = Text::new(format!("{} / {}", self.completed_tasks, self.tasks.len()));
 | 
					        let status = Text::new(format!("{} / {}", self.completed_tasks, self.tasks.len()));
 | 
				
			||||||
 | 
					        let unselect = checkbox("Un/select all", self.select_all).on_toggle(Message::ToggleUnselect);
 | 
				
			||||||
        let storage = checkbox("Local storage", self.local_storage).on_toggle(Message::StorageToggle);
 | 
					        let storage = checkbox("Local storage", self.local_storage).on_toggle(Message::StorageToggle);
 | 
				
			||||||
        let footer = row![status, Space::with_width(Length::Fill), storage].padding(10);
 | 
					        let footer = row![status, Space::with_width(Length::Fill), unselect, storage].padding(10).spacing(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut output = column![new_task.padding(10)];
 | 
					        let mut output = column![new_task.padding(10)];
 | 
				
			||||||
        output = if self.tasks.is_empty() { output.push(saved_tasks.height(Length::Fill)) } else { output.push(scrollable(saved_tasks).height(Length::Fill).spacing(10)) };
 | 
					        output = if self.tasks.is_empty() { output.push(saved_tasks.height(Length::Fill)) } else { output.push(scrollable(saved_tasks).height(Length::Fill).spacing(10)) };
 | 
				
			||||||
@@ -196,11 +312,11 @@ impl Todo {
 | 
				
			|||||||
        center(output).into()
 | 
					        center(output).into()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn theme(&self) -> Theme {
 | 
					     pub(crate) fn theme(&self) -> Theme {
 | 
				
			||||||
        Theme::Dark
 | 
					        Theme::Dark
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn subscription(&self) -> Subscription<Message> {
 | 
					     pub(crate) fn subscription(&self) -> Subscription<Message> {
 | 
				
			||||||
        event::listen().map(Message::Event)
 | 
					        event::listen().map(Message::Event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -212,4 +328,25 @@ impl Todo {
 | 
				
			|||||||
            task.can_delete = enable;
 | 
					            task.can_delete = enable;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn load_data_from_db(&mut self) {
 | 
				
			||||||
 | 
					        if let Ok(t) = db::get_tasks(&self.conn) {
 | 
				
			||||||
 | 
					            for item in t {
 | 
				
			||||||
 | 
					                let data = TaskData {
 | 
				
			||||||
 | 
					                    id: item.id,
 | 
				
			||||||
 | 
					                    checked: item.checked,
 | 
				
			||||||
 | 
					                    value: item.value,
 | 
				
			||||||
 | 
					                    edit: false,
 | 
				
			||||||
 | 
					                    can_update: true,
 | 
				
			||||||
 | 
					                    can_delete: true,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if item.checked {
 | 
				
			||||||
 | 
					                    self.completed_tasks += 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.tasks.push(data);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user