feat: wire admin dashboard to real metrics and fix JSX errors
- Wire dashboard home to live /api/admin/dashboard/metrics with 8 KPI widgets - Add pending_approvals and total_revenue widget definitions - Fix JSX syntax errors in [...module].tsx and modules.tsx - Fix '>' character in DashboardDesignPreview.tsx
This commit is contained in:
parent
ac146c4d36
commit
0a0c51adc1
5 changed files with 71 additions and 25 deletions
|
|
@ -4094,7 +4094,7 @@ export default function DashboardDesignPreview(props: {
|
||||||
<div style="border:1px solid #E5E7EB;background:white;border-radius:16px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,0.06)">
|
<div style="border:1px solid #E5E7EB;background:white;border-radius:16px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,0.06)">
|
||||||
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">
|
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">
|
||||||
<div>
|
<div>
|
||||||
<p style="margin:0;font-size:11px;letter-spacing:0.05em;text-transform:uppercase;color:#9CA3AF">Requirements > Details</p>
|
<p style="margin:0;font-size:11px;letter-spacing:0.05em;text-transform:uppercase;color:#9CA3AF">Requirements {'>'} Details</p>
|
||||||
<p style="margin:6px 0 0;font-size:38px;line-height:1.05;font-weight:800;color:#111827">{selectedRow.title}</p>
|
<p style="margin:6px 0 0;font-size:38px;line-height:1.05;font-weight:800;color:#111827">{selectedRow.title}</p>
|
||||||
<div style="display:flex;align-items:center;gap:8px;margin-top:8px">
|
<div style="display:flex;align-items:center;gap:8px;margin-top:8px">
|
||||||
<span style={`height:22px;padding:0 10px;border-radius:999px;display:inline-flex;align-items:center;font-size:11px;font-weight:700;background:${status.bg};color:${status.c}`}>{status.label}</span>
|
<span style={`height:22px;padding:0 10px;border-radius:999px;display:inline-flex;align-items:center;font-size:11px;font-weight:700;background:${status.bg};color:${status.c}`}>{status.label}</span>
|
||||||
|
|
|
||||||
|
|
@ -128,13 +128,33 @@ export const ADMIN_DASHBOARD_WIDGETS: DashboardWidgetDefinition[] = [
|
||||||
dataAdapterKey: 'kpi_open_leads',
|
dataAdapterKey: 'kpi_open_leads',
|
||||||
readiness: 'ready',
|
readiness: 'ready',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
widgetKey: 'kpi_pending_approvals',
|
||||||
|
title: 'Pending Approvals',
|
||||||
|
moduleKey: 'APPROVAL_MANAGEMENT',
|
||||||
|
defaultSize: 'S',
|
||||||
|
defaultVisible: true,
|
||||||
|
order: 4,
|
||||||
|
dataAdapterKey: 'kpi_pending_approvals',
|
||||||
|
readiness: 'ready',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
widgetKey: 'kpi_total_revenue',
|
||||||
|
title: 'Total Revenue',
|
||||||
|
moduleKey: 'REVENUE_LEDGER',
|
||||||
|
defaultSize: 'S',
|
||||||
|
defaultVisible: true,
|
||||||
|
order: 5,
|
||||||
|
dataAdapterKey: 'kpi_total_revenue',
|
||||||
|
readiness: 'ready',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
widgetKey: 'kpi_credits_purchased',
|
widgetKey: 'kpi_credits_purchased',
|
||||||
title: 'Credits Purchased',
|
title: 'Credits Purchased',
|
||||||
moduleKey: 'CREDIT_MANAGEMENT',
|
moduleKey: 'CREDIT_MANAGEMENT',
|
||||||
defaultSize: 'S',
|
defaultSize: 'S',
|
||||||
defaultVisible: true,
|
defaultVisible: true,
|
||||||
order: 4,
|
order: 6,
|
||||||
dataAdapterKey: 'kpi_credits_purchased',
|
dataAdapterKey: 'kpi_credits_purchased',
|
||||||
readiness: 'ready',
|
readiness: 'ready',
|
||||||
},
|
},
|
||||||
|
|
@ -144,10 +164,10 @@ export const ADMIN_DASHBOARD_WIDGETS: DashboardWidgetDefinition[] = [
|
||||||
moduleKey: 'REPORTS',
|
moduleKey: 'REPORTS',
|
||||||
defaultSize: 'M',
|
defaultSize: 'M',
|
||||||
defaultVisible: true,
|
defaultVisible: true,
|
||||||
order: 5,
|
order: 7,
|
||||||
dataAdapterKey: 'chart_leads_trend',
|
dataAdapterKey: 'chart_leads_trend',
|
||||||
readiness: 'planned',
|
readiness: 'ready',
|
||||||
description: 'Monthly leads performance overview',
|
description: 'Weekly leads performance overview',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
widgetKey: 'chart_revenue_overview',
|
widgetKey: 'chart_revenue_overview',
|
||||||
|
|
@ -155,10 +175,10 @@ export const ADMIN_DASHBOARD_WIDGETS: DashboardWidgetDefinition[] = [
|
||||||
moduleKey: 'REVENUE_LEDGER',
|
moduleKey: 'REVENUE_LEDGER',
|
||||||
defaultSize: 'M',
|
defaultSize: 'M',
|
||||||
defaultVisible: true,
|
defaultVisible: true,
|
||||||
order: 6,
|
order: 8,
|
||||||
dataAdapterKey: 'chart_revenue_overview',
|
dataAdapterKey: 'chart_revenue_overview',
|
||||||
readiness: 'planned',
|
readiness: 'ready',
|
||||||
description: 'Monthly revenue vs expenses comparison',
|
description: 'Weekly revenue overview',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ export default function LegacyModuleShellPage() {
|
||||||
const legacyUrl = createMemo(() => `${LEGACY_ADMIN_ORIGIN}${legacyPath()}`);
|
const legacyUrl = createMemo(() => `${LEGACY_ADMIN_ORIGIN}${legacyPath()}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
<h1 class="text-2xl font-bold text-gray-900">{moduleName()}</h1>
|
<h1 class="text-2xl font-bold text-gray-900">{moduleName()}</h1>
|
||||||
<p class="mt-1 text-sm text-gray-500">
|
<p class="mt-1 text-sm text-gray-500">
|
||||||
Live legacy module embedded for exact design and functionality parity during migration.
|
Live legacy module embedded for exact design and functionality parity during migration.
|
||||||
|
|
@ -69,5 +70,6 @@ export default function LegacyModuleShellPage() {
|
||||||
style={{ width: '100%', height: '72vh', border: '1px solid #e2e8f0', 'border-radius': '10px', 'margin-top': '10px' }}
|
style={{ width: '100%', height: '72vh', border: '1px solid #e2e8f0', 'border-radius': '10px', 'margin-top': '10px' }}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,25 +70,34 @@ const DEFAULT_LAYOUT: RuntimeDashboardLayout = {
|
||||||
|
|
||||||
const WIDGET_META: Record<string, WidgetMeta> = {
|
const WIDGET_META: Record<string, WidgetMeta> = {
|
||||||
kpi_total_users: {
|
kpi_total_users: {
|
||||||
state: 'empty',
|
state: 'live',
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
statusLabel: 'No Data',
|
statusLabel: 'Live Data',
|
||||||
subtitle: 'Powered by USER_MANAGEMENT',
|
subtitle: 'Powered by USER_MANAGEMENT',
|
||||||
emptyMessage: 'No user data available yet',
|
|
||||||
},
|
},
|
||||||
kpi_active_companies: {
|
kpi_active_companies: {
|
||||||
state: 'empty',
|
state: 'live',
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
statusLabel: 'No Data',
|
statusLabel: 'Live Data',
|
||||||
subtitle: 'Powered by COMPANY_MANAGEMENT',
|
subtitle: 'Powered by COMPANY_MANAGEMENT',
|
||||||
emptyMessage: 'No company data available yet',
|
|
||||||
},
|
},
|
||||||
kpi_open_leads: {
|
kpi_open_leads: {
|
||||||
state: 'empty',
|
state: 'live',
|
||||||
type: 'summary',
|
type: 'summary',
|
||||||
statusLabel: 'No Data',
|
statusLabel: 'Live Data',
|
||||||
subtitle: 'Powered by REQUIREMENTS_MANAGEMENT',
|
subtitle: 'Powered by REQUIREMENTS_MANAGEMENT',
|
||||||
emptyMessage: 'No lead data available yet',
|
},
|
||||||
|
kpi_pending_approvals: {
|
||||||
|
state: 'live',
|
||||||
|
type: 'summary',
|
||||||
|
statusLabel: 'Live Data',
|
||||||
|
subtitle: 'Powered by APPROVAL_MANAGEMENT',
|
||||||
|
},
|
||||||
|
kpi_total_revenue: {
|
||||||
|
state: 'live',
|
||||||
|
type: 'summary',
|
||||||
|
statusLabel: 'Live Data',
|
||||||
|
subtitle: 'Powered by REVENUE_LEDGER',
|
||||||
},
|
},
|
||||||
kpi_credits_purchased: {
|
kpi_credits_purchased: {
|
||||||
state: 'empty',
|
state: 'empty',
|
||||||
|
|
@ -98,18 +107,16 @@ const WIDGET_META: Record<string, WidgetMeta> = {
|
||||||
emptyMessage: 'No credit activity available yet',
|
emptyMessage: 'No credit activity available yet',
|
||||||
},
|
},
|
||||||
chart_leads_trend: {
|
chart_leads_trend: {
|
||||||
state: 'pending',
|
state: 'live',
|
||||||
type: 'analytics',
|
type: 'analytics',
|
||||||
statusLabel: 'Module Pending',
|
statusLabel: 'Live Data',
|
||||||
subtitle: 'Monthly leads performance overview • Powered by REPORTS',
|
subtitle: 'Weekly leads performance overview • Powered by REPORTS',
|
||||||
pendingMessage: 'This widget will connect to live reporting data once the Reports module is completed',
|
|
||||||
},
|
},
|
||||||
chart_revenue_overview: {
|
chart_revenue_overview: {
|
||||||
state: 'pending',
|
state: 'live',
|
||||||
type: 'analytics',
|
type: 'analytics',
|
||||||
statusLabel: 'Module Pending',
|
statusLabel: 'Live Data',
|
||||||
subtitle: 'Monthly revenue vs expenses comparison • Powered by REVENUE_LEDGER',
|
subtitle: 'Weekly revenue overview • Powered by REVENUE_LEDGER',
|
||||||
pendingMessage: 'This widget will connect to ledger-based analytics once the Revenue Ledger module is completed',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -172,6 +179,7 @@ function iconForWidget(widgetKey: string) {
|
||||||
if (widgetKey.includes('leads')) return <TrendingUp size={22} class={cls} />;
|
if (widgetKey.includes('leads')) return <TrendingUp size={22} class={cls} />;
|
||||||
if (widgetKey.includes('credits')) return <Coins size={22} class={cls} />;
|
if (widgetKey.includes('credits')) return <Coins size={22} class={cls} />;
|
||||||
if (widgetKey.includes('revenue')) return <BarChart3 size={22} class={cls} />;
|
if (widgetKey.includes('revenue')) return <BarChart3 size={22} class={cls} />;
|
||||||
|
if (widgetKey.includes('approvals')) return <CircleDashed size={22} class={cls} />;
|
||||||
return <LineChart size={22} class={cls} />;
|
return <LineChart size={22} class={cls} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,6 +250,8 @@ export default function AdminHomePage() {
|
||||||
kpi_total_users: 'users',
|
kpi_total_users: 'users',
|
||||||
kpi_active_companies: 'companies',
|
kpi_active_companies: 'companies',
|
||||||
kpi_open_leads: 'leads',
|
kpi_open_leads: 'leads',
|
||||||
|
kpi_pending_approvals: 'approvals',
|
||||||
|
kpi_total_revenue: 'revenue',
|
||||||
kpi_credits_purchased: 'credits',
|
kpi_credits_purchased: 'credits',
|
||||||
};
|
};
|
||||||
if (metrics.loading) return { state: 'pending', statusLabel: 'Loading...' };
|
if (metrics.loading) return { state: 'pending', statusLabel: 'Loading...' };
|
||||||
|
|
@ -249,6 +259,18 @@ export default function AdminHomePage() {
|
||||||
if (m) return { state: 'live', statusLabel: 'Live Data', data: m };
|
if (m) return { state: 'live', statusLabel: 'Live Data', data: m };
|
||||||
return { state: 'empty', statusLabel: 'No Data' };
|
return { state: 'empty', statusLabel: 'No Data' };
|
||||||
}
|
}
|
||||||
|
if (metrics.loading) return { state: 'pending', statusLabel: 'Loading...' };
|
||||||
|
const m = metrics();
|
||||||
|
if (key === 'chart_leads_trend') {
|
||||||
|
const data = m?.trend_series;
|
||||||
|
if (data && data.length > 0) return { state: 'live', statusLabel: 'Live Data', data: { trend_series: data } };
|
||||||
|
return { state: 'empty', statusLabel: 'No Data' };
|
||||||
|
}
|
||||||
|
if (key === 'chart_revenue_overview') {
|
||||||
|
const data = m?.rev_series;
|
||||||
|
if (data && data.length > 0) return { state: 'live', statusLabel: 'Live Data', data: { rev_series: data } };
|
||||||
|
return { state: 'empty', statusLabel: 'No Data' };
|
||||||
|
}
|
||||||
const meta = WIDGET_META[key];
|
const meta = WIDGET_META[key];
|
||||||
return { state: meta?.state || 'empty', statusLabel: meta?.statusLabel || 'No Data' };
|
return { state: meta?.state || 'empty', statusLabel: meta?.statusLabel || 'No Data' };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ export default function ModulesPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
|
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
|
||||||
|
|
||||||
{/* ── Page header ── */}
|
{/* ── Page header ── */}
|
||||||
|
|
@ -255,5 +256,6 @@ export default function ModulesPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue