Файловый менеджер - Редактировать - /home/gqdcvggs/aktascorp.com/support-chatbox-intgr/dashboard.html
Назад
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dashboard Chatbox - Imators</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f0f23; color: #e1e1e1; min-height: 100vh; } .container { display: flex; height: 100vh; } .sidebar { width: 320px; background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(10px); border-right: 1px solid rgba(255, 255, 255, 0.1); overflow-y: auto; flex-shrink: 0; } .sidebar-header { padding: 30px 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); position: sticky; top: 0; z-index: 10; } .sidebar-header h1 { font-size: 24px; font-weight: 600; margin-bottom: 10px; } .filter-section { padding: 20px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } .filter-section select { width: 100%; padding: 10px 15px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: #e1e1e1; font-size: 14px; outline: none; transition: all 0.2s; } .filter-section select:focus { border-color: #667eea; background: rgba(255, 255, 255, 0.08); } .conversations-list { padding: 10px; } .conversation-item { background: rgba(255, 255, 255, 0.05); border-radius: 12px; padding: 15px; margin-bottom: 10px; cursor: pointer; transition: all 0.2s; border: 1px solid transparent; } .conversation-item:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.1); transform: translateX(5px); } .conversation-item.active { background: rgba(102, 126, 234, 0.2); border-color: #667eea; } .conversation-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .conversation-site { font-size: 12px; color: #667eea; font-weight: 600; } .conversation-time { font-size: 11px; color: rgba(255, 255, 255, 0.5); } .conversation-visitor { font-size: 13px; color: rgba(255, 255, 255, 0.7); margin-bottom: 5px; } .conversation-preview { font-size: 14px; color: rgba(255, 255, 255, 0.9); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .conversation-badge { display: inline-block; background: #ef4444; color: white; font-size: 11px; padding: 2px 8px; border-radius: 10px; margin-left: 10px; } .main-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; } .chat-header { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); padding: 20px 30px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); display: flex; justify-content: space-between; align-items: center; } .chat-info h2 { font-size: 20px; margin-bottom: 5px; } .chat-info p { color: rgba(255, 255, 255, 0.6); font-size: 14px; } .chat-actions { display: flex; gap: 10px; } .btn { padding: 8px 16px; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; color: white; font-size: 14px; cursor: pointer; transition: all 0.2s; } .btn:hover { background: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.3); } .btn-primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3); } .chat-messages { flex: 1; overflow-y: auto; padding: 30px; background: rgba(0, 0, 0, 0.3); } .message { margin-bottom: 20px; display: flex; align-items: flex-start; gap: 15px; } .message.visitor { flex-direction: row-reverse; } .message-avatar { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; flex-shrink: 0; } .message.admin .message-avatar { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); } .message-content { max-width: 70%; } .message-bubble { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); padding: 15px 20px; border-radius: 18px; border: 1px solid rgba(255, 255, 255, 0.1); } .message.visitor .message-bubble { background: rgba(102, 126, 234, 0.2); border-color: rgba(102, 126, 234, 0.3); } .message-time { font-size: 12px; color: rgba(255, 255, 255, 0.4); margin-top: 8px; } .chat-input-container { padding: 20px 30px; background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); border-top: 1px solid rgba(255, 255, 255, 0.1); } .chat-input-wrapper { display: flex; gap: 15px; align-items: center; } .chat-input { flex: 1; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); padding: 15px 20px; border-radius: 25px; color: white; font-size: 15px; outline: none; transition: all 0.2s; } .chat-input:focus { background: rgba(255, 255, 255, 0.08); border-color: #667eea; } .send-button { width: 50px; height: 50px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; } .send-button:hover { transform: scale(1.1); box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4); } .send-button:active { transform: scale(0.95); } .send-button svg { width: 24px; height: 24px; fill: white; } .empty-state { flex: 1; display: flex; align-items: center; justify-content: center; flex-direction: column; color: rgba(255, 255, 255, 0.4); } .empty-state svg { width: 100px; height: 100px; fill: currentColor; margin-bottom: 20px; } .empty-state h3 { font-size: 20px; margin-bottom: 10px; } .sites-modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(10px); z-index: 1000; align-items: center; justify-content: center; } .sites-modal.active { display: flex; } .modal-content { background: #1a1a2e; border-radius: 20px; padding: 30px; max-width: 600px; width: 90%; max-height: 80vh; overflow-y: auto; border: 1px solid rgba(255, 255, 255, 0.1); } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; } .modal-header h2 { font-size: 24px; } .close-modal { width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 255, 255, 0.1); border: none; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; } .close-modal:hover { background: rgba(255, 255, 255, 0.15); transform: rotate(90deg); } .site-item { background: rgba(255, 255, 255, 0.05); border-radius: 12px; padding: 20px; margin-bottom: 15px; border: 1px solid rgba(255, 255, 255, 0.1); } .site-item h3 { font-size: 18px; margin-bottom: 15px; color: #667eea; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 8px; font-size: 14px; color: rgba(255, 255, 255, 0.7); } .form-group input { width: 100%; padding: 10px 15px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 8px; color: white; font-size: 14px; outline: none; transition: all 0.2s; } .form-group input:focus { background: rgba(255, 255, 255, 0.08); border-color: #667eea; } .integration-code { background: rgba(0, 0, 0, 0.5); border-radius: 8px; padding: 15px; margin-top: 15px; font-family: 'Courier New', monospace; font-size: 13px; color: #50fa7b; overflow-x: auto; } .status-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #10b981; margin-right: 8px; animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } .notification { position: fixed; top: 20px; right: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 20px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); transform: translateX(400px); transition: transform 0.3s; z-index: 2000; } .notification.show { transform: translateX(0); } </style> </head> <body> <div class="container"> <div class="sidebar"> <div class="sidebar-header"> <h1>Chatbox Dashboard</h1> <p><span class="status-indicator"></span>Connecté</p> </div> <div class="filter-section"> <select id="siteFilter"> <option value="">Tous les sites</option> </select> </div> <div class="conversations-list" id="conversationsList"> </div> </div> <div class="main-content"> <div id="emptyState" class="empty-state"> <svg viewBox="0 0 24 24"> <path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2z"/> </svg> <h3>Sélectionnez une conversation</h3> <p>Choisissez une conversation dans la liste de gauche</p> </div> <div id="chatArea" style="display: none; flex: 1; flex-direction: column;"> <div class="chat-header"> <div class="chat-info"> <h2 id="chatTitle">Conversation</h2> <p id="chatSubtitle">Site</p> </div> <div class="chat-actions"> <button class="btn" onclick="showSitesModal()">Gérer les sites</button> </div> </div> <div class="chat-messages" id="messagesContainer"> </div> <div class="chat-input-container"> <div class="chat-input-wrapper"> <input type="text" class="chat-input" id="messageInput" placeholder="Tapez votre message..." /> <button class="send-button" id="sendButton"> <svg viewBox="0 0 24 24"> <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/> </svg> </button> </div> </div> </div> </div> </div> <div class="sites-modal" id="sitesModal"> <div class="modal-content"> <div class="modal-header"> <h2>Gestion des sites</h2> <button class="close-modal" onclick="closeSitesModal()">×</button> </div> <div id="sitesList"></div> </div> </div> <div class="notification" id="notification"></div> <script> const WS_URL = 'wss://aktascorp.com:8081'; let ws = null; let currentConversationId = null; let conversations = []; let sites = []; function initWebSocket() { ws = new WebSocket(WS_URL); ws.onopen = () => { console.log('Connected to WebSocket'); loadConversations(); loadSites(); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); handleWebSocketMessage(data); }; ws.onclose = () => { setTimeout(initWebSocket, 3000); }; } function handleWebSocketMessage(data) { switch(data.type) { case 'conversations_list': conversations = data.conversations; renderConversations(); break; case 'messages_list': renderMessages(data.messages); break; case 'new_visitor_message': if (data.conversationId === currentConversationId) { addMessageToChat('visitor', data.message); } showNotification('Nouveau message', data.message); loadConversations(); break; } } function loadConversations() { ws.send(JSON.stringify({ type: 'get_conversations' })); } function loadSites() { fetch('?action=get_sites') .then(res => res.json()) .then(data => { sites = data; updateSiteFilter(); renderSitesList(); }); } function renderConversations() { const container = document.getElementById('conversationsList'); const filter = document.getElementById('siteFilter').value; const filtered = filter ? conversations.filter(c => c.domain === filter) : conversations; container.innerHTML = filtered.map(conv => ` <div class="conversation-item ${conv.id === currentConversationId ? 'active' : ''}" onclick="selectConversation(${conv.id})"> <div class="conversation-header"> <div class="conversation-site">${conv.domain}</div> <div class="conversation-time">${formatTime(conv.created_at)}</div> </div> <div class="conversation-visitor">${conv.visitor_id}</div> <div class="conversation-preview">${conv.last_message || 'Nouvelle conversation'}</div> </div> `).join(''); } function selectConversation(conversationId) { currentConversationId = conversationId; document.getElementById('emptyState').style.display = 'none'; document.getElementById('chatArea').style.display = 'flex'; const conv = conversations.find(c => c.id === conversationId); document.getElementById('chatTitle').textContent = conv.visitor_id; document.getElementById('chatSubtitle').textContent = conv.domain; ws.send(JSON.stringify({ type: 'get_messages', conversationId: conversationId })); renderConversations(); } function renderMessages(messages) { const container = document.getElementById('messagesContainer'); container.innerHTML = messages.map(msg => ` <div class="message ${msg.sender}"> <div class="message-avatar">${msg.sender === 'admin' ? 'A' : 'V'}</div> <div class="message-content"> <div class="message-bubble">${msg.message}</div> <div class="message-time">${formatTime(msg.created_at)}</div> </div> </div> `).join(''); container.scrollTop = container.scrollHeight; } function addMessageToChat(sender, message) { const container = document.getElementById('messagesContainer'); const messageEl = document.createElement('div'); messageEl.className = `message ${sender}`; messageEl.innerHTML = ` <div class="message-avatar">${sender === 'admin' ? 'A' : 'V'}</div> <div class="message-content"> <div class="message-bubble">${message}</div> <div class="message-time">${formatTime(new Date())}</div> </div> `; container.appendChild(messageEl); container.scrollTop = container.scrollHeight; } function sendMessage() { const input = document.getElementById('messageInput'); const message = input.value.trim(); if (message && currentConversationId) { ws.send(JSON.stringify({ type: 'admin_message', conversationId: currentConversationId, message: message })); addMessageToChat('admin', message); input.value = ''; } } function updateSiteFilter() { const filter = document.getElementById('siteFilter'); filter.innerHTML = '<option value="">Tous les sites</option>' + sites.map(site => `<option value="${site.domain}">${site.name}</option>`).join(''); } function renderSitesList() { const container = document.getElementById('sitesList'); container.innerHTML = sites.map(site => ` <div class="site-item"> <h3>${site.domain}</h3> <div class="form-group"> <label>Nom du site</label> <input type="text" value="${site.name}" onchange="updateSite(${site.id}, 'name', this.value)"> </div> <div class="form-group"> <label>Email admin</label> <input type="email" value="${site.admin_email}" onchange="updateSite(${site.id}, 'email', this.value)"> </div> <div class="integration-code"> <script src="https://aktascorp.com/support-chatbox-intgr/chatbox.js"></script> </div> </div> `).join(''); } function updateSite(id, field, value) { const site = sites.find(s => s.id === id); if (field === 'name') site.name = value; if (field === 'email') site.admin_email = value; fetch('?action=update_site', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `id=${id}&name=${site.name}&email=${site.admin_email}` }); } function showSitesModal() { document.getElementById('sitesModal').classList.add('active'); } function closeSitesModal() { document.getElementById('sitesModal').classList.remove('active'); } function showNotification(title, message) { const notif = document.getElementById('notification'); notif.innerHTML = `<strong>${title}</strong><br>${message}`; notif.classList.add('show'); setTimeout(() => { notif.classList.remove('show'); }, 5000); } function formatTime(dateString) { const date = new Date(dateString); const now = new Date(); const diff = now - date; if (diff < 60000) return 'À l\'instant'; if (diff < 3600000) return `Il y a ${Math.floor(diff / 60000)} min`; if (diff < 86400000) return `Il y a ${Math.floor(diff / 3600000)} h`; return date.toLocaleDateString('fr-FR'); } document.getElementById('sendButton').addEventListener('click', sendMessage); document.getElementById('messageInput').addEventListener('keypress', (e) => { if (e.key === 'Enter') sendMessage(); }); document.getElementById('siteFilter').addEventListener('change', renderConversations); initWebSocket(); </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка