// Tasks API endpoints use axum::{ extract::{Path, Query, State}, http::StatusCode, response::IntoResponse, Json, }; use serde::Deserialize; use vapora_shared::models::{Task, TaskPriority, TaskStatus}; use crate::api::state::AppState; use crate::api::ApiResult; #[derive(Debug, Deserialize)] pub struct TaskQueryParams { pub project_id: String, pub status: Option, pub assignee: Option, } #[derive(Debug, Deserialize)] pub struct ReorderTaskPayload { pub task_order: i32, pub status: Option, } #[derive(Debug, Deserialize)] pub struct AssignTaskPayload { pub assignee: String, } #[derive(Debug, Deserialize)] pub struct UpdatePriorityPayload { pub priority: TaskPriority, } /// List tasks with optional filters /// /// GET /api/v1/tasks?project_id=xxx&status=todo&assignee=agent1 pub async fn list_tasks( State(state): State, Query(params): Query, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let tasks = if let Some(status_str) = params.status { // Parse status let status: TaskStatus = serde_json::from_value(serde_json::json!(status_str))?; state .task_service .list_tasks_by_status(¶ms.project_id, tenant_id, status) .await? } else if let Some(assignee) = params.assignee { state .task_service .list_tasks_by_assignee(¶ms.project_id, tenant_id, &assignee) .await? } else { state .task_service .list_tasks(¶ms.project_id, tenant_id) .await? }; Ok(Json(tasks)) } /// Get a specific task /// /// GET /api/v1/tasks/:id pub async fn get_task( State(state): State, Path(id): Path, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let task = state.task_service.get_task(&id, tenant_id).await?; Ok(Json(task)) } /// Create a new task /// /// POST /api/v1/tasks pub async fn create_task( State(state): State, Json(mut task): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token task.tenant_id = "default".to_string(); let created = state.task_service.create_task(task).await?; Ok((StatusCode::CREATED, Json(created))) } /// Update a task /// /// PUT /api/v1/tasks/:id pub async fn update_task( State(state): State, Path(id): Path, Json(updates): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let updated = state .task_service .update_task(&id, tenant_id, updates) .await?; Ok(Json(updated)) } /// Delete a task /// /// DELETE /api/v1/tasks/:id pub async fn delete_task( State(state): State, Path(id): Path, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; state.task_service.delete_task(&id, tenant_id).await?; Ok(StatusCode::NO_CONTENT) } /// Reorder a task (for Kanban drag & drop) /// /// PUT /api/v1/tasks/:id/reorder pub async fn reorder_task( State(state): State, Path(id): Path, Json(payload): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let updated = state .task_service .reorder_task(&id, tenant_id, payload.task_order, payload.status) .await?; Ok(Json(updated)) } /// Update task status /// /// PUT /api/v1/tasks/:id/status pub async fn update_task_status( State(state): State, Path(id): Path, Json(payload): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let status: TaskStatus = serde_json::from_value(payload["status"].clone())?; let updated = state .task_service .update_task_status(&id, tenant_id, status) .await?; Ok(Json(updated)) } /// Assign a task to an agent/user /// /// PUT /api/v1/tasks/:id/assign pub async fn assign_task( State(state): State, Path(id): Path, Json(payload): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let updated = state .task_service .assign_task(&id, tenant_id, payload.assignee) .await?; Ok(Json(updated)) } /// Update task priority /// /// PUT /api/v1/tasks/:id/priority pub async fn update_priority( State(state): State, Path(id): Path, Json(payload): Json, ) -> ApiResult { // TODO: Extract tenant_id from JWT token let tenant_id = "default"; let updated = state .task_service .update_priority(&id, tenant_id, payload.priority) .await?; Ok(Json(updated)) }