// Enhanced notification management for LittleShop Admin // Handles real-time order notifications and admin alerts class AdminNotificationManager { constructor() { this.isSetupComplete = false; this.notificationQueue = []; this.init(); } async init() { console.log('Admin Notifications: Initializing...'); // Wait for PWA manager to be ready if (window.pwaManager) { await this.setupOrderNotifications(); } else { // Wait for PWA manager to load setTimeout(() => this.init(), 1000); } } async setupOrderNotifications() { try { // Ensure push notifications are enabled if (!window.pwaManager.pushSubscription) { console.log('Admin Notifications: Setting up push notifications...'); // Show admin-specific notification prompt this.showAdminNotificationPrompt(); return; } this.isSetupComplete = true; this.addNotificationStatusIndicator(); this.setupTestNotificationButton(); console.log('Admin Notifications: Setup complete'); } catch (error) { console.error('Admin Notifications: Setup failed:', error); } } showAdminNotificationPrompt() { // Check if prompt already exists if (document.getElementById('admin-notification-prompt')) { return; } const promptDiv = document.createElement('div'); promptDiv.id = 'admin-notification-prompt'; promptDiv.className = 'alert alert-warning alert-dismissible position-fixed'; promptDiv.style.cssText = ` top: 80px; right: 20px; z-index: 1055; max-width: 400px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); `; promptDiv.innerHTML = `
Enable Order Notifications

Get instant alerts for new orders, payments, and status changes.

`; document.body.appendChild(promptDiv); // Add event listeners document.getElementById('enable-admin-notifications').addEventListener('click', async () => { try { await this.enableNotifications(); promptDiv.remove(); } catch (error) { console.error('Failed to enable notifications:', error); this.showNotificationError('Failed to enable notifications. Please try again.'); } }); document.getElementById('remind-later').addEventListener('click', () => { promptDiv.remove(); // Set reminder for 1 hour setTimeout(() => this.showAdminNotificationPrompt(), 60 * 60 * 1000); }); } async enableNotifications() { const button = document.getElementById('enable-admin-notifications'); const originalText = button.innerHTML; button.disabled = true; button.innerHTML = 'Enabling...'; try { await window.pwaManager.subscribeToPushNotifications(); // Show success message this.showNotificationSuccess('✅ Order notifications enabled successfully!'); // Complete setup await this.setupOrderNotifications(); } finally { button.disabled = false; button.innerHTML = originalText; } } addNotificationStatusIndicator() { // Add status indicator to admin header/navbar const navbar = document.querySelector('.navbar-nav'); if (!navbar || document.getElementById('notification-status')) { return; } const statusItem = document.createElement('li'); statusItem.className = 'nav-item dropdown'; statusItem.innerHTML = ` Notifications `; navbar.appendChild(statusItem); // Add event listeners document.getElementById('test-notification').addEventListener('click', (e) => { e.preventDefault(); this.sendTestNotification(); }); document.getElementById('disable-notifications').addEventListener('click', (e) => { e.preventDefault(); this.disableNotifications(); }); } setupTestNotificationButton() { // Add test button to dashboard if we're on the dashboard page const dashboardContent = document.querySelector('.dashboard-content, .admin-dashboard'); if (!dashboardContent) { return; } const testButton = document.createElement('button'); testButton.className = 'btn btn-outline-primary btn-sm me-2'; testButton.innerHTML = 'Test Notification'; testButton.onclick = () => this.sendTestNotification(); // Find a good place to add it (e.g., near page title) const pageTitle = document.querySelector('h1, .page-title'); if (pageTitle) { pageTitle.parentNode.insertBefore(testButton, pageTitle.nextSibling); } } async sendTestNotification() { try { const response = await fetch('/api/push/test', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ title: '🧪 Test Notification', body: 'LittleShop admin notifications are working perfectly!' }), credentials: 'same-origin' }); if (response.ok) { this.showNotificationSuccess('Test notification sent!'); } else { throw new Error('Failed to send test notification'); } } catch (error) { console.error('Test notification failed:', error); this.showNotificationError('Failed to send test notification'); } } async disableNotifications() { if (confirm('Are you sure you want to disable order notifications?')) { try { await window.pwaManager.unsubscribeFromPushNotifications(); // Remove status indicator const statusElement = document.getElementById('notification-status'); if (statusElement) { statusElement.closest('.nav-item').remove(); } this.showNotificationSuccess('Notifications disabled'); // Reset setup status this.isSetupComplete = false; } catch (error) { console.error('Failed to disable notifications:', error); this.showNotificationError('Failed to disable notifications'); } } } showNotificationSuccess(message) { this.showToast(message, 'success'); } showNotificationError(message) { this.showToast(message, 'danger'); } showToast(message, type = 'info') { const toast = document.createElement('div'); toast.className = `alert alert-${type} alert-dismissible position-fixed`; toast.style.cssText = ` top: 20px; right: 20px; z-index: 1060; min-width: 300px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); `; toast.innerHTML = ` ${message} `; document.body.appendChild(toast); // Auto-remove after 5 seconds setTimeout(() => { if (toast.parentNode) { toast.remove(); } }, 5000); } // Handle incoming notifications (if using WebSocket/SignalR in future) handleOrderNotification(data) { if (!this.isSetupComplete) { this.notificationQueue.push(data); return; } // Update notification badge this.updateNotificationBadge(); // Show browser notification if page is not visible if (document.hidden && window.pwaManager) { window.pwaManager.showNotification(data.title, { body: data.body, icon: '/icons/icon-192x192.png', badge: '/icons/icon-72x72.png', tag: 'order-notification', requireInteraction: true, actions: [ { action: 'view', title: 'View Order' }, { action: 'dismiss', title: 'Dismiss' } ] }); } } updateNotificationBadge(count = null) { const badge = document.getElementById('notification-badge'); if (!badge) return; if (count === null) { // Get current count and increment const currentCount = parseInt(badge.textContent) || 0; count = currentCount + 1; } if (count > 0) { badge.textContent = count; badge.style.display = 'inline'; } else { badge.style.display = 'none'; } } } // Initialize admin notification manager document.addEventListener('DOMContentLoaded', () => { window.adminNotificationManager = new AdminNotificationManager(); }); // Export for global access window.AdminNotificationManager = AdminNotificationManager;