pub mod bulk_handlers;
pub mod export;
pub mod handlers;
pub use bulk_handlers::{bulk_approve, bulk_reject};
pub use export::{export_items, get_edit_history};
pub use handlers::{approve_all, approve_item, edit_item, reject_item};
use std::sync::Arc;
use axum::extract::{Query, State};
use axum::Json;
use serde::Deserialize;
use serde_json::{json, Value};
use tuitbot_core::storage::approval_queue;
use crate::account::AccountContext;
use crate::error::ApiError;
use crate::state::AppState;
#[derive(Deserialize)]
pub struct ApprovalQuery {
#[serde(default = "default_status")]
pub status: String,
#[serde(rename = "type")]
pub action_type: Option<String>,
pub reviewed_by: Option<String>,
pub since: Option<String>,
pub account_id: Option<String>,
}
fn default_status() -> String {
"pending".to_string()
}
pub async fn list_items(
State(state): State<Arc<AppState>>,
ctx: AccountContext,
Query(params): Query<ApprovalQuery>,
) -> Result<Json<Value>, ApiError> {
let statuses: Vec<&str> = params.status.split(',').map(|s| s.trim()).collect();
let action_type = params.action_type.as_deref();
let reviewed_by = params.reviewed_by.as_deref();
let since = params.since.as_deref();
let effective_account_id = match params.account_id.as_deref() {
Some(qid) if qid == ctx.account_id => qid,
Some(_) => &ctx.account_id, None => &ctx.account_id,
};
let items = approval_queue::get_filtered_for(
&state.db,
effective_account_id,
&statuses,
action_type,
reviewed_by,
since,
)
.await?;
Ok(Json(json!(items)))
}
pub async fn stats(
State(state): State<Arc<AppState>>,
ctx: AccountContext,
) -> Result<Json<Value>, ApiError> {
let stats = approval_queue::get_stats_for(&state.db, &ctx.account_id).await?;
Ok(Json(json!(stats)))
}
#[cfg(test)]
mod tests;