use axum::{
extract::{Path, Query, State},
http::StatusCode,
Json,
};
use serde::Deserialize;
use super::sessions::ErrorResponse;
use crate::web::state::WebState;
fn internal_err(e: anyhow::Error) -> (StatusCode, Json<ErrorResponse>) {
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(ErrorResponse { error: e.to_string() }),
)
}
fn not_found(msg: &str) -> (StatusCode, Json<ErrorResponse>) {
(
StatusCode::NOT_FOUND,
Json(ErrorResponse { error: msg.to_string() }),
)
}
#[derive(Deserialize)]
pub struct PathQuery {
pub path: String,
}
pub async fn list_path_notes(
State(state): State<WebState>,
Query(q): Query<PathQuery>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
let notes = state.db.list_path_notes(&q.path).await.map_err(internal_err)?;
Ok(Json(serde_json::json!({ "notes": notes })))
}
#[derive(Deserialize)]
pub struct CreateNoteBody {
pub path: String,
pub content: String,
}
pub async fn create_path_note(
State(state): State<WebState>,
Json(body): Json<CreateNoteBody>,
) -> Result<(StatusCode, Json<serde_json::Value>), (StatusCode, Json<ErrorResponse>)> {
if body.content.trim().is_empty() {
return Err((
StatusCode::UNPROCESSABLE_ENTITY,
Json(ErrorResponse { error: "content must not be empty".to_string() }),
));
}
let note = state
.db
.create_path_note(&body.path, &body.content)
.await
.map_err(internal_err)?;
Ok((StatusCode::CREATED, Json(serde_json::json!({ "note": note }))))
}
#[derive(Deserialize)]
pub struct UpdateNoteBody {
pub content: String,
}
pub async fn update_path_note(
State(state): State<WebState>,
Path(id): Path<String>,
Json(body): Json<UpdateNoteBody>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<ErrorResponse>)> {
if body.content.trim().is_empty() {
return Err((
StatusCode::UNPROCESSABLE_ENTITY,
Json(ErrorResponse { error: "content must not be empty".to_string() }),
));
}
let note = state
.db
.update_path_note(&id, &body.content)
.await
.map_err(internal_err)?
.ok_or_else(|| not_found("note not found"))?;
Ok(Json(serde_json::json!({ "note": note })))
}
pub async fn delete_path_note(
State(state): State<WebState>,
Path(id): Path<String>,
) -> Result<StatusCode, (StatusCode, Json<ErrorResponse>)> {
let deleted = state
.db
.delete_path_note(&id)
.await
.map_err(internal_err)?;
if deleted {
Ok(StatusCode::NO_CONTENT)
} else {
Err(not_found("note not found"))
}
}