Merge remote high-performance: keep local AI management page and resolve conflicts
This commit is contained in:
commit
41b3bf3e1d
2 changed files with 84 additions and 0 deletions
|
|
@ -247,6 +247,12 @@ const GROUPS: NavItem[][] = [
|
|||
icon: CreditCard,
|
||||
moduleKeys: ["CREDIT_MANAGEMENT", "CREDITS"],
|
||||
},
|
||||
{
|
||||
href: "/admin/ai-management",
|
||||
label: "AI Management",
|
||||
icon: Sparkles,
|
||||
moduleKeys: ["AI_MANAGEMENT", "AI"],
|
||||
},
|
||||
{
|
||||
href: "/admin/coupon",
|
||||
label: "Coupon Management",
|
||||
|
|
|
|||
|
|
@ -95,6 +95,62 @@ const adapterMap: Record<string, () => Promise<WidgetDataResult<AdminWidgetPaylo
|
|||
kpi_credits_purchased: async () => ({ state: 'success', payload: { kind: 'kpi', data: kpiData.creditsPurchased } }),
|
||||
chart_leads_trend: async () => ({ state: 'success', payload: { kind: 'line_chart', data: lineChartData } }),
|
||||
chart_revenue_overview: async () => ({ state: 'success', payload: { kind: 'bar_chart', data: barChartData } }),
|
||||
kpi_ai_users: async () => {
|
||||
try {
|
||||
const token = typeof sessionStorage !== 'undefined'
|
||||
? sessionStorage.getItem('nxtgauge_admin_access_token') || ''
|
||||
: '';
|
||||
const res = await fetch('/api/admin/ai/stats', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
credentials: 'include',
|
||||
});
|
||||
if (!res.ok) throw new Error('Failed');
|
||||
const data = await res.json();
|
||||
return {
|
||||
state: 'success',
|
||||
payload: {
|
||||
kind: 'kpi',
|
||||
data: {
|
||||
value: String(data.total_users_with_ai ?? 0),
|
||||
delta: '',
|
||||
note: `${data.total_generations_today ?? 0} today`,
|
||||
tone: 'up' as const,
|
||||
icon: 'users' as const,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
return { state: 'error', message: 'Failed to load AI stats' };
|
||||
}
|
||||
},
|
||||
kpi_ai_generations_today: async () => {
|
||||
try {
|
||||
const token = typeof sessionStorage !== 'undefined'
|
||||
? sessionStorage.getItem('nxtgauge_admin_access_token') || ''
|
||||
: '';
|
||||
const res = await fetch('/api/admin/ai/stats', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
credentials: 'include',
|
||||
});
|
||||
if (!res.ok) throw new Error('Failed');
|
||||
const data = await res.json();
|
||||
return {
|
||||
state: 'success',
|
||||
payload: {
|
||||
kind: 'kpi',
|
||||
data: {
|
||||
value: String(data.total_generations_today ?? 0),
|
||||
delta: '',
|
||||
note: `${data.total_generations_month ?? 0} this month`,
|
||||
tone: 'up' as const,
|
||||
icon: 'trend' as const,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
return { state: 'error', message: 'Failed to load AI usage' };
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const ADMIN_DASHBOARD_WIDGETS: DashboardWidgetDefinition[] = [
|
||||
|
|
@ -180,6 +236,28 @@ export const ADMIN_DASHBOARD_WIDGETS: DashboardWidgetDefinition[] = [
|
|||
readiness: 'ready',
|
||||
description: 'Weekly revenue overview',
|
||||
},
|
||||
{
|
||||
widgetKey: 'kpi_ai_users',
|
||||
title: 'AI Users',
|
||||
moduleKey: 'AI_MANAGEMENT',
|
||||
defaultSize: 'S',
|
||||
defaultVisible: true,
|
||||
order: 9,
|
||||
dataAdapterKey: 'kpi_ai_users',
|
||||
readiness: 'ready',
|
||||
description: 'Total users with active AI plans',
|
||||
},
|
||||
{
|
||||
widgetKey: 'kpi_ai_generations_today',
|
||||
title: 'AI Generations Today',
|
||||
moduleKey: 'AI_MANAGEMENT',
|
||||
defaultSize: 'S',
|
||||
defaultVisible: true,
|
||||
order: 10,
|
||||
dataAdapterKey: 'kpi_ai_generations_today',
|
||||
readiness: 'ready',
|
||||
description: 'AI generations used today',
|
||||
},
|
||||
];
|
||||
|
||||
export function loadWidgetData(definition: DashboardWidgetDefinition): Promise<WidgetDataResult<AdminWidgetPayload>> {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue