web/pages/commodity/
search.rs1use axum::http::StatusCode;
2use axum::{Extension, Json, extract::State};
3use serde::{Deserialize, Serialize};
4use server::command::{CmdResult, FinanceEntity, commodity::ListCommodities};
5use std::sync::Arc;
6
7use crate::{AppState, jwt_auth::JWTAuthMiddleware};
8
9#[derive(Deserialize)]
10pub struct CommoditySearch {
11 #[serde(rename = "commodity-search")]
12 query: Option<String>,
13}
14
15#[derive(Serialize)]
16pub struct CommodityJson {
17 id: String,
18 symbol: String,
19 name: String,
20}
21
22pub async fn search_commodities(
23 State(_data): State<Arc<AppState>>,
24 Extension(jwt_auth): Extension<JWTAuthMiddleware>,
25 Json(form): Json<CommoditySearch>,
26) -> Result<Json<Vec<CommodityJson>>, StatusCode> {
27 let result = match ListCommodities::new().user_id(jwt_auth.user.id).run().await {
28 Ok(Some(CmdResult::TaggedEntities { entities, .. })) => entities,
29 _ => return Ok(Json(vec![])),
30 };
31
32 let mut commodities = Vec::new();
33 for (entity, tags) in result {
34 if let FinanceEntity::Commodity(commodity) = entity {
35 let (symbol, name) = if let (FinanceEntity::Tag(s), FinanceEntity::Tag(n)) =
37 (&tags["symbol"], &tags["name"])
38 {
39 (s.tag_value.clone(), n.tag_value.clone())
40 } else {
41 continue;
42 };
43
44 if let Some(query) = &form.query {
46 if query.is_empty()
47 || symbol.to_lowercase().contains(&query.to_lowercase())
48 || name.to_lowercase().contains(&query.to_lowercase())
49 {
50 commodities.push(CommodityJson {
51 id: commodity.id.to_string(),
52 symbol,
53 name,
54 });
55 }
56 } else {
57 commodities.push(CommodityJson {
58 id: commodity.id.to_string(),
59 symbol,
60 name,
61 });
62 }
63 }
64 }
65
66 Ok(Json(commodities))
67}