141 lines
4.5 KiB
TypeScript
141 lines
4.5 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { useSession } from "next-auth/react"
|
|
import Link from "next/link"
|
|
import { ChineseCard, ChineseCardContent, ChineseCardHeader, ChineseCardTitle, ChineseCardDescription } from "@/components/ui/chinese-card"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Users, Calendar, Plus, ArrowRight } from "lucide-react"
|
|
import { format } from "date-fns"
|
|
import { zhCN } from "date-fns/locale"
|
|
|
|
interface FamilyTree {
|
|
id: string
|
|
name: string
|
|
description: string | null
|
|
createdAt: string
|
|
updatedAt: string
|
|
_count: {
|
|
members: number
|
|
collaborators: number
|
|
}
|
|
}
|
|
|
|
export function FamilyTreesList() {
|
|
const { data: session } = useSession()
|
|
const [trees, setTrees] = useState<FamilyTree[]>([])
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
if (session?.user?.id) {
|
|
fetch('/api/trees')
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
if (data.trees) {
|
|
setTrees(data.trees)
|
|
}
|
|
setLoading(false)
|
|
})
|
|
.catch(err => {
|
|
console.error('获取家族树失败:', err)
|
|
setLoading(false)
|
|
})
|
|
} else {
|
|
setLoading(false)
|
|
}
|
|
}, [session?.user?.id])
|
|
|
|
if (!session) {
|
|
return (
|
|
<ChineseCard variant="plaque" className="shadow-sm">
|
|
<ChineseCardHeader>
|
|
<ChineseCardTitle>我的家族树</ChineseCardTitle>
|
|
<ChineseCardDescription>请先登录查看您的家族树</ChineseCardDescription>
|
|
</ChineseCardHeader>
|
|
<ChineseCardContent>
|
|
<Link href="/auth/signin">
|
|
<Button>登录</Button>
|
|
</Link>
|
|
</ChineseCardContent>
|
|
</ChineseCard>
|
|
)
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<ChineseCard variant="plaque" className="shadow-sm">
|
|
<ChineseCardHeader>
|
|
<ChineseCardTitle>我的家族树</ChineseCardTitle>
|
|
</ChineseCardHeader>
|
|
<ChineseCardContent>
|
|
<p className="text-muted-foreground">加载中...</p>
|
|
</ChineseCardContent>
|
|
</ChineseCard>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ChineseCard variant="plaque" className="shadow-sm">
|
|
<ChineseCardHeader className="flex flex-row items-center justify-between">
|
|
<div>
|
|
<ChineseCardTitle>我的家族树</ChineseCardTitle>
|
|
<ChineseCardDescription>
|
|
{trees.length > 0 ? `共 ${trees.length} 个家族树` : '还没有家族树'}
|
|
</ChineseCardDescription>
|
|
</div>
|
|
<Link href="/trees/new">
|
|
<Button size="sm">
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
创建家族树
|
|
</Button>
|
|
</Link>
|
|
</ChineseCardHeader>
|
|
<ChineseCardContent>
|
|
{trees.length === 0 ? (
|
|
<div className="text-center py-8">
|
|
<p className="text-muted-foreground mb-4">您还没有创建任何家族树</p>
|
|
<Link href="/trees/new">
|
|
<Button>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
创建第一个家族树
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
) : (
|
|
<div className="space-y-4">
|
|
{trees.map((tree) => (
|
|
<div
|
|
key={tree.id}
|
|
className="flex items-center justify-between p-4 rounded-lg border bg-card/50 hover:bg-accent/50 transition-colors"
|
|
>
|
|
<div className="flex-1">
|
|
<h3 className="font-semibold text-lg">{tree.name}</h3>
|
|
{tree.description && (
|
|
<p className="text-sm text-muted-foreground mt-1">{tree.description}</p>
|
|
)}
|
|
<div className="flex items-center gap-4 mt-2 text-xs text-muted-foreground">
|
|
<span className="flex items-center gap-1">
|
|
<Users className="h-3 w-3" />
|
|
{tree._count.members} 个成员
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Calendar className="h-3 w-3" />
|
|
创建于 {format(new Date(tree.createdAt), 'yyyy年MM月dd日', { locale: zhCN })}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<Link href={`/tree?treeId=${tree.id}`}>
|
|
<Button variant="ghost" size="sm">
|
|
查看
|
|
<ArrowRight className="h-4 w-4 ml-2" />
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</ChineseCardContent>
|
|
</ChineseCard>
|
|
)
|
|
}
|