import { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Calendar, Plus, Trash2, Edit2, Loader2, AlertCircle, CheckCircle, } from 'lucide-react'; import { getAllHolidays, createHoliday, updateHoliday, deleteHoliday, Holiday } from '@/services/adminApi'; import { formatDateShort } from '@/utils/dateFormatter'; import { toast } from 'sonner'; export function HolidayManager() { const [holidays, setHolidays] = useState([]); const [loading, setLoading] = useState(true); const [selectedYear, setSelectedYear] = useState(new Date().getFullYear()); const [showAddDialog, setShowAddDialog] = useState(false); const [editingHoliday, setEditingHoliday] = useState(null); const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const [formData, setFormData] = useState({ holidayDate: '', holidayName: '', description: '', holidayType: 'ORGANIZATIONAL' as Holiday['holidayType'], isRecurring: false }); useEffect(() => { loadHolidays(); }, [selectedYear]); const loadHolidays = async () => { try { setLoading(true); setError(null); const data = await getAllHolidays(selectedYear); setHolidays(data); } catch (err: any) { setError(err.response?.data?.error || 'Failed to load holidays'); } finally { setLoading(false); } }; const handleAdd = () => { setFormData({ holidayDate: '', holidayName: '', description: '', holidayType: 'ORGANIZATIONAL', isRecurring: false }); setEditingHoliday(null); setShowAddDialog(true); }; const handleEdit = (holiday: Holiday) => { setFormData({ holidayDate: holiday.holidayDate, holidayName: holiday.holidayName, description: holiday.description || '', holidayType: holiday.holidayType, isRecurring: holiday.isRecurring }); setEditingHoliday(holiday); setShowAddDialog(true); }; // Calculate minimum date (tomorrow for new holidays, no restriction for editing) const getMinDate = () => { // Only enforce minimum date when adding new holidays, not when editing existing ones if (editingHoliday) { return undefined; // Allow editing past holidays } const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); return tomorrow.toISOString().split('T')[0]; }; const handleSave = async () => { try { setError(null); if (!formData.holidayDate || !formData.holidayName) { setError('Holiday date and name are required'); return; } if (editingHoliday) { // Update existing await updateHoliday(editingHoliday.holidayId, formData); toast.success('Holiday updated successfully'); } else { // Create new await createHoliday(formData); toast.success('Holiday created successfully'); } await loadHolidays(); setShowAddDialog(false); setTimeout(() => setSuccessMessage(null), 3000); } catch (err: any) { setError(err.response?.data?.error || 'Failed to save holiday'); } }; const handleDelete = async (holiday: Holiday) => { if (!confirm(`Delete "${holiday.holidayName}"?`)) { return; } try { setError(null); await deleteHoliday(holiday.holidayId); toast.success('Holiday deleted successfully'); await loadHolidays(); } catch (err: any) { const errorMsg = err.response?.data?.error || 'Failed to delete holiday'; setError(errorMsg); toast.error(errorMsg); } }; const getTypeColor = (type: Holiday['holidayType']) => { switch (type) { case 'NATIONAL': return 'bg-gradient-to-r from-red-50 to-rose-50 text-red-800 border-red-300'; case 'REGIONAL': return 'bg-gradient-to-r from-blue-50 to-cyan-50 text-blue-800 border-blue-300'; case 'ORGANIZATIONAL': return 'bg-gradient-to-r from-purple-50 to-violet-50 text-purple-800 border-purple-300'; case 'OPTIONAL': return 'bg-gradient-to-r from-slate-50 to-gray-50 text-slate-700 border-slate-300'; default: return 'bg-gradient-to-r from-red-50 to-rose-50 text-red-800 border-red-300'; } }; const years = Array.from({ length: 5 }, (_, i) => new Date().getFullYear() - 1 + i); // Group holidays by month const holidaysByMonth = holidays.reduce((acc, holiday) => { const month = new Date(holiday.holidayDate).toLocaleString('default', { month: 'long' }); if (!acc[month]) { acc[month] = []; } acc[month].push(holiday); return acc; }, {} as Record); // Sort months chronologically const sortedMonths = Object.keys(holidaysByMonth).sort((a, b) => { const monthA = new Date(Date.parse(a + " 1, 2000")).getMonth(); const monthB = new Date(Date.parse(b + " 1, 2000")).getMonth(); return monthA - monthB; }); return (
{/* Success Message */} {successMessage && (

{successMessage}

)} {/* Error Message */} {error && (

{error}

)} {/* Header */}
Holiday Calendar Manage organization holidays for TAT calculations
{/* Holidays List */} {loading ? (
) : holidays.length === 0 ? (

No holidays found for {selectedYear}

Add holidays to exclude them from TAT calculations

) : (
{sortedMonths.map(month => (
{month} {selectedYear} {holidaysByMonth[month]?.length || 0} holiday{(holidaysByMonth[month]?.length || 0) !== 1 ? 's' : ''}
{holidaysByMonth[month]?.map(holiday => (

{holiday.holidayName}

{holiday.holidayType} {holiday.isRecurring && ( Recurring )}

{formatDateShort(holiday.holidayDate)}

{holiday.description && (

{holiday.description}

)}
))}
))}
)} {/* Add/Edit Dialog */}
{editingHoliday ? 'Edit Holiday' : 'Add New Holiday'} {editingHoliday ? 'Update holiday information' : 'Add a new holiday to the calendar for TAT calculations'}
{/* Date Field */}
setFormData({ ...formData, holidayDate: e.target.value })} min={getMinDate()} className="h-11 border-slate-300 focus:border-re-green focus:ring-2 focus:ring-re-green/20 rounded-lg transition-all shadow-sm" />

{editingHoliday ? 'Select the holiday date' : 'Select the holiday date (minimum: tomorrow)'}

{/* Holiday Name Field */}
setFormData({ ...formData, holidayName: e.target.value })} className="h-11 border-slate-300 focus:border-re-green focus:ring-2 focus:ring-re-green/20 rounded-lg transition-all shadow-sm" />

Enter the official name of the holiday

{/* Description Field */}
setFormData({ ...formData, description: e.target.value })} className="h-11 border-slate-300 focus:border-re-green focus:ring-2 focus:ring-re-green/20 rounded-lg transition-all shadow-sm" />

Optional description or notes about the holiday

{/* Holiday Type Field */}

Select the category of this holiday

{/* Recurring Checkbox */}
setFormData({ ...formData, isRecurring: !formData.isRecurring })}> setFormData({ ...formData, isRecurring: e.target.checked })} className="mt-0.5 rounded border-slate-300 text-re-green focus:ring-2 focus:ring-re-green/20 focus:ring-offset-0 w-4 h-4 cursor-pointer" />

This holiday will automatically repeat every year on the same date

); }