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