/** * Sales Bot - Main Application JavaScript */ // Utility functions const Utils = { formatMoney(amount) { return new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN' }).format(amount || 0); }, formatDate(dateStr) { if (!dateStr) return ''; const date = new Date(dateStr); return date.toLocaleDateString('es-MX', { year: 'numeric', month: 'short', day: 'numeric' }); }, formatTime(dateStr) { if (!dateStr) return ''; const date = new Date(dateStr); return date.toLocaleTimeString('es-MX', { hour: '2-digit', minute: '2-digit' }); }, formatDateTime(dateStr) { if (!dateStr) return ''; return `${this.formatDate(dateStr)} ${this.formatTime(dateStr)}`; }, debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }, showNotification(message, type = 'info') { // Create notification element const notification = document.createElement('div'); notification.className = `notification notification-${type}`; notification.textContent = message; notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 15px 25px; border-radius: 8px; color: white; font-weight: 500; z-index: 9999; animation: slideIn 0.3s ease; background: ${type === 'success' ? '#00ff88' : type === 'error' ? '#ff4444' : '#00d4ff'}; color: ${type === 'success' || type === 'info' ? '#000' : '#fff'}; `; document.body.appendChild(notification); setTimeout(() => { notification.style.animation = 'slideOut 0.3s ease'; setTimeout(() => notification.remove(), 300); }, 3000); } }; // API Client const API = { async get(endpoint) { try { const response = await fetch(endpoint); if (!response.ok) throw new Error(`HTTP ${response.status}`); return await response.json(); } catch (error) { console.error(`API GET ${endpoint}:`, error); throw error; } }, async post(endpoint, data) { try { const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); if (!response.ok) throw new Error(`HTTP ${response.status}`); return await response.json(); } catch (error) { console.error(`API POST ${endpoint}:`, error); throw error; } } }; // Dashboard module const Dashboard = { async loadSummary() { try { const data = await API.get('/api/dashboard/resumen'); return data; } catch (error) { console.error('Error loading summary:', error); return null; } }, async loadRanking() { try { const data = await API.get('/api/dashboard/ranking'); return data; } catch (error) { console.error('Error loading ranking:', error); return []; } }, async loadRecentSales() { try { const data = await API.get('/api/dashboard/ventas-recientes'); return data; } catch (error) { console.error('Error loading recent sales:', error); return []; } } }; // Analytics module const Analytics = { async loadTrends(days = 30) { try { const data = await API.get(`/api/analytics/trends?days=${days}`); return data; } catch (error) { console.error('Error loading trends:', error); return null; } }, async loadPredictions(period = 30) { try { const data = await API.get(`/api/analytics/predictions?period=${period}`); return data; } catch (error) { console.error('Error loading predictions:', error); return null; } }, async loadComparisons(type = 'monthly') { try { const data = await API.get(`/api/analytics/comparisons?type=${type}`); return data; } catch (error) { console.error('Error loading comparisons:', error); return null; } } }; // Offline support const OfflineManager = { isOnline: navigator.onLine, init() { window.addEventListener('online', () => { this.isOnline = true; Utils.showNotification('Conexion restaurada', 'success'); this.syncData(); }); window.addEventListener('offline', () => { this.isOnline = false; Utils.showNotification('Sin conexion - Modo offline', 'error'); }); }, async cacheData(key, data) { try { localStorage.setItem(`salesbot_${key}`, JSON.stringify({ data, timestamp: Date.now() })); } catch (e) { console.error('Error caching data:', e); } }, getCachedData(key, maxAge = 300000) { // 5 minutes default try { const cached = localStorage.getItem(`salesbot_${key}`); if (!cached) return null; const { data, timestamp } = JSON.parse(cached); if (Date.now() - timestamp > maxAge) return null; return data; } catch (e) { return null; } }, syncData() { // Sync any pending data when back online console.log('Syncing data...'); } }; // Initialize document.addEventListener('DOMContentLoaded', () => { OfflineManager.init(); }); // Add CSS animations const style = document.createElement('style'); style.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } } `; document.head.appendChild(style); // Export for use in templates window.Utils = Utils; window.API = API; window.Dashboard = Dashboard; window.Analytics = Analytics;