import React, { useState, useEffect, useMemo } from "react"; import { FaUser, FaUsers, FaBuilding, FaChevronDown, FaChevronRight, FaEye, FaTh, FaSitemap, FaTimes, FaCalendar, FaEnvelope, FaPhone, FaMapMarkerAlt, FaBriefcase, } from "react-icons/fa"; import { HrEmployee, HrOrganizationChart as OrgChart } from "../../../types/hr"; import { mockEmployees } from "../../../mocks/mockEmployees"; import { mockDepartments } from "../../../mocks/mockDepartments"; import Widget from "../../../components/common/Widget"; // Dinamik organizasyon verisi oluşturma fonksiyonu const generateOrganizationData = (): OrgChart[] => { const orgData: OrgChart[] = []; // Çalışanları işle mockEmployees.forEach((employee) => { const department = mockDepartments.find( (d) => d.id === employee.departmantId ); let level = 3; // Varsayılan seviye (normal çalışan) let parentId: string | undefined = undefined; // Eğer bu çalışan bir departman yöneticisiyse if (department && department.managerId === employee.id) { if (!department.parentDepartmentId) { // Ana departman yöneticisi (CEO/Genel Müdür) level = 0; } else { // Alt departman yöneticisi level = 1; // Üst departmanın yöneticisini parent olarak bul const parentDept = mockDepartments.find( (d) => d.id === department.parentDepartmentId ); if (parentDept && parentDept.managerId) { parentId = parentDept.managerId; } } } else { // Normal çalışan - departman yöneticisine bağlı if (department && department.managerId) { parentId = department.managerId; // Departman yöneticisinin seviyesine göre belirleme const managerDept = mockDepartments.find( (d) => d.managerId === department.managerId ); if (managerDept && !managerDept.parentDepartmentId) { level = 2; // CEO'ya direkt bağlı } else { level = 3; // Orta kademe yöneticiye bağlı } } } orgData.push({ id: `org-${employee.id}`, employeeId: employee.id, employee: employee, parentId: parentId, level: level, position: employee.jobPosition?.name || "Belirsiz", isActive: employee.isActive, }); }); return orgData.sort((a, b) => a.level - b.level); }; interface TreeNode { employee: HrEmployee; children: TreeNode[]; level: number; } const OrganizationChart: React.FC = () => { const [employees] = useState(mockEmployees); const [organizationData] = useState(generateOrganizationData()); const [expandedNodes, setExpandedNodes] = useState>(new Set()); const [orgTree, setOrgTree] = useState([]); const [viewMode, setViewMode] = useState<"tree" | "cards">("tree"); const [selectedEmployee, setSelectedEmployee] = useState( null ); const [showModal, setShowModal] = useState(false); const [selectedDepartment, setSelectedDepartment] = useState("all"); const handleViewEmployee = (employee: HrEmployee) => { setSelectedEmployee(employee); setShowModal(true); }; const handleCloseModal = () => { setShowModal(false); setSelectedEmployee(null); }; useEffect(() => { // Build organization tree structure const buildTree = (): TreeNode[] => { const nodeMap = new Map(); // First, create all nodes employees.forEach((employee) => { nodeMap.set(employee.id, { employee, children: [], level: 0, }); }); // Then, build the tree structure const rootNodes: TreeNode[] = []; organizationData.forEach((orgData) => { const node = nodeMap.get(orgData.employeeId); if (node) { node.level = orgData.level; if (orgData.parentId) { const parentNode = nodeMap.get(orgData.parentId); if (parentNode) { parentNode.children.push(node); } } else { rootNodes.push(node); } } }); return rootNodes; }; setOrgTree(buildTree()); // Auto-expand first level const firstLevelIds = organizationData .filter((org) => org.level <= 1) .map((org) => org.employeeId); setExpandedNodes(new Set(firstLevelIds)); }, [employees, organizationData]); // Filtered data for views const filteredOrgTree = useMemo(() => { if (selectedDepartment === "all") { return orgTree; } const filterTree = (nodes: TreeNode[]): TreeNode[] => { const result: TreeNode[] = []; for (const node of nodes) { const filteredChildren = filterTree(node.children); if ( node.employee.departmantId === selectedDepartment || filteredChildren.length > 0 ) { result.push({ ...node, children: filteredChildren }); } } return result; }; return filterTree(orgTree); }, [orgTree, selectedDepartment]); const filteredEmployees = useMemo(() => { if (selectedDepartment === "all") { return employees; } return employees.filter((emp) => emp.departmantId === selectedDepartment); }, [employees, selectedDepartment]); const toggleNode = (nodeId: string) => { const newExpanded = new Set(expandedNodes); if (newExpanded.has(nodeId)) { newExpanded.delete(nodeId); } else { newExpanded.add(nodeId); } setExpandedNodes(newExpanded); }; const renderTreeNode = (node: TreeNode): React.ReactNode => { const isExpanded = expandedNodes.has(node.employee.id); const hasChildren = node.children.length > 0; return (
{/* Bağlantı çizgisi */} {node.level > 0 && ( )}
{/* Girinti ve bağlantı çizgisi */} {node.level > 0 && ( )} {/* Genişletme ikonu */}
{hasChildren && ( )}
{/* Grup Bilgisi */}

