import { useState, useEffect } from 'react'; import { DollarSign, Plus, Search, Edit, Trash2, CheckCircle, XCircle, X, Calculator, Clock, Calendar } from 'lucide-react'; import { ToastContainer, useToast } from '../../UI/Toast'; import Table, { Column } from '../../UI/Table'; import ActionButtons from '../../UI/ActionButtons'; import ButtonUI from '../../UI/ButtonUI'; import Pagination from '../../UI/Pagination'; import ToggleSwitch from '../../UI/ToggleSwitch'; import CustomInput from '../../UI/CustomInput'; interface PerHourCost { id: string; minimumSalary: number; maximumSalary: number; workingDays: number; workingHours: number; perHourCost: number; status: 'Active' | 'Inactive'; createdAt: string; updatedAt?: string; } // Create/Edit Modal Component interface ModalProps { isOpen: boolean; onClose: () => void; onSave: (data: { minimumSalary: number; maximumSalary: number; workingDays: number; workingHours: number; perHourCost: number }) => void; title: string; initialData?: { minimumSalary: number; maximumSalary: number; workingDays: number; workingHours: number } | null; } const Modal = ({ isOpen, onClose, onSave, title, initialData }: ModalProps) => { const [formData, setFormData] = useState({ minimumSalary: initialData?.minimumSalary || 0, maximumSalary: initialData?.maximumSalary || 0, workingDays: initialData?.workingDays || 26, workingHours: initialData?.workingHours || 7, }); const [perHourCost, setPerHourCost] = useState(0); useEffect(() => { if (initialData) { setFormData({ minimumSalary: initialData.minimumSalary || 0, maximumSalary: initialData.maximumSalary || 0, workingDays: initialData.workingDays || 26, workingHours: initialData.workingHours || 7, }); } }, [initialData]); useEffect(() => { if (isOpen && !initialData) { setFormData({ minimumSalary: 0, maximumSalary: 0, workingDays: 26, workingHours: 7, }); } }, [isOpen, initialData]); // Calculate per hour cost useEffect(() => { const { minimumSalary, maximumSalary, workingDays, workingHours } = formData; if (minimumSalary > 0 && maximumSalary > 0 && workingDays > 0 && workingHours > 0) { // Average salary calculation const avgSalary = (minimumSalary + maximumSalary) / 2; const totalHours = workingDays * workingHours; const cost = avgSalary / totalHours; setPerHourCost(cost); } else { setPerHourCost(0); } }, [formData]); if (!isOpen) return null; const handleInputChange = (field: string, value: any) => { setFormData((prev) => ({ ...prev, [field]: value })); }; const handleSubmit = () => { if (formData.minimumSalary <= 0 || formData.maximumSalary <= 0 || formData.workingDays <= 0 || formData.workingHours <= 0) { return; } onSave({ ...formData, perHourCost: perHourCost, }); }; const formatCurrency = (value: number) => { return new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(value); }; return ( <>

{title}

