0.0.9.0
This commit is contained in:
+70
-38
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user