{node.employee.fullName}

{node.employee.jobPosition?.name}

{node.employee.department?.name}

{hasChildren && ( {node.children.length} )}
{hasChildren && isExpanded && (
{node.children.map((child) => renderTreeNode(child))}
)}
); }; const renderCardView = () => { const groupedByLevel = filteredEmployees.reduce((acc, employee) => { const orgData = organizationData.find( (org) => org.employeeId === employee.id ); const level = orgData?.level || 0; if (!acc[level]) { acc[level] = []; } acc[level].push(employee); return acc; }, {} as Record); return (
{Object.entries(groupedByLevel) .sort(([a], [b]) => parseInt(a) - parseInt(b)) .map(([level, levelEmployees]) => (

{level === "0" ? "Üst Yönetim" : level === "1" ? "Orta Kademe Yönetim" : level === "2" ? "Alt Kademe Yönetim" : `${parseInt(level) + 1}. Seviye`} {levelEmployees.length} kişi

{levelEmployees.map((employee) => (

handleViewEmployee(employee)} className="font-medium text-sm text-blue-600 hover:underline cursor-pointer truncate" > {employee.fullName}

{employee.code}

{employee.jobPosition?.name}

{employee.department?.name}

))}
))}
); }; return (
{/* Header */}

Organizasyon Şeması

Kurumsal hiyerarşi ve raporlama yapısı

{/* Stats */}
e.department?.id).filter(Boolean)).size } color="purple" icon="FaBuilding" /> 0 ? Math.max(...organizationData.map((org) => org.level)) + 1 : 0 } color="orange" icon="FaUser" />
{/* Content */}
{viewMode === "tree" ? (
{filteredOrgTree.map((node) => renderTreeNode(node))}
) : ( renderCardView() )} {(viewMode === "tree" ? filteredOrgTree.length === 0 : filteredEmployees.length === 0) && (

Organizasyon verisi bulunamadı

Henüz organizasyon şeması oluşturulmamış.

)}
{/* Employee Detail Modal */} {showModal && selectedEmployee && (
{/* Modal Header */}

Personel Detayları

{/* Employee Info */}
{/* Basic Info */}

{selectedEmployee.fullName}

{selectedEmployee.code}

{selectedEmployee.jobPosition?.name}

{/* Contact Information */}
İletişim Bilgileri
E-posta: {selectedEmployee.email}
{selectedEmployee.phone && (
İş Telefonu: {selectedEmployee.phone}
)} {selectedEmployee.personalPhone && (
Kişisel Telefon: {selectedEmployee.personalPhone}
)}
{/* Employment Information */}
İş Bilgileri
Departman:

{selectedEmployee.department?.name}

Pozisyon:

{selectedEmployee.jobPosition?.name}

İşe Başlama Tarihi:

{new Date(selectedEmployee.hireDate).toLocaleDateString( "tr-TR" )}

İstihdam Türü:

{selectedEmployee.employmentType}

Çalışma Lokasyonu:

{selectedEmployee.workLocation}

Durum: {selectedEmployee.isActive ? "Aktif" : "Pasif"}
{/* Personal Information */}
Kişisel Bilgiler
Doğum Tarihi:

{new Date( selectedEmployee.birthDate ).toLocaleDateString("tr-TR")}

Cinsiyet:

{selectedEmployee.gender}

Medeni Durum:

{selectedEmployee.maritalStatus}

TC Kimlik No:

{selectedEmployee.nationalId}

{selectedEmployee.address && (
Adres:

{selectedEmployee.address.street},{" "} {selectedEmployee.address.city},{" "} {selectedEmployee.address.country}

)}
{/* Emergency Contact */} {selectedEmployee.emergencyContact && (
Acil Durum İletişim
İsim:

{selectedEmployee.emergencyContact.name}

Yakınlık:

{selectedEmployee.emergencyContact.relationship}

Telefon:

{selectedEmployee.emergencyContact.phone}

)}
{/* Modal Footer */}
)}
); }; export default OrganizationChart;