Skip to main content

things3_cloud/ui/components/
task_group.rs

1use crate::common::ICONS;
2use crate::ids::ThingsId;
3use crate::store::Task;
4use crate::ui::components::header::Header;
5use crate::ui::components::tasks::{TaskList, TaskOptions};
6use iocraft::prelude::*;
7
8#[derive(Clone)]
9pub enum TaskGroupHeader {
10    Area {
11        area_uuid: ThingsId,
12        title: String,
13        id_prefix_len: usize,
14    },
15    Project {
16        project_uuid: ThingsId,
17        title: String,
18        id_prefix_len: usize,
19    },
20}
21
22#[derive(Default, Props)]
23pub struct TaskGroupProps<'a> {
24    pub header: Option<TaskGroupHeader>,
25    pub items: Vec<&'a Task>,
26    pub id_prefix_len: usize,
27    pub options: TaskOptions,
28    pub indent_under_header: u16,
29    pub hidden_count: usize,
30}
31
32#[component]
33pub fn TaskGroup<'a>(props: &'a TaskGroupProps<'a>) -> impl Into<AnyElement<'a>> {
34    let header_el = match &props.header {
35        Some(TaskGroupHeader::Area {
36            area_uuid,
37            title,
38            id_prefix_len,
39        }) => element! {
40            Header(
41                uuid: area_uuid,
42                title: title.as_str(),
43                id_prefix_len: *id_prefix_len,
44                icon: ICONS.area,
45            )
46        }
47        .into_any(),
48        Some(TaskGroupHeader::Project {
49            project_uuid,
50            title,
51            id_prefix_len,
52        }) => element! {
53            Header(
54                uuid: project_uuid,
55                title: title.as_str(),
56                id_prefix_len: *id_prefix_len,
57                icon: ICONS.project,
58            )
59        }
60        .into_any(),
61        _ => element!(Fragment).into_any(),
62    };
63
64    let footer = if props.hidden_count > 0 {
65        let text = format!("Hiding {} more", props.hidden_count);
66        element!(Text(content: text, wrap: TextWrap::NoWrap, color: Color::DarkGrey)).into_any()
67    } else {
68        element!(Fragment).into_any()
69    };
70
71    element! {
72        View(flex_direction: FlexDirection::Column) {
73            #(header_el)
74            View(
75                flex_direction: FlexDirection::Column,
76                padding_left: if props.header.is_some() { props.indent_under_header as u32 } else { 0 },
77            ) {
78                TaskList(
79                    items: props.items.clone(),
80                    id_prefix_len: props.id_prefix_len,
81                    options: props.options,
82                )
83                #(footer)
84            }
85        }
86    }
87    .into_any()
88}