import { useState, useEffect } from "react"; const AddTimeEntryModal = ({ show, onHide, onAdd, isEdit = false, existingEntry = null, onUpdate, defaultAutoMode = false, }) => { const [entry, setEntry] = useState({ date: "", reason: "", hours: "", startDate: "", startTime: "", endDate: "", endTime: "", isAuto: false, }); const [previewHours, setPreviewHours] = useState(0); useEffect(() => { if (isEdit && existingEntry) { console.log("=== EDITING ENTRY ==="); console.log("Existing entry data:", existingEntry); console.log("Status:", existingEntry.status); console.log("startDate:", existingEntry.startDate); console.log("startTime:", existingEntry.startTime); const isAutoEntry = !!( existingEntry.startDate || existingEntry.startTime || existingEntry.status === "active" ); console.log("Calculated isAutoEntry:", isAutoEntry); setEntry({ date: existingEntry.date ? new Date(existingEntry.date).toISOString().split("T")[0] : "", reason: existingEntry.reason || "", hours: existingEntry.hours || "", startDate: existingEntry.startDate ? new Date(existingEntry.startDate).toISOString().split("T")[0] : "", startTime: existingEntry.startTime || "", endDate: existingEntry.endDate ? new Date(existingEntry.endDate).toISOString().split("T")[0] : "", endTime: existingEntry.endTime || "", isAuto: isAutoEntry, }); setPreviewHours(existingEntry.hours || 0); console.log("Final entry state set:", { isAuto: isAutoEntry, startDate: existingEntry.startDate, startTime: existingEntry.startTime, status: existingEntry.status, }); } else if (!isEdit) { setEntry({ date: "", reason: "", hours: "", startDate: "", startTime: "", endDate: "", endTime: "", isAuto: defaultAutoMode, }); setPreviewHours(0); } }, [isEdit, existingEntry, show, defaultAutoMode]); const handleSubmit = (e) => { e.preventDefault(); const submitData = { ...entry }; // Очищаем пустые поля Object.keys(submitData).forEach((key) => { if (submitData[key] === "" && key !== "reason") { submitData[key] = null; } }); // Для ручного режима используем date и hours if (!entry.isAuto) { submitData.startDate = null; submitData.startTime = null; submitData.endDate = null; submitData.endTime = null; } console.log("Final submit data:", submitData); if (isEdit && onUpdate) { onUpdate(existingEntry.id, submitData); } else { onAdd(submitData); } if (!isEdit) { setEntry({ date: "", reason: "", hours: "", startDate: "", startTime: "", endDate: "", endTime: "", isAuto: defaultAutoMode, }); setPreviewHours(0); } }; const handleChange = (e) => { const { name, value, type, checked } = e.target; const newValue = type === "checkbox" ? checked : value; setEntry({ ...entry, [name]: newValue }); }; // Функция предварительного расчета часов (соответствует бэкендовому алгоритму) const calculatePreviewHours = (startDate, startTime, endDate, endTime) => { if (!startDate || !startTime) return 0; try { const startDateTime = new Date(`${startDate}T${startTime || "09:00"}`); const endDateTime = endDate && endTime ? new Date(`${endDate}T${endTime}`) : null; // Если нет даты окончания - возвращаем 0 (открытая запись) if (!endDateTime) { return 0; } // Если дата окончания раньше даты начала - ошибка if (endDateTime < startDateTime) { throw new Error("Дата окончания не может быть раньше даты начала"); } const WORK_START = 9 * 60; // 09:00 в минутах const WORK_END = 18 * 60; // 18:00 в минутах const LUNCH_START = 12 * 60; // 12:00 в минутах const LUNCH_END = 13 * 60; // 13:00 в минутах let totalMinutes = 0; let currentDate = new Date(startDate); // Проходим по каждому дню от начала до окончания while ( currentDate <= (endDateTime ? new Date(endDate) : new Date(startDate)) ) { const day = currentDate.getDay(); // 0 = воскресенье, 1 = понедельник, ..., 6 = суббота if (day >= 1 && day <= 5) { // понедельник-пятница const dayStart = new Date(currentDate); dayStart.setHours(0, 0, 0, 0); const dayEnd = new Date(currentDate); dayEnd.setHours(23, 59, 59, 999); // Определяем время начала работы в этот день let workStartMinutes = WORK_START; if ( currentDate.toDateString() === new Date(startDate).toDateString() ) { // Первый день - берем время начала работы const startMinutes = startDateTime.getHours() * 60 + startDateTime.getMinutes(); workStartMinutes = Math.max(startMinutes, WORK_START); } // Определяем время окончания работы в этот день let workEndMinutes = WORK_END; if ( endDateTime && currentDate.toDateString() === new Date(endDate).toDateString() ) { // Последний день - берем время окончания работы const endMinutes = endDateTime.getHours() * 60 + endDateTime.getMinutes(); workEndMinutes = Math.min(endMinutes, WORK_END); } // Если время окончания раньше времени начала в этот день - пропускаем if (workEndMinutes > workStartMinutes) { let dayMinutes = workEndMinutes - workStartMinutes; // Вычитаем обед, если он попадает в рабочий интервал if (workStartMinutes < LUNCH_END && workEndMinutes > LUNCH_START) { const lunchOverlapStart = Math.max(workStartMinutes, LUNCH_START); const lunchOverlapEnd = Math.min(workEndMinutes, LUNCH_END); if (lunchOverlapEnd > lunchOverlapStart) { dayMinutes -= lunchOverlapEnd - lunchOverlapStart; } } totalMinutes += Math.max(0, dayMinutes); } } // Переходим к следующему дню currentDate.setDate(currentDate.getDate() + 1); } return Math.round((totalMinutes / 60) * 10) / 10; // Округляем до 0.1 часа } catch (error) { console.error("Calculation error:", error); return 0; } }; // Обновляем предварительный расчет при изменении полей useEffect(() => { if (entry.isAuto) { const hours = calculatePreviewHours( entry.startDate, entry.startTime, entry.endDate, entry.endTime ); setPreviewHours(hours); } }, [ entry.startDate, entry.startTime, entry.endDate, entry.endTime, entry.isAuto, ]); return (