/** * splash-loader.js — PWA splash screen + dynamic favicon * Show an animated splash while the app loads, then fade out. * Also provides dynamic favicon updates for notifications / offline states. */ (function() { 'use strict'; // ─── Create splash element ────────────────────────────────────────────── var splash = document.createElement('div'); splash.id = 'nx-splash'; splash.style.cssText = 'position:fixed;inset:0;z-index:99999;' + 'background:linear-gradient(135deg,#0d0d0d 0%,#1a1205 100%);' + 'display:flex;flex-direction:column;align-items:center;justify-content:center;' + 'transition:opacity 0.5s ease,visibility 0.5s ease;'; // Logo SVG (animated) var logoSvg = '' + '' + '' + '' + '' + '' + '' + '' + 'N' + ''; var title = '
Nexus
'; var subtitle = '
Autoparts POS
'; var spinner = '
'; splash.innerHTML = logoSvg + title + subtitle + spinner; // Inject keyframes if not present if (!document.getElementById('nx-splash-styles')) { var style = document.createElement('style'); style.id = 'nx-splash-styles'; style.textContent = '@keyframes nxDraw { to { stroke-dashoffset:0; } } @keyframes nxFadeIn { from { opacity:0;transform:translateY(8px); } to { opacity:1;transform:translateY(0); } }'; document.head.appendChild(style); } document.body.appendChild(splash); // Hide splash when DOM is ready + minimum display time var minDisplay = 800; var startTime = Date.now(); function hideSplash() { var elapsed = Date.now() - startTime; var remaining = Math.max(0, minDisplay - elapsed); setTimeout(function() { splash.style.opacity = '0'; splash.style.visibility = 'hidden'; setTimeout(function() { splash.remove(); }, 500); }, remaining); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', hideSplash); } else { hideSplash(); } // ─── Dynamic Favicon ──────────────────────────────────────────────────── window.NexusFavicon = { canvas: null, ctx: null, link: null, baseColor: '#F5A623', init: function() { this.canvas = document.createElement('canvas'); this.canvas.width = 64; this.canvas.height = 64; this.ctx = this.canvas.getContext('2d'); this.link = document.querySelector('link[rel*="icon"]') || document.createElement('link'); this.link.rel = 'shortcut icon'; this.link.type = 'image/png'; document.head.appendChild(this.link); this.setNormal(); }, draw: function(color, badge) { var ctx = this.ctx; var c = this.canvas; ctx.clearRect(0, 0, 64, 64); // Background circle ctx.beginPath(); ctx.arc(32, 32, 30, 0, Math.PI * 2); ctx.fillStyle = color || this.baseColor; ctx.fill(); // Letter N ctx.fillStyle = '#0d0d0d'; ctx.font = 'bold 36px system-ui,sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('N', 32, 33); // Badge dot if (badge) { ctx.beginPath(); ctx.arc(52, 12, 10, 0, Math.PI * 2); ctx.fillStyle = '#ef4444'; ctx.fill(); ctx.fillStyle = '#fff'; ctx.font = 'bold 11px system-ui,sans-serif'; ctx.fillText(badge > 9 ? '9+' : String(badge), 52, 13); } this.link.href = c.toDataURL('image/png'); }, setNormal: function() { this.draw(this.baseColor); }, setOffline: function() { this.draw('#666'); }, setNotify: function(count) { this.draw(this.baseColor, count); }, }; // Auto-init favicon if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { NexusFavicon.init(); }); } else { NexusFavicon.init(); } // Update favicon on online/offline window.addEventListener('online', function() { if (window.NexusFavicon) NexusFavicon.setNormal(); }); window.addEventListener('offline', function() { if (window.NexusFavicon) NexusFavicon.setOffline(); }); })();