/** * @fileoverview Calendar Manage Modal - модальное окно создания/редактирования календаря * @module components/calendarManageModal */ import { createCalendar, updateCalendar, deleteCalendar, } from "../api/calendarsApi.js"; import { getMyDepartments } from "../api/departmentsApi.js"; /** * Инициализация модального окна управления календарём * @param {Object} options - Параметры * @param {Function} options.onSuccess - Callback при успешном сохранении/удалении * @returns {Object} API модального окна */ export function initCalendarManageModal(options = {}) { const { onSuccess = () => {} } = options; const modal = document.getElementById("calendarManageModal"); if (!modal) { console.warn("[CalendarManageModal] Modal element not found"); return null; } const bsModal = new bootstrap.Modal(modal); // Elements const form = document.getElementById("calendarManageForm"); const titleEl = document.getElementById("calendarManageModalTitle"); const calendarIdInput = document.getElementById("calendarId"); const titleInput = document.getElementById("calendarTitle"); const descInput = document.getElementById("calendarDescription"); const colorInput = document.getElementById("calendarColor"); const colorTextInput = document.getElementById("calendarColorText"); const iconInput = document.getElementById("calendarIcon"); const ownerTypeInputs = document.querySelectorAll('input[name="owner_type"]'); const visibilitySelect = document.getElementById("calendarVisibility"); const deptSelect = document.getElementById("calendarDepartment"); const deptSelectWrapper = document.getElementById("calendarDepartmentSelect"); const autoSubscribeDeptWrapper = document.getElementById( "calendarAutoSubscribeDeptWrapper", ); const defaultCanEditCheckbox = document.getElementById( "calendarDefaultCanEdit", ); const saveBtn = document.getElementById("calendarSaveBtn"); const deleteBtn = document.getElementById("calendarDeleteBtn"); const errorEl = document.getElementById("calendarManageError"); let currentCalendar = null; /** * Открыть модальное окно для создания календаря */ function openForCreate() { currentCalendar = null; titleEl.textContent = "Создать календарь"; deleteBtn.classList.add("d-none"); resetForm(); bsModal.show(); } /** * Открыть модальное окно для редактирования календаря * @param {Object} calendar - Данные календаря */ function openForEdit(calendar) { console.log("[CalendarManageModal] openForEdit called with:", calendar); currentCalendar = calendar; titleEl.textContent = "Редактировать календарь"; deleteBtn.classList.remove("d-none"); // Заполнить форму calendarIdInput.value = calendar.id; titleInput.value = calendar.title; descInput.value = calendar.description || ""; colorInput.value = calendar.color || "#0d6efd"; colorTextInput.value = calendar.color || "#0d6efd"; iconInput.value = calendar.icon || ""; visibilitySelect.value = calendar.visibility || "custom"; // Определить тип владельца let ownerType = "personal"; if (calendar.is_global) { ownerType = "global"; } else if (calendar.is_department || calendar.owner_department) { ownerType = "department"; } else if (calendar.is_personal || calendar.owner_user) { ownerType = "personal"; } ownerTypeInputs.forEach((input) => { input.checked = input.value === ownerType; }); // Если отдел, выбрать его if (calendar.owner_department) { deptSelect.value = calendar.owner_department; } // Настройки defaultCanEditCheckbox.checked = calendar.default_can_edit || false; document.getElementById("calendarAutoSubscribeNewUsers").checked = calendar.auto_subscribe_new_users || false; document.getElementById("calendarAutoSubscribeDept").checked = calendar.auto_subscribe_department_members || false; updateOwnerTypeVisibility(); bsModal.show(); } /** * Сбросить форму */ function resetForm() { form.reset(); calendarIdInput.value = ""; colorInput.value = "#0d6efd"; colorTextInput.value = "#0d6efd"; visibilitySelect.value = "custom"; errorEl.classList.add("d-none"); updateOwnerTypeVisibility(); } /** * Обновить видимость полей в зависимости от типа владельца */ function updateOwnerTypeVisibility() { const selectedType = document.querySelector( 'input[name="owner_type"]:checked', )?.value; if (selectedType === "department") { deptSelectWrapper.classList.remove("d-none"); autoSubscribeDeptWrapper.classList.remove("d-none"); } else { deptSelectWrapper.classList.add("d-none"); autoSubscribeDeptWrapper.classList.add("d-none"); } } /** * Загрузить список отделов */ async function loadDepartments() { try { const departments = await getMyDepartments(); // Заполнить select deptSelect.innerHTML = '' + departments .map((dept) => ``) .join(""); } catch (error) { console.error("[CalendarManageModal] Failed to load departments:", error); } } /** * Собрать данные формы * @returns {Object} */ function getFormData() { const data = { title: titleInput.value.trim(), description: descInput.value.trim(), color: colorInput.value, icon: iconInput.value.trim(), visibility: visibilitySelect.value, default_can_edit: defaultCanEditCheckbox.checked, auto_subscribe_new_users: document.getElementById( "calendarAutoSubscribeNewUsers", ).checked, auto_subscribe_department_members: document.getElementById( "calendarAutoSubscribeDept", ).checked, }; const ownerType = document.querySelector( 'input[name="owner_type"]:checked', )?.value; if (ownerType === "personal") { // owner_user будет установлен автоматически на backend data.owner_user = null; // Явно указываем что это личный календарь data.owner_department = null; } else if (ownerType === "department") { data.owner_user = null; data.owner_department = parseInt(deptSelect.value); if (!data.owner_department) { throw new Error("Выберите отдел"); } } else if (ownerType === "global") { // Глобальный календарь - без владельца data.owner_user = null; data.owner_department = null; } return data; } /** * Сохранить календарь */ async function save() { try { errorEl.classList.add("d-none"); saveBtn.disabled = true; const data = getFormData(); if (currentCalendar) { // Обновление await updateCalendar(currentCalendar.id, data); } else { // Создание await createCalendar(data); } bsModal.hide(); onSuccess(); } catch (error) { console.error("[CalendarManageModal] Save failed:", error); errorEl.textContent = error.message || "Не удалось сохранить календарь"; errorEl.classList.remove("d-none"); } finally { saveBtn.disabled = false; } } /** * Удалить календарь */ async function remove() { if (!currentCalendar) return; if ( !confirm( `Удалить календарь "${currentCalendar.title}"?\n\nВсе события этого календаря будут удалены.`, ) ) { return; } try { deleteBtn.disabled = true; await deleteCalendar(currentCalendar.id); bsModal.hide(); onSuccess(); } catch (error) { console.error("[CalendarManageModal] Delete failed:", error); errorEl.textContent = error.message || "Не удалось удалить календарь"; errorEl.classList.remove("d-none"); } finally { deleteBtn.disabled = false; } } // Event listeners // Синхронизация цвета colorInput.addEventListener("input", (e) => { colorTextInput.value = e.target.value; }); colorTextInput.addEventListener("input", (e) => { const value = e.target.value; if (/^#[0-9A-Fa-f]{6}$/.test(value)) { colorInput.value = value; } }); // Изменение типа владельца ownerTypeInputs.forEach((input) => { input.addEventListener("change", updateOwnerTypeVisibility); }); // Сохранить saveBtn.addEventListener("click", save); // Удалить deleteBtn.addEventListener("click", remove); // Сброс при закрытии modal.addEventListener("hidden.bs.modal", resetForm); // Слушать событие редактирования из других компонентов document.addEventListener("calendar:edit", (e) => { openForEdit(e.detail); }); // Инициализация loadDepartments(); // Public API return { openForCreate, openForEdit, show: () => bsModal.show(), hide: () => bsModal.hide(), }; }