// Элементы DOM const statusIndicator = document.getElementById('statusIndicator'); const statusInfo = document.getElementById('statusInfo'); const btnOn = document.getElementById('btnOn'); const btnOff = document.getElementById('btnOff'); const notification = document.getElementById('notification'); const notificationMessage = document.getElementById('notificationMessage'); // Конфигурация API const API_BASE_URL = window.location.origin; const API_STATUS_ENDPOINT = `${API_BASE_URL}/api/v1/client/status`; const API_TOGGLE_ENDPOINT = `${API_BASE_URL}/api/v1/client/toggle`; // Переменные состояния let currentStatus = null; let isRequestInProgress = false; let hasIntegration = false; // Инициализация при загрузке страницы document.addEventListener('DOMContentLoaded', function () { loadInitialStatus(); btnOn.addEventListener('click', () => sendCommand(true)); btnOff.addEventListener('click', () => sendCommand(false)); }); // Функция загрузки начального статуса async function loadInitialStatus() { try { updateUIForLoading(); const response = await fetch(API_STATUS_ENDPOINT); const data = await response.json(); if (data.success) { hasIntegration = true; currentStatus = data.data.enabled; updateUIForStatus(currentStatus); showNotification(`Доступ разрешен. Ваш IP: ${data.data.ip}.`, 'success', true); } else { hasIntegration = false; updateUIForNoIntegration(data.error || 'Нет интеграции с сервисом'); } } catch (error) { console.error('Ошибка при загрузке статуса:', error); updateUIForError('Ошибка соединения с сервером API'); } } // Функция отправки команды на сервер async function sendCommand(enabled) { if (!hasIntegration || isRequestInProgress) return; // Прерываем, если запрашиваемое состояние уже активно if (enabled === currentStatus) return; isRequestInProgress = true; const action = enabled ? 'включения' : 'выключения'; updateUIForSendingCommand(enabled); try { const response = await fetch(API_TOGGLE_ENDPOINT, { method: 'PUT', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { currentStatus = data.data.enabled; updateUIForStatus(currentStatus); showNotification(`Команда ${action} успешно выполнена.`, 'success'); provideVisualFeedback(currentStatus); } else { showNotification(`Ошибка: ${data.error}`, 'error'); updateUIForStatus(currentStatus); } } catch (error) { console.error('Ошибка при отправке команды:', error); showNotification('Ошибка сети при отправке команды', 'error'); updateUIForStatus(currentStatus); } finally { isRequestInProgress = false; } } // Обновление UI при загрузке function updateUIForLoading() { statusIndicator.className = 'status-indicator status-loading'; statusIndicator.innerHTML = ' Загрузка...'; statusInfo.textContent = 'Получение текущего состояния с сервера...'; btnOn.classList.add('btn-disabled'); btnOff.classList.add('btn-disabled'); btnOn.disabled = true; btnOff.disabled = true; } // Обновление UI на основе текущего статуса function updateUIForStatus(enabled) { if (enabled) { statusIndicator.className = 'status-indicator status-on'; statusIndicator.innerHTML = ' Включено'; statusInfo.textContent = 'Устройство активно и работает в нормальном режиме'; btnOn.classList.add('btn-disabled'); btnOn.disabled = true; btnOff.classList.remove('btn-disabled'); btnOff.disabled = false; } else { statusIndicator.className = 'status-indicator status-off'; statusIndicator.innerHTML = ' Выключено'; statusInfo.textContent = 'Устройство отключено и не выполняет свои функции'; btnOff.classList.add('btn-disabled'); btnOff.disabled = true; btnOn.classList.remove('btn-disabled'); btnOn.disabled = false; } } // Обновление UI при отсутствии интеграции function updateUIForNoIntegration(message) { statusIndicator.className = 'status-indicator status-disabled'; statusIndicator.innerHTML = ' Нет доступа'; statusInfo.textContent = 'Ваш IP-адрес не найден в списке доверенных адресов'; btnOn.classList.add('btn-disabled'); btnOff.classList.add('btn-disabled'); btnOn.disabled = true; btnOff.disabled = true; showNotification(message, 'error', true); } // Обновление UI при ошибке function updateUIForError(errorMessage) { statusIndicator.className = 'status-indicator status-disabled'; statusIndicator.innerHTML = ' Ошибка'; statusInfo.textContent = 'Не удалось получить информацию о статусе устройства'; btnOn.classList.add('btn-disabled'); btnOff.classList.add('btn-disabled'); btnOn.disabled = true; btnOff.disabled = true; showNotification(errorMessage, 'error', true); } // Обновление UI при отправке команды function updateUIForSendingCommand(enabled) { const action = enabled ? 'включения' : 'выключения'; statusIndicator.className = 'status-indicator status-loading'; statusIndicator.innerHTML = ' Отправка...'; statusInfo.textContent = `Отправка команды ${action} на сервер...`; btnOn.classList.add('btn-disabled'); btnOff.classList.add('btn-disabled'); btnOn.disabled = true; btnOff.disabled = true; showNotification(`Отправка команды ${action}...`, 'warning'); } // Переменные для управления уведомлениями let baseNotificationContent = null; let notificationTimeout = null; // Показать уведомление function showNotification(message, type = 'info', isPersistent = false) { if (notificationTimeout) { clearTimeout(notificationTimeout); notificationTimeout = null; } notification.className = 'notification'; let icon = 'fa-info-circle'; let title = 'Информация:'; if (type === 'error') { notification.classList.add('notification-error'); icon = 'fa-exclamation-circle'; title = 'Ошибка:'; } else if (type === 'success') { notification.classList.add('notification-success'); icon = 'fa-check-circle'; title = 'Успешно:'; } else if (type === 'warning') { notification.classList.add('notification-warning'); icon = 'fa-sync-alt fa-spin'; title = 'Обработка:'; } const content = `

${title}

${message}
`; notification.innerHTML = content; if (isPersistent) { baseNotificationContent = content; } notification.style.opacity = '0'; notification.style.display = 'block'; // Плавное появление setTimeout(() => { notification.style.transition = 'opacity 0.3s ease'; notification.style.opacity = '1'; }, 10); // Авто-возврат к базовому уведомлению через 5 секунд (если это не само базовое и не "в обработке") if (!isPersistent && baseNotificationContent && type !== 'warning') { notificationTimeout = setTimeout(() => { notification.style.opacity = '0'; setTimeout(() => { notification.className = 'notification'; notification.innerHTML = baseNotificationContent; notification.style.opacity = '1'; }, 300); }, 5000); } } // Визуальная обратная связь function provideVisualFeedback(enabled) { if (enabled) { document.body.style.background = 'linear-gradient(135deg, #2ecc71 0%, #27ae60 100%)'; setTimeout(() => { document.body.style.background = 'linear-gradient(135deg, #1a2980 0%, #26d0ce 100%)'; }, 800); } else { document.body.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)'; setTimeout(() => { document.body.style.background = 'linear-gradient(135deg, #1a2980 0%, #26d0ce 100%)'; }, 800); } } // Дополнительная функция для ручного обновления статуса function refreshStatus() { if (!isRequestInProgress) { loadInitialStatus(); } } statusIndicator.addEventListener('dblclick', refreshStatus);