things3_cloud/commands/
logbook.rs1use 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}