1
use askama::Template;
2
use axum::{Extension, Json, extract::State, response::IntoResponse};
3
use serde::Deserialize;
4
use server::command::{CmdResult, FinanceEntity, commodity::ListCommodities};
5
use std::sync::Arc;
6

            
7
use crate::{AppState, jwt_auth::JWTAuthMiddleware, pages::HtmlTemplate};
8

            
9
#[derive(Deserialize)]
10
pub struct CommoditySearch {
11
    #[serde(rename = "commodity-search")]
12
    query: Option<String>,
13
}
14

            
15
#[derive(Template)]
16
#[template(path = "components/commodity/search_results.html")]
17
struct CommoditySearchResults {
18
    commodities: Vec<CommodityView>,
19
}
20

            
21
struct CommodityView {
22
    id: uuid::Uuid,
23
    symbol: String,
24
    name: String,
25
}
26

            
27
2
pub async fn search_commodities(
28
2
    State(_data): State<Arc<AppState>>,
29
2
    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
30
2
    Json(form): Json<CommoditySearch>,
31
3
) -> impl IntoResponse {
32
2
    let result = match ListCommodities::new().user_id(jwt_auth.user.id).run().await {
33
        Ok(Some(CmdResult::TaggedEntities(entities))) => entities,
34
        _ => {
35
2
            return HtmlTemplate(CommoditySearchResults {
36
2
                commodities: vec![],
37
2
            });
38
        }
39
    };
40

            
41
    let mut commodities = Vec::new();
42
    for (entity, tags) in result {
43
        if let FinanceEntity::Commodity(commodity) = entity {
44
            // Find symbol and name tags
45
            let (symbol, name) = if let (FinanceEntity::Tag(s), FinanceEntity::Tag(n)) =
46
                (&tags["symbol"], &tags["name"])
47
            {
48
                (s.tag_value.clone(), n.tag_value.clone())
49
            } else {
50
                continue;
51
            };
52

            
53
            // Filter by search query if provided
54
            if let Some(query) = &form.query {
55
                if query.is_empty()
56
                    || symbol.to_lowercase().contains(&query.to_lowercase())
57
                    || name.to_lowercase().contains(&query.to_lowercase())
58
                {
59
                    commodities.push(CommodityView {
60
                        id: commodity.id,
61
                        symbol,
62
                        name,
63
                    });
64
                }
65
            } else {
66
                commodities.push(CommodityView {
67
                    id: commodity.id,
68
                    symbol,
69
                    name,
70
                });
71
            }
72
        }
73
    }
74

            
75
    HtmlTemplate(CommoditySearchResults { commodities })
76
2
}