web/pages/commodity/
list.rs1use std::sync::Arc;
2
3use askama::Template;
4use axum::{Extension, extract::State, http::StatusCode, response::IntoResponse};
5use server::command::{CmdResult, FinanceEntity, commodity::ListCommodities};
6use sqlx::types::Uuid;
7
8use crate::{AppState, jwt_auth::JWTAuthMiddleware, pages::HtmlTemplate};
9
10#[derive(Template)]
11#[template(path = "pages/commodity/list.html")]
12struct CommodityListPage;
13
14pub async fn commodity_list_page() -> impl IntoResponse {
15 let template = CommodityListPage {};
16 HtmlTemplate(template)
17}
18
19struct CommodityView {
20 id: Uuid,
21 symbol: String,
22 name: String,
23}
24
25#[derive(Template)]
26#[template(path = "components/commodity/table.html")]
27struct CommodityTableTemplate {
28 commodities: Vec<CommodityView>,
29}
30
31pub async fn commodity_table(
32 State(_data): State<Arc<AppState>>,
33 Extension(jwt_auth): Extension<JWTAuthMiddleware>,
34) -> Result<impl IntoResponse, StatusCode> {
35 let result = ListCommodities::new()
36 .user_id(jwt_auth.user.id)
37 .run()
38 .await
39 .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
40 let mut commodities = Vec::new();
41 if let Some(CmdResult::TaggedEntities { entities, .. }) = result {
42 for (entity, tags) in entities {
43 if let FinanceEntity::Commodity(commodity) = entity {
44 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 return Err(StatusCode::INTERNAL_SERVER_ERROR);
51 };
52
53 commodities.push(CommodityView {
54 id: commodity.id,
55 symbol,
56 name,
57 });
58 }
59 }
60 }
61 Ok(HtmlTemplate(CommodityTableTemplate { commodities }))
62}