0.0.1.0
This commit is contained in:
+53
-11
@@ -9,35 +9,72 @@ import { ScrollArea } from "@/components/ui/scroll-area"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { UserPlus, Network, Map, Calendar, Users, ArrowRight, Clock, Search, BookOpen, BarChart3 } from "lucide-react"
|
||||
import { useFamily } from "@/context/family-context"
|
||||
import { useMemo, useState, useEffect } from "react"
|
||||
import { useMemo, useState, useEffect, useRef } from "react"
|
||||
import { StatisticsCharts } from "@/components/dashboard/statistics-charts"
|
||||
import { getActivityLogs } from "@/lib/activity-logger"
|
||||
import type { ActivityLog } from "@/lib/db"
|
||||
import { format } from "date-fns"
|
||||
import { useSession } from "next-auth/react"
|
||||
import { useSearchParams } from "next/navigation"
|
||||
|
||||
interface ActivityLog {
|
||||
id: string
|
||||
action: string
|
||||
entityType: string
|
||||
entityId?: string | null
|
||||
entityName?: string | null
|
||||
timestamp: string
|
||||
user?: {
|
||||
name?: string | null
|
||||
email?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export default function DashboardPage() {
|
||||
const { treeData } = useFamily()
|
||||
const { treeData, currentTree, isLoading } = useFamily()
|
||||
const { data: session } = useSession()
|
||||
const [recentActivities, setRecentActivities] = useState<ActivityLog[]>([])
|
||||
|
||||
// 调试日志
|
||||
console.log('Dashboard - treeData:', treeData, 'currentTree:', currentTree?.name, 'isLoading:', isLoading)
|
||||
|
||||
// 加载最近的操作日志
|
||||
useEffect(() => {
|
||||
getActivityLogs(10).then(setRecentActivities)
|
||||
}, [treeData])
|
||||
if (currentTree?.id && session?.user?.id) {
|
||||
fetch(`/api/trees/${currentTree.id}/activity-logs?limit=10`)
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error('获取活动日志失败')
|
||||
}
|
||||
return res.json()
|
||||
})
|
||||
.then(data => {
|
||||
if (data.logs) {
|
||||
setRecentActivities(data.logs)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('获取活动日志失败:', err)
|
||||
setRecentActivities([])
|
||||
})
|
||||
} else {
|
||||
setRecentActivities([])
|
||||
}
|
||||
}, [currentTree?.id, session?.user?.id])
|
||||
|
||||
// 计算统计数据
|
||||
const stats = useMemo(() => {
|
||||
const members = Object.values(treeData.members)
|
||||
const totalMembers = members.length
|
||||
|
||||
// 计算最大代数
|
||||
const maxGeneration = Math.max(...members.map(m => m.generation || 0))
|
||||
// 计算最大代数(处理空数组的情况)
|
||||
const generations = members.map(m => m.generation || 0)
|
||||
const maxGeneration = generations.length > 0 ? Math.max(...generations) : 0
|
||||
|
||||
// 计算最早出生年份
|
||||
const birthYears = members
|
||||
.map(m => m.birthDate ? new Date(m.birthDate).getFullYear() : null)
|
||||
.filter(y => y !== null) as number[]
|
||||
const earliestYear = birthYears.length > 0 ? Math.min(...birthYears) : new Date().getFullYear()
|
||||
const yearsSpan = new Date().getFullYear() - earliestYear
|
||||
const yearsSpan = birthYears.length > 0 ? new Date().getFullYear() - earliestYear : 0
|
||||
|
||||
return {
|
||||
totalMembers,
|
||||
@@ -106,8 +143,13 @@ export default function DashboardPage() {
|
||||
<main className="flex-1 container mx-auto py-8 px-4 md:px-6">
|
||||
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4 mb-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-serif font-bold text-foreground">李氏家族族谱</h1>
|
||||
<p className="text-muted-foreground mt-1">陇西堂 · 第 24 代传人</p>
|
||||
<h1 className="text-3xl font-serif font-bold text-foreground">
|
||||
{currentTree?.name || '家族族谱'}
|
||||
</h1>
|
||||
<p className="text-muted-foreground mt-1">
|
||||
{currentTree?.description || '记录家族历史,传承家族文化'}
|
||||
{stats.maxGeneration > 0 && ` · 第 ${stats.maxGeneration} 代传人`}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Link href="/tree">
|
||||
|
||||
Reference in New Issue
Block a user