Skip to main content

things3_cloud/commands/
logbook.rs

1use std::{io::Write, sync::Arc};
2
3use anyhow::Result;
4use clap::Args;
5use iocraft::prelude::*;
6
7use crate::{
8    app::Cli,
9    commands::{Command, DetailedArgs, detailed_json_conflict, write_json},
10    common::parse_day,
11    ui::{
12        render_element_to_string,
13        views::{json::common::build_tasks_json, logbook::LogbookView},
14    },
15};
16
17#[derive(Debug, Default, Args)]
18#[command(about = "Show the Logbook")]
19pub struct LogbookArgs {
20    #[command(flatten)]
21    pub detailed: DetailedArgs,
22    #[arg(
23        long = "from",
24        short = 'f',
25        help = "Show items completed on/after this date (YYYY-MM-DD)"
26    )]
27    pub from_date: Option<String>,
28    #[arg(
29        long = "to",
30        short = 't',
31        help = "Show items completed on/before this date (YYYY-MM-DD)"
32    )]
33    pub to_date: Option<String>,
34}
35
36impl Command for LogbookArgs {
37    fn run_with_ctx(
38        &self,
39        cli: &Cli,
40        out: &mut dyn Write,
41        ctx: &mut dyn crate::cmd_ctx::CmdCtx,
42    ) -> Result<()> {
43        let store = Arc::new(cli.load_store()?);
44        let today = ctx.today();
45
46        let from_day =
47            parse_day(self.from_date.as_deref(), "--from").map_err(anyhow::Error::msg)?;
48        let to_day = parse_day(self.to_date.as_deref(), "--to").map_err(anyhow::Error::msg)?;
49
50        if let (Some(from), Some(to)) = (from_day, to_day)
51            && from > to
52        {
53            eprintln!("--from date must be before or equal to --to date");
54            return Ok(());
55        }
56
57        let tasks = store.logbook(from_day, to_day);
58
59        let json = cli.json;
60        if json {
61            if detailed_json_conflict(json, self.detailed.detailed) {
62                return Ok(());
63            }
64            write_json(out, &build_tasks_json(&tasks, &store, &today))?;
65            return Ok(());
66        }
67
68        let mut ui = element! {
69            ContextProvider(value: Context::owned(store.clone())) {
70                ContextProvider(value: Context::owned(today)) {
71                    LogbookView(
72                        items: &tasks,
73                        detailed: self.detailed.detailed,
74                    )
75                }
76            }
77        };
78        let rendered = render_element_to_string(&mut ui, cli.no_color);
79        writeln!(out, "{}", rendered)?;
80
81        Ok(())
82    }
83}