/** * Generic modal helpers for the dashboard. * Handles open/close animations, error display, backdrop click, and Escape key. * Depends on: core/utils.js ($), core/navigation.js (navigateTo) */ /** * Open a modal by adding the `open` class and focusing the first input. * @param {string} id - The modal backdrop element ID. */ function openModal(id) { const el = $(id); if (!el) return; el.classList.add('open'); setTimeout(() => { const input = el.querySelector('input:not([type="checkbox"])'); if (input) input.focus(); }, 50); } /** * Close a modal by removing the `open` class and clearing any error messages. * @param {string} id - The modal backdrop element ID. */ function closeModal(id) { const el = $(id); if (!el) return; el.classList.remove('open'); el.querySelectorAll('.modal-error').forEach(e => { e.style.display = 'none'; e.textContent = ''; }); } /** * Display an error message inside a modal's error element. * @param {string} modalId - Unused; kept for API symmetry. * @param {string} errorId - ID of the error display element. * @param {string} msg - Error message text. */ function showModalError(modalId, errorId, msg) { const el = $(errorId); if (!el) return; el.textContent = msg; el.style.display = 'block'; } // Close modals on backdrop click or close button document.addEventListener('click', (e) => { const closeBtn = e.target.closest('[data-close-modal]'); if (closeBtn) { closeModal(closeBtn.dataset.closeModal); return; } if (e.target.classList.contains('modal-backdrop')) { closeModal(e.target.id); } const pageLink = e.target.closest('[data-page-link]'); if (pageLink) { navigateTo(pageLink.dataset.pageLink); } }); // Escape key closes topmost open modal document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { const open = document.querySelector('.modal-backdrop.open'); if (open) closeModal(open.id); } });