feat(approvals): add GET /submission/{user_id} handler for admin submission viewer
Returns user info + onboarding state progress_json for a given user and roleKey, enabling the admin panel to display full onboarding form answers during approval review. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
91534d74c0
commit
ac27184ae2
1 changed files with 66 additions and 0 deletions
|
|
@ -8,13 +8,18 @@ use axum::{
|
|||
};
|
||||
use contracts::auth_middleware::{require_admin, AuthUser};
|
||||
use db::models::job::JobRepository;
|
||||
use db::models::onboarding_state::OnboardingStateRepository;
|
||||
use db::models::requirement::RequirementRepository;
|
||||
use db::models::role::RoleRepository;
|
||||
use db::models::user::UserRepository;
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", get(list_pending))
|
||||
// Submission viewer: GET /api/admin/approvals/submission/{user_id}?roleKey=PHOTOGRAPHER
|
||||
.route("/submission/{user_id}", get(get_submission))
|
||||
.route("/profiles/company/{user_id}/approve", post(approve_company_profile))
|
||||
.route("/profiles/company/{user_id}/reject", post(reject_company_profile))
|
||||
.route("/profiles/customer/{user_id}/approve", post(approve_customer_profile))
|
||||
|
|
@ -27,6 +32,67 @@ pub fn router() -> Router<AppState> {
|
|||
.route("/requirements/{id}/reject", post(reject_requirement))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RoleKeyQuery {
|
||||
#[serde(rename = "roleKey", alias = "role_key")]
|
||||
pub role_key: Option<String>,
|
||||
}
|
||||
|
||||
/// GET /api/admin/approvals/submission/{user_id}?roleKey=PHOTOGRAPHER
|
||||
/// Returns the user info + their onboarding state (submitted form answers) for admin review.
|
||||
async fn get_submission(
|
||||
auth: AuthUser,
|
||||
State(state): State<AppState>,
|
||||
Path(user_id): Path<Uuid>,
|
||||
Query(q): Query<RoleKeyQuery>,
|
||||
) -> impl IntoResponse {
|
||||
if let Err(e) = require_admin(&auth) {
|
||||
return e.into_response();
|
||||
}
|
||||
|
||||
// Fetch user
|
||||
let user = match UserRepository::get_by_id(&state.pool, user_id).await {
|
||||
Ok(u) => u,
|
||||
Err(_) => return (StatusCode::NOT_FOUND, "User not found").into_response(),
|
||||
};
|
||||
|
||||
// Fetch onboarding state (for the given roleKey, or the user's active role)
|
||||
let role_key = q.role_key.filter(|k| !k.is_empty());
|
||||
let onboarding = if let Some(ref rk) = role_key {
|
||||
match RoleRepository::get_by_key(&state.pool, rk).await {
|
||||
Ok(role) => OnboardingStateRepository::get(&state.pool, user_id, role.id)
|
||||
.await
|
||||
.unwrap_or(None),
|
||||
Err(_) => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(serde_json::json!({
|
||||
"user": {
|
||||
"id": user.id,
|
||||
"name": user.full_name,
|
||||
"email": user.email,
|
||||
"phone": user.phone,
|
||||
"status": user.status,
|
||||
"email_verified": user.email_verified,
|
||||
"created_at": user.created_at,
|
||||
},
|
||||
"role_key": role_key,
|
||||
"onboarding": onboarding.map(|s| serde_json::json!({
|
||||
"status": s.status,
|
||||
"progress_json": s.progress_json,
|
||||
"completed_at": s.completed_at,
|
||||
"updated_at": s.updated_at,
|
||||
})),
|
||||
})),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ListQuery {
|
||||
pub page: Option<i64>,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue