"use client" import { useMemo, useState, useEffect } from "react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { Label } from "@/components/ui/label" import { ScrollArea } from "@/components/ui/scroll-area" import { MemberNameWithStatus } from "@/components/member-name-with-status" import { useFamily } from "@/context/family-context" import { useToast } from "@/components/ui/use-toast" import type { FamilyMember } from "@/types/family" interface AddRelationDialogProps { open: boolean onOpenChange: (open: boolean) => void member: FamilyMember relationType: "child" | "spouse" onCreateNew: (prefillName: string, relationType: "child" | "spouse") => void } interface CandidateMeta { member: FamilyMember fatherName?: string motherName?: string } export function AddRelationDialog({ open, onOpenChange, member, relationType, onCreateNew, }: AddRelationDialogProps) { const { treeData, updateMember } = useFamily() const { toast } = useToast() const [query, setQuery] = useState("") const [linkingId, setLinkingId] = useState(null) useEffect(() => { if (!open) { setQuery("") setLinkingId(null) } }, [open]) const normalizedQuery = query.trim().toLowerCase() const candidates: CandidateMeta[] = useMemo(() => { if (!normalizedQuery) return [] const members = Object.values(treeData.members) return members .filter((candidate) => { if (candidate.id === member.id) return false if (!candidate.fullName.toLowerCase().includes(normalizedQuery) && !(candidate.givenName || "").toLowerCase().includes(normalizedQuery) && !(candidate.courtesyName || "").toLowerCase().includes(normalizedQuery)) { return false } if (relationType === "child") { if (candidate.generation !== (member.generation + 1)) return false if (member.childrenIds?.includes(candidate.id)) return false if (member.spouseIds?.includes(candidate.id)) return false const fatherMatches = candidate.fatherId ? candidate.fatherId === member.id : true const motherMatches = candidate.motherId ? candidate.motherId === member.id : true if (member.gender === "MALE" && !fatherMatches) return false if (member.gender === "FEMALE" && !motherMatches) return false if (member.gender !== "MALE" && member.gender !== "FEMALE") { // 非男女成员,允许填补任一缺失的父母 if (candidate.fatherId && candidate.motherId) return false } } else { if (candidate.generation !== member.generation) return false if (member.spouseIds?.includes(candidate.id)) return false if (candidate.spouseIds?.includes(member.id)) return false if (candidate.gender === member.gender) return false } return true }) .slice(0, 8) .map((candidate) => ({ member: candidate, fatherName: candidate.fatherId ? treeData.members[candidate.fatherId]?.fullName : undefined, motherName: candidate.motherId ? treeData.members[candidate.motherId]?.fullName : undefined, })) }, [member, relationType, treeData.members, normalizedQuery]) const handleLink = async (target: FamilyMember) => { try { setLinkingId(target.id) if (relationType === "child") { const payload: Partial = {} if (member.gender === "FEMALE") { payload.motherId = member.id } else if (member.gender === "MALE") { payload.fatherId = member.id } else { if (!target.fatherId) { payload.fatherId = member.id } else if (!target.motherId) { payload.motherId = member.id } else { throw new Error("该成员已绑定父母") } } await updateMember(target.id, payload) toast({ title: "关联成功", description: `已将 ${target.fullName} 标记为 ${member.fullName} 的子女。` }) } else { const existing = new Set(member.spouseIds || []) existing.add(target.id) await updateMember(member.id, { spouseIds: Array.from(existing) }) toast({ title: "关联成功", description: `${member.fullName} 与 ${target.fullName} 已建立配偶关系。` }) } onOpenChange(false) } catch (error) { const message = error instanceof Error ? error.message : "关联失败" toast({ title: "操作失败", description: message, variant: "destructive", }) } finally { setLinkingId(null) } } const handleCreateNew = () => { if (!normalizedQuery) return onCreateNew(query.trim(), relationType) } return ( 添加{relationType === "child" ? "子女" : "配偶"} 先输入姓名,系统会检索已有成员。若没有匹配,可直接新建。
setQuery(e.target.value)} />
{normalizedQuery ? ( candidates.length > 0 ? (

找到以下可能的匹配:

{candidates.map(({ member: candidate, fatherName, motherName }) => (

第 {candidate.generation} 世 · {candidate.gender === "FEMALE" ? "女" : "男"}

父亲:{fatherName || "未登记"}
母亲:{motherName || "未登记"}
))}
) : (

未找到匹配成员,可直接创建新成员。

) ) : (

请输入姓名以搜索已有成员。

)}
) }