//! Käsittelijät — CRUD-operaatiot todo-entiteetille. use axum::extract::{Path, State}; use axum::http::StatusCode; use axum::Json; use sqlx::SqlitePool; use crate::models::{CreateTodo, Todo, UpdateTodo}; /// Luo uusi tehtävä. pub async fn create_todo( State(pool): State, Json(input): Json, ) -> Result<(StatusCode, Json), StatusCode> { let priority = input.priority.unwrap_or(1); let status = input.status.unwrap_or_else(|| "pending".to_string()); let result = sqlx::query_as::<_, Todo>( "INSERT INTO todos (title, description, due_date, priority, status) VALUES (?, ?, ?, ?, ?) RETURNING id, title, description, due_date, priority, status", ) .bind(&input.title) .bind(&input.description) .bind(&input.due_date) .bind(priority) .bind(&status) .fetch_one(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok((StatusCode::CREATED, Json(result))) } /// Listaa kaikki tehtävät. pub async fn list_todos( State(pool): State, ) -> Result>, StatusCode> { let todos = sqlx::query_as::<_, Todo>("SELECT id, title, description, due_date, priority, status FROM todos") .fetch_all(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok(Json(todos)) } /// Hae tehtävä id:llä. pub async fn get_todo( State(pool): State, Path(id): Path, ) -> Result, StatusCode> { let todo = sqlx::query_as::<_, Todo>( "SELECT id, title, description, due_date, priority, status FROM todos WHERE id = ?", ) .bind(id) .fetch_optional(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; match todo { Some(t) => Ok(Json(t)), None => Err(StatusCode::NOT_FOUND), } } /// Päivitä tehtävä id:llä. pub async fn update_todo( State(pool): State, Path(id): Path, Json(input): Json, ) -> Result, StatusCode> { let existing = sqlx::query_as::<_, Todo>( "SELECT id, title, description, due_date, priority, status FROM todos WHERE id = ?", ) .bind(id) .fetch_optional(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; let existing = existing.ok_or(StatusCode::NOT_FOUND)?; let title = input.title.unwrap_or(existing.title); let description = input.description.or(existing.description); let due_date = input.due_date.or(existing.due_date); let priority = input.priority.unwrap_or(existing.priority); let status = input.status.unwrap_or(existing.status); let updated = sqlx::query_as::<_, Todo>( "UPDATE todos SET title = ?, description = ?, due_date = ?, priority = ?, status = ? WHERE id = ? RETURNING id, title, description, due_date, priority, status", ) .bind(&title) .bind(&description) .bind(&due_date) .bind(priority) .bind(&status) .bind(id) .fetch_one(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok(Json(updated)) } /// Poista tehtävä id:llä. pub async fn delete_todo( State(pool): State, Path(id): Path, ) -> Result { let result = sqlx::query("DELETE FROM todos WHERE id = ?") .bind(id) .execute(&pool) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; if result.rows_affected() == 0 { return Err(StatusCode::NOT_FOUND); } Ok(StatusCode::NO_CONTENT) }