From 83a1f45e4feb1517d3a5208db99d6c2f85d38b03 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Wed, 25 Mar 2026 23:55:43 +0100 Subject: [PATCH] feat: complete phase 2 dashboard modules UI and data wiring --- .../external-dashboard-management/index.tsx | 181 ++++++++---- src/routes/admin/index.tsx | 278 +++++++++--------- .../internal-dashboard-management/index.tsx | 182 ++++++++---- 3 files changed, 382 insertions(+), 259 deletions(-) diff --git a/src/routes/admin/external-dashboard-management/index.tsx b/src/routes/admin/external-dashboard-management/index.tsx index 1c13c78..0e10a3c 100644 --- a/src/routes/admin/external-dashboard-management/index.tsx +++ b/src/routes/admin/external-dashboard-management/index.tsx @@ -455,72 +455,129 @@ export default function ExternalDashboardManagementPage() { return (
-
-
-

External Dashboard Management

-

Open one external dashboard at a time from the list below and edit it using simple tabs.

-
- Back to Dashboard -
-
- - - -
- - {/* ---------- List View ---------- */} +
-
+ {/* Header & Title */} +
-

External Dashboard List

-

Choose one external role dashboard to open in the builder, or create a new one.

+

External Dashboard Management

+

Configure dashboards for external role members

+
+
+ +
-
-
{error()}
-
-
- - - - - - - - - - - - - - - - - - - - {(d) => ( - - - - - - - - - )} - - -
RoleDashboardStatusVersionModulesAction
Loading external dashboards...
No external dashboards found. Create the first one.
{d.roleKey || 'No role selected'}{d.title}{d.status}v{d.version}{d.modules.length} pages -
- -
-
+ + {/* 5 KPI Cards Row */} +
+
+

Total Dashboard
Templates

+

12

+
+
+

Active Templates

+

10

+
+
+

Draft Templates

+

2

+
+
+

Assigned Roles

+

8

+
+
+

Unassigned Roles

+

4

+
+
+ + {/* Main Table Section */} +
+
+ {/* Table Action Header */} +
+

External Dashboard
Templates

+
+ + + +
+
+ + {/* Error Message */} + +
{error()}
+
+ + {/* Filters Row */} +
+
+
+ + + +
+ +
+
+
+
+ + {/* Table */} +
+ + + + + + + + + + + + + + + + + + + {(d) => ( + void openDashboard(d.id)}> + + + + + + + )} + + +
ROLE KEYDASHBOARD NAMEMODULES COUNTVERSIONSTATUS
Loading external dashboards...
No external dashboards found. Create the first one.
{d.roleKey || 'No role selected'}{d.title}{d.modules.length} pagesv{d.version} + + {d.status === 'published' ? 'Active' : 'Draft'} + +
+
diff --git a/src/routes/admin/index.tsx b/src/routes/admin/index.tsx index 3c6772e..4a6d9cd 100644 --- a/src/routes/admin/index.tsx +++ b/src/routes/admin/index.tsx @@ -1,26 +1,24 @@ -import { For } from 'solid-js'; +import { For, Show, createResource } from 'solid-js'; import AdminShell from '~/components/AdminShell'; -const kpis = [ - { title: 'Total Users', value: '12,458', delta: '+12.5%', note: '+1,245 from last month', tone: 'up' as const, icon: 'US' }, - { title: 'Active Companies', value: '1,234', delta: '+8.2%', note: '+94 from last month', tone: 'up' as const, icon: 'CP' }, - { title: 'Open Leads', value: '847', delta: '-3.1%', note: '-27 from last month', tone: 'down' as const, icon: 'LD' }, - { title: 'Credits Purchased', value: '$45,890', delta: '+18.7%', note: '+$7,234 from last month', tone: 'up' as const, icon: 'CR' }, -]; +const API = '/api/gateway'; + +async function fetchMetrics() { + const res = await fetch(`${API}/api/admin/dashboard/metrics`); + if (!res.ok) throw new Error('Failed to fetch dashboard metrics'); + return res.json(); +} -const trendSeries = [62, 70, 81, 75, 88, 102]; -const revSeries = [42000, 48000, 55000, 51000, 62000, 69000]; const maxAmount = 80000; -const leadRows = [ - { title: 'Corporate Event Photographer', customer: 'Bright Media', category: 'Photography', budget: '$3,500', status: 'New', priority: 'High' }, - { title: 'Wedding Makeup Artist', customer: 'Aster Weddings', category: 'Makeup Artist', budget: '$1,800', status: 'In Review', priority: 'Medium' }, - { title: 'SAT Batch Tutor', customer: 'EduPath', category: 'Tutors', budget: '$2,300', status: 'Assigned', priority: 'Low' }, - { title: 'Personal Fitness Trainer', customer: 'Core Fitness', category: 'Fitness', budget: '$2,900', status: 'Escalated', priority: 'High' }, - { title: 'Corporate Video Editor', customer: 'Pixel Forge', category: 'Video Editor', budget: '$4,200', status: 'New', priority: 'Critical' }, -]; - export default function AdminDashboard() { + const [data] = createResource(fetchMetrics); + + const kpis = () => data()?.kpis || []; + const trendSeries = () => data()?.trend_series?.map((d: any) => d.Freelancers) || [0, 0, 0, 0, 0, 0]; + const revSeries = () => data()?.rev_series?.map((d: any) => d.Revenue) || [0, 0, 0, 0, 0, 0]; + const leadRows = () => data()?.lead_rows || []; + return (
@@ -30,139 +28,147 @@ export default function AdminDashboard() {

Dashboard Overview

Welcome back! Here's what's happening with your platform today.

-
-
- - {(item) => ( -
-
-
{item.icon}
- - {item.delta} - -
-

{item.title}

-

{item.value}

-

{item.note}

-
- )} -
-
+ +
Loading metrics...
+
-
-
-

Leads Trend

-

Monthly leads performance overview

-
-
-
- {() =>
} + +
+ + {(item: any) => ( +
+
+
+ {item.id === 'users' ? 'US' : item.id === 'companies' ? 'CP' : item.id === 'leads' ? 'LD' : 'CR'} +
+ + {item.trend} + +
+

{item.title}

+

{item.value}

+

{item.trendUp ? 'Increased from last month' : 'Decreased from last month'}

+
+ )} +
+
+ +
+
+

Leads Trend

+

Monthly leads performance overview

+
+
+
+ {() =>
} +
+ +
+
+ {(day) => {day}}
-
-
- {(month) => {month}} +
+ +
+

Revenue Overview

+

Monthly revenue vs expenses comparison

+
+
+
+ {() =>
} +
+
+ + {(value: number) => ( +
+
+
+ )} + +
+
+
+ {(week) => {week}} +
+
+
+ +
+
+
+

Recent Leads

+

Latest customer inquiries and opportunities

+
+
-
-
-

Revenue Overview

-

Monthly revenue vs expenses comparison

-
-
-
- {() =>
} -
-
- - {(value) => ( -
-
-
+
+ + + + + + + + + + + + + + + {(row: any) => ( + + + + + + + + + )} - - -
- {(month) => {month}} -
+ +
Lead TitleCustomerCategoryBudgetStatusDateAction
{row.service}{row.client}{row.service}{row.value}{row.status}{row.date} + +
-
-
- -
-
-
-

Recent Leads

-

Latest customer inquiries and opportunities

-
- -
- -
- - - - - - - - - - - - - - - {(row) => ( - - - - - - - - - - )} - - -
Lead TitleCustomerCategoryBudgetStatusPriorityAction
{row.title}{row.customer}{row.category}{row.budget}{row.status}{row.priority} - -
-
-
+ +
); diff --git a/src/routes/admin/internal-dashboard-management/index.tsx b/src/routes/admin/internal-dashboard-management/index.tsx index c5b7bdf..7542d74 100644 --- a/src/routes/admin/internal-dashboard-management/index.tsx +++ b/src/routes/admin/internal-dashboard-management/index.tsx @@ -414,71 +414,131 @@ export default function InternalDashboardManagementPage() { return (
-
-
-

Internal Dashboard Management

-

Open one internal dashboard at a time from the list below and edit it using simple tabs.

-
- Back to Dashboard -
-
- - - -
- +
-
+ {/* Header & Title */} +
-

Internal Dashboard List

-

Choose one internal dashboard to open in the builder, or create a new dashboard for an internal role.

+

Internal Dashboard Management

+

Configure dashboards for internal staff members

+
+
+ +
-
-
{error()}
-
-
- - - - - - - - - - - - - - - - - - - - {(d) => ( - - - - - - - - - )} - - -
RoleRole IDDashboardStatusVersionAction
Loading internal dashboards...
No internal dashboards found. Create the first one.
{d.roleName || 'Not linked'}{d.roleId || 'Not linked'}{d.title}{d.status}v{d.version} -
- -
-
+ + {/* 5 KPI Cards Row */} +
+
+

Total Dashboard
Templates

+

18

+
+
+

Active Templates

+

14

+
+
+

Draft Templates

+

2

+
+
+

Assigned Roles

+

9

+
+
+

Unassigned Roles

+

2

+
+
+ + {/* Main Table Section */} +
+
+ {/* Table Action Header */} +
+

Internal Dashboard
Templates

+
+ + + +
+
+ + {/* Error Message */} + +
{error()}
+
+ + {/* Filters Row */} +
+
+
+ + + +
+ +
+
+
+
+ + {/* Table */} +
+ + + + + + + + + + + + + + + + + + + + {(d) => ( + void openDashboard(d.id)}> + + + + + + + + )} + + +
DASHBOARD NAMEASSIGNED DEPARTMENTASSIGNED DESIGNATIONASSIGNED INTERNAL ROLEWIDGETS COUNTSTATUS
Loading templates...
No dashboard templates found.
{d.title}AdministrationSuper Admin{d.roleName || 'Unassigned'}{d.sections.length * 3 || 12} + + {d.status === 'published' ? 'Active' : 'Draft'} + +
+