use crate::{print_warn, tr};
use serde::Serialize;
use serde_json::Value;
use tabled::settings::{Alignment, Modify, Style, object::Rows};
use tabled::{Table, Tabled};
pub fn build_table<T, I>(rows: I) -> String
where
T: Tabled,
I: IntoIterator<Item = T>,
{
let s = Style::modern();
Table::new(rows)
.with(s)
.with(Modify::new(Rows::new(1..)).with(Alignment::left()))
.to_string()
}
#[derive(Tabled)]
struct VerticalRow {
#[tabled(rename = "Field")]
field: String,
#[tabled(rename = "Value")]
value: String,
}
pub fn build_vertical_table<T: Serialize>(record: &T, compact: bool) {
let value = serde_json::to_value(record).expect("Failed to serialize record");
if let Value::Object(map) = value {
let field_order = [
"id", "title", "author", "editor", "year", "isbn", "language", "pages", "genre",
"summary", "room", "shelf", "row", "position", "added_at",
];
let field_labels = [
tr("list.header.id"),
tr("list.header.title"),
tr("list.header.author"),
tr("list.header.editor"),
tr("list.header.year"),
tr("list.header.ISBN"),
tr("list.header.language"),
tr("list.header.pages"),
tr("list.header.genre"),
tr("list.header.summary"),
tr("list.header.room"),
tr("list.header.shelf"),
tr("list.header.row"),
tr("list.header.position"),
tr("list.header.added_at"),
];
let mut rows: Vec<VerticalRow> = Vec::new();
for (i, key) in field_order.iter().enumerate() {
let value_str = map
.get(*key)
.map(|v| match v {
Value::Null => "—".to_string(),
Value::String(s) => s.clone(),
Value::Number(n) => n.to_string(),
Value::Bool(b) => b.to_string(),
other => other.to_string(),
})
.unwrap_or_else(|| "—".to_string());
if compact && value_str == "—" {
continue;
}
rows.push(VerticalRow {
field: field_labels[i].clone(),
value: value_str,
});
}
let mut table = Table::new(rows);
table.with(Style::rounded());
println!("{}", table);
} else {
print_warn(&tr("error.unable_display_record"));
}
}