import React, { useState } from "react"; import { FaClock, FaUser, FaPlus, FaEdit, FaCheck, FaTimes, FaEye, FaUsers, } from "react-icons/fa"; import { LeaveStatusEnum, HrOvertime } from "../../../types/hr"; import DataTable, { Column } from "../../../components/common/DataTable"; import { mockOvertimes } from "../../../mocks/mockOvertimes"; import { mockEmployees } from "../../../mocks/mockEmployees"; import { mockDepartments } from "../../../mocks/mockDepartments"; import Widget from "../../../components/common/Widget"; import { getLeaveStatusColor, getLeaveStatusText } from "../../../utils/erp"; const OvertimeManagement: React.FC = () => { // Overtime states const [overtimes, setOvertimes] = useState(mockOvertimes); const [overtimeSelectedStatus, setOvertimeSelectedStatus] = useState("all"); const [overtimeSelectedPeriod, setOvertimeSelectedPeriod] = useState("all"); const [searchOvertimesTerm, setSearchOvertimesTerm] = useState(""); const [selectedDepartment, setSelectedDepartment] = useState("all"); // Overtime modal states const [showOvertimeAddModal, setShowOvertimeAddModal] = useState(false); const [showOvertimeEditModal, setShowOvertimeEditModal] = useState(false); const [showOvertimeViewModal, setShowOvertimeViewModal] = useState(false); const [showOvertimeRejectModal, setShowOvertimeRejectModal] = useState(false); const [showBulkOvertimeModal, setShowBulkOvertimeModal] = useState(false); const [selectedOvertime, setSelectedOvertime] = useState( null ); const [overtimeRejectReason, setOvertimeRejectReason] = useState(""); // Overtime form state const [overtimeFormData, setOvertimeFormData] = useState({ employeeId: "", date: "", startTime: "", endTime: "", reason: "", rate: 1.5, }); // Bulk overtime form state const [bulkOvertimeFormData, setBulkOvertimeFormData] = useState({ departmentId: "", selectedEmployees: [] as string[], date: "", startTime: "", endTime: "", reason: "", rate: 1.5, }); // Get employees by department const getEmployeesByDepartment = (departmentId: string) => { return mockEmployees.filter((emp) => emp.departmantId === departmentId); }; // Get selected employee object const getSelectedEmployee = (employeeId: string) => { return mockEmployees.find((emp) => emp.id === employeeId); }; // Overtime handlers const handleOvertimeAdd = () => { setOvertimeFormData({ employeeId: "", date: "", startTime: "", endTime: "", reason: "", rate: 1.5, }); setShowOvertimeAddModal(true); }; const handleOvertimeEdit = (overtime: HrOvertime) => { setSelectedOvertime(overtime); setOvertimeFormData({ employeeId: overtime.employeeId, date: new Date(overtime.date).toISOString().split("T")[0], startTime: overtime.startTime, endTime: overtime.endTime, reason: overtime.reason, rate: overtime.rate || 1.5, }); setShowOvertimeEditModal(true); }; const handleOvertimeApprove = (id: string) => { setOvertimes((prevOvertimes) => prevOvertimes.map((overtime) => overtime.id === id ? { ...overtime, status: LeaveStatusEnum.Approved, lastModificationTime: new Date(), } : overtime ) ); alert("Mesai talebi onaylandı!"); }; const handleOvertimeReject = (id: string, reason?: string) => { if (reason) { setOvertimes((prevOvertimes) => prevOvertimes.map((overtime) => overtime.id === id ? { ...overtime, status: LeaveStatusEnum.Rejected, lastModificationTime: new Date(), } : overtime ) ); setShowOvertimeRejectModal(false); setOvertimeRejectReason(""); alert("Mesai talebi reddedildi!"); } else { const overtime = overtimes.find((o) => o.id === id); if (overtime) { setSelectedOvertime(overtime); setShowOvertimeRejectModal(true); } } }; const handleOvertimeView = (overtime: HrOvertime) => { setSelectedOvertime(overtime); setShowOvertimeViewModal(true); }; const handleSubmitOvertimeAdd = () => { if ( !overtimeFormData.employeeId || !overtimeFormData.date || !overtimeFormData.startTime || !overtimeFormData.endTime ) { alert("Lütfen tüm gerekli alanları doldurun!"); return; } const startTime = new Date(`2000-01-01 ${overtimeFormData.startTime}`); const endTime = new Date(`2000-01-01 ${overtimeFormData.endTime}`); const totalHours = (endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60); if (totalHours <= 0) { alert("Bitiş saati başlangıç saatinden sonra olmalıdır!"); return; } const newOvertime: HrOvertime = { id: `ot_${Date.now()}`, employeeId: overtimeFormData.employeeId, date: new Date(overtimeFormData.date), startTime: overtimeFormData.startTime, endTime: overtimeFormData.endTime, totalHours: totalHours, reason: overtimeFormData.reason, status: LeaveStatusEnum.Pending, rate: overtimeFormData.rate, amount: totalHours * 100 * overtimeFormData.rate, // Assuming 100 TL/hour base rate creationTime: new Date(), lastModificationTime: new Date(), }; setOvertimes((prevOvertimes) => [...prevOvertimes, newOvertime]); setShowOvertimeAddModal(false); alert("Mesai talebi başarıyla oluşturuldu!"); }; const handleSubmitOvertimeEdit = () => { if (!selectedOvertime) return; if ( !overtimeFormData.employeeId || !overtimeFormData.date || !overtimeFormData.startTime || !overtimeFormData.endTime ) { alert("Lütfen tüm gerekli alanları doldurun!"); return; } const startTime = new Date(`2000-01-01 ${overtimeFormData.startTime}`); const endTime = new Date(`2000-01-01 ${overtimeFormData.endTime}`); const totalHours = (endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60); if (totalHours <= 0) { alert("Bitiş saati başlangıç saatinden sonra olmalıdır!"); return; } setOvertimes((prevOvertimes) => prevOvertimes.map((overtime) => overtime.id === selectedOvertime.id ? { ...overtime, employeeId: overtimeFormData.employeeId, date: new Date(overtimeFormData.date), startTime: overtimeFormData.startTime, endTime: overtimeFormData.endTime, totalHours: totalHours, reason: overtimeFormData.reason, rate: overtimeFormData.rate, amount: totalHours * 100 * overtimeFormData.rate, lastModificationTime: new Date(), } : overtime ) ); setShowOvertimeEditModal(false); setSelectedOvertime(null); alert("Mesai talebi başarıyla güncellendi!"); }; const handleSubmitOvertimeReject = () => { if (!selectedOvertime || !overtimeRejectReason.trim()) { alert("Lütfen red nedeni giriniz!"); return; } handleOvertimeReject(selectedOvertime.id, overtimeRejectReason); }; const handleBulkOvertimeAdd = () => { setBulkOvertimeFormData({ departmentId: "", selectedEmployees: [], date: "", startTime: "", endTime: "", reason: "", rate: 1.5, }); setShowBulkOvertimeModal(true); }; const handleSubmitBulkOvertime = () => { if ( !bulkOvertimeFormData.selectedEmployees.length || !bulkOvertimeFormData.date || !bulkOvertimeFormData.startTime || !bulkOvertimeFormData.endTime ) { alert( "Lütfen en az bir personel seçin ve tüm gerekli alanları doldurun!" ); return; } const startTime = new Date(`2000-01-01 ${bulkOvertimeFormData.startTime}`); const endTime = new Date(`2000-01-01 ${bulkOvertimeFormData.endTime}`); const totalHours = (endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60); if (totalHours <= 0) { alert("Bitiş saati başlangıç saatinden sonra olmalıdır!"); return; } const newOvertimes: HrOvertime[] = bulkOvertimeFormData.selectedEmployees.map((employeeId) => { const employee = getSelectedEmployee(employeeId); return { id: `ot_${Date.now()}_${employeeId}`, employeeId: employeeId, employee: employee, date: new Date(bulkOvertimeFormData.date), startTime: bulkOvertimeFormData.startTime, endTime: bulkOvertimeFormData.endTime, totalHours: totalHours, reason: bulkOvertimeFormData.reason, status: LeaveStatusEnum.Pending, rate: bulkOvertimeFormData.rate, amount: totalHours * 100 * bulkOvertimeFormData.rate, // 100 TL/hour base rate creationTime: new Date(), lastModificationTime: new Date(), }; }); setOvertimes((prevOvertimes) => [...prevOvertimes, ...newOvertimes]); setShowBulkOvertimeModal(false); setBulkOvertimeFormData({ departmentId: "", selectedEmployees: [], date: "", startTime: "", endTime: "", reason: "", rate: 1.5, }); alert( `${newOvertimes.length} personel için toplu mesai talebi başarıyla oluşturuldu!` ); }; // Filter overtime data const filteredOvertimes = overtimes.filter((overtime) => { if ( overtimeSelectedStatus !== "all" && overtime.status !== overtimeSelectedStatus ) { return false; } if ( selectedDepartment !== "all" && overtime.employee?.department?.name !== selectedDepartment ) { return false; } if (overtimeSelectedPeriod !== "all") { const now = new Date(); const overtimeDate = new Date(overtime.date); switch (overtimeSelectedPeriod) { case "this-month": { const currentMonth = now.getMonth(); const currentYear = now.getFullYear(); return ( overtimeDate.getMonth() === currentMonth && overtimeDate.getFullYear() === currentYear ); } case "last-month": { const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1); return ( overtimeDate.getMonth() === lastMonth.getMonth() && overtimeDate.getFullYear() === lastMonth.getFullYear() ); } case "last-3-months": { const threeMonthsAgo = new Date( now.getFullYear(), now.getMonth() - 3 ); return overtimeDate >= threeMonthsAgo; } default: return true; } } // Search filter if (searchOvertimesTerm.trim() !== "") { if (overtime.employeeId !== searchOvertimesTerm) { return false; } } return true; }); // Overtime table columns const overtimeColumns: Column[] = [ { key: "employee", header: "Personel", render: (overtime: HrOvertime) => { const employee = mockEmployees.find( (emp) => emp.id === overtime.employeeId ); return (
{employee?.fullName}
{employee?.code}
); }, }, { key: "date", header: "Tarih", render: (overtime: HrOvertime) => (
{new Date(overtime.date).toLocaleDateString("tr-TR")}
), }, { key: "time", header: "Mesai Saatleri", render: (overtime: HrOvertime) => (
{overtime.startTime} - {overtime.endTime}
{overtime.totalHours} saat
), }, { key: "reason", header: "Neden", render: (overtime: HrOvertime) => (
{overtime.reason}
), }, { key: "rate", header: "Çarpan", render: (overtime: HrOvertime) => (
x{overtime.rate}
), }, { key: "amount", header: "Tutar", render: (overtime: HrOvertime) => (
{overtime.amount?.toLocaleString("tr-TR")} ₺
), }, { key: "status", header: "Durum", render: (overtime: HrOvertime) => ( {getLeaveStatusText(overtime.status)} ), }, { key: "actions", header: "İşlemler", render: (overtime: HrOvertime) => (
{overtime.status === LeaveStatusEnum.Pending && ( <> )}
), }, ]; return (
{/* Header */}

Mesai Yönetimi

Personel mesai talepleri ve onay süreçleri

{/* Stats Cards */}
o.status === LeaveStatusEnum.Pending).length } color="yellow" icon="FaClock" /> o.status === LeaveStatusEnum.Approved) .length } color="green" icon="FaCheck" /> o.status === LeaveStatusEnum.Approved) .reduce((sum, o) => sum + (o.amount || 0), 0) .toLocaleString("tr-TR")} ₺`} color="purple" icon="FaDollarSign" />
{/* Filters */}
{/* Data Table */}
{filteredOvertimes.length === 0 && (

Mesai talebi bulunamadı

Seçilen kriterlere uygun mesai talebi bulunmamaktadır.

)} {/* Overtime Add/Edit Modal */} {(showOvertimeAddModal || showOvertimeEditModal) && selectedOvertime && (

{showOvertimeAddModal ? "Yeni Mesai Talebi" : "Mesai Talebini Düzenle"}

setOvertimeFormData({ ...overtimeFormData, date: e.target.value, }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
setOvertimeFormData({ ...overtimeFormData, startTime: e.target.value, }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
setOvertimeFormData({ ...overtimeFormData, endTime: e.target.value, }) } className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />