'use client' import { useState, useEffect } from 'react' import { toast } from 'react-hot-toast' import { ChevronDown, ChevronRight, Building2, User, Plus, ExternalLink, Loader2 } from 'lucide-react' import { contactsAPI, Contact } from '@/lib/api/contacts' import Link from 'next/link' interface HierarchyNode extends Contact { children?: HierarchyNode[] expanded?: boolean } interface HierarchyTreeProps { rootContactId: string } export default function HierarchyTree({ rootContactId }: HierarchyTreeProps) { const [root, setRoot] = useState(null) const [loading, setLoading] = useState(true) const [expandedNodes, setExpandedNodes] = useState>(new Set([rootContactId])) useEffect(() => { fetchHierarchy() }, [rootContactId]) const fetchHierarchy = async () => { setLoading(true) try { // Fetch root contact const rootContact = await contactsAPI.getById(rootContactId) // Fetch all contacts to build hierarchy const allContacts = await contactsAPI.getAll({ pageSize: 1000 }) // Build tree structure const tree = buildTree(rootContact, allContacts.contacts) setRoot(tree) } catch (error: any) { toast.error('Failed to load hierarchy') } finally { setLoading(false) } } const buildTree = (rootContact: Contact, allContacts: Contact[]): HierarchyNode => { const findChildren = (parentId: string): HierarchyNode[] => { return allContacts .filter(c => c.parentId === parentId) .map(child => ({ ...child, children: findChildren(child.id), expanded: expandedNodes.has(child.id) })) } return { ...rootContact, children: findChildren(rootContact.id), expanded: expandedNodes.has(rootContact.id) } } const toggleNode = (nodeId: string) => { setExpandedNodes(prev => { const newSet = new Set(prev) if (newSet.has(nodeId)) { newSet.delete(nodeId) } else { newSet.add(nodeId) } return newSet }) } const renderNode = (node: HierarchyNode, level: number = 0) => { const hasChildren = node.children && node.children.length > 0 const isExpanded = expandedNodes.has(node.id) const Icon = node.type === 'INDIVIDUAL' ? User : Building2 return (
0 ? 'ml-8' : '' }`} style={{ paddingLeft: `${level * 32 + 12}px` }} > {/* Expand/Collapse Button */} {hasChildren ? ( ) : (
)} {/* Contact Icon */} {/* Contact Info */}
{node.name} {node.type} {node.id === rootContactId && ( Root )}
{(node.email || node.phone) && (

{node.email || node.phone}

)}
{/* Actions */}
{/* Render Children */} {hasChildren && isExpanded && (
{node.children!.map(child => renderNode(child, level + 1))}
)}
) } if (loading) { return (
) } if (!root) { return (

Failed to load hierarchy

) } const totalNodes = root.children ? countNodes(root) : 1 return (

الهيكل التنظيمي - Company Hierarchy

{totalNodes} contact{totalNodes !== 1 ? 's' : ''} in hierarchy

|
{renderNode(root, 0)}
{root.children && root.children.length === 0 && (

No child contacts in this hierarchy

Add First Child Contact
)}
) } // Helper functions function countNodes(node: HierarchyNode): number { let count = 1 if (node.children) { node.children.forEach(child => { count += countNodes(child) }) } return count } function getAllNodeIds(node: HierarchyNode): string[] { let ids = [node.id] if (node.children) { node.children.forEach(child => { ids = ids.concat(getAllNodeIds(child)) }) } return ids }