//! Admin management of the alternative display currencies. //! //! EUR is the base/transaction currency and is shown read-only for context. The //! admin sets each alternative currency's exchange rate (units per 1 EUR) and //! toggles whether buyers may switch to it. The currencies themselves are fixed //! and seeded by `initializers::currency_seeder`. use axum_extra::extract::cookie::CookieJar; use loco_rs::prelude::*; use sea_orm::{ActiveModelTrait, EntityTrait, QueryOrder, Set}; use serde::Deserialize; use serde_json::json; use crate::{ controllers::i18n::current_lang, models::currencies, shared::{ currency::{self, BASE_CODE, BASE_SYMBOL}, guard, }, }; #[derive(Debug, Deserialize)] struct CurrencyForm { rate: String, enabled: Option, } fn is_checked(value: &Option) -> bool { matches!(value.as_deref(), Some("on" | "true" | "1")) } #[debug_handler] async fn index( auth: auth::JWT, jar: CookieJar, ViewEngine(v): ViewEngine, State(ctx): State, ) -> Result { guard::current_admin(auth, &ctx).await?; let rows = currencies::Entity::find() .order_by_asc(currencies::Column::Code) .all(&ctx.db) .await?; let currencies_json: Vec = rows .iter() .map(|c| { json!({ "id": c.id, "code": c.code, "symbol": c.symbol, "rate": currency::format_rate(c.rate_e4), "enabled": c.enabled, }) }) .collect(); format::view( &v, "admin/currencies/index.html", json!({ "base_code": BASE_CODE, "base_symbol": BASE_SYMBOL, "currencies": currencies_json, "lang": current_lang(&jar), }), ) } #[debug_handler] async fn update( auth: auth::JWT, Path(id): Path, State(ctx): State, Form(form): Form, ) -> Result { guard::current_admin(auth, &ctx).await?; let row = currencies::Entity::find_by_id(id) .one(&ctx.db) .await? .ok_or_else(|| Error::NotFound)?; let mut active = row.into_active_model(); active.rate_e4 = Set(currency::parse_rate(&form.rate)?); active.enabled = Set(is_checked(&form.enabled)); active.update(&ctx.db).await?; // Keep the navbar/settings chrome snapshot in sync with the new rate/state. currency::refresh_snapshot(&ctx.db).await?; format::redirect("/admin/currencies") } pub fn routes() -> Routes { Routes::new() .add("/admin/currencies", get(index)) .add("/admin/currencies/{id}", post(update)) }