This commit is contained in:
freedakgmail
2025-11-24 16:07:24 +08:00
parent 3d075c6076
commit b25f4bea02
426 changed files with 3619 additions and 4468 deletions
+70 -38
View File
@@ -1,6 +1,6 @@
"use client"
import { useState } from 'react'
import { useState, useEffect } from 'react'
import { SiteHeader } from '@/components/site-header'
import { useFamily } from '@/context/family-context'
import { useRelationship } from '@/hooks/use-relationship'
@@ -9,14 +9,19 @@ import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command'
import { Check, ChevronsUpDown } from 'lucide-react'
import { Check, ChevronsUpDown, Users, User } from 'lucide-react'
import { cn } from '@/lib/utils'
import { MemberNameWithStatus } from '@/components/member-name-with-status'
import { RelationshipPathDisplay } from '@/components/relationship-path-display'
import { useSession } from 'next-auth/react'
import { EmptyStateBadge } from '@/components/empty-state-badge'
import { useRouter } from 'next/navigation'
export default function RelationshipTestPage() {
const { treeData } = useFamily()
const { calculateRelationship, getDirectRelatives, getSiblings } = useRelationship()
const { data: session, status } = useSession()
const router = useRouter()
const [fromId, setFromId] = useState<string>('')
const [toId, setToId] = useState<string>('')
@@ -24,6 +29,13 @@ export default function RelationshipTestPage() {
const [openFromCombobox, setOpenFromCombobox] = useState(false)
const [openToCombobox, setOpenToCombobox] = useState(false)
// 未登录时重定向到登录页
useEffect(() => {
if (status === 'unauthenticated') {
router.push('/auth/signin')
}
}, [status, router])
const members = Object.values(treeData.members)
const handleCalculate = () => {
@@ -40,28 +52,48 @@ export default function RelationshipTestPage() {
})
}
// 未登录时不渲染内容(已在 useEffect 中重定向)
if (status === 'loading' || !session) {
return null
}
// 无数据时显示空状态
if (members.length === 0) {
return (
<div className="min-h-screen flex flex-col bg-background">
<SiteHeader />
<main className="flex-1 flex items-center justify-center">
<EmptyStateBadge
icon={!session ? User : Users}
text={!session ? '请先登录' : '暂无成员'}
/>
</main>
</div>
)
}
return (
<div className="min-h-screen flex flex-col bg-background">
<SiteHeader />
<main className="flex-1 container mx-auto px-4 py-12">
<div className="max-w-4xl mx-auto space-y-8">
<main className="flex-1 container mx-auto px-4 py-6">
<div className="max-w-4xl mx-auto space-y-6">
{/* 标题 */}
<div>
<h1 className="text-3xl font-serif font-bold mb-2"></h1>
<p className="text-muted-foreground">
<h1 className="text-2xl font-serif font-bold mb-1"></h1>
<p className="text-sm text-muted-foreground">
</p>
</div>
{/* 选择成员 */}
<Card className="border-none shadow-sm bg-card/50 backdrop-blur">
<CardHeader className="text-center">
<CardTitle className="text-2xl font-serif font-light"></CardTitle>
<CardDescription className="font-light"></CardDescription>
<CardHeader className="text-center pb-4">
<CardTitle className="text-xl font-serif font-light"></CardTitle>
<CardDescription className="text-sm font-light"></CardDescription>
</CardHeader>
<CardContent className="space-y-8">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<label className="text-sm font-medium">A</label>
<Popover open={openFromCombobox} onOpenChange={setOpenFromCombobox}>
@@ -182,7 +214,7 @@ export default function RelationshipTestPage() {
<Button
onClick={handleCalculate}
disabled={!fromId || !toId}
className="w-full h-12 bg-primary text-primary-foreground hover:bg-primary/90"
className="w-full h-10 bg-primary text-primary-foreground hover:bg-primary/90"
>
</Button>
@@ -192,13 +224,13 @@ export default function RelationshipTestPage() {
{/* 计算结果 */}
{result && (
<Card className="border-none shadow-sm bg-card/50 backdrop-blur">
<CardHeader className="text-center">
<CardTitle className="text-2xl font-serif font-light"></CardTitle>
<CardHeader className="text-center pb-4">
<CardTitle className="text-xl font-serif font-light"></CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-center gap-6 p-8 bg-muted/30 rounded-lg">
<CardContent className="space-y-3">
<div className="flex items-center justify-center gap-4 p-5 bg-muted/30 rounded-lg">
<div className="text-center">
<div className="text-2xl font-serif font-light mb-1">
<div className="text-xl font-serif font-light mb-1">
<MemberNameWithStatus
name={result.from.fullName}
isDead={!!result.from.deathDate}
@@ -209,8 +241,8 @@ export default function RelationshipTestPage() {
</div>
</div>
<div className="flex flex-col items-center gap-2">
<Badge className="text-lg px-6 py-2 bg-primary text-primary-foreground">
<div className="flex flex-col items-center gap-1.5">
<Badge className="text-base px-5 py-1.5 bg-primary text-primary-foreground">
{result.relationship.term}
</Badge>
{result.relationship.path && (
@@ -222,7 +254,7 @@ export default function RelationshipTestPage() {
</div>
<div className="text-center">
<div className="text-2xl font-serif font-light mb-1">
<div className="text-xl font-serif font-light mb-1">
<MemberNameWithStatus
name={result.to.fullName}
isDead={!!result.to.deathDate}
@@ -235,7 +267,7 @@ export default function RelationshipTestPage() {
</div>
{result.relationship.description && (
<div className="p-6 bg-primary/5 rounded-lg">
<div className="p-4 bg-primary/5 rounded-lg">
<div className="text-sm font-light mb-2 text-center"></div>
<div className="text-muted-foreground font-light text-center">
<strong><MemberNameWithStatus name={result.from.fullName} isDead={!!result.from.deathDate} /></strong> <strong><MemberNameWithStatus name={result.to.fullName} isDead={!!result.to.deathDate} /></strong> <strong className="text-primary">{result.relationship.term}</strong>
@@ -256,11 +288,11 @@ export default function RelationshipTestPage() {
{/* 直系亲属信息 */}
{(fromId || toId) && (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{fromId && (
<Card className="border-none shadow-sm bg-card/50 backdrop-blur">
<CardHeader>
<CardTitle className="text-xl font-serif font-light">
<CardHeader className="pb-3">
<CardTitle className="text-lg font-serif font-light">
<MemberNameWithStatus
name={treeData.members[fromId]?.fullName || ''}
isDead={!!treeData.members[fromId]?.deathDate}
@@ -274,9 +306,9 @@ export default function RelationshipTestPage() {
return (
<>
<div className="grid grid-cols-1 gap-3">
<div className="grid grid-cols-1 gap-2">
{relatives.father && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
<div className="font-medium">
<MemberNameWithStatus
@@ -287,7 +319,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.mother && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
<div className="font-medium">
<MemberNameWithStatus
@@ -298,7 +330,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.spouses.length > 0 && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
{relatives.spouses.map((spouse: any) => (
<div key={spouse.id} className="font-medium">
@@ -311,7 +343,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.children.length > 0 && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1">
({relatives.children.length})
</div>
@@ -339,7 +371,7 @@ export default function RelationshipTestPage() {
if (siblings.length === 0) return null
return (
<div className="mt-3 p-3 bg-muted rounded-lg">
<div className="mt-2 p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-2">
({siblings.length})
</div>
@@ -365,8 +397,8 @@ export default function RelationshipTestPage() {
{toId && (
<Card className="border-none shadow-sm bg-card/50 backdrop-blur">
<CardHeader>
<CardTitle className="text-xl font-serif font-light">
<CardHeader className="pb-3">
<CardTitle className="text-lg font-serif font-light">
{treeData.members[toId]?.fullName}
</CardTitle>
</CardHeader>
@@ -377,9 +409,9 @@ export default function RelationshipTestPage() {
return (
<>
<div className="grid grid-cols-1 gap-3">
<div className="grid grid-cols-1 gap-2">
{relatives.father && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
<div className="font-medium">
<MemberNameWithStatus
@@ -390,7 +422,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.mother && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
<div className="font-medium">
<MemberNameWithStatus
@@ -401,7 +433,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.spouses.length > 0 && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1"></div>
{relatives.spouses.map((spouse: any) => (
<div key={spouse.id} className="font-medium">
@@ -414,7 +446,7 @@ export default function RelationshipTestPage() {
</div>
)}
{relatives.children.length > 0 && (
<div className="p-3 bg-muted rounded-lg">
<div className="p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-1">
({relatives.children.length})
</div>
@@ -442,7 +474,7 @@ export default function RelationshipTestPage() {
if (siblings.length === 0) return null
return (
<div className="mt-3 p-3 bg-muted rounded-lg">
<div className="mt-2 p-2.5 bg-muted rounded-lg">
<div className="text-sm text-muted-foreground mb-2">
({siblings.length})
</div>