use crate::{
commands::{Config, is_available, not_available},
database::Result,
entities::{Client, Limit, format_client_id, format_duration, format_opt},
jobber::{JobberGet, JobberIter, JobberWork},
views::ApplyTableStyle,
};
use tabled::{
Table, Tabled,
settings::{Alignment, object::Columns},
};
#[derive(Tabled)]
pub(crate) struct ClientView {
#[tabled(skip)]
pub(crate) order: String,
#[tabled(rename = "ID")]
pub(crate) id: String,
#[tabled(rename = "Name")]
pub(crate) name: String,
#[tabled(rename = "Street")]
pub(crate) street: String,
#[tabled(rename = "ZIP")]
pub(crate) zip: String,
#[tabled(rename = "City")]
pub(crate) city: String,
#[tabled(rename = "Country")]
pub(crate) country: String,
#[tabled(rename = "VAT")]
pub(crate) vat: String,
#[tabled(rename = "Rate")]
pub(crate) rate: String,
#[tabled(rename = "Interval")]
pub(crate) interval: String,
#[tabled(rename = "Billing")]
pub(crate) billing: String,
#[tabled(rename = "Work")]
pub(crate) work: String,
}
impl ClientView {
pub(crate) fn new(
id: &str,
config: &Config,
database: &(impl JobberGet + JobberIter + JobberWork),
ansi: bool,
) -> Result<Self> {
Self::from(id, database.get_client(id)?, config, database, ansi)
}
pub(crate) fn from(
id: &str,
client: &Client,
config: &Config,
database: &(impl JobberGet + JobberIter + JobberWork),
ansi: bool,
) -> Result<Self> {
let scheme = &client.scheme;
Ok(Self {
order: id.to_string(),
id: format_client_id(id, database, config, ansi)?,
name: client.address.name.clone(),
street: client.address.street.clone(),
zip: client.address.zip.clone(),
city: client.address.city.clone(),
country: client
.address
.country
.clone()
.unwrap_or(not_available(ansi)),
vat: client.vat.clone().unwrap_or(not_available(ansi)),
rate: format_opt(&scheme.rate, ansi),
billing: format_opt(&scheme.billing_period, ansi),
interval: scheme.format_duration(
scheme.min_work_interval.duration(),
Limit::None,
ansi,
),
work: format_duration(database.duration_by_client(id), Limit::None, ansi),
})
}
}
impl std::fmt::Display for ClientView {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, " Client ID: {}", self.id)?;
writeln!(f, " Name: {}", self.name)?;
writeln!(f, " Rate: {}", self.rate)?;
writeln!(f, "Min. Work Interval: {}", self.interval)?;
writeln!(f, " Billing Period: {}", self.billing)?;
if is_available(&self.work) {
write!(f, " Work: {}", self.work)?;
}
Ok(())
}
}
pub(crate) fn create_client_table(
rows: impl IntoIterator<Item = ClientView>,
config: &Config,
) -> Table {
let mut table = Table::new(rows);
table.modify(Columns::first(), Alignment::right());
table.modify(Columns::one(2), Alignment::right());
table.modify(Columns::one(3), Alignment::right());
table.modify(Columns::one(4), Alignment::center());
table.modify(Columns::one(5), Alignment::right());
table.style(&config.table_style);
table
}