Skip to main content

things3_cloud/ui/views/
logbook.rs

1use std::sync::Arc;
2
3use iocraft::prelude::*;
4
5use crate::{
6    common::{ICONS, fmt_date_local},
7    store::{Task, ThingsStore},
8    ui::components::{
9        empty_text::EmptyText,
10        tasks::{TaskList, TaskOptions},
11    },
12};
13
14const LIST_INDENT: u32 = 4;
15
16#[derive(Default, Props)]
17pub struct LogbookViewProps<'a> {
18    pub items: Option<&'a Vec<Task>>,
19    pub detailed: bool,
20}
21
22#[component]
23pub fn LogbookView<'a>(hooks: Hooks, props: &LogbookViewProps<'a>) -> impl Into<AnyElement<'a>> {
24    let store = hooks.use_context::<Arc<ThingsStore>>().clone();
25    let Some(items) = props.items else {
26        return element! { Text(content: "") }.into_any();
27    };
28
29    if items.is_empty() {
30        return element! { EmptyText(content: "Logbook is empty.") }.into_any();
31    }
32
33    let mut groups: Vec<(String, Vec<&Task>)> = Vec::new();
34    for task in items {
35        let day = fmt_date_local(task.stop_date);
36        if let Some((current_day, day_tasks)) = groups.last_mut()
37            && *current_day == day
38        {
39            day_tasks.push(task);
40        } else {
41            groups.push((day, vec![task]));
42        }
43    }
44
45    let options = TaskOptions {
46        detailed: props.detailed,
47        show_project: true,
48        show_area: false,
49        show_today_markers: false,
50        show_staged_today_marker: false,
51    };
52
53    let id_prefix_len =
54        store.unique_prefix_length(&items.iter().map(|t| t.uuid.clone()).collect::<Vec<_>>());
55    let mut sections: Vec<AnyElement<'a>> = Vec::new();
56    for (day, day_items) in groups.into_iter() {
57        sections.push(
58            element! {
59                View(flex_direction: FlexDirection::Column) {
60                    Text(content: format!("  {}", day), wrap: TextWrap::NoWrap, weight: Weight::Bold)
61                    View(flex_direction: FlexDirection::Column, padding_left: LIST_INDENT) {
62                        TaskList(items: day_items, id_prefix_len: id_prefix_len, options)
63                    }
64                }
65            }
66            .into_any(),
67        );
68    }
69
70    element! {
71        View(flex_direction: FlexDirection::Column, gap: 1) {
72            Text(
73                content: format!("{} Logbook  ({} tasks)", ICONS.done, items.len()),
74                wrap: TextWrap::NoWrap,
75                color: Color::Green,
76                weight: Weight::Bold,
77            )
78            View(flex_direction: FlexDirection::Column, gap: 1) {
79                #(sections)
80            }
81        }
82    }
83    .into_any()
84}