From 0be46d328a8e0e9c714c2441bd94e3a056c536d2 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Wed, 25 Mar 2026 23:55:44 +0100 Subject: [PATCH] feat: add phase 2 dashboard metrics api --- apps/gateway/src/main.rs | 1 + apps/users/src/handlers/dashboard.rs | 56 ++++++++++++++++++++++++++++ apps/users/src/handlers/mod.rs | 1 + apps/users/src/main.rs | 1 + 4 files changed, 59 insertions(+) create mode 100644 apps/users/src/handlers/dashboard.rs diff --git a/apps/gateway/src/main.rs b/apps/gateway/src/main.rs index e43f644..81a241e 100644 --- a/apps/gateway/src/main.rs +++ b/apps/gateway/src/main.rs @@ -77,6 +77,7 @@ impl Services { || path.starts_with("/api/admin/permissions") || path.starts_with("/api/admin/onboarding-config") || path.starts_with("/api/admin/dashboard-config") + || path.starts_with("/api/admin/dashboard") || path.starts_with("/api/admin/users") || path.starts_with("/api/admin/employees") || path.starts_with("/api/admin/departments") diff --git a/apps/users/src/handlers/dashboard.rs b/apps/users/src/handlers/dashboard.rs new file mode 100644 index 0000000..6b8a8d0 --- /dev/null +++ b/apps/users/src/handlers/dashboard.rs @@ -0,0 +1,56 @@ +use axum::{routing::get, Json, Router}; +use serde::Serialize; +use serde_json::{json, Value}; + +#[derive(Serialize)] +pub struct DashboardMetricsResponse { + kpis: Vec, + trend_series: Vec, + rev_series: Vec, + lead_rows: Vec, +} + +pub fn router() -> Router { + Router::new().route("/metrics", get(get_metrics)) +} + +async fn get_metrics() -> Json { + // Return realistic mock metrics to wire the frontend + let kpis = vec![ + json!({ "id": "users", "title": "Total Users", "value": "12,450", "trend": "+12%", "trendUp": true }), + json!({ "id": "companies", "title": "Active Companies", "value": "840", "trend": "+5%", "trendUp": true }), + json!({ "id": "leads", "title": "Open Leads", "value": "3,210", "trend": "-2%", "trendUp": false }), + json!({ "id": "credits", "title": "Credits Purchased", "value": "$45,200", "trend": "+18%", "trendUp": true }), + ]; + + let trend_series = vec![ + json!({ "name": "Mon", "Freelancers": 40, "Agencies": 24 }), + json!({ "name": "Tue", "Freelancers": 30, "Agencies": 13 }), + json!({ "name": "Wed", "Freelancers": 20, "Agencies": 58 }), + json!({ "name": "Thu", "Freelancers": 27, "Agencies": 39 }), + json!({ "name": "Fri", "Freelancers": 18, "Agencies": 48 }), + json!({ "name": "Sat", "Freelancers": 23, "Agencies": 38 }), + json!({ "name": "Sun", "Freelancers": 34, "Agencies": 43 }), + ]; + + let rev_series = vec![ + json!({ "name": "Week 1", "Revenue": 4000, "Profit": 2400 }), + json!({ "name": "Week 2", "Revenue": 3000, "Profit": 1398 }), + json!({ "name": "Week 3", "Revenue": 2000, "Profit": 9800 }), + json!({ "name": "Week 4", "Revenue": 2780, "Profit": 3908 }), + ]; + + let lead_rows = vec![ + json!({ "id": "L-1001", "client": "Acme Corp", "service": "Photography", "status": "Open", "value": "$1,200", "date": "Oct 24, 2023" }), + json!({ "id": "L-1002", "client": "Stark Ind", "service": "Web Dev", "status": "In Progress", "value": "$4,500", "date": "Oct 23, 2023" }), + json!({ "id": "L-1003", "client": "Wayne Ent", "service": "SEO", "status": "Closed", "value": "$800", "date": "Oct 22, 2023" }), + json!({ "id": "L-1004", "client": "Daily Bugle", "service": "Copywriting", "status": "Open", "value": "$350", "date": "Oct 21, 2023" }), + ]; + + Json(DashboardMetricsResponse { + kpis, + trend_series: trend_series, + rev_series: rev_series, + lead_rows: lead_rows, + }) +} diff --git a/apps/users/src/handlers/mod.rs b/apps/users/src/handlers/mod.rs index 72612af..77ded43 100644 --- a/apps/users/src/handlers/mod.rs +++ b/apps/users/src/handlers/mod.rs @@ -1,6 +1,7 @@ pub mod approvals; pub mod auth; pub mod config; +pub mod dashboard; pub mod notifications; pub mod onboarding; pub mod permissions; diff --git a/apps/users/src/main.rs b/apps/users/src/main.rs index da67f6e..09397bc 100644 --- a/apps/users/src/main.rs +++ b/apps/users/src/main.rs @@ -69,6 +69,7 @@ async fn main() { // ── Admin: Onboarding + Dashboard Config ────────────────────────── .nest("/api/admin/onboarding-config", handlers::config::onboarding_router()) .nest("/api/admin/dashboard-config", handlers::config::dashboard_router()) + .nest("/api/admin/dashboard", handlers::dashboard::router()) // ── Public Config ───────────────────────────────────────────────── .nest("/api/config/onboarding", handlers::config::onboarding_router()) .nest("/api/config/dashboard", handlers::config::dashboard_router())