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}