use kit::{json_response, Request, Response};
use kit::database::{Model, ModelMut};
use crate::models::todos::{Entity as Todos, ActiveModel, Model as Todo};
use sea_orm::ActiveValue::Set;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct CreateTodoRequest {
pub title: String,
pub description: Option<String>,
}
#[derive(Deserialize)]
pub struct UpdateTodoRequest {
pub title: Option<String>,
pub description: Option<String>,
pub completed: Option<bool>,
}
// GET /api/todos
pub async fn index(_req: Request) -> Response {
match Todos::all().await {
Ok(todos) => json_response!({
"data": todos,
"count": todos.len()
}),
Err(e) => json_response!({
"error": e.to_string()
}, 500),
}
}
// GET /api/todos/:id
pub async fn show(req: Request) -> Response {
let id: i32 = match req.param("id").unwrap().parse() {
Ok(id) => id,
Err(_) => return json_response!({"error": "Invalid ID"}, 400),
};
match Todos::find_by_pk(id).await {
Ok(Some(todo)) => json_response!({"data": todo}),
Ok(None) => json_response!({"error": "Todo not found"}, 404),
Err(e) => json_response!({"error": e.to_string()}, 500),
}
}
// POST /api/todos
pub async fn store(req: Request) -> Response {
let body: CreateTodoRequest = match req.json().await {
Ok(body) => body,
Err(_) => return json_response!({"error": "Invalid request body"}, 400),
};
let now = chrono::Utc::now().naive_utc();
let new_todo = ActiveModel {
title: Set(body.title),
description: Set(body.description),
completed: Set(false),
created_at: Set(now),
updated_at: Set(now),
..Default::default()
};
match Todos::insert_one(new_todo).await {
Ok(result) => json_response!({
"message": "Todo created",
"id": result.last_insert_id
}, 201),
Err(e) => json_response!({"error": e.to_string()}, 500),
}
}
// PUT /api/todos/:id
pub async fn update(req: Request) -> Response {
let id: i32 = match req.param("id").unwrap().parse() {
Ok(id) => id,
Err(_) => return json_response!({"error": "Invalid ID"}, 400),
};
let body: UpdateTodoRequest = match req.json().await {
Ok(body) => body,
Err(_) => return json_response!({"error": "Invalid request body"}, 400),
};
// Find existing todo
let existing = match Todos::find_by_pk(id).await {
Ok(Some(todo)) => todo,
Ok(None) => return json_response!({"error": "Todo not found"}, 404),
Err(e) => return json_response!({"error": e.to_string()}, 500),
};
// Update fields
let mut active: ActiveModel = existing.into();
if let Some(title) = body.title {
active.title = Set(title);
}
if let Some(description) = body.description {
active.description = Set(Some(description));
}
if let Some(completed) = body.completed {
active.completed = Set(completed);
}
active.updated_at = Set(chrono::Utc::now().naive_utc());
match Todos::update_one(active).await {
Ok(updated) => json_response!({"data": updated}),
Err(e) => json_response!({"error": e.to_string()}, 500),
}
}
// DELETE /api/todos/:id
pub async fn destroy(req: Request) -> Response {
let id: i32 = match req.param("id").unwrap().parse() {
Ok(id) => id,
Err(_) => return json_response!({"error": "Invalid ID"}, 400),
};
match Todos::delete_by_pk(id).await {
Ok(result) => {
if result.rows_affected > 0 {
json_response!({"message": "Todo deleted"})
} else {
json_response!({"error": "Todo not found"}, 404)
}
}
Err(e) => json_response!({"error": e.to_string()}, 500),
}
}