{/* Minimum Salary */}
handleInputChange('minimumSalary', value)} type="number" placeholder="Enter Minimum Salary" required icon={} />
{/* Maximum Salary */}
handleInputChange('maximumSalary', value)} type="number" placeholder="Enter Maximum Salary" required icon={} />
{/* Working Days */}
handleInputChange('workingDays', value)} type="number" placeholder="Enter Working Days" required icon={} />
{/* Working Hours */}
handleInputChange('workingHours', value)} type="number" placeholder="Enter Working Hours" required icon={} />
{/* Per Hour Cost - Auto Calculated */} {perHourCost > 0 && (
Per Hour Cost
{formatCurrency(perHourCost)}
)}
Cancel {initialData ? 'Update Per Hour Cost' : 'Create Per Hour Cost'}
); }; const PerHourCost = () => { const toast = useToast(); const [searchTerm, setSearchTerm] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [showEntries, setShowEntries] = useState(10); const [showCreateModal, setShowCreateModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [selectedCost, setSelectedCost] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [costToDelete, setCostToDelete] = useState(null); const [isDeleting, setIsDeleting] = useState(false); // Mock data for per hour cost const [perHourCosts, setPerHourCosts] = useState([ { id: '1', minimumSalary: 10000, maximumSalary: 15000, workingDays: 26, workingHours: 7, perHourCost: 68.68, status: 'Active', createdAt: '2024-01-15', }, { id: '2', minimumSalary: 15000, maximumSalary: 20000, workingDays: 26, workingHours: 7, perHourCost: 96.15, status: 'Active', createdAt: '2024-02-10', }, { id: '3', minimumSalary: 20000, maximumSalary: 25000, workingDays: 25, workingHours: 8, perHourCost: 112.5, status: 'Active', createdAt: '2024-03-05', }, { id: '4', minimumSalary: 25000, maximumSalary: 30000, workingDays: 26, workingHours: 7, perHourCost: 151.1, status: 'Inactive', createdAt: '2024-04-20', }, { id: '5', minimumSalary: 30000, maximumSalary: 35000, workingDays: 26, workingHours: 7, perHourCost: 178.57, status: 'Active', createdAt: '2024-05-15', }, ]); const handleAddCost = () => { setSelectedCost(null); setShowCreateModal(true); }; const handleEditCost = (cost: PerHourCost) => { setSelectedCost(cost); setShowEditModal(true); }; const handleDeleteCost = (cost: PerHourCost) => { setCostToDelete(cost); setShowDeleteModal(true); }; const handleConfirmDelete = () => { if (!costToDelete) return; setIsDeleting(true); setTimeout(() => { setPerHourCosts(perHourCosts.filter((c) => c.id !== costToDelete.id)); setShowDeleteModal(false); setCostToDelete(null); setIsDeleting(false); toast.success(`Per hour cost deleted successfully!`); }, 1000); }; const handleSaveCost = (formData: { minimumSalary: number; maximumSalary: number; workingDays: number; workingHours: number; perHourCost: number }) => { if (formData.minimumSalary <= 0 || formData.maximumSalary <= 0 || formData.workingDays <= 0 || formData.workingHours <= 0) { toast.error('Please fill in all required fields'); return; } if (selectedCost) { setPerHourCosts( perHourCosts.map((c) => c.id === selectedCost.id ? { ...c, ...formData, updatedAt: new Date().toISOString().split('T')[0], } : c, ), ); toast.success('Per hour cost updated successfully!'); setShowEditModal(false); setSelectedCost(null); } else { const newCost: PerHourCost = { id: String(perHourCosts.length + 1), ...formData, status: 'Active', createdAt: new Date().toISOString().split('T')[0], }; setPerHourCosts([...perHourCosts, newCost]); toast.success('Per hour cost created successfully!'); setShowCreateModal(false); } }; const handleToggleStatus = (id: string) => { setPerHourCosts(perHourCosts.map((c) => (c.id === id ? { ...c, status: c.status === 'Active' ? 'Inactive' : 'Active' } : c))); const cost = perHourCosts.find((c) => c.id === id); toast.info(`Per hour cost status changed to ${cost?.status === 'Active' ? 'Inactive' : 'Active'}`); }; const filteredCosts = perHourCosts.filter((cost) => { const searchLower = searchTerm.toLowerCase(); return cost.minimumSalary.toString().includes(searchTerm) || cost.maximumSalary.toString().includes(searchTerm) || cost.perHourCost.toString().includes(searchTerm); }); const totalPages = Math.ceil(filteredCosts.length / showEntries); const startIndex = (currentPage - 1) * showEntries; const currentCosts = filteredCosts.slice(startIndex, startIndex + showEntries); const formatCurrency = (value: number) => { return new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(value); }; const columns: Column[] = [ { key: 'sno', header: 'S.No', align: 'center', accessor: (_row: PerHourCost, index: number) => { const page = currentPage || 1; const entries = showEntries || 10; const calculatedIndex = (page - 1) * entries + (index || 0) + 1; return {calculatedIndex}; }, }, { key: 'salaryRange', header: 'SALARY RANGE', accessor: (row: PerHourCost) => (
{formatCurrency(row.minimumSalary)} - {formatCurrency(row.maximumSalary)}
Min / Max Salary
), }, { key: 'workingDetails', header: 'WORKING DETAILS', accessor: (row: PerHourCost) => (
{row.workingDays} days | {row.workingHours} hrs
), }, { key: 'perHourCost', header: 'PER HOUR COST', accessor: (row: PerHourCost) =>
{formatCurrency(row.perHourCost)}
, }, { key: 'status', header: 'STATUS', align: 'center', accessor: (row: PerHourCost) => handleToggleStatus(row.id)} activeColor="bg-green-600" inactiveColor="bg-gray-300" />, }, { key: 'actions', header: 'ACTION', align: 'center', accessor: (row: PerHourCost) => ( handleEditCost(row)} onDelete={() => handleDeleteCost(row)} showView={false} editTooltip="Edit Per Hour Cost" deleteTooltip="Delete Per Hour Cost" size="sm" /> ), }, ]; return ( <>

Per Hour Cost

Manage per hour cost calculations

} onClick={handleAddCost}> Create Per Hour Cost

Total Records

{perHourCosts.length}

Active

{perHourCosts.filter((c) => c.status === 'Active').length}

Inactive

{perHourCosts.filter((c) => c.status === 'Inactive').length}

Show
setSearchTerm(e.target.value)} className="w-full pl-9 pr-4 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20" />
{filteredCosts.length > 0 && ( )} { setShowCreateModal(false); setSelectedCost(null); }} onSave={handleSaveCost} title="Create Per Hour Cost" initialData={null} /> { setShowEditModal(false); setSelectedCost(null); }} onSave={handleSaveCost} title="Edit Per Hour Cost" initialData={ selectedCost ? { minimumSalary: selectedCost.minimumSalary, maximumSalary: selectedCost.maximumSalary, workingDays: selectedCost.workingDays, workingHours: selectedCost.workingHours, } : null } /> {showDeleteModal && (

Delete Per Hour Cost

Are you sure you want to delete this per hour cost record? This action cannot be undone.

{ setShowDeleteModal(false); setCostToDelete(null); }} > Cancel {isDeleting ? 'Deleting...' : 'Delete'}
)} ); }; export default PerHourCost;