diff --git a/src/bin/todo/create.rs b/src/bin/todo/create.rs index 87eb22d..7218d34 100644 --- a/src/bin/todo/create.rs +++ b/src/bin/todo/create.rs @@ -9,14 +9,10 @@ pub struct Args { description: String, #[clap(long)] priority: Priority, - #[clap(long, value_parser=parse_datetime)] + #[clap(long, value_parser=mindmap::parse_datetime)] deadline: NaiveDateTime, } -fn parse_datetime(s: &str) -> Result { - NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") -} - pub async fn command(args: &Args) { let task = Task { diff --git a/src/bin/todo/delete.rs b/src/bin/todo/delete.rs index a230449..aede550 100644 --- a/src/bin/todo/delete.rs +++ b/src/bin/todo/delete.rs @@ -1,8 +1,18 @@ use clap::Parser; +use mindmap::db::get_client; #[derive(Parser)] -pub struct Args {} +pub struct Args { + #[clap(long)] + description: String, +} + +pub async fn command(args: &Args) { + + let description = args.description.clone(); + + let client = get_client().await.expect("Failed to fetch client"); + client.execute("DELETE FROM todo WHERE description = $1", &[&description],).await.expect("Failed to delete task"); -pub fn command(_args: &Args) { - println!("Deleted task successfully!") + println!("Task \"{}\" deleted successfully!", description); } diff --git a/src/bin/todo/list.rs b/src/bin/todo/list.rs index 572ac47..6e3c1f1 100644 --- a/src/bin/todo/list.rs +++ b/src/bin/todo/list.rs @@ -1,8 +1,24 @@ +use chrono::Local; use clap::Parser; +use mindmap::db::get_client; #[derive(Parser)] pub struct Args {} -pub fn command(_args: &Args) { - println!("Tasks due today:"); +pub async fn command(_args: &Args) { + + let client = get_client().await.expect("Failed to fetch client"); + let today = Local::now().date_naive(); + let rows = client.query("SELECT description, priority, deadline FROM todo WHERE DATE(deadline) = $1::date", &[&today]).await.expect("Failed to fetch tasks"); + + for row in rows { + let description: String = row.get(0); + let priority: mindmap::Priority = row.get(1); + let deadline: chrono::NaiveDateTime = row.get(2); + + println!("Task: {}", description); + println!("Priority: {:?}", priority); + println!("Deadline: {}", deadline); + println!(); + } } diff --git a/src/bin/todo/main.rs b/src/bin/todo/main.rs index f39b39c..bafd5e2 100644 --- a/src/bin/todo/main.rs +++ b/src/bin/todo/main.rs @@ -33,9 +33,9 @@ async fn main() { match &cli.command { Commands::Create(args) => create::command(args).await, - Commands::List(args) => list::command(args), + Commands::List(args) => list::command(args).await, Commands::Show(args) => show::command(args), - Commands::Update(args) => update::command(args), - Commands::Delete(args) => delete::command(args), + Commands::Update(args) => update::command(args).await, + Commands::Delete(args) => delete::command(args).await, } } diff --git a/src/bin/todo/update.rs b/src/bin/todo/update.rs index 4eccd35..138c188 100644 --- a/src/bin/todo/update.rs +++ b/src/bin/todo/update.rs @@ -1,8 +1,39 @@ +use chrono::NaiveDateTime; use clap::Parser; +use mindmap::Priority; #[derive(Parser)] -pub struct Args {} +pub struct Args { + #[clap(long)] + description: String, + #[clap(long)] + new_description: String, + #[clap(long)] + new_priority: Priority, + #[clap(long, value_parser=mindmap::parse_datetime)] + new_deadline: NaiveDateTime, +} + +pub async fn command(_args: &Args) { + + let client = mindmap::db::get_client().await.expect("Failed to fetch client"); + + let rows = client.query("SELECT description, priority, deadline FROM todo WHERE description = $1", &[&_args.description]).await.expect("Failed to fetch task"); + + if rows.is_empty() { + println!("Task not found!"); + return; + } + + let description = _args.description.clone(); + let new_description = _args.new_description.clone(); + let new_priority = _args.new_priority.clone(); + let new_deadline = _args.new_deadline; + + client.execute( + "UPDATE todo SET description = $1, priority = $2, deadline = $3 WHERE description = $4", + &[&new_description, &new_priority, &new_deadline, &description], + ).await.expect("Failed to update task"); -pub fn command(_args: &Args) { - println!("Updated task successfully!") + println!("Task updated successfully!"); } diff --git a/src/lib.rs b/src/lib.rs index ae5ac09..2c0c249 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,9 @@ pub mod db; use chrono::NaiveDateTime; use clap::ValueEnum; -use tokio_postgres::types::{IsNull, ToSql, Type}; +use tokio_postgres::types::{IsNull, ToSql, FromSql, Type}; use std::error::Error as StdError; +use std::str::FromStr; use bytes::BytesMut; #[derive(Debug, Clone, ValueEnum)] @@ -34,6 +35,36 @@ impl ToSql for Priority { tokio_postgres::types::to_sql_checked!(); } +impl FromStr for Priority { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "low" => Ok(Priority::Low), + "neutral" => Ok(Priority::Neutral), + "unknown" => Ok(Priority::Unknown), + "high" => Ok(Priority::High), + "critical" => Ok(Priority::Critical), + _ => Err(format!("Invalid priority: {}", s)), + } + } +} + +impl<'a> FromSql<'a> for Priority { + fn from_sql(_ty: &Type, raw: &'a [u8]) -> Result> { + let s = std::str::from_utf8(raw)?; + s.parse().map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::InvalidData, e)) as Box) + } + + fn accepts(ty: &Type) -> bool { + ty.name() == "priority" + } +} + +pub fn parse_datetime(s: &str) -> Result { + NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") +} + #[derive(Debug, Clone)] pub struct Task { pub description: String,