class NotificationSettings extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.config = null; this.isLoading = false; this.error = null; this.whatsAppStatusInterval = null; this.currentQrCode = null; } static get observedAttributes() { return ['loading', 'error', 'config']; } connectedCallback() { this.render(); this.loadSettings(); } disconnectedCallback() { this.stopWhatsAppPolling(); } async loadSettings() { this.isLoading = true; this.error = null; this.render(); try { // Simulated API call await new Promise(r => setTimeout(r, 800)); this.config = { telegram: { enabled: true, chatId: '-1001234567890', hasToken: true }, whatsapp: { enabled: false, gatewayUrl: 'http://localhost:3000', phoneNumber: '+1234567890', hasApiKey: false } }; this.isLoading = false; this.render(); this.startWhatsAppPolling(); } catch (err) { this.isLoading = false; this.error = err.message || 'Failed to load settings'; this.render(); } } startWhatsAppPolling() { this.refreshWhatsAppStatus(); this.whatsAppStatusInterval = setInterval(() => this.refreshWhatsAppStatus(), 3000); } stopWhatsAppPolling() { if (this.whatsAppStatusInterval) { clearInterval(this.whatsAppStatusInterval); this.whatsAppStatusInterval = null; } } async refreshWhatsAppStatus() { // Simulated status fetch const states = ['connected', 'disconnected', 'connecting']; const state = Math.random() < 0.6 ? 'connected' : (Math.random() < 0.5 ? 'connecting' : 'disconnected'); const status = { state: state, phoneNumber: state === 'connected' ? this.config?.whatsapp?.phoneNumber : null, qrCode: state === 'disconnected' ? 'mock-qr-' + Date.now() : null, timestamp: new Date().toISOString() }; this.updateWhatsAppStatusUI(status); } updateWhatsAppStatusUI(status) { const container = this.shadowRoot.getElementById('whatsapp-status-badge'); if (!container) return; const isConnected = status.state === 'connected'; const isConnecting = status.state === 'connecting'; let badgeClass = 'bg-gray-100 text-gray-800'; let dotClass = 'bg-gray-500'; let text = 'Checking...'; if (isConnected) { badgeClass = 'bg-green-100 text-green-800'; dotClass = 'bg-green-500 animate-pulse'; text = 'Connected'; } else if (isConnecting) { badgeClass = 'bg-yellow-100 text-yellow-800'; dotClass = 'bg-yellow-500 animate-pulse'; text = 'Connecting...'; } else { badgeClass = 'bg-red-100 text-red-800'; dotClass = 'bg-red-500'; text = 'Not connected'; } container.className = `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${badgeClass}`; container.innerHTML = `${text}`; // Update status info const stateEl = this.shadowRoot.getElementById('status-state'); const phoneEl = this.shadowRoot.getElementById('status-phone'); const updatedEl = this.shadowRoot.getElementById('status-updated'); const qrContainer = this.shadowRoot.getElementById('qr-code-container'); const qrInstructions = this.shadowRoot.getElementById('qr-instructions'); if (stateEl) stateEl.textContent = status.state.charAt(0).toUpperCase() + status.state.slice(1); if (phoneEl) phoneEl.textContent = status.phoneNumber || '-'; if (updatedEl) updatedEl.textContent = new Date(status.timestamp).toLocaleTimeString(); // QR Code handling if (status.state === 'disconnected' && status.qrCode) { if (status.qrCode !== this.currentQrCode) { this.currentQrCode = status.qrCode; this.renderQRCode(status.qrCode); } if (qrInstructions) qrInstructions.classList.remove('hidden'); } else { this.currentQrCode = null; if (qrContainer) { if (isConnected) { qrContainer.innerHTML = `

Connected

${status.phoneNumber || 'WhatsApp Web active'}

`; } else { qrContainer.innerHTML = `

Waiting for connection...

`; } } if (qrInstructions) qrInstructions.classList.add('hidden'); } } renderQRCode(data) { const container = this.shadowRoot.getElementById('qr-code-container'); if (!container) return; container.innerHTML = `

${data.slice(0, 20)}...

`; } async saveTelegramConfig() { const enabled = this.shadowRoot.getElementById('telegram-enabled').checked; const chatId = this.shadowRoot.getElementById('telegram-chat-id').value.trim(); const token = this.shadowRoot.getElementById('telegram-bot-token').value.trim(); try { // Simulated API call await new Promise(r => setTimeout(r, 600)); this.config.telegram = { ...this.config.telegram, enabled, chatId, hasToken: !!token || this.config.telegram.hasToken }; this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'success', title: 'Success', message: 'Telegram configuration saved' }, bubbles: true, composed: true })); this.shadowRoot.getElementById('telegram-bot-token').value = ''; this.render(); } catch (err) { this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'error', title: 'Error', message: err.message || 'Failed to save Telegram settings' }, bubbles: true, composed: true })); } } async saveWhatsAppConfig() { const enabled = this.shadowRoot.getElementById('whatsapp-enabled').checked; const gatewayUrl = this.shadowRoot.getElementById('whatsapp-gateway').value.trim(); const phoneNumber = this.shadowRoot.getElementById('whatsapp-phone').value.trim(); const apiKey = this.shadowRoot.getElementById('whatsapp-api-key').value.trim(); try { await new Promise(r => setTimeout(r, 600)); this.config.whatsapp = { ...this.config.whatsapp, enabled, gatewayUrl, phoneNumber, hasApiKey: !!apiKey || this.config.whatsapp.hasApiKey }; this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'success', title: 'Success', message: 'WhatsApp configuration saved' }, bubbles: true, composed: true })); this.shadowRoot.getElementById('whatsapp-api-key').value = ''; this.render(); } catch (err) { this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'error', title: 'Error', message: err.message || 'Failed to save WhatsApp settings' }, bubbles: true, composed: true })); } } async sendTestMessage() { const phone = this.shadowRoot.getElementById('whatsapp-phone').value.trim(); const btn = this.shadowRoot.getElementById('test-message-btn'); const feedback = this.shadowRoot.getElementById('test-message-feedback'); if (!phone) return; btn.disabled = true; btn.innerHTML = '
'; try { await new Promise(r => setTimeout(r, 1000)); feedback.textContent = 'Test message sent successfully!'; feedback.className = 'mt-1 text-xs text-green-600'; this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'success', title: 'Test Sent', message: 'WhatsApp test message delivered' }, bubbles: true, composed: true })); } catch (err) { feedback.textContent = `Failed: ${err.message}`; feedback.className = 'mt-1 text-xs text-red-600'; this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'error', title: 'Test Failed', message: err.message }, bubbles: true, composed: true })); } finally { this.updateTestButtonState(); } } updateTestButtonState() { const phone = this.shadowRoot?.getElementById('whatsapp-phone')?.value.trim() || ''; const btn = this.shadowRoot?.getElementById('test-message-btn'); if (!btn) return; const hasPhone = phone.length > 0; btn.disabled = !hasPhone; btn.innerHTML = ' Test'; btn.className = hasPhone ? 'inline-flex items-center gap-2 px-4 py-2 border border-transparent rounded-lg text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-200 active:scale-95' : 'inline-flex items-center gap-2 px-4 py-2 border border-transparent rounded-lg text-sm font-medium text-white bg-gray-400 cursor-not-allowed transition-all duration-200'; } async resetWhatsAppSession() { if (!confirm('Are you sure you want to reset the WhatsApp session? You will need to scan the QR code again.')) { return; } try { await new Promise(r => setTimeout(r, 800)); this.currentQrCode = null; this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'success', title: 'Session Reset', message: 'WhatsApp session cleared. Scan the new QR code to reconnect.' }, bubbles: true, composed: true })); this.refreshWhatsAppStatus(); } catch (err) { this.dispatchEvent(new CustomEvent('toast', { detail: { type: 'error', title: 'Error', message: err.message || 'Failed to reset session' }, bubbles: true, composed: true })); } } togglePassword(inputId) { const input = this.shadowRoot.getElementById(inputId); const type = input.type === 'password' ? 'text' : 'password'; input.type = type; } refreshAll() { this.loadSettings(); } render() { const loadingHtml = `

Loading settings...

`; const errorHtml = `

Configuration Error

${this.error}

`; const contentHtml = this.config ? `

Telegram

Bot notifications via Telegram

The chat ID where notifications will be sent

Token: ${this.config.telegram.hasToken ? 'Set' : 'Not set'}

WhatsApp

Notifications via Baileys gateway

API Key: ${this.config.whatsapp.hasApiKey ? 'Set' : 'Not set'}

WhatsApp Connection Status

Checking...
Connection State Unknown
Recipient Phone -
Last Updated -

Loading QR code...

` : ''; this.shadowRoot.innerHTML = `

Notification Settings

Configure and monitor Telegram and WhatsApp notification channels

${this.isLoading ? loadingHtml : this.error ? errorHtml : contentHtml} `; // Attach event listeners if (!this.isLoading && !this.error && this.config) { this.shadowRoot.getElementById('save-telegram')?.addEventListener('click', () => this.saveTelegramConfig()); this.shadowRoot.getElementById('save-whatsapp')?.addEventListener('click', () => this.saveWhatsAppConfig()); this.shadowRoot.getElementById('test-message-btn')?.addEventListener('click', () => this.sendTestMessage()); this.shadowRoot.getElementById('refresh-whatsapp')?.addEventListener('click', () => this.refreshWhatsAppStatus()); this.shadowRoot.getElementById('reset-whatsapp')?.addEventListener('click', () => this.resetWhatsAppSession()); this.shadowRoot.getElementById('refresh-all')?.addEventListener('click', () => this.refreshAll()); this.shadowRoot.getElementById('whatsapp-phone')?.addEventListener('input', () => this.updateTestButtonState()); this.shadowRoot.querySelectorAll('.toggle-password').forEach(btn => { btn.addEventListener('click', (e) => { const inputId = e.target.closest('.relative').querySelector('input').id; this.togglePassword(inputId); }); }); // Initial button state this.updateTestButtonState(); } } } customElements.define('notification-settings', NotificationSettings);