// main.js - Главный файл инициализации // Глобальная переменная для вида задач (используем window, чтобы избежать конфликтов) window.currentTaskView = 'all'; // 'all', 'my_assigned', 'assigned_to_me' let allTasksCache = []; // Кэш всех задач (может быть полезен) document.addEventListener('DOMContentLoaded', function() { checkAuth(); // setupEventListeners убран отсюда – будет вызван после загрузки всех скриптов initializeTimeSelectors(); const taskViewFilter = document.getElementById('task-view-filter'); if (taskViewFilter) { taskViewFilter.value = window.currentTaskView; } // По умолчанию показываем секцию задач showSection('tasks'); }); // Функция настройки обработчиков событий – будет вызвана после загрузки всех скриптов function setupEventListeners() { console.log('🔧 Настройка обработчиков событий...'); const loginForm = document.getElementById('login-form'); if (loginForm) loginForm.addEventListener('submit', login); const createForm = document.getElementById('create-task-form'); if (createForm) createForm.addEventListener('submit', createTask); const editForm = document.getElementById('edit-task-form'); if (editForm) editForm.addEventListener('submit', updateTask); const copyForm = document.getElementById('copy-task-form'); if (copyForm) copyForm.addEventListener('submit', copyTask); const editAssignmentForm = document.getElementById('edit-assignment-form'); if (editAssignmentForm) editAssignmentForm.addEventListener('submit', updateAssignment); const reworkForm = document.getElementById('rework-task-form'); if (reworkForm) reworkForm.addEventListener('submit', sendForRework); const filesInput = document.getElementById('files'); if (filesInput) filesInput.addEventListener('change', updateFileList); const editFilesInput = document.getElementById('edit-files'); if (editFilesInput) editFilesInput.addEventListener('change', updateEditFileList); const notificationForm = document.getElementById('notification-settings-form'); if (notificationForm) notificationForm.addEventListener('submit', saveNotificationSettings); initializeFileUploads(); } // Функция для изменения вида задач function changeTaskView() { const select = document.getElementById('task-view-filter'); window.currentTaskView = select.value; loadTasks(); } // Обновленная функция для создания задачи async function createTask(event) { event.preventDefault(); if (!currentUser) { alert('Требуется аутентификация'); return; } const title = document.getElementById('title').value; const description = document.getElementById('description').value; const taskType = document.getElementById('task-type').value; // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('due-date', 'due-time'); if (!title || !fullDateTime) { alert('Название задачи и дата выполнения обязательны'); return; } if (selectedUsers.length === 0) { alert('Выберите хотя бы одного исполнителя'); return; } // Дополнительная проверка для задач типа "document" if (taskType === 'document' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - секретари for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Секретарь' || (typeof group === 'string' && group.includes('Секретарь')) ); if (!hasSecretaryGroup) { alert('Для задач типа "Согласование документа" можно выбирать только пользователей с правом "согласовать документы"'); return; } } } // Дополнительная проверка для задач типа "it" if (taskType === 'it' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'ИТ специалист' || (typeof group === 'string' && group.includes('ИТ специалист')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "ИТ специалист"'); return; } } } // Дополнительная проверка для задач типа "ahch" if (taskType === 'ahch' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'АХЧ' || (typeof group === 'string' && group.includes('АХЧ')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники АХЧ"'); return; } } } // Дополнительная проверка для задач типа "psychologist" if (taskType === 'psychologist' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'психолог' || (typeof group === 'string' && group.includes('психолог')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники психологи"'); return; } } } // Дополнительная проверка для задач типа "speech_therapist" if (taskType === 'speech_therapist' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - speech_therapist for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'логопед' || (typeof group === 'string' && group.includes('логопед')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники логопеды"'); return; } } } // Дополнительная проверка для задач типа "hr" if (taskType === 'hr' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - hr for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Диспетчер' || (typeof group === 'string' && group.includes('Диспетчер')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "Диспетчер расписания"'); return; } } } // Дополнительная проверка для задач типа "certificate" if (taskType === 'certificate' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - certificate for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Администрация' || (typeof group === 'string' && group.includes('Администрация')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "секретари и завучи"'); return; } } } // Дополнительная проверка для задач типа "e_journal" if (taskType === 'e_journal' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - e_journal for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Админ ЭЖ' || (typeof group === 'string' && group.includes('Админ ЭЖ')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "администраторы электронного журнала"'); return; } } } // Дополнительная проверка для задач типа "Social_educator" if (taskType === 'Social_educator' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - Social_educator for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Социальный педагог' || (typeof group === 'string' && group.includes('Социальный педагог')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "Социальный педагог"'); return; } } } const formData = new FormData(); formData.append('title', title); formData.append('description', description); formData.append('taskType', taskType); formData.append('dueDate', fullDateTime); selectedUsers.forEach(userId => { formData.append('assignedUsers', userId); }); const files = document.getElementById('files').files; for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } // Проверка прав для типа "regular" const userGroups = currentUser?.groups || []; const isAdmin = currentUser?.role === 'admin'; const hasTasksGroup = currentUser?.role === 'tasks'; const hasSecretaryGroup = currentUser?.role === 'secretary'; if (taskType === 'regular' && !(isAdmin || hasTasksGroup || hasSecretaryGroup)) { alert('У вас нет прав для создания обычных задач. Выберите другой тип задачи.'); return; } try { const response = await fetch('/api/tasks', { method: 'POST', body: formData }); if (response.ok) { alert('Задача успешно создана!'); // Сброс формы document.getElementById('create-task-form').reset(); document.getElementById('file-list').innerHTML = ''; document.getElementById('user-search').value = ''; selectedUsers = []; // Сбрасываем дату и время const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); document.getElementById('due-date').value = tomorrow.toISOString().split('T')[0]; document.getElementById('due-time').value = '12:00'; // Сбрасываем активные кнопки const timeButtons = document.querySelectorAll('.time-btn'); timeButtons.forEach(btn => btn.classList.remove('active')); if (timeButtons.length > 0) { timeButtons[0].classList.add('active'); } // Обновляем отображение кнопок updateDateTimeDisplay(); // Обновляем список пользователей renderUsersChecklist(); // Загружаем задачи и логи loadTasks(); loadActivityLogs(); // Показываем секцию задач showSection('tasks'); } else { const error = await response.json(); alert(error.error || 'Ошибка создания задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка создания задачи'); } } // Обновленная функция открытия модального окна редактирования async function openEditModal(taskId) { try { const response = await fetch(`/api/tasks/${taskId}`); if (!response.ok) { if (response.status === 404) { alert('Задача не найдена или у вас нет прав доступа'); } throw new Error('Ошибка загрузки задачи'); } const task = await response.json(); if (!canUserEditTask(task)) { alert('У вас нет прав для редактирования этой задачи'); return; } document.getElementById('edit-task-id').value = task.id; document.getElementById('edit-title').value = task.title; document.getElementById('edit-description').value = task.description || ''; // Устанавливаем дату и время с помощью новой функции setDateTimeForEdit(task.due_date); // Устанавливаем выбранных пользователей editSelectedUsers = task.assignments ? task.assignments.map(a => a.user_id) : []; renderEditUsersChecklist(users); // Показываем существующие файлы currentEditTaskFiles = task.files || []; updateEditFileList(); document.getElementById('edit-task-modal').style.display = 'block'; } catch (error) { console.error('Ошибка:', error); alert('Ошибка загрузки задачи'); } } // Обновленная функция обновления задачи async function updateTask(event) { event.preventDefault(); const taskId = document.getElementById('edit-task-id').value; const title = document.getElementById('edit-title').value; const description = document.getElementById('edit-description').value; // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('edit-due-date', 'edit-due-time'); if (!fullDateTime) { alert('Дата и время выполнения обязательны'); return; } // Используем editSelectedUsers const assignedUserIds = editSelectedUsers; const formData = new FormData(); formData.append('title', title); formData.append('description', description); formData.append('assignedUsers', JSON.stringify(assignedUserIds)); formData.append('dueDate', fullDateTime); const files = document.getElementById('edit-files').files; for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } try { const response = await fetch(`/api/tasks/${taskId}`, { method: 'PUT', body: formData }); if (response.ok) { alert('Задача успешно обновлена!'); closeEditModal(); loadTasks(); loadActivityLogs(); } else { const error = await response.json(); alert(error.error || 'Ошибка обновления задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка обновления задачи'); } } // Обновленная функция создания копии задачи async function copyTask(event) { event.preventDefault(); const taskId = document.getElementById('copy-task-id').value; // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('copy-due-date', 'copy-due-time'); if (!fullDateTime) { alert('Дата и время выполнения обязательны для копии задачи'); return; } // Используем copySelectedUsers const assignedUserIds = copySelectedUsers; if (assignedUserIds.length === 0) { alert('Выберите хотя бы одного исполнителя для копии задачи'); return; } try { const response = await fetch(`/api/tasks/${taskId}/copy`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ assignedUsers: assignedUserIds, dueDate: fullDateTime }) }); if (response.ok) { alert('Копия задачи успешно создана!'); closeCopyModal(); loadTasks(); loadActivityLogs(); } else { const error = await response.json(); alert(error.error || 'Ошибка создания копии задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка создания копии задачи'); } } // Функция для отображения секции function showSection(sectionName) { document.querySelectorAll('.section').forEach(section => { section.classList.remove('active'); }); document.getElementById(sectionName + '-section').classList.add('active'); if (sectionName === 'tasks') { window.currentTaskView = 'all'; loadTasks(); } else if (sectionName === 'logs') { loadActivityLogs(); } else if (sectionName === 'kanban') { loadKanbanTasks(); } else if (sectionName === 'mytasks') { showMyTasksSection(); // из loadMyCreatedTasks.js } else if (sectionName === 'runtasks') { showRunTasksSection(); // из loadMyCreatedTasks.js } // Загрузка профиля при переходе в личный кабинет if (sectionName === 'profile') { loadUserProfile(); loadNotificationSettings(); } } // Функция для отображения Канбан доски function showKanbanSection() { showSection('kanban'); } window.setupEventListeners = setupEventListeners;