use color_print::cformat;
use tabled::{
Table, Tabled,
settings::{Alignment, object::Columns},
};
use crate::{
commands::{Config, current_client, current_job, current_worker, not_available},
entities::{Company, format_job_id},
jobber::{Deleted, JobberGet, JobberIter},
views::ApplyTableStyle,
};
#[derive(Tabled)]
pub(crate) struct InfoView {
#[tabled(rename = "Company")]
pub(crate) company: String,
#[tabled(rename = "Workers")]
pub(crate) workers: String,
#[tabled(rename = "Clients")]
pub(crate) clients: String,
#[tabled(rename = "Jobs")]
pub(crate) jobs: String,
#[tabled(rename = "Tags")]
pub(crate) tags: String,
#[tabled(rename = "Invoices")]
pub(crate) invoices: String,
#[tabled(rename = "Selected Job")]
pub(crate) current: String,
}
pub(crate) struct Counts {
workers: usize,
clients: usize,
jobs: usize,
tags: usize,
invoices: usize,
deleted_workers: usize,
deleted_clients: usize,
deleted_jobs: usize,
deleted_tags: usize,
deleted_invoices: usize,
}
fn format_count(count: usize, deleted: usize, ansi: bool) -> String {
if ansi {
let deleted = if deleted != 0 {
cformat!(" <dim>({deleted})</>")
} else {
String::new()
};
if count == 0 {
cformat!("<dim>-</>{deleted}")
} else {
cformat!("<s>{}</>{deleted}", count)
}
} else {
let deleted = if deleted != 0 {
cformat!(" ({deleted})")
} else {
String::new()
};
if count == 0 {
cformat!("-{deleted}")
} else {
cformat!("{}{deleted}", count)
}
}
}
impl InfoView {
pub(crate) fn new(
company: String,
counts: Counts,
current_job: Option<String>,
current_worker: String,
current_client: String,
ansi: bool,
) -> Self {
Self {
company,
workers: format_count(counts.workers, counts.deleted_workers, ansi),
clients: format_count(counts.clients, counts.deleted_clients, ansi),
jobs: format_count(counts.jobs, counts.deleted_jobs, ansi),
tags: format_count(counts.tags, counts.deleted_tags, ansi),
invoices: format_count(counts.invoices, counts.deleted_invoices, ansi),
current: if let Some(current_job) = current_job {
if ansi {
cformat!(
"<s>{current_job}</> (<s>{current_worker}</> for <s>{current_client}</>)"
)
} else {
format!("{current_job} ({current_worker} for {current_client})")
}
} else {
not_available(ansi)
},
}
}
}
pub(crate) fn create_overview_table(
config: &Config,
database: &(impl JobberIter + JobberGet),
ansi: bool,
) -> crate::commands::Result<Table> {
let mut table = Table::new([InfoView::new(
database
.get_company()
.map_or("-".to_string(), |c: &Company| c.address.name.clone()),
Counts {
workers: database.iter_workers(Deleted::No).count(),
clients: database.iter_clients(Deleted::No).count(),
jobs: database.iter_jobs(Deleted::No).count(),
tags: database.iter_tags(Deleted::No).count(),
invoices: database.iter_invoices(Deleted::No).count(),
deleted_workers: database.iter_workers(Deleted::Yes).count(),
deleted_clients: database.iter_clients(Deleted::Yes).count(),
deleted_jobs: database.iter_jobs(Deleted::Yes).count(),
deleted_tags: database.iter_tags(Deleted::Yes).count(),
deleted_invoices: database.iter_invoices(Deleted::Yes).count(),
},
current_job(config, database)
.ok()
.and_then(|job_id| format_job_id(job_id, database, config, ansi).ok()),
current_worker(config, database, ansi)?,
current_client(config, database, ansi)?,
ansi,
)]);
table.modify(Columns::first(), Alignment::left());
table.modify(Columns::one(1), Alignment::center());
table.modify(Columns::one(2), Alignment::center());
table.modify(Columns::one(3), Alignment::center());
table.modify(Columns::one(4), Alignment::center());
table.modify(Columns::one(5), Alignment::center());
table.style(&config.table_style);
Ok(table)
}