Temporarily disable anti-forgery validation for HTTPS proxy compatibility
This commit is contained in:
317
publish/littleshop-hotfix/wwwroot/js/notifications.js
Normal file
317
publish/littleshop-hotfix/wwwroot/js/notifications.js
Normal file
@@ -0,0 +1,317 @@
|
||||
// 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 = `
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-bell-slash text-warning me-3 fa-2x"></i>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="alert-heading mb-1">Enable Order Notifications</h6>
|
||||
<p class="mb-2">Get instant alerts for new orders, payments, and status changes.</p>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-warning btn-sm" id="enable-admin-notifications">
|
||||
<i class="fas fa-bell me-1"></i>Enable Now
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" id="remind-later">
|
||||
Later
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`;
|
||||
|
||||
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 = '<i class="fas fa-spinner fa-spin me-1"></i>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 = `
|
||||
<a class="nav-link dropdown-toggle" href="#" id="notification-status" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-bell text-success"></i>
|
||||
<span class="d-none d-md-inline ms-1">Notifications</span>
|
||||
<span id="notification-badge" class="badge bg-danger ms-1" style="display: none;">0</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><h6 class="dropdown-header">Notification Settings</h6></li>
|
||||
<li><a class="dropdown-item" href="#" id="test-notification">
|
||||
<i class="fas fa-vial me-2"></i>Send Test Notification
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="notification-history">
|
||||
<i class="fas fa-history me-2"></i>Recent Notifications
|
||||
</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item text-danger" href="#" id="disable-notifications">
|
||||
<i class="fas fa-bell-slash me-2"></i>Disable Notifications
|
||||
</a></li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
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 = '<i class="fas fa-bell me-1"></i>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}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`;
|
||||
|
||||
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;
|
||||
Reference in New Issue
Block a user