Skip to main content

web/pages/tag/
create.rs

1use askama::Template;
2use axum::{
3    Extension, Json,
4    extract::{Path, State},
5    http::StatusCode,
6    response::IntoResponse,
7};
8use serde::Deserialize;
9use sqlx::types::Uuid;
10use std::sync::Arc;
11
12use crate::{AppState, jwt_auth::JWTAuthMiddleware, pages::HtmlTemplate};
13
14#[derive(Template)]
15#[template(path = "pages/tag/create.html")]
16struct TagCreatePage;
17
18pub async fn tag_create_page() -> impl IntoResponse {
19    HtmlTemplate(TagCreatePage {})
20}
21
22#[derive(Deserialize)]
23pub struct TagForm {
24    tag_name: String,
25    tag_value: String,
26    description: Option<String>,
27}
28
29pub async fn create_tag(
30    State(_data): State<Arc<AppState>>,
31    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
32    Json(form): Json<TagForm>,
33) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
34    let user = &jwt_auth.user;
35    let server_user = server::user::User { id: user.id };
36
37    let description = form.description.filter(|desc| !desc.is_empty());
38
39    match server_user
40        .create_tag(form.tag_name, form.tag_value, description)
41        .await
42    {
43        Ok(id) => Ok(format!("{}: {}", t!("New tag id"), id)),
44        Err(e) => {
45            let error_response = serde_json::json!({
46                "status": "fail",
47                "message": t!("Failed to create tag"),
48            });
49
50            log::error!("Failed to create tag: {e:?}");
51            Err((StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)))
52        }
53    }
54}
55
56pub async fn create_transaction_tag(
57    Path(transaction_id): Path<String>,
58    State(_data): State<Arc<AppState>>,
59    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
60    Json(form): Json<TagForm>,
61) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
62    let user = &jwt_auth.user;
63
64    let tx_uuid = Uuid::parse_str(&transaction_id).map_err(|_| {
65        let error_response = serde_json::json!({
66            "status": "fail",
67            "message": "Invalid transaction ID format",
68        });
69        (StatusCode::BAD_REQUEST, Json(error_response))
70    })?;
71
72    let server_user = server::user::User { id: user.id };
73    let description = form.description.filter(|desc| !desc.is_empty());
74
75    match server_user
76        .create_transaction_tag(tx_uuid, form.tag_name, form.tag_value, description)
77        .await
78    {
79        Ok(id) => Ok(format!("{}: {}", t!("New transaction tag id"), id)),
80        Err(e) => {
81            let error_response = serde_json::json!({
82                "status": "fail",
83                "message": t!("Failed to create transaction tag"),
84            });
85
86            log::error!("Failed to create transaction tag: {e:?}");
87            Err((StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)))
88        }
89    }
90}
91
92pub async fn create_account_tag(
93    Path(account_id): Path<String>,
94    State(_data): State<Arc<AppState>>,
95    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
96    Json(form): Json<TagForm>,
97) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
98    let user = &jwt_auth.user;
99
100    let account_uuid = Uuid::parse_str(&account_id).map_err(|_| {
101        let error_response = serde_json::json!({
102            "status": "fail",
103            "message": "Invalid account ID format",
104        });
105        (StatusCode::BAD_REQUEST, Json(error_response))
106    })?;
107
108    let server_user = server::user::User { id: user.id };
109    let description = form.description.filter(|desc| !desc.is_empty());
110
111    match server_user
112        .create_account_tag(account_uuid, form.tag_name, form.tag_value, description)
113        .await
114    {
115        Ok(id) => Ok(format!("{}: {}", t!("New account tag id"), id)),
116        Err(e) => {
117            let error_response = serde_json::json!({
118                "status": "fail",
119                "message": t!("Failed to create account tag"),
120            });
121
122            log::error!("Failed to create account tag: {e:?}");
123            Err((StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)))
124        }
125    }
126}
127
128pub async fn create_split_tag(
129    Path(split_id): Path<String>,
130    State(_data): State<Arc<AppState>>,
131    Extension(jwt_auth): Extension<JWTAuthMiddleware>,
132    Json(form): Json<TagForm>,
133) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
134    let user = &jwt_auth.user;
135
136    let split_uuid = Uuid::parse_str(&split_id).map_err(|_| {
137        let error_response = serde_json::json!({
138            "status": "fail",
139            "message": "Invalid split ID format",
140        });
141        (StatusCode::BAD_REQUEST, Json(error_response))
142    })?;
143
144    let server_user = server::user::User { id: user.id };
145    let description = form.description.filter(|desc| !desc.is_empty());
146
147    match server_user
148        .create_split_tag(split_uuid, form.tag_name, form.tag_value, description)
149        .await
150    {
151        Ok(id) => Ok(format!("{}: {}", t!("New split tag id"), id)),
152        Err(e) => {
153            let error_response = serde_json::json!({
154                "status": "fail",
155                "message": t!("Failed to create split tag"),
156            });
157
158            log::error!("Failed to create split tag: {e:?}");
159            Err((StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)))
160        }
161    }
162}