import React, { useState, useEffect } from 'react'; import { X, Calendar, AlertCircle, Upload } from 'lucide-react'; const EditLeaveRequestModal = ({ onClose, request, availableLeaveCounters, accessToken, userId, userEmail, userRole, userName, onRequestUpdated }) => { const [leaveType, setLeaveType] = useState(request.typeId || ''); const [startDate, setStartDate] = useState(request.startDate || ''); const [endDate, setEndDate] = useState(request.endDate || ''); const [reason, setReason] = useState(request.reason || ''); const [businessDays, setBusinessDays] = useState(request.days || 0); const [saturdayCount, setSaturdayCount] = useState(0); const [medicalDocuments, setMedicalDocuments] = useState([]); const [errors, setErrors] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false); const [submitMessage, setSubmitMessage] = useState({ type: '', text: '' }); // ⭐ Types de congés disponibles selon le rôle const getLeaveTypes = () => { const baseTypes = [ { id: 1, name: 'Congé payé', key: 'CP', counter: availableLeaveCounters.availableCP }, ]; // Ajouter RTT sauf pour les apprentis if (userRole !== 'Apprenti') { baseTypes.push({ id: 2, name: 'RTT', key: 'RTT', counter: availableLeaveCounters.availableRTT }); } // Ajouter les types sans compteur baseTypes.push( { id: 3, name: 'Arrêt maladie', key: 'ABS', counter: null }, { id: 5, name: 'Récupération (samedi)', key: 'Récup', counter: null } ); // Ajouter Formation pour les apprentis if (userRole === 'Apprenti') { baseTypes.push({ id: 4, name: 'Formation', key: 'Formation', counter: null }); } return baseTypes; }; const leaveTypes = getLeaveTypes(); // ⭐ Calcul des jours ouvrés ET des samedis useEffect(() => { if (startDate && endDate) { const result = calculateBusinessDaysAndSaturdays(startDate, endDate); setBusinessDays(result.workingDays); setSaturdayCount(result.saturdays); } }, [startDate, endDate]); const calculateBusinessDaysAndSaturdays = (start, end) => { const startD = new Date(start); const endD = new Date(end); let workingDays = 0; let saturdays = 0; const current = new Date(startD); while (current <= endD) { const dayOfWeek = current.getDay(); if (dayOfWeek === 6) { saturdays++; } else if (dayOfWeek !== 0) { // Pas dimanche workingDays++; } current.setDate(current.getDate() + 1); } return { workingDays, saturdays }; }; const validateForm = () => { const newErrors = {}; if (!leaveType) { newErrors.leaveType = 'Veuillez sélectionner un type de congé'; } if (!startDate) { newErrors.startDate = 'La date de début est requise'; } if (!endDate) { newErrors.endDate = 'La date de fin est requise'; } if (startDate && endDate && new Date(startDate) > new Date(endDate)) { newErrors.endDate = 'La date de fin doit être après la date de début'; } // ⭐ Validation spécifique pour Récupération const selectedType = leaveTypes.find(t => t.id === parseInt(leaveType)); if (selectedType?.key === 'Récup') { if (saturdayCount === 0) { newErrors.days = 'Une récupération nécessite au moins un samedi dans la période sélectionnée'; } } // ⭐ Validation spécifique pour Arrêt maladie if (selectedType?.key === 'ABS' && medicalDocuments.length === 0) { newErrors.medical = 'Un justificatif médical est obligatoire pour un arrêt maladie'; } // Vérification du solde disponible (CP et RTT uniquement) if (selectedType && selectedType.counter !== null && businessDays > selectedType.counter) { newErrors.days = `Solde insuffisant. Disponible : ${selectedType.counter} jour(s)`; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleFileUpload = (e) => { const files = Array.from(e.target.files); const validFiles = []; const maxSize = 5 * 1024 * 1024; // 5MB for (const file of files) { const validTypes = ['application/pdf', 'image/jpeg', 'image/jpg', 'image/png']; if (!validTypes.includes(file.type)) { setSubmitMessage({ type: 'error', text: `Le fichier "${file.name}" n'est pas un format valide.` }); continue; } if (file.size > maxSize) { setSubmitMessage({ type: 'error', text: `Le fichier "${file.name}" est trop volumineux (max 5MB).` }); continue; } validFiles.push(file); } setMedicalDocuments(prev => [...prev, ...validFiles]); e.target.value = ''; }; const removeDocument = (index) => { setMedicalDocuments(prev => prev.filter((_, i) => i !== index)); }; const formatFileSize = (bytes) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const handleSubmit = async (e) => { e.preventDefault(); if (!validateForm()) { return; } setIsSubmitting(true); setSubmitMessage({ type: '', text: '' }); try { const formDataToSend = new FormData(); formDataToSend.append('requestId', request.id); formDataToSend.append('leaveType', parseInt(leaveType)); formDataToSend.append('startDate', startDate); formDataToSend.append('endDate', endDate); formDataToSend.append('reason', reason); formDataToSend.append('userId', userId); formDataToSend.append('userEmail', userEmail); formDataToSend.append('userName', userName); formDataToSend.append('accessToken', accessToken); // ⭐ Calcul des jours selon le type const selectedType = leaveTypes.find(t => t.id === parseInt(leaveType)); const daysToSend = selectedType?.key === 'Récup' ? saturdayCount : businessDays; formDataToSend.append('businessDays', daysToSend); // ⭐ Documents médicaux medicalDocuments.forEach((file) => { formDataToSend.append('medicalDocuments', file); }); const response = await fetch('http://localhost:3000/updateRequest', { method: 'POST', body: formDataToSend }); const data = await response.json(); if (data.success) { setSubmitMessage({ type: 'success', text: '✅ Demande modifiée avec succès ! Le manager a été informé par email.' }); setTimeout(() => { onRequestUpdated(); onClose(); }, 2000); } else { setSubmitMessage({ type: 'error', text: `❌ ${data.message || 'Erreur lors de la modification'}` }); } } catch (error) { console.error('Erreur:', error); setSubmitMessage({ type: 'error', text: '❌ Une erreur est survenue. Veuillez réessayer.' }); } finally { setIsSubmitting(false); } }; const getMinDate = () => { const today = new Date(); return today.toISOString().split('T')[0]; }; const selectedType = leaveTypes.find(t => t.id === parseInt(leaveType)); return (