82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
"use client"
|
|
import type { FamilyMember } from "@/types/family"
|
|
import { FamilyNode } from "./family-node"
|
|
import { useFamily } from "@/context/family-context"
|
|
|
|
interface TreeLayoutProps {
|
|
rootId: string
|
|
onSelectMember?: (member: FamilyMember) => void
|
|
}
|
|
|
|
export function TreeLayout({ rootId, onSelectMember }: TreeLayoutProps) {
|
|
const { getMember } = useFamily()
|
|
const root = getMember(rootId)
|
|
|
|
if (!root) return null
|
|
|
|
// Recursive component to render the tree
|
|
const TreeNode = ({ memberId }: { memberId: string }) => {
|
|
const member = getMember(memberId)
|
|
if (!member) return null
|
|
|
|
const hasChildren = member.childrenIds && member.childrenIds.length > 0
|
|
|
|
return (
|
|
<div className="flex flex-col items-center">
|
|
<div className="relative z-10">
|
|
<FamilyNode member={member} onSelect={onSelectMember} />
|
|
|
|
{/* Connector to children */}
|
|
{hasChildren && <div className="absolute top-full left-1/2 -translate-x-1/2 h-8 w-px bg-border" />}
|
|
</div>
|
|
|
|
{hasChildren && (
|
|
<div className="flex items-start pt-8 relative">
|
|
{/* Horizontal connecting line */}
|
|
{member.childrenIds.length > 1 && (
|
|
<div className="absolute top-0 left-[50%] -translate-x-1/2 h-px bg-border w-[calc(100%-8rem)]" /> // Rough approx for connector width
|
|
)}
|
|
|
|
<div className="flex gap-8 relative">
|
|
{/* Top connecting lines for children */}
|
|
{member.childrenIds.length > 1 && (
|
|
<div className="absolute top-0 left-0 right-0 h-px bg-transparent">
|
|
{/* This needs precise calculation or just use CSS pseudo elements on children */}
|
|
</div>
|
|
)}
|
|
|
|
{member.childrenIds.map((childId, index) => (
|
|
<div key={childId} className="flex flex-col items-center relative">
|
|
{/* Vertical line from parent's horizontal line to child */}
|
|
<div className="h-8 w-px bg-border absolute -top-8 left-1/2 -translate-x-1/2"></div>
|
|
|
|
{/* Horizontal connector fix for first/last child */}
|
|
{member.childrenIds.length > 1 && (
|
|
<>
|
|
{index === 0 && <div className="absolute -top-8 right-0 w-1/2 h-px bg-border"></div>}
|
|
{index === member.childrenIds.length - 1 && (
|
|
<div className="absolute -top-8 left-0 w-1/2 h-px bg-border"></div>
|
|
)}
|
|
{index > 0 && index < member.childrenIds.length - 1 && (
|
|
<div className="absolute -top-8 left-0 w-full h-px bg-border"></div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
<TreeNode memberId={childId} />
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="p-12 min-w-fit">
|
|
<TreeNode memberId={rootId} />
|
|
</div>
|
|
)
|
|
}
|