things3_cloud/ui/components/
task_group.rs1use 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}