jobber 0.1.1-alpha

Minimalistic console work time tracker
use crate::{
    commands::{Cli, Config, Result, current_job, from_end, from_start},
    jobber::JobberWork,
    print_tip,
};
use clap::Parser;
use color_print::cprintln;

/// Add a working position
///
/// Like start and end together in one command.
///
/// This function can be undone with `jobber undo`.
#[derive(Parser, Debug)]
pub(crate) struct Add {
    /// Date/time work begins
    ///
    /// Available formats:
    ///
    /// | Example            |  Description           |
    /// | -------------------|------------------------|
    /// | `now`              |  current time          |
    /// | `2026-05-31 13:15` |  date/time             |
    /// | `13:15`            |  time today            |
    /// | `15m`              |  minutes in past       |
    /// | `+15m`             |  minutes in future     |
    /// | `8h`               |  hours in past         |
    /// | `+8h`              |  hours in future       |
    #[clap(verbatim_doc_comment)]
    start: String,
    /// Time when work ended (or current time if not given)
    ///
    /// Available formats:
    ///
    /// | Example            |  Description          |
    /// | -------------------|-----------------------|
    /// | `now`              |  current time         |
    /// | `2026-05-31 13:15` |  date/time            |
    /// | `13:15`            |  time behind start    |
    /// | `15m`              |  minutes past start   |
    /// | `8h`               |  hours past start     |
    #[clap(verbatim_doc_comment)]
    end: String,
    /// Subject of the work
    subject: String,
    /// Comma-separated list of tags (no spaces allowed e.g. support,test)
    #[clap(short, long, value_delimiter = ',')]
    tags: Vec<String>,
    /// ID of the job to add work for (default is current job)
    #[clap(short, long)]
    job: Option<usize>,
}

impl Add {
    pub(crate) fn run(&self, cli: &Cli) -> Result<()> {
        let config = Config::load()?;
        let mut database = cli.open_database()?;
        let start = from_start(&self.start)?;
        let end = from_end(&self.end, start)?;
        let job_id = self.job.unwrap_or(current_job(&config, &database)?);
        database.add_work(job_id, start, end, self.subject.clone(), self.tags.clone())?;
        cli.close_database(database)?;
        cprintln!("Successfully added new work to job <s>{job_id}</>.");
        if !cli.no_tips {
            print_tip!(cli);
            print_tip!(
                cli,
                "Use <s>jobber show work{}</> to take a view.",
                self.job.map(|j| format!(" {j}")).unwrap_or_default()
            );
        }
        Ok(())
    }
}