From 87c38032363700c8a8189ee612499d3ff5abc278 Mon Sep 17 00:00:00 2001 From: William Tso Date: Tue, 1 Apr 2025 22:40:33 +0800 Subject: [PATCH] add filter --- app/(app)/dashboard/page.tsx | 376 ++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 139 deletions(-) diff --git a/app/(app)/dashboard/page.tsx b/app/(app)/dashboard/page.tsx index 50f73e9..c97c2de 100644 --- a/app/(app)/dashboard/page.tsx +++ b/app/(app)/dashboard/page.tsx @@ -8,6 +8,8 @@ import GeoAnalytics from '@/app/components/analytics/GeoAnalytics'; import DevicePieCharts from '@/app/components/charts/DevicePieCharts'; import { EventsSummary, TimeSeriesData, GeoData, DeviceAnalytics as DeviceAnalyticsType } from '@/app/api/types'; import { TeamSelector } from '@/app/components/ui/TeamSelector'; +import { ProjectSelector } from '@/app/components/ui/ProjectSelector'; +import { TagSelector } from '@/app/components/ui/TagSelector'; // 事件类型定义 interface Event { @@ -102,6 +104,11 @@ export default function DashboardPage() { // 添加团队选择状态 - 使用数组支持多选 const [selectedTeamIds, setSelectedTeamIds] = useState([]); + // 添加项目选择状态 - 使用数组支持多选 + const [selectedProjectIds, setSelectedProjectIds] = useState([]); + // 添加标签选择状态 - 使用数组支持多选 + const [selectedTagIds, setSelectedTagIds] = useState([]); + const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [summary, setSummary] = useState(null); @@ -132,6 +139,20 @@ export default function DashboardPage() { params.append('teamId', teamId); }); } + + // 添加项目ID参数 - 支持多个项目 + if (selectedProjectIds.length > 0) { + selectedProjectIds.forEach(projectId => { + params.append('projectId', projectId); + }); + } + + // 添加标签ID参数 - 支持多个标签 + if (selectedTagIds.length > 0) { + selectedTagIds.forEach(tagId => { + params.append('tagId', tagId); + }); + } // 并行获取所有数据 const [summaryRes, timeSeriesRes, geoRes, deviceRes, eventsRes] = await Promise.all([ @@ -169,7 +190,7 @@ export default function DashboardPage() { }; fetchData(); - }, [dateRange, selectedTeamIds]); + }, [dateRange, selectedTeamIds, selectedProjectIds, selectedTagIds]); if (loading) { return ( @@ -191,13 +212,27 @@ export default function DashboardPage() {

Analytics Dashboard

-
+
setSelectedTeamIds(Array.isArray(value) ? value : [value])} className="w-[250px]" multiple={true} /> + setSelectedProjectIds(Array.isArray(value) ? value : [value])} + className="w-[250px]" + multiple={true} + teamId={selectedTeamIds.length === 1 ? selectedTeamIds[0] : undefined} + /> + setSelectedTagIds(Array.isArray(value) ? value : [value])} + className="w-[250px]" + multiple={true} + teamId={selectedTeamIds.length === 1 ? selectedTeamIds[0] : undefined} + /> )} - {summary && ( -
-
-

Total Events

-

- {typeof summary.totalEvents === 'number' ? summary.totalEvents.toLocaleString() : summary.totalEvents} -

-
-
-

Unique Visitors

-

- {typeof summary.uniqueVisitors === 'number' ? summary.uniqueVisitors.toLocaleString() : summary.uniqueVisitors} -

-
-
-

Total Conversions

-

- {typeof summary.totalConversions === 'number' ? summary.totalConversions.toLocaleString() : summary.totalConversions} -

-
-
-

Avg. Time Spent

-

- {summary.averageTimeSpent?.toFixed(1) || '0'}s -

+ {/* 显示项目选择信息 */} + {selectedProjectIds.length > 0 && ( +
+ + {selectedProjectIds.length === 1 ? 'Project filter:' : 'Projects filter:'} + +
+ {selectedProjectIds.map(projectId => ( + + {projectId} + + + ))} + {selectedProjectIds.length > 0 && ( + + )}
)} -
-

Event Trends

-
- + {/* 显示标签选择信息 */} + {selectedTagIds.length > 0 && ( +
+ + {selectedTagIds.length === 1 ? 'Tag filter:' : 'Tags filter:'} + +
+ {selectedTagIds.map(tagId => ( + + {tagId} + + + ))} + {selectedTagIds.length > 0 && ( + + )} +
-
+ )} -
-

Device Analytics

- {deviceData && } -
- -
-

Geographic Distribution

- -
- - {/* 事件列表部分 */} -
-
-

Recent Events

-
- -
- - - - - - - - - - - - - - {events.map((event, index) => { - const info = extractEventInfo(event); - return ( - - - - - - - - - - ); - })} - -
- Time - - Link Name - - Original URL - - Event Type - - User - - Team/Project - - Device Info -
- {formatDate(info.eventTime)} - - {info.linkName} -
- ID: {event.link_id?.substring(0, 8) || '-'} -
-
- - {info.originalUrl} - - - - {info.eventType} - - -
{info.userInfo}
-
{info.visitorId}...
-
-
{info.teamName}
-
{info.projectName}
-
-
- - Device: - {info.device} - - - Browser: - {info.browser} - - - OS: - {info.os} - -
-
-
- - {/* 表格为空状态 */} - {!loading && events.length === 0 && ( -
- No events found + {/* 仪表板内容 */} + <> + {summary && ( +
+
+

Total Events

+

+ {typeof summary.totalEvents === 'number' ? summary.totalEvents.toLocaleString() : summary.totalEvents} +

+
+
+

Unique Visitors

+

+ {typeof summary.uniqueVisitors === 'number' ? summary.uniqueVisitors.toLocaleString() : summary.uniqueVisitors} +

+
+
+

Total Conversions

+

+ {typeof summary.totalConversions === 'number' ? summary.totalConversions.toLocaleString() : summary.totalConversions} +

+
+
+

Avg. Time Spent

+

+ {summary.averageTimeSpent?.toFixed(1) || '0'}s +

+
)} -
+ +
+

Event Trends

+
+ +
+
+ +
+

Device Analytics

+ {deviceData && } +
+ +
+

Geographic Distribution

+ +
+ + {/* 事件列表部分 */} +
+
+

Recent Events

+
+ +
+ + + + + + + + + + + + + + {events.map((event, index) => { + const info = extractEventInfo(event); + return ( + + + + + + + + + + ); + })} + +
+ Time + + Link Name + + Original URL + + Event Type + + User + + Team/Project + + Device Info +
+ {formatDate(info.eventTime)} + + {info.linkName} +
+ ID: {event.link_id?.substring(0, 8) || '-'} +
+
+ + {info.originalUrl} + + + + {info.eventType} + + +
{info.userInfo}
+
{info.visitorId}...
+
+
{info.teamName}
+
{info.projectName}
+
+
+ + Device: + {info.device} + + + Browser: + {info.browser} + + + OS: + {info.os} + +
+
+
+ + {/* 表格为空状态 */} + {!loading && events.length === 0 && ( +
+ No events found +
+ )} +
+
); } \ No newline at end of file