Lines
26.32 %
Functions
16.67 %
Branches
100 %
use askama::Template;
use axum::{Extension, Json, extract::State, response::IntoResponse};
use serde::Deserialize;
use server::command::{CmdResult, FinanceEntity, commodity::ListCommodities};
use std::sync::Arc;
use crate::{AppState, jwt_auth::JWTAuthMiddleware, pages::HtmlTemplate};
#[derive(Deserialize)]
pub struct CommoditySearch {
#[serde(rename = "commodity-search")]
query: Option<String>,
}
#[derive(Template)]
#[template(path = "components/commodity/search_results.html")]
struct CommoditySearchResults {
commodities: Vec<CommodityView>,
struct CommodityView {
id: uuid::Uuid,
symbol: String,
name: String,
pub async fn search_commodities(
State(_data): State<Arc<AppState>>,
Extension(jwt_auth): Extension<JWTAuthMiddleware>,
Json(form): Json<CommoditySearch>,
) -> impl IntoResponse {
let result = match ListCommodities::new().user_id(jwt_auth.user.id).run().await {
Ok(Some(CmdResult::TaggedEntities(entities))) => entities,
_ => {
return HtmlTemplate(CommoditySearchResults {
commodities: vec![],
});
};
let mut commodities = Vec::new();
for (entity, tags) in result {
if let FinanceEntity::Commodity(commodity) = entity {
// Find symbol and name tags
let (symbol, name) = if let (FinanceEntity::Tag(s), FinanceEntity::Tag(n)) =
(&tags["symbol"], &tags["name"])
{
(s.tag_value.clone(), n.tag_value.clone())
} else {
continue;
// Filter by search query if provided
if let Some(query) = &form.query {
if query.is_empty()
|| symbol.to_lowercase().contains(&query.to_lowercase())
|| name.to_lowercase().contains(&query.to_lowercase())
commodities.push(CommodityView {
id: commodity.id,
symbol,
name,
HtmlTemplate(CommoditySearchResults { commodities })