feat: list sorting #42
@ -13,3 +13,4 @@ pub(crate) mod reoccurrence_input;
|
|||||||
pub(crate) mod layout;
|
pub(crate) mod layout;
|
||||||
pub(crate) mod navigation_item;
|
pub(crate) mod navigation_item;
|
||||||
pub(crate) mod subtasks_form;
|
pub(crate) mod subtasks_form;
|
||||||
|
pub(crate) mod task_list_item;
|
||||||
|
@ -6,11 +6,12 @@ use crate::query::QueryValue;
|
|||||||
use chrono::{Local, Locale};
|
use chrono::{Local, Locale};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_query::prelude::QueryResult;
|
use dioxus_query::prelude::QueryResult;
|
||||||
|
use crate::components::task_list_item::TaskListItem;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub(crate) fn CategoryTodayPage() -> Element {
|
pub(crate) fn CategoryTodayPage() -> Element {
|
||||||
let today_date = Local::now().date_naive();
|
let today_date = Local::now().date_naive();
|
||||||
|
|
||||||
let calendar_tasks_query = use_tasks_with_subtasks_in_category_query(Category::Calendar {
|
let calendar_tasks_query = use_tasks_with_subtasks_in_category_query(Category::Calendar {
|
||||||
date: today_date,
|
date: today_date,
|
||||||
reoccurrence: None,
|
reoccurrence: None,
|
||||||
@ -26,48 +27,36 @@ pub(crate) fn CategoryTodayPage() -> Element {
|
|||||||
class: "pt-4 flex flex-col gap-8",
|
class: "pt-4 flex flex-col gap-8",
|
||||||
match long_term_tasks_query_result.value() {
|
match long_term_tasks_query_result.value() {
|
||||||
QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks))
|
QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks))
|
||||||
| QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => rsx! {
|
| QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => {
|
||||||
div {
|
let mut tasks = tasks.clone();
|
||||||
class: "flex flex-col gap-4",
|
tasks.sort();
|
||||||
|
rsx! {
|
||||||
div {
|
div {
|
||||||
class: "px-8 flex flex-row items-center gap-2 font-bold",
|
class: "flex flex-col gap-4",
|
||||||
i {
|
div {
|
||||||
class: "fa-solid fa-water text-xl w-6 text-center"
|
class: "px-8 flex flex-row items-center gap-2 font-bold",
|
||||||
|
i {
|
||||||
|
class: "fa-solid fa-water text-xl w-6 text-center"
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "mt-1",
|
||||||
|
"Long-term"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
class: "mt-1",
|
for task in tasks {
|
||||||
"Long-term"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
for task in tasks {
|
|
||||||
div {
|
|
||||||
key: "{task.task().id()}",
|
|
||||||
class: format!(
|
|
||||||
"px-8 pt-5 {} flex flex-row gap-4",
|
|
||||||
if task.task().deadline().is_some() {
|
|
||||||
"pb-0.5"
|
|
||||||
} else {
|
|
||||||
"pb-5"
|
|
||||||
}
|
|
||||||
),
|
|
||||||
div {
|
div {
|
||||||
class: "flex flex-col",
|
key: "{task.task().id()}",
|
||||||
div {
|
class: format!(
|
||||||
class: "mt grow font-medium",
|
"px-8 pt-5 {} flex flex-row gap-4",
|
||||||
{task.task().title()}
|
if task.task().deadline().is_some() {
|
||||||
},
|
"pb-0.5"
|
||||||
div {
|
} else {
|
||||||
class: "flex flex-row gap-3",
|
"pb-5"
|
||||||
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()}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
TaskListItem {
|
||||||
|
task: task.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use dioxus::core_macro::rsx;
|
|||||||
use dioxus::dioxus_core::Element;
|
use dioxus::dioxus_core::Element;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_query::prelude::use_query_client;
|
use dioxus_query::prelude::use_query_client;
|
||||||
|
use crate::components::task_list_item::TaskListItem;
|
||||||
use crate::query::{QueryErrors, QueryKey, QueryValue};
|
use crate::query::{QueryErrors, QueryKey, QueryValue};
|
||||||
use crate::server::tasks::complete_task;
|
use crate::server::tasks::complete_task;
|
||||||
|
|
||||||
@ -12,6 +13,8 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>
|
|||||||
let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>();
|
let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>();
|
||||||
let mut task_being_edited = use_context::<Signal<Option<Task>>>();
|
let mut task_being_edited = use_context::<Signal<Option<Task>>>();
|
||||||
|
|
||||||
|
tasks.sort();
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
class: format!("flex flex-col {}", class.unwrap_or("")),
|
class: format!("flex flex-col {}", class.unwrap_or("")),
|
||||||
@ -74,50 +77,8 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
div {
|
TaskListItem {
|
||||||
class: "flex flex-col",
|
task: task.clone()
|
||||||
div {
|
|
||||||
class: "mt-1 grow font-medium",
|
|
||||||
{task.task().title()}
|
|
||||||
},
|
|
||||||
div {
|
|
||||||
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()}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Category::Calendar { time, .. } = task.task().category() {
|
|
||||||
if let Some(calendar_time) = time {
|
|
||||||
div {
|
|
||||||
class: "text-sm text-zinc-400",
|
|
||||||
i {
|
|
||||||
class: "fa-solid fa-clock"
|
|
||||||
},
|
|
||||||
{calendar_time.time().format(" %k:%M").to_string()}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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()
|
|
||||||
)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
61
src/components/task_list_item.rs
Normal file
61
src/components/task_list_item.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use chrono::{Datelike, Local};
|
||||||
|
use crate::models::category::Category;
|
||||||
|
use crate::models::task::TaskWithSubtasks;
|
||||||
|
use dioxus::core_macro::rsx;
|
||||||
|
use dioxus::dioxus_core::Element;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
class: "flex flex-col",
|
||||||
|
div {
|
||||||
|
class: "mt-1 grow font-medium",
|
||||||
|
{task.task().title()}
|
||||||
|
},
|
||||||
|
div {
|
||||||
|
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(if deadline.year() == Local::now().year() {
|
||||||
|
" %m. %-d."
|
||||||
|
} else {
|
||||||
|
" %m. %-d. %Y"
|
||||||
|
}).to_string()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Category::Calendar { time, .. } = task.task().category() {
|
||||||
|
if let Some(calendar_time) = time {
|
||||||
|
div {
|
||||||
|
class: "text-sm text-zinc-400",
|
||||||
|
i {
|
||||||
|
class: "fa-solid fa-clock"
|
||||||
|
},
|
||||||
|
{calendar_time.time().format(" %k:%M").to_string()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user
Approved:
TaskListItem
component implementation.The component is well-implemented with effective use of conditional rendering and UI elements. The handling of tasks, deadlines, and subtasks is appropriate and enhances user interaction.
Consider adding comments to complex conditional blocks for better maintainability and readability, especially for new developers or when revisiting the code later.