/* Korea Tourism Agency Admin Panel Custom Scripts */ // Функция для открытия редактора изображений function openImageEditor(fieldName, currentValue) { const editorUrl = `/image-editor.html?field=${fieldName}¤t=${encodeURIComponent(currentValue || '')}`; const editorWindow = window.open(editorUrl, 'imageEditor', 'width=1200,height=800,scrollbars=yes,resizable=yes'); // Слушаем сообщения от редактора const messageHandler = (event) => { if (event.origin !== window.location.origin) return; if (event.data.type === 'imageSelected' && event.data.targetField === fieldName) { const field = document.querySelector(`input[name="${fieldName}"], input[id="${fieldName}"]`); if (field) { field.value = event.data.path; field.dispatchEvent(new Event('change', { bubbles: true })); // Обновляем превью если есть updateImagePreview(fieldName, event.data.path); } window.removeEventListener('message', messageHandler); editorWindow.close(); } }; window.addEventListener('message', messageHandler); // Очистка обработчика при закрытии окна const checkClosed = setInterval(() => { if (editorWindow.closed) { window.removeEventListener('message', messageHandler); clearInterval(checkClosed); } }, 1000); } // Функция обновления превью изображения function updateImagePreview(fieldName, imagePath) { const previewId = `${fieldName}_preview`; let preview = document.getElementById(previewId); if (!preview) { // Создаем превью если его нет const field = document.querySelector(`input[name="${fieldName}"], input[id="${fieldName}"]`); if (field) { preview = document.createElement('img'); preview.id = previewId; preview.className = 'img-thumbnail mt-2'; preview.style.maxWidth = '200px'; preview.style.maxHeight = '200px'; field.parentNode.appendChild(preview); } } if (preview) { preview.src = imagePath || '/images/placeholders/no-image.png'; preview.alt = 'Preview'; } } // Функция добавления кнопки редактора к полю function addImageEditorButton(field) { const fieldName = field.name || field.id; if (!fieldName) return; // Проверяем, не добавлена ли уже кнопка if (field.parentNode.querySelector('.image-editor-btn')) return; const wrapper = document.createElement('div'); wrapper.className = 'input-group'; const button = document.createElement('button'); button.type = 'button'; button.className = 'btn btn-outline-secondary image-editor-btn'; button.innerHTML = ' Выбрать'; button.onclick = () => openImageEditor(fieldName, field.value); const buttonWrapper = document.createElement('div'); buttonWrapper.className = 'input-group-append'; buttonWrapper.appendChild(button); // Перестраиваем структуру field.parentNode.insertBefore(wrapper, field); wrapper.appendChild(field); wrapper.appendChild(buttonWrapper); // Добавляем превью если есть значение if (field.value) { updateImagePreview(fieldName, field.value); } } $(document).ready(function() { // Initialize tooltips $('[data-toggle="tooltip"]').tooltip(); // Initialize popovers $('[data-toggle="popover"]').popover(); // Auto-hide alerts after 5 seconds setTimeout(function() { $('.alert').fadeOut('slow'); }, 5000); // Добавляем кнопки редактора к полям изображений $('input[type="text"], input[type="url"]').each(function() { const field = this; const fieldName = field.name || field.id || ''; // Проверяем, относится ли поле к изображениям if (fieldName.includes('image') || fieldName.includes('photo') || fieldName.includes('avatar') || fieldName.includes('picture') || fieldName.includes('thumbnail') || fieldName.includes('banner') || $(field).closest('label').text().toLowerCase().includes('изображение') || $(field).closest('label').text().toLowerCase().includes('картинка') || $(field).closest('label').text().toLowerCase().includes('фото')) { addImageEditorButton(field); } }); // Обработчик для динамически добавляемых полей $(document).on('focus', 'input[type="text"], input[type="url"]', function() { const field = this; const fieldName = field.name || field.id || ''; if ((fieldName.includes('image') || fieldName.includes('photo') || fieldName.includes('avatar') || fieldName.includes('picture') || fieldName.includes('thumbnail') || fieldName.includes('banner')) && !field.parentNode.querySelector('.image-editor-btn')) { addImageEditorButton(field); } }); // Confirm delete actions $('.btn-delete').on('click', function(e) { e.preventDefault(); const item = $(this).data('item') || 'item'; const url = $(this).attr('href') || $(this).data('url'); if (confirm(`Are you sure you want to delete this ${item}?`)) { if ($(this).data('method') === 'DELETE') { // AJAX delete $.ajax({ url: url, method: 'DELETE', success: function(response) { if (response.success) { location.reload(); } else { alert('Error: ' + response.message); } }, error: function() { alert('An error occurred while deleting.'); } }); } else { // Regular form submission or redirect window.location.href = url; } } }); // Form validation enhancement $('form').on('submit', function() { const submitBtn = $(this).find('button[type="submit"]'); submitBtn.prop('disabled', true); submitBtn.html(' Processing...'); }); // Image preview functionality function readURL(input, target) { if (input.files && input.files[0]) { const reader = new FileReader(); reader.onload = function(e) { $(target).attr('src', e.target.result).show(); }; reader.readAsDataURL(input.files[0]); } } $('input[type="file"]').on('change', function() { const targetImg = $(this).closest('.form-group').find('.img-preview'); if (targetImg.length) { readURL(this, targetImg); } }); // Auto-save draft functionality for forms let autoSaveTimer; $('textarea, input[type="text"]').on('input', function() { clearTimeout(autoSaveTimer); autoSaveTimer = setTimeout(function() { // Auto-save logic here console.log('Auto-saving draft...'); }, 2000); }); // Enhanced DataTables configuration if (typeof $.fn.dataTable !== 'undefined') { $('.data-table').each(function() { $(this).DataTable({ responsive: true, lengthChange: false, autoWidth: false, pageLength: 25, language: { search: "Search:", lengthMenu: "Show _MENU_ entries", info: "Showing _START_ to _END_ of _TOTAL_ entries", paginate: { first: "First", last: "Last", next: "Next", previous: "Previous" } }, dom: '<"row"<"col-sm-6"l><"col-sm-6"f>>' + '<"row"<"col-sm-12"tr>>' + '<"row"<"col-sm-5"i><"col-sm-7"p>>', }); }); } // Status toggle functionality $('.status-toggle').on('change', function() { const checkbox = $(this); const id = checkbox.data('id'); const type = checkbox.data('type'); const field = checkbox.data('field'); const isChecked = checkbox.is(':checked'); $.ajax({ url: `/admin/${type}/${id}/toggle`, method: 'POST', data: { field: field, value: isChecked }, success: function(response) { if (response.success) { showNotification('Status updated successfully!', 'success'); } else { checkbox.prop('checked', !isChecked); showNotification('Error updating status: ' + response.message, 'error'); } }, error: function() { checkbox.prop('checked', !isChecked); showNotification('Error updating status', 'error'); } }); }); // Notification system function showNotification(message, type = 'info') { const alertClass = type === 'success' ? 'alert-success' : type === 'error' ? 'alert-danger' : type === 'warning' ? 'alert-warning' : 'alert-info'; const notification = ` `; $('body').append(notification); // Auto-hide after 3 seconds setTimeout(function() { $('.alert').last().fadeOut('slow', function() { $(this).remove(); }); }, 3000); } // Make notification function globally available window.showNotification = showNotification; // Quick search functionality $('#quick-search').on('input', function() { const searchTerm = $(this).val().toLowerCase(); const searchableElements = $('.searchable'); if (searchTerm === '') { searchableElements.show(); } else { searchableElements.each(function() { const text = $(this).text().toLowerCase(); if (text.includes(searchTerm)) { $(this).show(); } else { $(this).hide(); } }); } }); // Bulk actions functionality $('#select-all').on('change', function() { $('.item-checkbox').prop('checked', $(this).is(':checked')); updateBulkActionButtons(); }); $('.item-checkbox').on('change', function() { updateBulkActionButtons(); // Update select-all checkbox state const totalCheckboxes = $('.item-checkbox').length; const checkedCheckboxes = $('.item-checkbox:checked').length; if (checkedCheckboxes === 0) { $('#select-all').prop('indeterminate', false).prop('checked', false); } else if (checkedCheckboxes === totalCheckboxes) { $('#select-all').prop('indeterminate', false).prop('checked', true); } else { $('#select-all').prop('indeterminate', true); } }); function updateBulkActionButtons() { const checkedItems = $('.item-checkbox:checked').length; if (checkedItems > 0) { $('.bulk-actions').show(); $('.bulk-count').text(checkedItems); } else { $('.bulk-actions').hide(); } } // Image upload preview $('.image-upload').on('change', function() { const file = this.files[0]; const preview = $(this).siblings('.image-preview'); if (file) { const reader = new FileReader(); reader.onload = function(e) { preview.html(``); }; reader.readAsDataURL(file); } }); // Chart initialization (if Chart.js is available) if (typeof Chart !== 'undefined' && $('#dashboard-chart').length) { const ctx = document.getElementById('dashboard-chart').getContext('2d'); new Chart(ctx, { type: 'line', data: { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], datasets: [{ label: 'Bookings', data: [12, 19, 3, 5, 2, 3], borderColor: '#3b82f6', backgroundColor: 'rgba(59, 130, 246, 0.1)', tension: 0.4 }] }, options: { responsive: true, plugins: { legend: { position: 'top', } }, scales: { y: { beginAtZero: true } } } }); } }); // Global utility functions window.AdminUtils = { // Format currency formatCurrency: function(amount) { return '₩' + new Intl.NumberFormat('ko-KR').format(amount); }, // Format date formatDate: function(date) { return new Date(date).toLocaleDateString('ko-KR'); }, // Validate email isValidEmail: function(email) { const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(email); }, // Show loading spinner showLoading: function(element) { $(element).addClass('loading').append('
'); }, // Hide loading spinner hideLoading: function(element) { $(element).removeClass('loading').find('.spinner').remove(); } };