use axum::{extract::{Path, Query, State}, Json}; use api_types::requests::{PaginationQuery, SearchQuery}; use application::use_cases::feed::{get_home_feed, get_public_feed, get_followers, get_following, get_user_feed, get_by_tag}; use domain::models::feed::PageParams; use crate::{errors::ApiError, extractors::{AuthUser, OptionalAuthUser}, handlers::auth::to_user_response, state::AppState}; use application::use_cases::profile::get_user_by_username; pub async fn home_feed(State(s): State, AuthUser(uid): AuthUser, Query(q): Query) -> Result, ApiError> { let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_home_feed(&*s.feed, &*s.follows, &uid, page).await?; Ok(Json(serde_json::json!({ "items": result.items.iter().map(|e| e.thought.id.as_uuid()).collect::>(), "total": result.total, "page": result.page }))) } pub async fn public_feed(State(s): State, OptionalAuthUser(viewer): OptionalAuthUser, Query(q): Query) -> Result, ApiError> { let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_public_feed(&*s.feed, viewer.as_ref(), page).await?; Ok(Json(serde_json::json!({ "items": result.items.iter().map(|e| e.thought.id.as_uuid()).collect::>(), "total": result.total, "page": result.page }))) } pub async fn search_handler( State(s): State, OptionalAuthUser(viewer): OptionalAuthUser, Query(q): Query, ) -> Result, ApiError> { let page = PageParams { page: q.page.unwrap_or(1), per_page: q.per_page.unwrap_or(20) }; let query = q.q.trim().to_string(); let (thoughts_result, users_result) = tokio::join!( s.search.search_thoughts(&query, &page, viewer.as_ref()), s.search.search_users(&query, &page), ); let thoughts = thoughts_result?.items.into_iter().map(|e| serde_json::json!({ "id": e.thought.id.as_uuid(), "content": e.thought.content.as_str(), "author": to_user_response(&e.author), "like_count": e.like_count, "boost_count": e.boost_count, "reply_count": e.reply_count, "created_at": e.thought.created_at, })).collect::>(); let users = users_result?.items.into_iter().map(|u| to_user_response(&u)).collect::>(); Ok(Json(serde_json::json!({ "query": query, "thoughts": thoughts, "users": users, }))) } pub async fn get_following_handler(State(s): State, Path(username): Path, Query(q): Query) -> Result, ApiError> { let user = get_user_by_username(&*s.users, &username).await?; let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_following(&*s.follows, &user.id, page).await?; Ok(Json(serde_json::json!({ "total": result.total, "items": result.items.iter().map(to_user_response).collect::>() }))) } pub async fn get_followers_handler(State(s): State, Path(username): Path, Query(q): Query) -> Result, ApiError> { let user = get_user_by_username(&*s.users, &username).await?; let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_followers(&*s.follows, &user.id, page).await?; Ok(Json(serde_json::json!({ "total": result.total, "items": result.items.iter().map(to_user_response).collect::>() }))) } pub async fn user_thoughts_handler( State(s): State, Path(username): Path, Query(q): Query, ) -> Result, ApiError> { let user = get_user_by_username(&*s.users, &username).await?; let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_user_feed(&*s.thoughts, &user.id, page).await?; Ok(Json(serde_json::json!({ "total": result.total, "page": result.page, "per_page": result.per_page, "items": result.items.iter().map(|e| serde_json::json!({ "id": e.thought.id.as_uuid(), "content": e.thought.content.as_str(), "visibility": e.thought.visibility.as_str(), "like_count": e.like_count, "boost_count": e.boost_count, "reply_count": e.reply_count, "created_at": e.thought.created_at, "updated_at": e.thought.updated_at, })).collect::>() }))) } pub async fn tag_thoughts_handler( State(s): State, Path(tag_name): Path, Query(q): Query, ) -> Result, ApiError> { let page = PageParams { page: q.page(), per_page: q.per_page() }; let result = get_by_tag(&*s.tags, &tag_name, page).await?; Ok(Json(serde_json::json!({ "tag": tag_name, "total": result.total, "page": result.page, "per_page": result.per_page, "items": result.items.iter().map(|t| serde_json::json!({ "id": t.id.as_uuid(), "content": t.content.as_str(), "visibility": t.visibility.as_str(), "created_at": t.created_at, })).collect::>() }))) }