Skip to main content

web/pages/account/
search.rs

1use askama::Template;
2use axum::{Extension, Json, extract::State, response::IntoResponse};
3use serde::Deserialize;
4use server::command::{CmdResult, FinanceEntity, account::ListAccounts};
5use sqlx::types::Uuid;
6use std::sync::Arc;
7
8use crate::{AppState, jwt_auth::JWTAuthMiddleware, pages::HtmlTemplate};
9
10#[derive(Deserialize)]
11pub struct AccountSearch {
12    #[serde(rename = "parent-search")]
13    query: Option<String>,
14}
15
16#[derive(Template)]
17#[template(path = "components/account/search_results.html")]
18struct AccountSearchResults {
19    accounts: Vec<AccountView>,
20}
21
22struct AccountView {
23    id: Uuid,
24    name: String,
25}
26
27pub async fn search_accounts(
28    State(_data): State<Arc<AppState>>,
29    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
30    Json(form): Json<AccountSearch>,
31) -> impl IntoResponse {
32    let result = match ListAccounts::new().user_id(jwt_auth.user.id).run().await {
33        Ok(Some(CmdResult::TaggedEntities { entities, .. })) => entities,
34        _ => return HtmlTemplate(AccountSearchResults { accounts: vec![] }),
35    };
36
37    let mut accounts = Vec::new();
38    for (entity, tags) in result {
39        if let FinanceEntity::Account(account) = entity {
40            // Find name tag
41            let name = if let FinanceEntity::Tag(n) = &tags["name"] {
42                n.tag_value.clone()
43            } else {
44                continue;
45            };
46
47            // Filter by search query if provided
48            if let Some(query) = &form.query {
49                if query.is_empty() || name.to_lowercase().contains(&query.to_lowercase()) {
50                    accounts.push(AccountView {
51                        id: account.id,
52                        name,
53                    });
54                }
55            } else {
56                accounts.push(AccountView {
57                    id: account.id,
58                    name,
59                });
60            }
61        }
62    }
63
64    HtmlTemplate(AccountSearchResults { accounts })
65}