erp-platform/ui/src/views/hr/components/OrganizationChart.tsx

645 lines
24 KiB
TypeScript
Raw Normal View History

2025-09-15 19:46:52 +00:00
import React, { useState, useEffect, useMemo } from 'react'
2025-09-15 09:31:47 +00:00
import {
FaUser,
FaUsers,
FaBuilding,
FaChevronDown,
FaChevronRight,
FaEye,
FaTh,
FaSitemap,
FaTimes,
FaCalendar,
FaEnvelope,
FaPhone,
FaMapMarkerAlt,
FaBriefcase,
2025-09-15 19:46:52 +00:00
} 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'
import { Container } from '@/components/shared'
2025-09-15 09:31:47 +00:00
// Dinamik organizasyon verisi oluşturma fonksiyonu
const generateOrganizationData = (): OrgChart[] => {
2025-09-15 19:46:52 +00:00
const orgData: OrgChart[] = []
2025-09-15 09:31:47 +00:00
// Çalışanları işle
mockEmployees.forEach((employee) => {
2025-09-15 19:46:52 +00:00
const department = mockDepartments.find((d) => d.id === employee.departmantId)
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
let level = 3 // Varsayılan seviye (normal çalışan)
let parentId: string | undefined = undefined
2025-09-15 09:31:47 +00:00
// 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)
2025-09-15 19:46:52 +00:00
level = 0
2025-09-15 09:31:47 +00:00
} else {
// Alt departman yöneticisi
2025-09-15 19:46:52 +00:00
level = 1
2025-09-15 09:31:47 +00:00
// Üst departmanın yöneticisini parent olarak bul
2025-09-15 19:46:52 +00:00
const parentDept = mockDepartments.find((d) => d.id === department.parentDepartmentId)
2025-09-15 09:31:47 +00:00
if (parentDept && parentDept.managerId) {
2025-09-15 19:46:52 +00:00
parentId = parentDept.managerId
2025-09-15 09:31:47 +00:00
}
}
} else {
// Normal çalışan - departman yöneticisine bağlı
if (department && department.managerId) {
2025-09-15 19:46:52 +00:00
parentId = department.managerId
2025-09-15 09:31:47 +00:00
// Departman yöneticisinin seviyesine göre belirleme
2025-09-15 19:46:52 +00:00
const managerDept = mockDepartments.find((d) => d.managerId === department.managerId)
2025-09-15 09:31:47 +00:00
if (managerDept && !managerDept.parentDepartmentId) {
2025-09-15 19:46:52 +00:00
level = 2 // CEO'ya direkt bağlı
2025-09-15 09:31:47 +00:00
} else {
2025-09-15 19:46:52 +00:00
level = 3 // Orta kademe yöneticiye bağlı
2025-09-15 09:31:47 +00:00
}
}
}
orgData.push({
id: `org-${employee.id}`,
employeeId: employee.id,
employee: employee,
parentId: parentId,
level: level,
2025-09-15 19:46:52 +00:00
position: employee.jobPosition?.name || 'Belirsiz',
2025-09-15 09:31:47 +00:00
isActive: employee.isActive,
2025-09-15 19:46:52 +00:00
})
})
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
return orgData.sort((a, b) => a.level - b.level)
}
2025-09-15 09:31:47 +00:00
interface TreeNode {
2025-09-15 19:46:52 +00:00
employee: HrEmployee
children: TreeNode[]
level: number
2025-09-15 09:31:47 +00:00
}
const OrganizationChart: React.FC = () => {
2025-09-15 19:46:52 +00:00
const [employees] = useState<HrEmployee[]>(mockEmployees)
const [organizationData] = useState<OrgChart[]>(generateOrganizationData())
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())
const [orgTree, setOrgTree] = useState<TreeNode[]>([])
const [viewMode, setViewMode] = useState<'tree' | 'cards'>('tree')
const [selectedEmployee, setSelectedEmployee] = useState<HrEmployee | null>(null)
const [showModal, setShowModal] = useState(false)
const [selectedDepartment, setSelectedDepartment] = useState<string>('all')
2025-09-15 09:31:47 +00:00
const handleViewEmployee = (employee: HrEmployee) => {
2025-09-15 19:46:52 +00:00
setSelectedEmployee(employee)
setShowModal(true)
}
2025-09-15 09:31:47 +00:00
const handleCloseModal = () => {
2025-09-15 19:46:52 +00:00
setShowModal(false)
setSelectedEmployee(null)
}
2025-09-15 09:31:47 +00:00
useEffect(() => {
// Build organization tree structure
const buildTree = (): TreeNode[] => {
2025-09-15 19:46:52 +00:00
const nodeMap = new Map<string, TreeNode>()
2025-09-15 09:31:47 +00:00
// First, create all nodes
employees.forEach((employee) => {
nodeMap.set(employee.id, {
employee,
children: [],
level: 0,
2025-09-15 19:46:52 +00:00
})
})
2025-09-15 09:31:47 +00:00
// Then, build the tree structure
2025-09-15 19:46:52 +00:00
const rootNodes: TreeNode[] = []
2025-09-15 09:31:47 +00:00
organizationData.forEach((orgData) => {
2025-09-15 19:46:52 +00:00
const node = nodeMap.get(orgData.employeeId)
2025-09-15 09:31:47 +00:00
if (node) {
2025-09-15 19:46:52 +00:00
node.level = orgData.level
2025-09-15 09:31:47 +00:00
if (orgData.parentId) {
2025-09-15 19:46:52 +00:00
const parentNode = nodeMap.get(orgData.parentId)
2025-09-15 09:31:47 +00:00
if (parentNode) {
2025-09-15 19:46:52 +00:00
parentNode.children.push(node)
2025-09-15 09:31:47 +00:00
}
} else {
2025-09-15 19:46:52 +00:00
rootNodes.push(node)
2025-09-15 09:31:47 +00:00
}
}
2025-09-15 19:46:52 +00:00
})
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
return rootNodes
}
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
setOrgTree(buildTree())
2025-09-15 09:31:47 +00:00
// Auto-expand first level
const firstLevelIds = organizationData
.filter((org) => org.level <= 1)
2025-09-15 19:46:52 +00:00
.map((org) => org.employeeId)
setExpandedNodes(new Set(firstLevelIds))
}, [employees, organizationData])
2025-09-15 09:31:47 +00:00
// Filtered data for views
const filteredOrgTree = useMemo(() => {
2025-09-15 19:46:52 +00:00
if (selectedDepartment === 'all') {
return orgTree
2025-09-15 09:31:47 +00:00
}
const filterTree = (nodes: TreeNode[]): TreeNode[] => {
2025-09-15 19:46:52 +00:00
const result: TreeNode[] = []
2025-09-15 09:31:47 +00:00
for (const node of nodes) {
2025-09-15 19:46:52 +00:00
const filteredChildren = filterTree(node.children)
if (node.employee.departmantId === selectedDepartment || filteredChildren.length > 0) {
result.push({ ...node, children: filteredChildren })
2025-09-15 09:31:47 +00:00
}
}
2025-09-15 19:46:52 +00:00
return result
}
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
return filterTree(orgTree)
}, [orgTree, selectedDepartment])
2025-09-15 09:31:47 +00:00
const filteredEmployees = useMemo(() => {
2025-09-15 19:46:52 +00:00
if (selectedDepartment === 'all') {
return employees
2025-09-15 09:31:47 +00:00
}
2025-09-15 19:46:52 +00:00
return employees.filter((emp) => emp.departmantId === selectedDepartment)
}, [employees, selectedDepartment])
2025-09-15 09:31:47 +00:00
const toggleNode = (nodeId: string) => {
2025-09-15 19:46:52 +00:00
const newExpanded = new Set(expandedNodes)
2025-09-15 09:31:47 +00:00
if (newExpanded.has(nodeId)) {
2025-09-15 19:46:52 +00:00
newExpanded.delete(nodeId)
2025-09-15 09:31:47 +00:00
} else {
2025-09-15 19:46:52 +00:00
newExpanded.add(nodeId)
2025-09-15 09:31:47 +00:00
}
2025-09-15 19:46:52 +00:00
setExpandedNodes(newExpanded)
}
2025-09-15 09:31:47 +00:00
const renderTreeNode = (node: TreeNode): React.ReactNode => {
2025-09-15 19:46:52 +00:00
const isExpanded = expandedNodes.has(node.employee.id)
const hasChildren = node.children.length > 0
2025-09-15 09:31:47 +00:00
return (
<div key={node.employee.id} className="relative">
{/* Bağlantı çizgisi */}
{node.level > 0 && (
<span
className="absolute border-l border-gray-300"
style={{
left: `${node.level * 1.25 - 0.7}rem`,
top: 0,
2025-09-15 19:46:52 +00:00
height: '100%',
2025-09-15 09:31:47 +00:00
}}
/>
)}
<div
className="flex items-center space-x-2 py-1.5 rounded-md hover:bg-gray-50"
style={{ paddingLeft: `${node.level * 1.25}rem` }}
>
{/* Girinti ve bağlantı çizgisi */}
{node.level > 0 && (
<span
className="absolute border-t border-gray-300 w-3"
2025-09-15 19:46:52 +00:00
style={{ left: `${node.level * 1.25 - 0.7}rem`, top: '1.1rem' }}
2025-09-15 09:31:47 +00:00
/>
)}
{/* Genişletme ikonu */}
<div className="w-5 flex-shrink-0 text-center">
{hasChildren && (
<button
onClick={() => toggleNode(node.employee.id)}
className="p-1 text-gray-500 hover:text-gray-800 rounded-full hover:bg-gray-200"
>
2025-09-15 19:46:52 +00:00
{isExpanded ? <FaChevronDown size={10} /> : <FaChevronRight size={10} />}
2025-09-15 09:31:47 +00:00
</button>
)}
</div>
{/* Grup Bilgisi */}
<div className="flex-grow flex items-center space-x-3">
<div className="flex-1 min-w-0">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium text-sm text-gray-900 truncate">
{node.employee.fullName}
</h4>
<p className="text-xs text-gray-600 truncate">
{node.employee.jobPosition?.name}
</p>
2025-09-15 19:46:52 +00:00
<p className="text-xs text-gray-500 truncate">{node.employee.department?.name}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
</div>
<div className="flex items-center space-x-2 pr-2">
<div className="flex items-center gap-2 ml-4">
{hasChildren && (
<span className="flex items-center text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded-full">
<FaUsers className="w-3 h-3 mr-1" />
{node.children.length}
</span>
)}
<button // İşlemler
onClick={() => handleViewEmployee(node.employee)}
className="p-1 text-blue-600 hover:bg-blue-50 rounded"
title="Görüntüle"
>
<FaEye className="w-4 h-4" />
</button>
</div>
</div>
</div>
</div>
{hasChildren && isExpanded && (
<div>{node.children.map((child) => renderTreeNode(child))}</div>
)}
</div>
2025-09-15 19:46:52 +00:00
)
}
2025-09-15 09:31:47 +00:00
const renderCardView = () => {
2025-09-15 19:46:52 +00:00
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<number, HrEmployee[]>,
)
2025-09-15 09:31:47 +00:00
return (
<div className="space-y-6">
{Object.entries(groupedByLevel)
.sort(([a], [b]) => parseInt(a) - parseInt(b))
.map(([level, levelEmployees]) => (
<div key={level}>
<h3 className="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
<FaBuilding className="w-5 h-5" />
2025-09-15 19:46:52 +00:00
{level === '0'
? 'Üst Yönetim'
: level === '1'
? 'Orta Kademe Yönetim'
: level === '2'
? 'Alt Kademe Yönetim'
: `${parseInt(level) + 1}. Seviye`}
2025-09-15 09:31:47 +00:00
<span className="text-sm text-gray-500 bg-gray-100 px-2 py-1 rounded-full">
{levelEmployees.length} kişi
</span>
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 gap-3">
{levelEmployees.map((employee) => (
<div
key={employee.id}
className="bg-white p-3 rounded-lg border shadow-sm hover:shadow-md transition-shadow"
>
<div className="flex items-center mb-3">
<div
className={`w-8 h-8 rounded-full flex items-center justify-center mr-2 ${
2025-09-15 19:46:52 +00:00
level === '0'
? 'bg-blue-100'
: level === '1'
? 'bg-green-100'
: 'bg-gray-100'
2025-09-15 09:31:47 +00:00
}`}
>
<FaUser
className={`w-4 h-4 ${
2025-09-15 19:46:52 +00:00
level === '0'
? 'text-blue-600'
: level === '1'
? 'text-green-600'
: 'text-gray-600'
2025-09-15 09:31:47 +00:00
}`}
/>
</div>
<div className="flex-1 min-w-0">
<h4
onClick={() => handleViewEmployee(employee)}
className="font-medium text-sm text-blue-600 hover:underline cursor-pointer truncate"
>
{employee.fullName}
</h4>
2025-09-15 19:46:52 +00:00
<p className="text-sm text-gray-600 truncate">{employee.code}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
<div className="space-y-1 mb-2">
<p className="text-xs text-gray-800 font-medium truncate">
{employee.jobPosition?.name}
</p>
2025-09-15 19:46:52 +00:00
<p className="text-xs text-gray-600 truncate">{employee.department?.name}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
))}
</div>
</div>
))}
</div>
2025-09-15 19:46:52 +00:00
)
}
2025-09-15 09:31:47 +00:00
return (
2025-09-15 19:46:52 +00:00
<Container>
<div className="space-y-2">
{/* Header */}
<div className="flex items-center justify-between">
<div>
2025-09-15 21:02:48 +00:00
<h2 className="text-2xl font-bold text-gray-900">Organizasyon Şeması</h2>
<p className="text-gray-600">Kurumsal hiyerarşi ve raporlama yapısı</p>
2025-09-15 19:46:52 +00:00
</div>
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
<div className="flex items-center gap-2">
<select
value={selectedDepartment}
onChange={(e) => setSelectedDepartment(e.target.value)}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
2025-09-15 09:31:47 +00:00
>
2025-09-15 19:46:52 +00:00
<option value="all">Tüm Departmanlar</option>
{mockDepartments.map((dept) => (
<option key={dept.id} value={dept.id}>
{dept.name}
</option>
))}
</select>
<div className="flex bg-gray-100 rounded-lg p-0.5">
<button
onClick={() => setViewMode('tree')}
className={`p-1.5 rounded-md transition-colors ${
viewMode === 'tree'
? 'bg-white text-blue-600 shadow-sm'
: 'text-gray-600 hover:text-gray-900'
}`}
>
<FaSitemap className="w-4 h-4" />
</button>
<button
onClick={() => setViewMode('cards')}
className={`p-1.5 rounded-md transition-colors ${
viewMode === 'cards'
? 'bg-white text-blue-600 shadow-sm'
: 'text-gray-600 hover:text-gray-900'
}`}
>
<FaTh className="w-4 h-4" />
</button>
</div>
2025-09-15 09:31:47 +00:00
</div>
</div>
2025-09-15 19:46:52 +00:00
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<Widget title="Toplam Personel" value={employees.length} color="blue" icon="FaBuilding" />
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
<Widget
title="Departmanlar"
value={new Set(employees.map((e) => e.department?.id).filter(Boolean)).size}
color="purple"
icon="FaBuilding"
/>
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
<Widget
title="Seviye Sayısı"
value={
organizationData.length > 0
? Math.max(...organizationData.map((org) => org.level)) + 1
: 0
}
color="orange"
icon="FaUser"
/>
</div>
{/* Content */}
<div className="bg-white rounded-lg border p-4">
{viewMode === 'tree' ? (
<div className="pt-2">{filteredOrgTree.map((node) => renderTreeNode(node))}</div>
) : (
renderCardView()
)}
{(viewMode === 'tree'
? filteredOrgTree.length === 0
: filteredEmployees.length === 0) && (
<div className="text-center py-12">
<FaBuilding className="w-10 h-10 text-gray-400 mx-auto mb-3" />
<h3 className="text-base font-medium text-gray-900 mb-2">
Organizasyon verisi bulunamadı
</h3>
<p className="text-gray-500">Henüz organizasyon şeması oluşturulmamış.</p>
</div>
)}
</div>
2025-09-15 09:31:47 +00:00
</div>
{/* Employee Detail Modal */}
{showModal && selectedEmployee && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
<div className="bg-white rounded-lg p-4 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
{/* Modal Header */}
<div className="flex justify-between items-center mb-4">
2025-09-15 19:46:52 +00:00
<h3 className="text-lg font-semibold text-gray-900">Personel Detayları</h3>
<button onClick={handleCloseModal} className="text-gray-400 hover:text-gray-600 p-1">
2025-09-15 09:31:47 +00:00
<FaTimes className="w-5 h-5" />
</button>
</div>
{/* Employee Info */}
<div className="space-y-4">
{/* Basic Info */}
<div className="flex items-center space-x-4">
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center">
<FaUser className="w-8 h-8 text-blue-600" />
</div>
<div>
2025-09-15 19:46:52 +00:00
<h4 className="text-lg font-bold text-gray-900">{selectedEmployee.fullName}</h4>
2025-09-15 09:31:47 +00:00
<p className="text-gray-600">{selectedEmployee.code}</p>
2025-09-15 19:46:52 +00:00
<p className="text-sm text-gray-500">{selectedEmployee.jobPosition?.name}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
{/* Contact Information */}
<div>
<h5 className="text-base font-semibold text-gray-900 mb-2 flex items-center">
<FaEnvelope className="w-5 h-5 mr-2 text-blue-600" />
İletişim Bilgileri
</h5>
<div className="bg-gray-50 p-3 rounded-lg space-y-2">
<div className="flex items-center">
<FaEnvelope className="w-4 h-4 text-gray-500 mr-3" />
<span className="text-sm">E-posta:</span>
2025-09-15 19:46:52 +00:00
<span className="ml-2 text-sm font-medium">{selectedEmployee.email}</span>
2025-09-15 09:31:47 +00:00
</div>
{selectedEmployee.phone && (
<div className="flex items-center">
<FaPhone className="w-4 h-4 text-gray-500 mr-3" />
<span className="text-sm">İş Telefonu:</span>
2025-09-15 19:46:52 +00:00
<span className="ml-2 text-sm font-medium">{selectedEmployee.phone}</span>
2025-09-15 09:31:47 +00:00
</div>
)}
{selectedEmployee.personalPhone && (
<div className="flex items-center">
<FaPhone className="w-4 h-4 text-gray-500 mr-3" />
<span className="text-sm">Kişisel Telefon:</span>
<span className="ml-2 text-sm font-medium">
{selectedEmployee.personalPhone}
</span>
</div>
)}
</div>
</div>
{/* Employment Information */}
<div>
<h5 className="text-base font-semibold text-gray-900 mb-2 flex items-center">
<FaBriefcase className="w-5 h-5 mr-2 text-green-600" />
İş Bilgileri
</h5>
<div className="bg-gray-50 p-3 rounded-lg space-y-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<span className="text-sm text-gray-600">Departman:</span>
2025-09-15 19:46:52 +00:00
<p className="font-medium">{selectedEmployee.department?.name}</p>
2025-09-15 09:31:47 +00:00
</div>
<div>
<span className="text-sm text-gray-600">Pozisyon:</span>
2025-09-15 19:46:52 +00:00
<p className="font-medium">{selectedEmployee.jobPosition?.name}</p>
2025-09-15 09:31:47 +00:00
</div>
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">İşe Başlama Tarihi:</span>
2025-09-15 09:31:47 +00:00
<p className="font-medium flex items-center">
<FaCalendar className="w-4 h-4 mr-1 text-gray-500" />
2025-09-15 19:46:52 +00:00
{new Date(selectedEmployee.hireDate).toLocaleDateString('tr-TR')}
2025-09-15 09:31:47 +00:00
</p>
</div>
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">İstihdam Türü:</span>
<p className="font-medium">{selectedEmployee.employmentType}</p>
2025-09-15 09:31:47 +00:00
</div>
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">Çalışma Lokasyonu:</span>
2025-09-15 09:31:47 +00:00
<p className="font-medium flex items-center">
<FaMapMarkerAlt className="w-4 h-4 mr-1 text-gray-500" />
{selectedEmployee.workLocation}
</p>
</div>
<div>
<span className="text-sm text-gray-600">Durum:</span>
<span
className={`inline-flex px-2 py-1 text-xs font-medium rounded-full ${
selectedEmployee.isActive
2025-09-15 19:46:52 +00:00
? 'bg-green-100 text-green-800'
: 'bg-red-100 text-red-800'
2025-09-15 09:31:47 +00:00
}`}
>
2025-09-15 19:46:52 +00:00
{selectedEmployee.isActive ? 'Aktif' : 'Pasif'}
2025-09-15 09:31:47 +00:00
</span>
</div>
</div>
</div>
</div>
{/* Personal Information */}
<div>
<h5 className="text-base font-semibold text-gray-900 mb-2 flex items-center">
<FaUser className="w-5 h-5 mr-2 text-purple-600" />
Kişisel Bilgiler
</h5>
<div className="bg-gray-50 p-3 rounded-lg space-y-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">Doğum Tarihi:</span>
2025-09-15 09:31:47 +00:00
<p className="font-medium flex items-center">
<FaCalendar className="w-4 h-4 mr-1 text-gray-500" />
2025-09-15 19:46:52 +00:00
{new Date(selectedEmployee.birthDate).toLocaleDateString('tr-TR')}
2025-09-15 09:31:47 +00:00
</p>
</div>
<div>
<span className="text-sm text-gray-600">Cinsiyet:</span>
<p className="font-medium">{selectedEmployee.gender}</p>
</div>
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">Medeni Durum:</span>
<p className="font-medium">{selectedEmployee.maritalStatus}</p>
2025-09-15 09:31:47 +00:00
</div>
<div>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">TC Kimlik No:</span>
<p className="font-medium">{selectedEmployee.nationalId}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
{selectedEmployee.address && (
<div>
<span className="text-sm text-gray-600">Adres:</span>
<p className="font-medium flex items-start">
<FaMapMarkerAlt className="w-4 h-4 mr-1 text-gray-500 mt-0.5" />
2025-09-15 19:46:52 +00:00
{selectedEmployee.address.street}, {selectedEmployee.address.city},{' '}
2025-09-15 09:31:47 +00:00
{selectedEmployee.address.country}
</p>
</div>
)}
</div>
</div>
{/* Emergency Contact */}
{selectedEmployee.emergencyContact && (
<div>
<h5 className="text-base font-semibold text-gray-900 mb-2 flex items-center">
<FaPhone className="w-5 h-5 mr-2 text-red-600" />
Acil Durum İletişim
</h5>
<div className="bg-gray-50 p-3 rounded-lg">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<span className="text-sm text-gray-600">İsim:</span>
2025-09-15 19:46:52 +00:00
<p className="font-medium">{selectedEmployee.emergencyContact.name}</p>
2025-09-15 09:31:47 +00:00
</div>
<div>
<span className="text-sm text-gray-600">Yakınlık:</span>
<p className="font-medium">
{selectedEmployee.emergencyContact.relationship}
</p>
</div>
<div>
<span className="text-sm text-gray-600">Telefon:</span>
2025-09-15 19:46:52 +00:00
<p className="font-medium">{selectedEmployee.emergencyContact.phone}</p>
2025-09-15 09:31:47 +00:00
</div>
</div>
</div>
</div>
)}
</div>
{/* Modal Footer */}
<div className="flex justify-end gap-3 mt-4 pt-4 border-t">
<button
onClick={handleCloseModal}
className="px-3 py-1.5 text-sm text-gray-600 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
>
Kapat
</button>
</div>
</div>
</div>
)}
2025-09-15 19:46:52 +00:00
</Container>
)
}
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
export default OrganizationChart