Skip to main content

things3_cloud/ui/components/
task_group.rs

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