Product-enhancements-and-validation-fixes

This commit is contained in:
sysadmin
2025-09-01 08:03:00 +01:00
parent c8a55c143b
commit ee4a5c3578
12 changed files with 340 additions and 211 deletions

View File

@@ -37,12 +37,13 @@ class PWAManager {
// Setup push notifications
this.setupPushNotifications();
// Show manual install option after 3 seconds if no prompt appeared and app not installed
// Show manual install option after 5 seconds if no prompt appeared and app not installed
setTimeout(() => {
if (!document.getElementById('pwa-install-btn') && !this.isInstalled()) {
console.log('PWA: No install prompt appeared, showing manual install guide');
this.showManualInstallButton();
}
}, 3000);
}, 5000);
}
setupInstallPrompt() {
@@ -70,6 +71,9 @@ class PWAManager {
this.hideInstallButton();
} else {
console.log('PWA: App is not installed, waiting for install prompt...');
console.log('PWA: Current URL:', window.location.href);
console.log('PWA: Display mode:', window.matchMedia('(display-mode: standalone)').matches ? 'standalone' : 'browser');
console.log('PWA: User agent:', navigator.userAgent);
}
// Periodically check if app becomes installed (for cases where user installs via browser menu)
@@ -210,7 +214,27 @@ class PWAManager {
`;
installBtn.addEventListener('click', () => {
alert('To install this app:\\n\\n1. Click the browser menu (⋮)\\n2. Select "Install LittleShop Admin"\\n\\nOr look for the install icon in the address bar!');
const isChrome = navigator.userAgent.includes('Chrome');
const isEdge = navigator.userAgent.includes('Edge');
const isFirefox = navigator.userAgent.includes('Firefox');
let instructions = 'To install this app:\\n\\n';
if (isChrome || isEdge) {
instructions += '1. Look for the install icon (⬇️) in the address bar\\n';
instructions += '2. Or click the browser menu (⋮) → "Install LittleShop Admin"\\n';
instructions += '3. Or check if there\'s an "Install app" option in the browser menu';
} else if (isFirefox) {
instructions += '1. Firefox doesn\'t support PWA installation yet\\n';
instructions += '2. You can bookmark this page for easy access\\n';
instructions += '3. Or use Chrome/Edge for the full PWA experience';
} else {
instructions += '1. Look for an install or "Add to Home Screen" option\\n';
instructions += '2. Check your browser menu for app installation\\n';
instructions += '3. Or bookmark this page for quick access';
}
alert(instructions);
});
document.body.appendChild(installBtn);
@@ -230,25 +254,21 @@ class PWAManager {
}
try {
// Check if user has dismissed push notifications recently
const dismissedUntil = localStorage.getItem('pushNotificationsDismissedUntil');
if (dismissedUntil && new Date() < new Date(dismissedUntil)) {
console.log('PWA: Push notifications dismissed by user, skipping setup');
return;
}
// Get VAPID public key from server
await this.getVapidPublicKey();
// Check if user is already subscribed
await this.checkPushSubscription();
// Only show setup UI if not subscribed and not recently dismissed
const isSubscribedFromCache = localStorage.getItem('pushNotificationsSubscribed') === 'true';
if (!this.pushSubscription && !isSubscribedFromCache) {
this.showPushNotificationSetup();
// Simple logic: only show prompt if user is not subscribed
if (!this.pushSubscription) {
// Check if we've already asked this session
if (!sessionStorage.getItem('pushNotificationPromptShown')) {
this.showPushNotificationSetup();
sessionStorage.setItem('pushNotificationPromptShown', 'true');
}
} else {
console.log('PWA: User already subscribed to push notifications, skipping setup UI');
console.log('PWA: User already subscribed to push notifications');
}
} catch (error) {
@@ -280,34 +300,9 @@ class PWAManager {
try {
this.pushSubscription = await this.swRegistration.pushManager.getSubscription();
if (this.pushSubscription) {
console.log('PWA: Browser has push subscription');
// Verify server-side subscription still exists by trying to send a test
try {
const response = await fetch('/api/push/subscriptions', {
credentials: 'same-origin'
});
if (response.ok) {
const subscriptions = await response.json();
const hasServerSubscription = subscriptions.some(sub =>
sub.endpoint && this.pushSubscription.endpoint.includes(sub.endpoint.substring(0, 50))
);
if (!hasServerSubscription) {
console.log('PWA: Server subscription missing, will re-subscribe on next attempt');
localStorage.removeItem('pushNotificationsSubscribed');
} else {
console.log('PWA: Server subscription confirmed');
localStorage.setItem('pushNotificationsSubscribed', 'true');
}
}
} catch (error) {
console.log('PWA: Could not verify server subscription:', error.message);
}
console.log('PWA: User has active push subscription');
} else {
console.log('PWA: User is not subscribed to push notifications');
localStorage.removeItem('pushNotificationsSubscribed');
}
} catch (error) {
console.error('PWA: Error checking push subscription:', error);
@@ -358,12 +353,7 @@ class PWAManager {
if (response.ok) {
this.pushSubscription = subscription;
console.log('PWA: Successfully subscribed to push notifications');
// Cache subscription state
localStorage.setItem('pushNotificationsSubscribed', 'true');
localStorage.setItem('pushNotificationsSubscribedAt', new Date().toISOString());
this.updatePushNotificationUI();
this.hidePushNotificationSetup();
return true;
} else {
throw new Error('Failed to save push subscription to server');
@@ -397,12 +387,6 @@ class PWAManager {
this.pushSubscription = null;
console.log('PWA: Successfully unsubscribed from push notifications');
// Clear subscription cache
localStorage.removeItem('pushNotificationsSubscribed');
localStorage.removeItem('pushNotificationsSubscribedAt');
this.updatePushNotificationUI();
return true;
} catch (error) {
console.error('PWA: Failed to unsubscribe from push notifications:', error);
@@ -427,32 +411,24 @@ class PWAManager {
max-width: 350px;
`;
const isSubscribed = !!this.pushSubscription;
setupDiv.innerHTML = `
<div class="d-flex align-items-center">
<i class="fas fa-bell me-2"></i>
<div class="flex-grow-1">
<strong>Push Notifications</strong><br>
<small>${isSubscribed ? 'You are subscribed to notifications' : 'Get notified of new orders and updates'}</small>
<small>Get notified of new orders and updates</small>
</div>
<div class="ms-2">
${isSubscribed ?
'<button type="button" class="btn btn-sm btn-outline-danger" id="unsubscribe-push-btn">Turn Off</button>' :
'<div class="d-flex flex-column gap-1"><button type="button" class="btn btn-sm btn-primary" id="subscribe-push-btn">Turn On</button><button type="button" class="btn btn-sm btn-outline-secondary" id="dismiss-push-btn">Not Now</button></div>'
}
<button type="button" class="btn btn-sm btn-primary" id="subscribe-push-btn">Enable</button>
</div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" id="close-push-setup"></button>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(setupDiv);
// Add event listeners
// Add event listener for subscribe button
const subscribeBtn = document.getElementById('subscribe-push-btn');
const unsubscribeBtn = document.getElementById('unsubscribe-push-btn');
const dismissBtn = document.getElementById('dismiss-push-btn');
const closeBtn = document.getElementById('close-push-setup');
if (subscribeBtn) {
subscribeBtn.addEventListener('click', async () => {
@@ -475,76 +451,17 @@ class PWAManager {
alert('Failed to enable push notifications: ' + userMessage);
subscribeBtn.disabled = false;
subscribeBtn.innerHTML = 'Turn On';
subscribeBtn.innerHTML = 'Enable';
}
});
}
if (unsubscribeBtn) {
unsubscribeBtn.addEventListener('click', async () => {
unsubscribeBtn.disabled = true;
unsubscribeBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Disabling...';
try {
await this.unsubscribeFromPushNotifications();
this.showNotification('Push notifications disabled', {
body: 'You will no longer receive push notifications.'
});
} catch (error) {
alert('Failed to disable push notifications: ' + error.message);
unsubscribeBtn.disabled = false;
unsubscribeBtn.innerHTML = 'Turn Off';
}
});
}
// Handle dismiss button
if (dismissBtn) {
dismissBtn.addEventListener('click', () => {
// Dismiss for 24 hours
const dismissUntil = new Date();
dismissUntil.setHours(dismissUntil.getHours() + 24);
localStorage.setItem('pushNotificationsDismissedUntil', dismissUntil.toISOString());
const element = document.getElementById('push-notification-setup');
if (element) {
element.remove();
}
console.log('PWA: Push notifications dismissed for 24 hours');
});
}
// Handle close button
if (closeBtn) {
closeBtn.addEventListener('click', () => {
// Dismiss for 1 hour
const dismissUntil = new Date();
dismissUntil.setHours(dismissUntil.getHours() + 1);
localStorage.setItem('pushNotificationsDismissedUntil', dismissUntil.toISOString());
console.log('PWA: Push notifications dismissed for 1 hour');
});
}
// Auto-hide after 15 seconds
setTimeout(() => {
const element = document.getElementById('push-notification-setup');
if (element) {
element.remove();
// Auto-dismiss for 2 hours if user ignores
const dismissUntil = new Date();
dismissUntil.setHours(dismissUntil.getHours() + 2);
localStorage.setItem('pushNotificationsDismissedUntil', dismissUntil.toISOString());
console.log('PWA: Push notifications auto-dismissed for 2 hours');
}
}, 15000);
}
updatePushNotificationUI() {
hidePushNotificationSetup() {
const setupDiv = document.getElementById('push-notification-setup');
if (setupDiv) {
setupDiv.remove();
this.showPushNotificationSetup();
console.log('PWA: Push notification setup hidden');
}
}