use crate::ui::{Model, PriceTable, theme};
pub const OPEN: &str = "prices…";
pub const CLOSE: &str = "done";
pub const HEADING: &str = "what the world is charged";
pub const NOT_ANSWERED: &str = "waiting to hear what these engines charge";
pub const NO_ROWS: &str = "no row is priced, so no count carries money";
pub const PRICE: &str = "price it";
pub const UNPRICE: &str = "unprice";
pub const SET: &str = "set ceiling";
pub const LIFT: &str = "lift ceiling";
pub fn render(ui: &mut egui::Ui, model: &mut Model) -> bool {
if !model.pricing() {
return false;
}
ui.heading(HEADING);
ui.horizontal_wrapped(|ui| {
if ui.button(CLOSE).clicked() {
model.close_lookup();
}
});
ui.separator();
drafting(ui, model);
ui.separator();
let tables = model.pricing.tables.clone();
if tables.is_empty() {
ui.label(NOT_ANSWERED);
return true;
}
egui::ScrollArea::vertical()
.id_salt(HEADING)
.auto_shrink(false)
.show(ui, |ui| {
for table in &tables {
ui.separator();
ui.label(crate::ui::roster::header(&table.channel));
section(ui, model, table);
}
});
true
}
fn drafting(ui: &mut egui::Ui, model: &mut Model) {
let draft = &mut model.pricing;
ui.horizontal_wrapped(|ui| {
ui.add(egui::TextEdit::singleline(&mut draft.provider).hint_text("provider"));
ui.add(egui::TextEdit::singleline(&mut draft.model).hint_text("model, or *"));
ui.add(
egui::TextEdit::singleline(&mut draft.rates)
.hint_text("input output [cache-read [cache-write]] per Mtok"),
);
});
ui.add(egui::TextEdit::singleline(&mut draft.bound).hint_text("ceiling in USD, or off"));
}
fn section(ui: &mut egui::Ui, model: &mut Model, table: &PriceTable) {
ui.label(table.prices.standing());
if let Some(woke) = table.prices.woke() {
ui.colored_label(theme::NOTICE, woke);
}
if table.prices.rows.is_empty() {
theme::paint::empty(ui, NO_ROWS);
}
for row in &table.prices.rows {
let mut fired = false;
ui.horizontal_wrapped(|ui| {
ui.label(row.said());
let off = ui.button(UNPRICE);
crate::ui::act::tag(&off, &[crate::verbs::PRICE]);
fired = off.clicked();
});
if fired {
model.post_unprice(&table.channel, &row.provider, &row.model);
}
}
acts(ui, model, table);
}
fn acts(ui: &mut egui::Ui, model: &mut Model, table: &PriceTable) {
let channel = &table.channel;
let unpriceable = model.unpriceable(channel);
let unbounded = model.unbounded();
let (mut price, mut set, mut lift) = (false, false, false);
ui.horizontal_wrapped(|ui| {
let act = ui.add_enabled(unpriceable.is_none(), egui::Button::new(PRICE));
crate::ui::act::tag(&act, &[crate::verbs::PRICE]);
price = act.clicked();
let act = ui.add_enabled(unbounded.is_none(), egui::Button::new(SET));
crate::ui::act::tag(&act, &[crate::verbs::CEILING]);
set = act.clicked();
if table.prices.ceiling.is_some() {
let act = ui.button(LIFT);
crate::ui::act::tag(&act, &[crate::verbs::CEILING]);
lift = act.clicked();
}
});
for why in [unpriceable, unbounded].into_iter().flatten() {
ui.colored_label(theme::NOTICE, why);
}
if price {
model.post_price(channel);
}
if set {
model.post_ceiling(channel);
}
if lift {
model.post_lift(channel);
}
}
#[cfg(test)]
mod tests;