jobber 0.1.1-alpha

Minimalistic console work time tracker
use crate::{
    commands::{Cli, Config, Result, current_job, shorten_date},
    jobber::JobberGet,
    print_tip,
    views::{JobView, WorkView, create_work_table},
};
use clap::Parser;
use color_print::cprintln;

#[derive(Parser, Debug)]
pub(crate) struct ListWork {
    /// Job's identifier (or current if not given)
    job_id: Option<usize>,
    /// List only deleted work
    #[clap(short, long)]
    deleted: bool,
}

impl ListWork {
    pub(crate) fn run(&self, cli: &Cli) -> Result<()> {
        cprintln!();
        let config = Config::load()?;
        let database = cli.open_database()?;
        let job_id = if let Some(id) = self.job_id {
            id
        } else {
            current_job(&config, &database)?
        };
        let job = database.get_job(job_id)?;
        println!("{}", JobView::new(job_id, &config, &database, cli.ansi())?);
        let scheme = &job.scheme(job_id)?;
        if job.work.is_empty() {
            println!("There is no work in job {job_id}");
            return Ok(());
        }
        let mut rows: Vec<_> = job
            .work
            .iter()
            .filter(|work| work.deleted == self.deleted)
            .enumerate()
            .map(|(n, w)| WorkView::new(Some(n), w, database.get_tags(), scheme, cli.ansi()))
            .collect();
        rows.sort_by_key(|r| r.order);
        let mut rows: Vec<_> = rows
            .iter_mut()
            .scan(None, |prev: &mut Option<WorkView>, row: &mut WorkView| {
                let p = row.clone();
                if let Some(prev) = prev {
                    shorten_date(&mut row.start, &prev.start);
                }
                *prev = Some(p);
                Some(row.clone())
            })
            .collect();
        if let Some(running) = &job.running {
            rows.push(WorkView::new_running(running, scheme, cli.ansi()));
        }
        println!("{}", create_work_table(rows, &config));
        print_tip!(cli);
        print_tip!(cli, "Use <s>jobber show work</> to view a work unit.");
        if job.running.is_some() {
            print_tip!(cli, "Use <s>jobber end</> to end current work.");
            print_tip!(cli, "Use <s>jobber cancel</> to cancel work.");
        } else {
            print_tip!(cli, "Use <s>jobber start</> to start work.");
        }
        if let Some(job_id) = &self.job_id {
            print_tip!(
                cli,
                "Use <s>jobber create invoice {}</> to generate an invoice.",
                job_id
            );
        } else {
            print_tip!(
                cli,
                "Use <s>jobber create invoice</> to generate an invoice."
            );
        }
        Ok(())
    }
}