"use client"; import { useState, useEffect } from 'react'; import { format } from 'date-fns'; import { DateRangePicker } from '@/app/components/ui/DateRangePicker'; import TimeSeriesChart from '@/app/components/charts/TimeSeriesChart'; import GeoAnalytics from '@/app/components/analytics/GeoAnalytics'; import DeviceAnalytics from '@/app/components/analytics/DeviceAnalytics'; import { EventsSummary, TimeSeriesData, GeoData, DeviceAnalytics as DeviceAnalyticsType } from '@/app/api/types'; export default function DashboardPage() { const [dateRange, setDateRange] = useState({ from: new Date('2024-02-01'), to: new Date('2025-03-05') }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [summary, setSummary] = useState(null); const [timeSeriesData, setTimeSeriesData] = useState([]); const [geoData, setGeoData] = useState([]); const [deviceData, setDeviceData] = useState(null); // 获取统计数据 const fetchSummary = async () => { try { const startTime = format(dateRange.from, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const endTime = format(dateRange.to, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const response = await fetch( `/api/events/summary?startTime=${startTime}&endTime=${endTime}` ); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch summary'); } if (data.success && data.data) { console.log('Summary data:', data.data); // 添加日志 setSummary(data.data); } } catch (err) { console.error('Error fetching summary:', err); setError(err instanceof Error ? err.message : 'Failed to load summary'); } }; // 获取时间序列数据 const fetchTimeSeriesData = async () => { try { const startTime = format(dateRange.from, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const endTime = format(dateRange.to, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const response = await fetch( `/api/events/time-series?startTime=${startTime}&endTime=${endTime}&granularity=day` ); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch time series data'); } if (data.success && Array.isArray(data.data)) { setTimeSeriesData(data.data); } } catch (err) { console.error('Error fetching time series:', err); } }; // 获取地理位置数据 const fetchGeoData = async () => { try { const startTime = format(dateRange.from, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const endTime = format(dateRange.to, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const response = await fetch( `/api/events/geo?startTime=${startTime}&endTime=${endTime}` ); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch geo data'); } if (data.success && Array.isArray(data.data)) { setGeoData(data.data); } } catch (err) { console.error('Error fetching geo data:', err); } }; // 获取设备数据 const fetchDeviceData = async () => { try { const startTime = format(dateRange.from, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const endTime = format(dateRange.to, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const response = await fetch( `/api/events/devices?startTime=${startTime}&endTime=${endTime}` ); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch device data'); } if (data.success && data.data) { setDeviceData(data.data); } } catch (err) { console.error('Error fetching device data:', err); } }; // 加载所有数据 const loadAllData = async () => { setLoading(true); await Promise.all([ fetchSummary(), fetchTimeSeriesData(), fetchGeoData(), fetchDeviceData() ]); setLoading(false); }; // 当日期范围改变时重新加载数据 useEffect(() => { loadAllData(); }, [dateRange]); if (error) { return (
{error}
); } return (

Analytics Dashboard

Total Events

{loading ? ( Loading... ) : ( summary?.totalEvents?.toLocaleString() || '0' )}

Unique Visitors

{loading ? ( Loading... ) : ( summary?.uniqueVisitors?.toLocaleString() || '0' )}

Total Conversions

{loading ? ( Loading... ) : ( summary?.totalConversions?.toLocaleString() || '0' )}

Avg. Time Spent

{loading ? ( Loading... ) : ( `${summary?.averageTimeSpent?.toFixed(1) || '0'}s` )}

Event Trends

{loading ? (
Loading...
) : ( )}

Device Analytics

{loading ? (
Loading...
) : ( deviceData && )}

Geographic Distribution

{loading ? (
Loading...
) : ( )}
); }