use rich_rs::{Columns, Console, Json, OverflowMethod, Panel, Renderable, Text};
use serde_json::Value;
fn get_content(user: &Value) -> Text {
let first = user
.get("name")
.and_then(|name| name.get("first"))
.and_then(Value::as_str)
.unwrap_or("Unknown");
let last = user
.get("name")
.and_then(|name| name.get("last"))
.and_then(Value::as_str)
.unwrap_or("User");
let country = user
.get("location")
.and_then(|location| location.get("country"))
.and_then(Value::as_str)
.unwrap_or("Unknown");
let markup = format!("[b]{} {}[/b]\n[yellow]{}", first, last, country);
Text::from_markup(&markup, false)
.unwrap_or_else(|_| Text::plain(&format!("{first} {last}\n{country}")))
}
fn fetch_users(results: usize) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
let url = format!("https://randomuser.me/api/?results={results}");
let response = ureq::get(&url).call()?;
let body = response.into_body().read_to_string()?;
let root: Value = serde_json::from_str(&body)?;
let users = root
.get("results")
.and_then(Value::as_array)
.cloned()
.unwrap_or_default();
Ok(users)
}
fn main() {
let mut console = Console::new();
let users = match fetch_users(30) {
Ok(users) => users,
Err(err) => {
eprintln!("Failed to fetch users from randomuser.me: {err}");
std::process::exit(1);
}
};
let users_payload = serde_json::to_string_pretty(&users).unwrap_or_else(|_| "[]".to_string());
let users_json = Json::new(&users_payload, 2, true, false);
let _ = console.print(
&users_json,
None,
None,
Some(OverflowMethod::Ignore),
true,
"\n",
);
let user_renderables: Vec<Box<dyn Renderable + Send + Sync>> = users
.iter()
.map(|user| {
let content = get_content(user);
Box::new(Panel::fit(Box::new(content))) as Box<dyn Renderable + Send + Sync>
})
.collect();
let columns = Columns::new(user_renderables);
let _ = console.print(&columns, None, None, None, false, "\n");
}