things3_cloud/ui/views/
find.rs1use crate::common::ICONS;
2use crate::store::{Task, ThingsStore};
3use crate::ui::components::empty_text::EmptyText;
4use crate::ui::components::project_item::ProjectItem;
5use crate::ui::components::task_item::TaskItem;
6use crate::ui::components::tasks::TaskOptions;
7use iocraft::prelude::*;
8use std::sync::Arc;
9
10#[derive(Clone)]
11pub struct FindRow<'a> {
12 pub task: &'a Task,
13 pub force_detailed: bool,
14}
15
16#[derive(Default, Props)]
17pub struct FindViewProps<'a> {
18 pub rows: Vec<FindRow<'a>>,
19 pub detailed: bool,
20}
21
22#[component]
23pub fn FindView<'a>(hooks: Hooks, props: &FindViewProps<'a>) -> impl Into<AnyElement<'a>> {
24 let store = hooks.use_context::<Arc<ThingsStore>>().clone();
25
26 if props.rows.is_empty() {
27 return element! { EmptyText(content: "No matching tasks.") }.into_any();
28 }
29
30 let id_prefix_len = store.unique_prefix_length(
31 &props
32 .rows
33 .iter()
34 .map(|row| row.task.uuid.clone())
35 .collect::<Vec<_>>(),
36 );
37
38 let count = props.rows.len();
39 let label = if count == 1 { "task" } else { "tasks" };
40
41 let mut body: Vec<AnyElement<'a>> = Vec::new();
42 for row in &props.rows {
43 let options = TaskOptions {
44 detailed: props.detailed || row.force_detailed,
45 show_project: true,
46 show_area: false,
47 show_today_markers: true,
48 show_staged_today_marker: false,
49 };
50 let line = if row.task.is_project() {
51 element! {
52 View(flex_direction: FlexDirection::Column, padding_left: 2) {
53 ProjectItem(project: row.task, options, id_prefix_len)
54 }
55 }
56 .into_any()
57 } else {
58 element! {
59 View(flex_direction: FlexDirection::Column, padding_left: 2) {
60 TaskItem(task: row.task, options, id_prefix_len)
61 }
62 }
63 .into_any()
64 };
65 body.push(line);
66 }
67
68 element! {
69 View(flex_direction: FlexDirection::Column) {
70 Text(
71 content: format!("{} Find ({} {})", ICONS.find, count, label),
72 wrap: TextWrap::NoWrap,
73 color: Color::Cyan,
74 weight: Weight::Bold,
75 )
76 Text(content: "", wrap: TextWrap::NoWrap)
77 #(body)
78 }
79 }
80 .into_any()
81}