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' import { Container } from '@/components/shared' 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.departmentId === 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" />