'use client'; import { useSearchParams } from 'next/navigation'; import { useState, useEffect, useCallback, Suspense } from 'react'; import PayPageLayout from '@/components/PayPageLayout'; import DashboardStats from '@/components/admin/DashboardStats'; import DailyChart from '@/components/admin/DailyChart'; import Leaderboard from '@/components/admin/Leaderboard'; import PaymentMethodChart from '@/components/admin/PaymentMethodChart'; import { resolveLocale } from '@/lib/locale'; interface DashboardData { summary: { today: { amount: number; orderCount: number; paidCount: number }; total: { amount: number; orderCount: number; paidCount: number }; successRate: number; avgAmount: number; }; dailySeries: { date: string; amount: number; count: number }[]; leaderboard: { userId: number; userName: string | null; userEmail: string | null; totalAmount: number; orderCount: number; }[]; paymentMethods: { paymentType: string; amount: number; count: number; percentage: number }[]; meta: { days: number; generatedAt: string }; } const DAYS_OPTIONS = [7, 30, 90] as const; function DashboardContent() { const searchParams = useSearchParams(); const token = searchParams.get('token'); const theme = searchParams.get('theme') === 'dark' ? 'dark' : 'light'; const uiMode = searchParams.get('ui_mode') || 'standalone'; const locale = resolveLocale(searchParams.get('lang')); const isDark = theme === 'dark'; const isEmbedded = uiMode === 'embedded'; const text = locale === 'en' ? { missingToken: 'Missing admin token', missingTokenHint: 'Please access the admin page from the Sub2API platform.', invalidToken: 'Invalid admin token', requestFailed: 'Request failed', loadFailed: 'Failed to load data', title: 'Dashboard', subtitle: 'Recharge order analytics and insights', daySuffix: 'd', orders: 'Order Management', refresh: 'Refresh', loading: 'Loading...', } : { missingToken: '缺少管理员凭证', missingTokenHint: '请从 Sub2API 平台正确访问管理页面', invalidToken: '管理员凭证无效', requestFailed: '请求失败', loadFailed: '加载数据失败', title: '数据概览', subtitle: '充值订单统计与分析', daySuffix: '天', orders: '订单管理', refresh: '刷新', loading: '加载中...', }; const [days, setDays] = useState(30); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const fetchData = useCallback(async () => { if (!token) return; setLoading(true); setError(''); try { const res = await fetch(`/api/admin/dashboard?token=${encodeURIComponent(token)}&days=${days}`); if (!res.ok) { if (res.status === 401) { setError(text.invalidToken); return; } throw new Error(text.requestFailed); } setData(await res.json()); } catch { setError(text.loadFailed); } finally { setLoading(false); } }, [token, days]); useEffect(() => { fetchData(); }, [fetchData]); if (!token) { return (

{text.missingToken}

{text.missingTokenHint}

); } const navParams = new URLSearchParams(); navParams.set('token', token); if (locale === 'en') navParams.set('lang', 'en'); if (theme === 'dark') navParams.set('theme', 'dark'); if (isEmbedded) navParams.set('ui_mode', 'embedded'); const btnBase = [ 'inline-flex items-center rounded-lg border px-3 py-1.5 text-xs font-medium transition-colors', isDark ? 'border-slate-600 text-slate-200 hover:bg-slate-800' : 'border-slate-300 text-slate-700 hover:bg-slate-100', ].join(' '); const btnActive = [ 'inline-flex items-center rounded-lg px-3 py-1.5 text-xs font-medium', isDark ? 'bg-indigo-500/30 text-indigo-200 ring-1 ring-indigo-400/40' : 'bg-blue-600 text-white', ].join(' '); return ( {DAYS_OPTIONS.map((d) => ( ))} {text.orders} } > {error && (
{error}
)} {loading ? (
{text.loading}
) : data ? (
) : null}
); } function DashboardPageFallback() { const searchParams = useSearchParams(); const locale = resolveLocale(searchParams.get('lang')); return (
{locale === 'en' ? 'Loading...' : '加载中...'}
); } export default function DashboardPage() { return ( }> ); }