use crate::{ApiResponse, error::ApiError}; use actix_web::{HttpResponse, Result, web}; use service::AppService; use service::error::AppError; use service::project::activity::{ActivityLogListResponse, ActivityLogParams, ActivityLogResponse}; use session::Session; #[derive(serde::Deserialize, utoipa::IntoParams)] pub struct ActivityQuery { pub page: Option, pub per_page: Option, pub event_type: Option, pub start_date: Option, pub end_date: Option, } impl From for service::project::activity::ActivityParams { fn from(q: ActivityQuery) -> Self { service::project::activity::ActivityParams { event_type: q.event_type, start_date: q.start_date, end_date: q.end_date, } } } #[utoipa::path( get, path = "/api/projects/{project_name}/activities", params( ("project_name" = String, Path), ("page" = Option, Query), ("per_page" = Option, Query), ("event_type" = Option, Query), ("start_date" = Option, Query, description = "ISO 8601 datetime, e.g. 2025-01-01T00:00:00Z"), ("end_date" = Option, Query, description = "ISO 8601 datetime, e.g. 2025-12-31T23:59:59Z"), ), responses( (status = 200, description = "List project activities", body = ApiResponse), (status = 401, description = "Unauthorized"), (status = 403, description = "Forbidden — no access to this project"), (status = 404, description = "Project not found"), ), tag = "Project" )] pub async fn project_activities( service: web::Data, session: Session, path: web::Path, query: web::Query, ) -> Result { let project_name = path.into_inner(); let page = query.page; let per_page = query.per_page; let params = service::project::activity::ActivityParams::from(query.into_inner()); let resp = service .project_get_activities(project_name, page, per_page, Some(params), &session) .await?; Ok(ApiResponse::ok(resp).to_response()) } #[utoipa::path( post, path = "/api/projects/{project_name}/activities", params(("project_name" = String, Path)), request_body = ActivityLogParams, responses( (status = 200, description = "Activity logged", body = ApiResponse), (status = 401, description = "Unauthorized"), (status = 404, description = "Project not found"), ), tag = "Project" )] pub async fn project_log_activity( service: web::Data, session: Session, path: web::Path, body: web::Json, ) -> Result { let project_name = path.into_inner(); let _project = service.utils_find_project_by_name(project_name).await?; let user_uid = session.user().ok_or(AppError::Unauthorized)?; let resp = service .project_log_activity(_project.id, body.repo_id, user_uid, body.into_inner()) .await?; Ok(ApiResponse::ok(resp).to_response()) }