erp-platform/ui/src/views/hr/components/EmployeeView.tsx
2025-09-15 22:46:52 +03:00

497 lines
21 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import {
FaTimes,
FaUser,
FaIdCard,
FaEnvelope,
FaPhone,
FaCalendar,
FaBuilding,
FaBriefcase,
FaDollarSign,
FaMapMarkerAlt,
FaUserShield,
FaHeartbeat,
FaEdit,
FaClock,
FaBirthdayCake,
FaGraduationCap,
FaAward,
FaHistory,
} from "react-icons/fa";
import { HrEmployee } from "../../../types/hr";
import {
getEmployeeStatusColor,
getEmployeeStatusIcon,
getEmployeeStatusText,
} from "../../../utils/erp";
interface EmployeeViewModalProps {
isOpen: boolean;
onClose: () => void;
employee: HrEmployee | null;
onEdit?: (employee: HrEmployee) => void;
}
const EmployeeViewModal: React.FC<EmployeeViewModalProps> = ({
isOpen,
onClose,
employee,
onEdit,
}) => {
if (!isOpen || !employee) return null;
const formatDate = (date: Date | string): string => {
return new Date(date).toLocaleDateString("tr-TR");
};
const calculateWorkDuration = (hireDate: Date): string => {
const now = new Date();
const hire = new Date(hireDate);
const diffTime = Math.abs(now.getTime() - hire.getTime());
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
const years = Math.floor(diffDays / 365);
const months = Math.floor((diffDays % 365) / 30);
if (years > 0) {
return `${years} yıl ${months} ay`;
}
return `${months} ay`;
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg shadow-2xl w-full max-w-4xl max-h-[95vh] overflow-hidden flex flex-col">
{/* Header */}
<div className="bg-gradient-to-r from-blue-600 to-indigo-700 text-white p-3 flex-shrink-0">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-white bg-opacity-20 rounded-full flex items-center justify-center">
<FaUser className="w-5 h-5 text-white" />
</div>
<div>
<h2 className="text-lg font-bold">{employee.fullName}</h2>
<p className="text-blue-100 text-sm">
{employee.jobPosition?.name || "Pozisyon Belirtilmemiş"}
</p>
<p className="text-blue-200 text-xs">{employee.code}</p>
</div>
</div>
<div className="flex items-center space-x-2">
<div
className={`px-2 py-0.5 rounded-full border flex items-center space-x-1.5 text-xs ${getEmployeeStatusColor(
employee.employeeStatus
)} bg-opacity-90`}
>
{getEmployeeStatusIcon(employee.employeeStatus)}
<span className="font-medium text-xs">
{getEmployeeStatusText(employee.employeeStatus)}
</span>
</div>
{onEdit && (
<button
onClick={() => onEdit(employee)}
className="bg-white bg-opacity-20 hover:bg-opacity-30 text-white px-2 py-1 text-xs rounded-md flex items-center space-x-1.5 transition-all"
>
<FaEdit className="w-3 h-3" />
<span>Düzenle</span>
</button>
)}
<button
onClick={onClose}
className="text-white hover:bg-white hover:bg-opacity-20 p-1 rounded-lg transition-all"
>
<FaTimes className="w-5 h-5" />
</button>
</div>
</div>
</div>
{/* Content */}
<div className="p-3 overflow-y-auto flex-grow">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-3">
{/* Left Column - Personal Info */}
<div className="space-y-3">
{/* Kişisel Bilgiler */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaIdCard className="w-4 h-4 text-blue-600 mr-2" />
Kişisel Bilgiler
</h3>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<FaBirthdayCake className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Doğum Tarihi</p>
<p className="font-medium text-sm">
{formatDate(employee.birthDate)}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaUser className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Cinsiyet</p>
<p className="font-medium text-sm">{employee.gender}</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaHeartbeat className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Medeni Durum</p>
<p className="font-medium text-sm">
{employee.maritalStatus}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaIdCard className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">TC Kimlik No</p>
<p className="font-medium text-sm">
{employee.nationalId}
</p>
</div>
</div>
</div>
</div>
{/* İletişim Bilgileri */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaPhone className="w-4 h-4 text-green-600 mr-2" />
İletişim Bilgileri
</h3>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<FaEnvelope className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">E-posta</p>
<p className="font-medium text-sm text-blue-600">
{employee.email}
</p>
</div>
</div>
{employee.phone && (
<div className="flex items-center space-x-2">
<FaPhone className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">İş Telefonu</p>
<p className="font-medium text-sm">{employee.phone}</p>
</div>
</div>
)}
{employee.personalPhone && (
<div className="flex items-center space-x-2">
<FaPhone className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Kişisel Telefon</p>
<p className="font-medium text-sm">
{employee.personalPhone}
</p>
</div>
</div>
)}
{employee.address && (
<div className="flex items-start space-x-2">
<FaMapMarkerAlt className="w-3 h-3 text-gray-500 mt-0.5" />
<div>
<p className="text-xs text-gray-600">Adres</p>
<p className="font-medium text-sm">
{employee.address.street}
<br />
{employee.address.city}, {employee.address.state}
<br />
{employee.address.postalCode},{" "}
{employee.address.country}
</p>
</div>
</div>
)}
</div>
</div>
{/* Acil Durum İletişim */}
{employee.emergencyContact && (
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaUserShield className="w-4 h-4 text-red-600 mr-2" />
Acil Durum İletişim
</h3>
<div className="space-y-2">
<div>
<p className="text-xs text-gray-600">İsim</p>
<p className="font-medium text-sm">
{employee.emergencyContact.name}
</p>
</div>
<div>
<p className="text-xs text-gray-600">Telefon</p>
<p className="font-medium text-sm">
{employee.emergencyContact.phone}
</p>
</div>
<div>
<p className="text-xs text-gray-600">Yakınlık</p>
<p className="font-medium text-sm">
{employee.emergencyContact.relationship}
</p>
</div>
</div>
</div>
)}
</div>
{/* Middle Column - Work Info */}
<div className="space-y-3">
{/* İş Bilgileri */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaBriefcase className="w-4 h-4 text-purple-600 mr-2" />
İş Bilgileri
</h3>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<FaBuilding className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Departman</p>
<p className="font-medium text-sm">
{employee.department?.name || "Belirtilmemiş"}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaGraduationCap className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Pozisyon</p>
<p className="font-medium text-sm">
{employee.jobPosition?.name || "Belirtilmemiş"}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaCalendar className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">
İşe Başlama Tarihi
</p>
<p className="font-medium text-sm">
{formatDate(employee.hireDate)}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaHistory className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Çalışma Süresi</p>
<p className="font-medium text-sm">
{calculateWorkDuration(employee.hireDate)}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<FaBriefcase className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Çalışma Türü</p>
<p className="font-medium text-sm">
{employee.employmentType}
</p>
</div>
</div>
{employee.workLocation && (
<div className="flex items-center space-x-2">
<FaMapMarkerAlt className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">
Çalışma Lokasyonu
</p>
<p className="font-medium text-sm">
{employee.workLocation}
</p>
</div>
</div>
)}
{employee.badgeNumber && (
<div className="flex items-center space-x-2">
<FaIdCard className="w-3 h-3 text-gray-500" />
<div>
<p className="text-xs text-gray-600">Rozet Numarası</p>
<p className="font-medium text-sm">
{employee.badgeNumber}
</p>
</div>
</div>
)}
</div>
</div>
{/* Yönetici Bilgileri */}
{employee.manager && (
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaUserShield className="w-4 h-4 text-indigo-600 mr-2" />
Yönetici
</h3>
<div className="flex items-center space-x-2">
<div className="w-10 h-10 bg-indigo-100 rounded-full flex items-center justify-center">
<FaUser className="w-5 h-5 text-indigo-600" />
</div>
<div>
<p className="font-medium text-sm text-gray-900">
{employee.manager.fullName}
</p>
<p className="text-xs text-gray-600">
{employee.manager.jobPosition?.name}
</p>
<p className="text-sm text-gray-600">
{employee.manager.email}
</p>
</div>
</div>
</div>
)}
{/* Performans ve Eğitimler */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaAward className="w-4 h-4 text-amber-600 mr-2" />
Performans & Gelişim
</h3>
<div className="grid grid-cols-2 gap-3">
<div className="text-center p-1.5 bg-white rounded-md">
<p className="text-xl font-bold text-amber-600">
{employee.evaluations?.length || 0}
</p>
<p className="text-xs text-gray-600">Değerlendirme</p>
</div>
<div className="text-center p-1.5 bg-white rounded-md">
<p className="text-xl font-bold text-emerald-600">
{employee.trainings?.length || 0}
</p>
<p className="text-xs text-gray-600">Eğitim</p>
</div>
</div>
</div>
</div>
{/* Right Column - Financial & Additional Info */}
<div className="space-y-3">
{/* Maaş Bilgileri */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaDollarSign className="w-4 h-4 text-emerald-600 mr-2" />
Maaş Bilgileri
</h3>
<div className="space-y-2">
<div>
<p className="text-xs text-gray-600">Temel Maaş</p>
<p className="text-xl font-bold text-emerald-600">
{employee.baseSalary?.toLocaleString()}{" "}
{employee.currency || "TRY"}
</p>
</div>
{employee.payrollGroup && (
<div>
<p className="text-xs text-gray-600">Bordro Grubu</p>
<p className="font-medium text-sm">
{employee.payrollGroup}
</p>
</div>
)}
</div>
</div>
{/* Banka Bilgileri */}
{employee.bankAccount && (
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaDollarSign className="w-4 h-4 text-slate-600 mr-2" />
Banka Bilgileri
</h3>
<div className="space-y-2">
<div>
<p className="text-xs text-gray-600">Banka Adı</p>
<p className="font-medium text-sm">
{employee.bankAccount.bankName}
</p>
</div>
<div>
<p className="text-xs text-gray-600">Hesap Numarası</p>
<p className="font-mono text-xs">
{employee.bankAccount.accountNumber}
</p>
</div>
<div>
<p className="text-xs text-gray-600">IBAN</p>
<p className="font-mono text-xs">
{employee.bankAccount.iban}
</p>
</div>
</div>
</div>
)}
{/* İzin Durumu */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaCalendar className="w-4 h-4 text-sky-600 mr-2" />
İzin Durumu
</h3>
<div className="grid grid-cols-1 gap-2">
<div className="bg-white p-1.5 rounded-md flex justify-between items-center">
<span className="text-xs text-gray-600">Toplam İzin</span>
<span className="font-bold text-sm text-sky-600">
{employee.leaves?.length || 0}
</span>
</div>
<div className="bg-white p-1.5 rounded-md flex justify-between items-center">
<span className="text-xs text-gray-600">Kalan İzin</span>
<span className="font-bold text-sm text-emerald-600">
15 gün
</span>
</div>
</div>
</div>
{/* Sistem Bilgileri */}
<div className="bg-gray-50 rounded-lg p-3 border border-gray-100">
<h3 className="text-sm font-semibold text-gray-900 mb-2 flex items-center">
<FaClock className="w-4 h-4 text-gray-600 mr-2" />
Sistem Bilgileri
</h3>
<div className="space-y-2 text-xs">
<div>
<p className="text-gray-600">Oluşturulma Tarihi</p>
<p className="font-medium text-gray-800">
{formatDate(employee.creationTime)}
</p>
</div>
<div>
<p className="text-gray-600">Son Güncelleme</p>
<p className="font-medium text-gray-800">
{formatDate(employee.lastModificationTime)}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Footer */}
<div className="bg-gray-50 px-3 py-2 border-t flex-shrink-0">
<div className="flex justify-end">
<button
onClick={onClose}
className="px-3 py-1 text-sm bg-gray-600 text-white rounded-md hover:bg-gray-700 transition-colors"
>
Kapat
</button>
</div>
</div>
</div>
</div>
);
};
export default EmployeeViewModal;