feat: display the subtask count in task lists
This commit is contained in:
		| @@ -6,14 +6,14 @@ use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::QueryResult; | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::query::QueryValue; | ||||
| use crate::query::tasks::use_tasks_in_category_query; | ||||
| use crate::models::task::Task; | ||||
| use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | ||||
| use crate::models::task::{TaskWithSubtasks}; | ||||
|  | ||||
| const CALENDAR_LENGTH_DAYS: usize = 366 * 3; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn CategoryCalendarPage() -> Element { | ||||
|     let tasks = use_tasks_in_category_query(Category::Calendar { | ||||
|     let tasks = use_tasks_with_subtasks_in_category_query(Category::Calendar { | ||||
|         date: Local::now().date_naive(), | ||||
|         reoccurrence: None, | ||||
|         time: None, | ||||
| @@ -22,8 +22,8 @@ pub(crate) fn CategoryCalendarPage() -> Element { | ||||
|  | ||||
|     rsx! { | ||||
|         match tasks_query_result.value() { | ||||
|             QueryResult::Ok(QueryValue::Tasks(tasks)) | ||||
|             | QueryResult::Loading(Some(QueryValue::Tasks(tasks))) => { | ||||
|             QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||
|             | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => { | ||||
|                 let today_date = Local::now().date_naive(); | ||||
|                  | ||||
|                 rsx! { | ||||
| @@ -52,12 +52,13 @@ pub(crate) fn CategoryCalendarPage() -> Element { | ||||
|                                 } | ||||
|                                 TaskList { | ||||
|                                     tasks: tasks.iter().filter(|task| { | ||||
|                                         if let Category::Calendar { date, .. } = task.category() { | ||||
|                                         if let Category::Calendar { date, .. }  | ||||
|                                             = task.task().category() { | ||||
|                                             *date == date_current | ||||
|                                         } else { | ||||
|                                             panic!("Unexpected category."); | ||||
|                                         } | ||||
|                                     }).cloned().collect::<Vec<Task>>() | ||||
|                                     }).cloned().collect::<Vec<TaskWithSubtasks>>() | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::models::category::Category; | ||||
| use crate::query::tasks::use_tasks_in_category_query; | ||||
| use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | ||||
| use crate::query::QueryValue; | ||||
| use dioxus::core_macro::rsx; | ||||
| use dioxus::dioxus_core::Element; | ||||
| @@ -9,12 +9,12 @@ use dioxus_query::prelude::QueryResult; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn CategoryPage(category: Category) -> Element { | ||||
|     let tasks_query = use_tasks_in_category_query(category); | ||||
|     let tasks_query = use_tasks_with_subtasks_in_category_query(category); | ||||
|     let tasks_query_result = tasks_query.result(); | ||||
|  | ||||
|     match tasks_query_result.value() { | ||||
|         QueryResult::Ok(QueryValue::Tasks(tasks)) | ||||
|         | QueryResult::Loading(Some(QueryValue::Tasks(tasks))) => rsx! { | ||||
|         QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||
|         | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => rsx! { | ||||
|             TaskList { | ||||
|                 tasks: tasks.clone(), | ||||
|                 class: "pb-36" | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::models::category::Category; | ||||
| use crate::models::task::Task; | ||||
| use crate::query::tasks::use_tasks_in_category_query; | ||||
| use crate::models::task::TaskWithSubtasks; | ||||
| use crate::query::tasks::{use_tasks_with_subtasks_in_category_query}; | ||||
| use crate::query::QueryValue; | ||||
| use chrono::{Local, Locale}; | ||||
| use dioxus::prelude::*; | ||||
| @@ -11,22 +11,22 @@ use dioxus_query::prelude::QueryResult; | ||||
| pub(crate) fn CategoryTodayPage() -> Element { | ||||
|     let today_date = Local::now().date_naive(); | ||||
|      | ||||
|     let calendar_tasks_query = use_tasks_in_category_query(Category::Calendar { | ||||
|     let calendar_tasks_query = use_tasks_with_subtasks_in_category_query(Category::Calendar { | ||||
|         date: today_date, | ||||
|         reoccurrence: None, | ||||
|         time: None, | ||||
|     }); | ||||
|     let calendar_tasks_query_result = calendar_tasks_query.result(); | ||||
|  | ||||
|     let long_term_tasks_query = use_tasks_in_category_query(Category::LongTerm); | ||||
|     let long_term_tasks_query = use_tasks_with_subtasks_in_category_query(Category::LongTerm); | ||||
|     let long_term_tasks_query_result = long_term_tasks_query.result(); | ||||
|  | ||||
|     rsx! { | ||||
|         div { | ||||
|             class: "pt-4 flex flex-col gap-8", | ||||
|             match long_term_tasks_query_result.value() { | ||||
|                 QueryResult::Ok(QueryValue::Tasks(tasks)) | ||||
|                 | QueryResult::Loading(Some(QueryValue::Tasks(tasks))) => rsx! { | ||||
|                 QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||
|                 | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => rsx! { | ||||
|                     div { | ||||
|                         class: "flex flex-col gap-4", | ||||
|                         div { | ||||
| @@ -42,10 +42,10 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                         div { | ||||
|                             for task in tasks { | ||||
|                                 div { | ||||
|                                     key: "{task.id()}", | ||||
|                                     key: "{task.task().id()}", | ||||
|                                     class: format!( | ||||
|                                         "px-8 pt-5 {} flex flex-row gap-4", | ||||
|                                         if task.deadline().is_some() { | ||||
|                                         if task.task().deadline().is_some() { | ||||
|                                             "pb-0.5" | ||||
|                                         } else { | ||||
|                                             "pb-5" | ||||
| @@ -55,11 +55,11 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                                         class: "flex flex-col", | ||||
|                                         div { | ||||
|                                             class: "mt grow font-medium", | ||||
|                                             {task.title()} | ||||
|                                             {task.task().title()} | ||||
|                                         }, | ||||
|                                         div { | ||||
|                                             class: "flex flex-row gap-3", | ||||
|                                             if let Some(deadline) = task.deadline() { | ||||
|                                             if let Some(deadline) = task.task().deadline() { | ||||
|                                                 div { | ||||
|                                                     class: "text-sm text-zinc-400", | ||||
|                                                     i { | ||||
| @@ -86,22 +86,22 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                 value => panic!("Unexpected query result: {value:?}") | ||||
|             } | ||||
|             match calendar_tasks_query_result.value() { | ||||
|                 QueryResult::Ok(QueryValue::Tasks(tasks)) | ||||
|                 | QueryResult::Loading(Some(QueryValue::Tasks(tasks))) => { | ||||
|                 QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||
|                 | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => { | ||||
|                     let today_tasks = tasks.iter().filter(|task| { | ||||
|                         if let Category::Calendar { date, .. } = task.category() { | ||||
|                         if let Category::Calendar { date, .. } = task.task().category() { | ||||
|                             *date == today_date | ||||
|                         } else { | ||||
|                             panic!("Unexpected category."); | ||||
|                         } | ||||
|                     }).cloned().collect::<Vec<Task>>(); | ||||
|                     }).cloned().collect::<Vec<TaskWithSubtasks>>(); | ||||
|                     let overdue_tasks = tasks.iter().filter(|task| { | ||||
|                         if let Category::Calendar { date, .. } = task.category() { | ||||
|                         if let Category::Calendar { date, .. } = task.task().category() { | ||||
|                             *date < today_date | ||||
|                         } else { | ||||
|                             panic!("Unexpected category."); | ||||
|                         } | ||||
|                     }).cloned().collect::<Vec<Task>>(); | ||||
|                     }).cloned().collect::<Vec<TaskWithSubtasks>>(); | ||||
|          | ||||
|                     rsx! { | ||||
|                         if !overdue_tasks.is_empty() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| use crate::models::subtask::NewSubtask; | ||||
| use crate::models::task::Task; | ||||
| use crate::query::subtasks::use_subtasks_of_task_query; | ||||
| use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||
| use crate::server::subtasks::{create_subtask, delete_subtask, edit_subtask}; | ||||
| @@ -8,151 +9,172 @@ use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::{use_query_client, QueryResult}; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn SubtasksForm(task_id: i32) -> Element { | ||||
| pub(crate) fn SubtasksForm(task: Task) -> Element { | ||||
|     let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||
|     let subtasks_query = use_subtasks_of_task_query(task_id); | ||||
|      | ||||
|     let subtasks_query = use_subtasks_of_task_query(task.id()); | ||||
|  | ||||
|     let mut new_title = use_signal(String::new); | ||||
|  | ||||
|     rsx! { | ||||
|             form { | ||||
|                 class: "flex flex-row items-center gap-3", | ||||
|                 onsubmit: move |event| async move { | ||||
|         form { | ||||
|             class: "flex flex-row items-center gap-3", | ||||
|             onsubmit: move |event| { | ||||
|                 let task = task.clone(); | ||||
|                 async move { | ||||
|                     let new_subtask = NewSubtask::new( | ||||
|                         task_id, | ||||
|                         task.id(), | ||||
|                         event.values().get("title").unwrap().as_value(), | ||||
|                         false | ||||
|                     ); | ||||
|                     let _ = create_subtask(new_subtask).await; | ||||
|                     query_client.invalidate_queries(&[QueryKey::SubtasksOfTaskId(task_id)]); | ||||
|                     query_client.invalidate_queries(&[ | ||||
|                         QueryKey::SubtasksOfTaskId(task.id()), | ||||
|                         QueryKey::TasksWithSubtasksInCategory(task.category().clone()), | ||||
|                     ]); | ||||
|                     new_title.set(String::new()); | ||||
|                 }, | ||||
|                 label { | ||||
|                     r#for: "input_new_title", | ||||
|                     class: "min-w-6 text-center", | ||||
|                     i { | ||||
|                         class: "fa-solid fa-list-check text-zinc-400/50" | ||||
|                     } | ||||
|                 } | ||||
|                 div { | ||||
|                     class: "grow grid grid-cols-6 gap-2", | ||||
|                     input { | ||||
|                         name: "title", | ||||
|                         required: true, | ||||
|                         value: new_title, | ||||
|                         r#type: "text", | ||||
|                         class: "grow py-2 px-3 col-span-5 bg-zinc-800/50 rounded-lg", | ||||
|                         id: "input_new_title", | ||||
|                         onchange: move |event| new_title.set(event.value()) | ||||
|                     } | ||||
|                     button { | ||||
|                         r#type: "submit", | ||||
|                         class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", | ||||
|                         i { | ||||
|                             class: "fa-solid fa-plus" | ||||
|                         } | ||||
|             }, | ||||
|             label { | ||||
|                 r#for: "input_new_title", | ||||
|                 class: "min-w-6 text-center", | ||||
|                 i { | ||||
|                     class: "fa-solid fa-list-check text-zinc-400/50" | ||||
|                 } | ||||
|             } | ||||
|             div { | ||||
|                 class: "grow grid grid-cols-6 gap-2", | ||||
|                 input { | ||||
|                     name: "title", | ||||
|                     required: true, | ||||
|                     value: new_title, | ||||
|                     r#type: "text", | ||||
|                     class: "grow py-2 px-3 col-span-5 bg-zinc-800/50 rounded-lg", | ||||
|                     id: "input_new_title", | ||||
|                     onchange: move |event| new_title.set(event.value()) | ||||
|                 } | ||||
|                 button { | ||||
|                     r#type: "submit", | ||||
|                     class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", | ||||
|                     i { | ||||
|                         class: "fa-solid fa-plus" | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             match subtasks_query.result().value() { | ||||
|                 QueryResult::Ok(QueryValue::Subtasks(subtasks)) | ||||
|                 | QueryResult::Loading(Some(QueryValue::Subtasks(subtasks))) => { | ||||
|                     rsx! { | ||||
|                         for subtask in subtasks.clone() { | ||||
|                             div { | ||||
|                                 key: "{subtask.id()}", | ||||
|                                 class: "flex flex-row items-center gap-3", | ||||
|                                 i { | ||||
|                                     class: format!( | ||||
|                                         "{} min-w-6 text-center text-2xl text-zinc-400/50", | ||||
|                                         if subtask.is_completed() { | ||||
|                                             "fa solid fa-square-check" | ||||
|                                         } else { | ||||
|                                             "fa-regular fa-square" | ||||
|                                         } | ||||
|                                     ), | ||||
|                                     onclick: { | ||||
|         } | ||||
|         match subtasks_query.result().value() { | ||||
|             QueryResult::Ok(QueryValue::Subtasks(subtasks)) | ||||
|             | QueryResult::Loading(Some(QueryValue::Subtasks(subtasks))) => { | ||||
|                 rsx! { | ||||
|                     for subtask in subtasks.clone() { | ||||
|                         div { | ||||
|                             key: "{subtask.id()}", | ||||
|                             class: "flex flex-row items-center gap-3", | ||||
|                             i { | ||||
|                                 class: format!( | ||||
|                                     "{} min-w-6 text-center text-2xl text-zinc-400/50", | ||||
|                                     if subtask.is_completed() { | ||||
|                                         "fa solid fa-square-check" | ||||
|                                     } else { | ||||
|                                         "fa-regular fa-square" | ||||
|                                     } | ||||
|                                 ), | ||||
|                                 onclick: { | ||||
|                                     let subtask = subtask.clone(); | ||||
|                                     let task = task.clone(); | ||||
|                                     move |_| { | ||||
|                                         let subtask = subtask.clone(); | ||||
|                                         move |_| { | ||||
|                                         let task = task.clone(); | ||||
|                                         async move { | ||||
|                                             let new_subtask = NewSubtask::new( | ||||
|                                                 subtask.task_id(), | ||||
|                                                 subtask.title().to_owned(), | ||||
|                                                 !subtask.is_completed() | ||||
|                                             ); | ||||
|                                             let _ = edit_subtask( | ||||
|                                                 subtask.id(), | ||||
|                                                 new_subtask | ||||
|                                             ).await; | ||||
|                                             query_client.invalidate_queries(&[ | ||||
|                                                 QueryKey::SubtasksOfTaskId(task.id()), | ||||
|                                                 QueryKey::TasksWithSubtasksInCategory( | ||||
|                                                     task.category().clone() | ||||
|                                                 ), | ||||
|                                             ]); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             div { | ||||
|                                 class: "grow grid grid-cols-6 gap-2", | ||||
|                                 input { | ||||
|                                     r#type: "text", | ||||
|                                     class: "grow py-2 px-3 col-span-5 bg-zinc-800/50 rounded-lg", | ||||
|                                     id: "input_new_title", | ||||
|                                     initial_value: subtask.title(), | ||||
|                                     onchange: { | ||||
|                                         let subtask = subtask.clone(); | ||||
|                                         let task = task.clone(); | ||||
|                                         move |event| { | ||||
|                                             let subtask = subtask.clone(); | ||||
|                                             let task = task.clone(); | ||||
|                                             async move { | ||||
|                                                 let new_subtask = NewSubtask::new( | ||||
|                                                     subtask.task_id(), | ||||
|                                                     subtask.title().to_owned(), | ||||
|                                                     !subtask.is_completed() | ||||
|                                                     event.value(), | ||||
|                                                     subtask.is_completed() | ||||
|                                                 ); | ||||
|                                                 let _ = edit_subtask( | ||||
|                                                     subtask.id(), | ||||
|                                                     new_subtask | ||||
|                                                 ).await; | ||||
|                                                 query_client.invalidate_queries(&[ | ||||
|                                                     QueryKey::SubtasksOfTaskId(task_id) | ||||
|                                                     QueryKey::SubtasksOfTaskId(task.id()), | ||||
|                                                     QueryKey::TasksWithSubtasksInCategory( | ||||
|                                                         task.category().clone() | ||||
|                                                     ), | ||||
|                                                 ]); | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 div { | ||||
|                                     class: "grow grid grid-cols-6 gap-2", | ||||
|                                     input { | ||||
|                                         r#type: "text", | ||||
|                                         class: "grow py-2 px-3 col-span-5 bg-zinc-800/50 rounded-lg", | ||||
|                                         id: "input_new_title", | ||||
|                                         initial_value: subtask.title(), | ||||
|                                         onchange: { | ||||
|                                 button { | ||||
|                                     r#type: "button", | ||||
|                                     class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", | ||||
|                                     onclick: { | ||||
|                                         let subtask = subtask.clone(); | ||||
|                                         let task = task.clone(); | ||||
|                                         move |_| { | ||||
|                                             let subtask = subtask.clone(); | ||||
|                                             move |event| { | ||||
|                                                 let subtask = subtask.clone(); | ||||
|                                                 async move { | ||||
|                                                     let new_subtask = NewSubtask::new( | ||||
|                                                         subtask.task_id(), | ||||
|                                                         event.value(), | ||||
|                                                         subtask.is_completed() | ||||
|                                                     ); | ||||
|                                                     let _ = edit_subtask( | ||||
|                                                         subtask.id(), | ||||
|                                                         new_subtask | ||||
|                                                     ).await; | ||||
|                                                     query_client.invalidate_queries(&[ | ||||
|                                                         QueryKey::SubtasksOfTaskId(task_id) | ||||
|                                                     ]); | ||||
|                                                 } | ||||
|                                             let task = task.clone(); | ||||
|                                             async move { | ||||
|                                                 let _ = delete_subtask(subtask.id()).await; | ||||
|                                                 query_client.invalidate_queries(&[ | ||||
|                                                     QueryKey::SubtasksOfTaskId(task.id()), | ||||
|                                                     QueryKey::TasksWithSubtasksInCategory( | ||||
|                                                         task.category().clone() | ||||
|                                                     ), | ||||
|                                                 ]); | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                     button { | ||||
|                                         r#type: "button", | ||||
|                                         class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", | ||||
|                                         onclick: { | ||||
|                                             let subtask = subtask.clone(); | ||||
|                                             move |_| { | ||||
|                                                 let subtask = subtask.clone(); | ||||
|                                                 async move { | ||||
|                                                     let _ = delete_subtask(subtask.id()).await; | ||||
|                                                     query_client.invalidate_queries(&[ | ||||
|                                                         QueryKey::SubtasksOfTaskId(task_id) | ||||
|                                                     ]); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         }, | ||||
|                                         i { | ||||
|                                             class: "fa-solid fa-trash-can" | ||||
|                                         } | ||||
|                                     }, | ||||
|                                     i { | ||||
|                                         class: "fa-solid fa-trash-can" | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 QueryResult::Loading(None) => rsx! { | ||||
|                     // TODO: Add a loading indicator. | ||||
|                 }, | ||||
|                 QueryResult::Err(errors) => rsx! { | ||||
|                     div { | ||||
|                         "Errors occurred: {errors:?}" | ||||
|                     } | ||||
|                 }, | ||||
|                 value => panic!("Unexpected query result: {value:?}") | ||||
|             } | ||||
|                 } | ||||
|             }, | ||||
|             QueryResult::Loading(None) => rsx! { | ||||
|                 // TODO: Add a loading indicator. | ||||
|             }, | ||||
|             QueryResult::Err(errors) => rsx! { | ||||
|                 div { | ||||
|                     "Errors occurred: {errors:?}" | ||||
|                 } | ||||
|             }, | ||||
|             value => panic!("Unexpected query result: {value:?}") | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -133,7 +133,8 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|                         } | ||||
|                         query_client.invalidate_queries(&[ | ||||
|                             QueryKey::Tasks, | ||||
|                             QueryKey::TasksInCategory(selected_category()) | ||||
|                             QueryKey::TasksInCategory(selected_category()), | ||||
|                             QueryKey::TasksWithSubtasksInCategory(selected_category()), | ||||
|                         ]); | ||||
|                         on_successful_submit.call(()); | ||||
|                     } | ||||
| @@ -151,6 +152,7 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|                         name: "title", | ||||
|                         required: true, | ||||
|                         initial_value: task.as_ref().map(|task| task.title().to_owned()), | ||||
|                         autofocus: task.is_none(), | ||||
|                         r#type: "text", | ||||
|                         class: "py-2 px-3 grow bg-zinc-800/50 rounded-lg", | ||||
|                         id: "input_title" | ||||
| @@ -345,7 +347,7 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|             }, | ||||
|             if let Some(task) = task.as_ref() { | ||||
|                 SubtasksForm { | ||||
|                     task_id: task.id() | ||||
|                     task: task.clone() | ||||
|                 } | ||||
|             } | ||||
|             div { | ||||
| @@ -371,8 +373,9 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|                                 } | ||||
|  | ||||
|                                 query_client.invalidate_queries(&[ | ||||
|                                     QueryKey::TasksInCategory(task.category().clone()), | ||||
|                                     QueryKey::Tasks, | ||||
|                                     QueryKey::TasksInCategory(task.category().clone()), | ||||
|                                     QueryKey::TasksWithSubtasksInCategory(selected_category()), | ||||
|                                 ]); | ||||
|                             } | ||||
|                             on_successful_submit.call(()); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| use crate::models::category::Category; | ||||
| use crate::models::task::Task; | ||||
| use crate::models::task::{Task, TaskWithSubtasks}; | ||||
| use dioxus::core_macro::rsx; | ||||
| use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
| @@ -8,7 +8,7 @@ use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||
| use crate::server::tasks::complete_task; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element { | ||||
| pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>) -> Element { | ||||
|     let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||
|     let mut task_being_edited = use_context::<Signal<Option<Task>>>(); | ||||
|  | ||||
| @@ -17,12 +17,12 @@ pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element | ||||
|             class: format!("flex flex-col {}", class.unwrap_or("")), | ||||
|             for task in tasks.clone() { | ||||
|                 div { | ||||
|                     key: "{task.id()}", | ||||
|                     key: "{task.task().id()}", | ||||
|                     class: format!( | ||||
|                         "px-8 pt-5 {} flex flex-row gap-4 select-none {}", | ||||
|                         if task.deadline().is_some() { | ||||
|                         if task.task().deadline().is_some() || !task.subtasks().is_empty() { | ||||
|                             "pb-0.5" | ||||
|                         } else if let Category::Calendar { time, .. } = task.category() { | ||||
|                         } else if let Category::Calendar { time, .. } = task.task().category() { | ||||
|                             if time.is_some() { | ||||
|                                 "pb-0.5" | ||||
|                             } else { | ||||
| @@ -31,18 +31,18 @@ pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element | ||||
|                         } else { | ||||
|                             "pb-5" | ||||
|                         }, | ||||
|                         if task_being_edited().is_some_and(|t| t.id() == task.id()) { | ||||
|                         if task_being_edited().is_some_and(|t| t.id() == task.task().id()) { | ||||
|                             "bg-zinc-700" | ||||
|                         } else { "" } | ||||
|                     ), | ||||
|                     onclick: { | ||||
|                         let task = task.clone(); | ||||
|                         move |_| task_being_edited.set(Some(task.clone())) | ||||
|                         move |_| task_being_edited.set(Some(task.task().clone())) | ||||
|                     }, | ||||
|                     i { | ||||
|                         class: format!( | ||||
|                             "{} text-3xl text-zinc-500", | ||||
|                             if *(task.category()) == Category::Done { | ||||
|                             if *(task.task().category()) == Category::Done { | ||||
|                                 "fa solid fa-square-check" | ||||
|                             } else { | ||||
|                                 "fa-regular fa-square" | ||||
| @@ -55,16 +55,19 @@ pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element | ||||
|                                 event.stop_propagation(); | ||||
|                                 let task = task.clone(); | ||||
|                                 async move { | ||||
|                                     let completed_task = complete_task(task.id()).await; | ||||
|                                     let completed_task = complete_task(task.task().id()).await.unwrap(); | ||||
|                                     let mut query_keys = vec![ | ||||
|                                         QueryKey::Tasks, | ||||
|                                         QueryKey::TasksInCategory( | ||||
|                                             completed_task.unwrap().category().clone() | ||||
|                                         ) | ||||
|                                             completed_task.category().clone() | ||||
|                                         ), | ||||
|                                         QueryKey::TasksWithSubtasksInCategory(completed_task.category().clone()), | ||||
|                                     ]; | ||||
|                                     if let Category::Calendar { reoccurrence: Some(_), .. } | ||||
|                                         = task.category() { | ||||
|                                         query_keys.push(QueryKey::SubtasksOfTaskId(task.id())); | ||||
|                                         = task.task().category() { | ||||
|                                         query_keys.push( | ||||
|                                             QueryKey::SubtasksOfTaskId(task.task().id()) | ||||
|                                         ); | ||||
|                                     } | ||||
|                                     query_client.invalidate_queries(&query_keys); | ||||
|                                 } | ||||
| @@ -75,20 +78,20 @@ pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element | ||||
|                         class: "flex flex-col", | ||||
|                         div { | ||||
|                             class: "mt-1 grow font-medium", | ||||
|                             {task.title()} | ||||
|                             {task.task().title()} | ||||
|                         }, | ||||
|                         div { | ||||
|                             class: "flex flex-row gap-3", | ||||
|                             if let Some(deadline) = task.deadline() { | ||||
|                             class: "flex flex-row gap-4", | ||||
|                             if let Some(deadline) = task.task().deadline() { | ||||
|                                 div { | ||||
|                                     class: "text-sm text-zinc-400", | ||||
|                                     i { | ||||
|                                         class: "fa-solid fa-bomb" | ||||
|                                     }, | ||||
|                                     {deadline.format(" %m. %d.").to_string()} | ||||
|                                     {deadline.format(" %m. %-d.").to_string()} | ||||
|                                 } | ||||
|                             } | ||||
|                             if let Category::Calendar { time, .. } = task.category() { | ||||
|                             if let Category::Calendar { time, .. } = task.task().category() { | ||||
|                                 if let Some(calendar_time) = time { | ||||
|                                     div { | ||||
|                                         class: "text-sm text-zinc-400", | ||||
| @@ -99,6 +102,21 @@ pub(crate) fn TaskList(tasks: Vec<Task>, class: Option<&'static str>) -> Element | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             if !task.subtasks().is_empty() { | ||||
|                                 div { | ||||
|                                     class: "text-sm text-zinc-400", | ||||
|                                     i { | ||||
|                                         class: "fa-solid fa-list-check" | ||||
|                                     }, | ||||
|                                     {format!( | ||||
|                                         " {}/{}", | ||||
|                                         task.subtasks().iter() | ||||
|                                             .filter(|subtask| subtask.is_completed()) | ||||
|                                             .count(), | ||||
|                                         task.subtasks().len() | ||||
|                                     )} | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user