Spaces:
Running
Running
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>La Cogotuda - Panel de Fabricación</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;900&display=swap" rel="stylesheet"> | |
| <style> | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: #FDFBF8; | |
| color: #1a202c; | |
| } | |
| .logo-font { | |
| font-weight: 900; | |
| letter-spacing: -0.05em; | |
| } | |
| .dashboard-bg { | |
| background-color: #f0eada; | |
| } | |
| .btn-primary { | |
| background-color: #D95F43; | |
| color: white; | |
| transition: background-color 0.3s ease; | |
| } | |
| .btn-primary:hover { | |
| background-color: #b94e36; | |
| } | |
| .btn-secondary { | |
| background-color: #2C4A6E; | |
| color: white; | |
| transition: background-color 0.3s ease; | |
| } | |
| .btn-secondary:hover { | |
| background-color: #1f3550; | |
| } | |
| .btn-success { | |
| background-color: #4CAF50; | |
| color: white; | |
| } | |
| .btn-success:hover { | |
| background-color: #45a049; | |
| } | |
| .btn-warning { | |
| background-color: #FF9800; | |
| color: white; | |
| } | |
| .btn-warning:hover { | |
| background-color: #e68900; | |
| } | |
| .status-pending { | |
| background-color: #FFF3E0; | |
| color: #FF9800; | |
| } | |
| .status-processing { | |
| background-color: #E3F2FD; | |
| color: #2196F3; | |
| } | |
| .status-shipped { | |
| background-color: #E8F5E9; | |
| color: #4CAF50; | |
| } | |
| .status-completed { | |
| background-color: #F3E5F5; | |
| color: #9C27B0; | |
| } | |
| .progress-bar { | |
| height: 8px; | |
| background-color: #e2e8f0; | |
| border-radius: 4px; | |
| overflow: hidden; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background-color: #D95F43; | |
| border-radius: 4px; | |
| transition: width 0.3s ease; | |
| } | |
| .card { | |
| background: white; | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
| border: 1px solid #e2e8f0; | |
| } | |
| .notification { | |
| animation: slideIn 0.3s ease-out; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| transform: translateX(100%); | |
| opacity: 0; | |
| } | |
| to { | |
| transform: translateX(0); | |
| opacity: 1; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Header --> | |
| <header class="bg-white/80 backdrop-blur-lg sticky top-0 z-40 border-b border-gray-200"> | |
| <div class="container mx-auto px-6 py-4 flex justify-between items-center"> | |
| <div class="flex items-center space-x-3"> | |
| <img src="https://huggingface.co/spaces/Lukeetah/COGOTUDA/resolve/main/cogotuda.png" alt="Logo La Cogotuda" class="h-10 w-10 object-cover rounded-md shadow-sm"> | |
| <span class="text-2xl logo-font text-gray-800">LA COGOTUDA</span> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <span class="text-gray-600">Panel de Fabricación</span> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-3 h-3 bg-green-500 rounded-full"></div> | |
| <span class="text-sm text-gray-600">En línea</span> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="py-8"> | |
| <div class="container mx-auto px-6"> | |
| <!-- Dashboard Header --> | |
| <div class="mb-8"> | |
| <h1 class="text-3xl font-black text-gray-800 mb-2">Panel de Control de Fabricación</h1> | |
| <p class="text-gray-600">Gestiona pedidos, producción y envíos en tiempo real</p> | |
| </div> | |
| <!-- Stats Cards --> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8"> | |
| <div class="card p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500 text-sm">Pedidos Pendientes</p> | |
| <p class="text-3xl font-bold text-gray-800" id="pending-count">12</p> | |
| </div> | |
| <div class="bg-orange-100 p-3 rounded-lg"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D95F43" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500 text-sm">En Producción</p> | |
| <p class="text-3xl font-bold text-gray-800" id="processing-count">8</p> | |
| </div> | |
| <div class="bg-blue-100 p-3 rounded-lg"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2C4A6E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500 text-sm">Listos para Enviar</p> | |
| <p class="text-3xl font-bold text-gray-800" id="ready-count">5</p> | |
| </div> | |
| <div class="bg-green-100 p-3 rounded-lg"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card p-6"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <p class="text-gray-500 text-sm">Total Hoy</p> | |
| <p class="text-3xl font-bold text-gray-800" id="total-count">25</p> | |
| </div> | |
| <div class="bg-purple-100 p-3 rounded-lg"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#9C27B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path><line x1="3" y1="6" x2="21" y2="6"></line><path d="M16 10a4 4 0 0 1-8 0"></path></svg> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Orders Section --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Pending Orders --> | |
| <div class="lg:col-span-2"> | |
| <div class="card"> | |
| <div class="p-6 border-b border-gray-200"> | |
| <h2 class="text-xl font-bold text-gray-800">Pedidos Pendientes</h2> | |
| <p class="text-gray-500 text-sm">Pedidos que requieren atención inmediata</p> | |
| </div> | |
| <div class="p-6"> | |
| <div class="space-y-4" id="pending-orders"> | |
| <!-- Pending orders will be populated here --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Production Queue --> | |
| <div> | |
| <div class="card mb-6"> | |
| <div class="p-6 border-b border-gray-200"> | |
| <h2 class="text-xl font-bold text-gray-800">Cola de Producción</h2> | |
| <p class="text-gray-500 text-sm">Pedidos en proceso de fabricación</p> | |
| </div> | |
| <div class="p-6"> | |
| <div class="space-y-4" id="production-queue"> | |
| <!-- Production queue will be populated here --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Shipping Queue --> | |
| <div class="card"> | |
| <div class="p-6 border-b border-gray-200"> | |
| <h2 class="text-xl font-bold text-gray-800">Listos para Enviar</h2> | |
| <p class="text-gray-500 text-sm">Pedidos completados y preparados</p> | |
| </div> | |
| <div class="p-6"> | |
| <div class="space-y-4" id="shipping-queue"> | |
| <!-- Shipping queue will be populated here --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Order Detail Modal --> | |
| <div id="order-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"> | |
| <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto"> | |
| <div class="p-6 border-b border-gray-200 flex justify-between items-center"> | |
| <h3 class="text-2xl font-bold text-gray-800">Detalles del Pedido</h3> | |
| <button id="close-modal" class="text-gray-500 hover:text-gray-700"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| <div class="p-6" id="order-details-content"> | |
| <!-- Order details will be populated here --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Notification Container --> | |
| <div id="notification-container" class="fixed bottom-4 right-4 space-y-2 z-50"></div> | |
| <script> | |
| // Mock data for orders | |
| const orders = [ | |
| { | |
| id: "ORD-001", | |
| customer: "María González", | |
| email: "maria@example.com", | |
| date: "2024-01-15", | |
| items: [ | |
| { name: "Kit 50x70cm", type: "Lino Premium", quantity: 1, price: 4500 } | |
| ], | |
| total: 4500, | |
| status: "pending", | |
| address: "Av. Corrientes 1234, Buenos Aires", | |
| phone: "+54 11 1234-5678", | |
| notes: "Entrega urgente para exposición" | |
| }, | |
| { | |
| id: "ORD-002", | |
| customer: "Juan Pérez", | |
| email: "juan@example.com", | |
| date: "2024-01-15", | |
| items: [ | |
| { name: "Kit 30x40cm", type: "Algodón Universal", quantity: 2, price: 2200 }, | |
| { name: "Kit 80x100cm", type: "Lino Premium", quantity: 1, price: 8900 } | |
| ], | |
| total: 13300, | |
| status: "processing", | |
| address: "Calle Florida 567, Buenos Aires", | |
| phone: "+54 11 9876-5432", | |
| notes: "Incluir tarjeta de regalo" | |
| }, | |
| { | |
| id: "ORD-003", | |
| customer: "Ana Rodríguez", | |
| email: "ana@example.com", | |
| date: "2024-01-14", | |
| items: [ | |
| { name: "Kit 50x70cm", type: "Algodón Universal", quantity: 1, price: 3000 } | |
| ], | |
| total: 3000, | |
| status: "shipped", | |
| address: "Av. Santa Fe 890, Buenos Aires", | |
| phone: "+54 11 5555-4444", | |
| tracking: "TRK-789456123" | |
| }, | |
| { | |
| id: "ORD-004", | |
| customer: "Carlos López", | |
| email: "carlos@example.com", | |
| date: "2024-01-14", | |
| items: [ | |
| { name: "Kit 80x100cm", type: "Lino Premium", quantity: 3, price: 26700 } | |
| ], | |
| total: 26700, | |
| status: "completed", | |
| address: "San Martín 321, Rosario", | |
| phone: "+54 341 123-4567", | |
| tracking: "TRK-159753468" | |
| }, | |
| { | |
| id: "ORD-005", | |
| customer: "Laura Martínez", | |
| email: "laura@example.com", | |
| date: "2024-01-16", | |
| items: [ | |
| { name: "Kit 30x40cm", type: "Lino Premium", quantity: 1, price: 1650 } | |
| ], | |
| total: 1650, | |
| status: "pending", | |
| address: "Belgrano 456, Córdoba", | |
| phone: "+54 351 987-6543", | |
| notes: "Cliente nuevo, verificar datos" | |
| } | |
| ]; | |
| // DOM Elements | |
| const pendingOrdersEl = document.getElementById('pending-orders'); | |
| const productionQueueEl = document.getElementById('production-queue'); | |
| const shippingQueueEl = document.getElementById('shipping-queue'); | |
| const orderModal = document.getElementById('order-modal'); | |
| const closeModal = document.getElementById('close-modal'); | |
| const orderDetailsContent = document.getElementById('order-details-content'); | |
| const notificationContainer = document.getElementById('notification-container'); | |
| // Initialize dashboard | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderOrders(); | |
| updateStats(); | |
| }); | |
| // Render orders in their respective sections | |
| function renderOrders() { | |
| // Clear sections | |
| pendingOrdersEl.innerHTML = ''; | |
| productionQueueEl.innerHTML = ''; | |
| shippingQueueEl.innerHTML = ''; | |
| // Filter orders by status | |
| const pendingOrders = orders.filter(order => order.status === 'pending'); | |
| const processingOrders = orders.filter(order => order.status === 'processing'); | |
| const readyOrders = orders.filter(order => order.status === 'shipped' || order.status === 'completed'); | |
| // Render pending orders | |
| if (pendingOrders.length === 0) { | |
| pendingOrdersEl.innerHTML = '<p class="text-gray-500 text-center py-4">No hay pedidos pendientes</p>'; | |
| } else { | |
| pendingOrders.forEach(order => { | |
| pendingOrdersEl.appendChild(createOrderCard(order)); | |
| }); | |
| } | |
| // Render production queue | |
| if (processingOrders.length === 0) { | |
| productionQueueEl.innerHTML = '<p class="text-gray-500 text-center py-4">No hay pedidos en producción</p>'; | |
| } else { | |
| processingOrders.forEach(order => { | |
| productionQueueEl.appendChild(createOrderCard(order)); | |
| }); | |
| } | |
| // Render shipping queue | |
| if (readyOrders.length === 0) { | |
| shippingQueueEl.innerHTML = '<p class="text-gray-500 text-center py-4">No hay pedidos listos para enviar</p>'; | |
| } else { | |
| readyOrders.forEach(order => { | |
| shippingQueueEl.appendChild(createOrderCard(order)); | |
| }); | |
| } | |
| } | |
| // Create order card element | |
| function createOrderCard(order) { | |
| const card = document.createElement('div'); | |
| card.className = 'border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow cursor-pointer'; | |
| card.onclick = () => showOrderDetails(order); | |
| let statusClass = ''; | |
| let statusText = ''; | |
| switch(order.status) { | |
| case 'pending': | |
| statusClass = 'status-pending'; | |
| statusText = 'Pendiente'; | |
| break; | |
| case 'processing': | |
| statusClass = 'status-processing'; | |
| statusText = 'En Producción'; | |
| break; | |
| case 'shipped': | |
| statusClass = 'status-shipped'; | |
| statusText = 'Enviado'; | |
| break; | |
| case 'completed': | |
| statusClass = 'status-completed'; | |
| statusText = 'Completado'; | |
| break; | |
| } | |
| card.innerHTML = ` | |
| <div class="flex justify-between items-start mb-3"> | |
| <div> | |
| <h4 class="font-bold text-gray-800">${order.id}</h4> | |
| <p class="text-gray-600 text-sm">${order.customer}</p> | |
| </div> | |
| <span class="px-2 py-1 rounded-full text-xs font-medium ${statusClass}">${statusText}</span> | |
| </div> | |
| <div class="mb-3"> | |
| <p class="text-gray-800 font-semibold">$${order.total.toLocaleString('es-AR')}</p> | |
| <p class="text-gray-500 text-sm">${order.date}</p> | |
| </div> | |
| <div class="text-sm text-gray-600"> | |
| ${order.items.map(item => `${item.quantity}x ${item.name} (${item.type})`).join('<br>')} | |
| </div> | |
| `; | |
| return card; | |
| } | |
| // Show order details modal | |
| function showOrderDetails(order) { | |
| let statusClass = ''; | |
| let statusText = ''; | |
| switch(order.status) { | |
| case 'pending': | |
| statusClass = 'status-pending'; | |
| statusText = 'Pendiente'; | |
| break; | |
| case 'processing': | |
| statusClass = 'status-processing'; | |
| statusText = 'En Producción'; | |
| break; | |
| case 'shipped': | |
| statusClass = 'status-shipped'; | |
| statusText = 'Enviado'; | |
| break; | |
| case 'completed': | |
| statusClass = 'status-completed'; | |
| statusText = 'Completado'; | |
| break; | |
| } | |
| orderDetailsContent.innerHTML = ` | |
| <div class="mb-6"> | |
| <div class="flex justify-between items-start mb-4"> | |
| <div> | |
| <h3 class="text-xl font-bold text-gray-800">${order.id}</h3> | |
| <p class="text-gray-600">${order.customer}</p> | |
| </div> | |
| <span class="px-3 py-1 rounded-full text-sm font-medium ${statusClass}">${statusText}</span> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <p class="text-gray-500 text-sm">Email</p> | |
| <p class="text-gray-800">${order.email}</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500 text-sm">Teléfono</p> | |
| <p class="text-gray-800">${order.phone}</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500 text-sm">Fecha</p> | |
| <p class="text-gray-800">${order.date}</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-500 text-sm">Total</p> | |
| <p class="text-xl font-bold text-gray-800">$${order.total.toLocaleString('es-AR')}</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h4 class="font-bold text-gray-800 mb-3">Dirección de Envío</h4> | |
| <p class="text-gray-800">${order.address}</p> | |
| </div> | |
| <div class="mb-6"> | |
| <h4 class="font-bold text-gray-800 mb-3">Artículos</h4> | |
| <div class="space-y-3"> | |
| ${order.items.map(item => ` | |
| <div class="flex justify-between items-center p-3 bg-gray-50 rounded-lg"> | |
| <div> | |
| <p class="font-medium text-gray-800">${item.name}</p> | |
| <p class="text-gray-600 text-sm">${item.type}</p> | |
| </div> | |
| <div class="text-right"> | |
| <p class="font-medium text-gray-800">x${item.quantity}</p> | |
| <p class="text-gray-600 text-sm">$${item.price.toLocaleString('es-AR')}</p> | |
| </div> | |
| </div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| ${order.notes ? ` | |
| <div class="mb-6"> | |
| <h4 class="font-bold text-gray-800 mb-3">Notas del Cliente</h4> | |
| <p class="text-gray-800 bg-yellow-50 p-3 rounded-lg">${order.notes}</p> | |
| </div> | |
| ` : ''} | |
| ${order.tracking ? ` | |
| <div class="mb-6"> | |
| <h4 class="font-bold text-gray-800 mb-3">Número de Seguimiento</h4> | |
| <p class="text-gray-800 font-mono bg-blue-50 p-3 rounded-lg">${order.tracking}</p> | |
| </div> | |
| ` : ''} | |
| <div class="flex flex-wrap gap-3 pt-4 border-t border-gray-200"> | |
| ${order.status === 'pending' ? ` | |
| <button onclick="updateOrderStatus('${order.id}', 'processing')" class="btn-primary px-4 py-2 rounded-lg font-medium">Iniciar Producción</button> | |
| <button onclick="updateOrderStatus('${order.id}', 'shipped')" class="btn-warning px-4 py-2 rounded-lg font-medium">Marcar como Enviado</button> | |
| ` : ''} | |
| ${order.status === 'processing' ? ` | |
| <button onclick="updateOrderStatus('${order.id}', 'shipped')" class="btn-success px-4 py-2 rounded-lg font-medium">Marcar como Enviado</button> | |
| <button onclick="updateOrderStatus('${order.id}', 'completed')" class="btn-secondary px-4 py-2 rounded-lg font-medium">Completar Pedido</button> | |
| ` : ''} | |
| ${order.status === 'shipped' ? ` | |
| <button onclick="updateOrderStatus('${order.id}', 'completed')" class="btn-success px-4 py-2 rounded-lg font-medium">Completar Pedido</button> | |
| ` : ''} | |
| <button onclick="deleteOrder('${order.id}')" class="ml-auto text-red-500 hover:text-red-700 px-4 py-2 rounded-lg font-medium">Eliminar Pedido</button> | |
| </div> | |
| `; | |
| orderModal.classList.remove('hidden'); | |
| } | |
| // Close modal | |
| closeModal.addEventListener('click', () => { | |
| orderModal.classList.add('hidden'); | |
| }); | |
| // Close modal when clicking outside | |
| orderModal.addEventListener('click', (e) => { | |
| if (e.target === orderModal) { | |
| orderModal.classList.add('hidden'); | |
| } | |
| }); | |
| // Update order status | |
| function updateOrderStatus(orderId, newStatus) { | |
| const order = orders.find(o => o.id === orderId); | |
| if (order) { | |
| order.status = newStatus; | |
| renderOrders(); | |
| updateStats(); | |
| let statusText = ''; | |
| switch(newStatus) { | |
| case 'processing': | |
| statusText = 'En Producción'; | |
| break; | |
| case 'shipped': | |
| statusText = 'Enviado'; | |
| break; | |
| case 'completed': | |
| statusText = 'Completado'; | |
| break; | |
| } | |
| showNotification(`Pedido ${orderId} actualizado a: ${statusText}`, 'success'); | |
| orderModal.classList.add('hidden'); | |
| } | |
| } | |
| // Delete order | |
| function deleteOrder(orderId) { | |
| const index = orders.findIndex(o => o.id === orderId); | |
| if (index !== -1) { | |
| const order = orders[index]; | |
| orders.splice(index, 1); | |
| renderOrders(); | |
| updateStats(); | |
| showNotification(`Pedido ${orderId} eliminado`, 'warning'); | |
| orderModal.classList.add('hidden'); | |
| } | |
| } | |
| // Update statistics | |
| function updateStats() { | |
| const pendingCount = orders.filter(o => o.status === 'pending').length; | |
| const processingCount = orders.filter(o => o.status === 'processing').length; | |
| const readyCount = orders.filter(o => o.status === 'shipped' || o.status === 'completed').length; | |
| const totalCount = orders.length; | |
| document.getElementById('pending-count').textContent = pendingCount; | |
| document.getElementById('processing-count').textContent = processingCount; | |
| document.getElementById('ready-count').textContent = readyCount; | |
| document.getElementById('total-count').textContent = totalCount; | |
| } | |
| // Show notification | |
| function showNotification(message, type = 'info') { | |
| const notification = document.createElement('div'); | |
| notification.className = `notification px-4 py-3 rounded-lg shadow-lg max-w-md transform transition-all duration-300`; | |
| let bgColor = ''; | |
| switch(type) { | |
| case 'success': | |
| bgColor = 'bg-green-500 text-white'; | |
| break; | |
| case 'warning': | |
| bgColor = 'bg-yellow-500 text-white'; | |
| break; | |
| case 'error': | |
| bgColor = 'bg-red-500 text-white'; | |
| break; | |
| default: | |
| bgColor = 'bg-blue-500 text-white'; | |
| } | |
| notification.className += ` ${bgColor}`; | |
| notification.textContent = message; | |
| notificationContainer.appendChild(notification); | |
| // Remove notification after 3 seconds | |
| setTimeout(() => { | |
| notification.style.opacity = '0'; | |
| setTimeout(() => { | |
| if (notification.parentNode) { | |
| notification.parentNode.removeChild(notification); | |
| } | |
| }, 300); | |
| }, 3000); | |
| } | |
| // Simulate real-time updates | |
| setInterval(() => { | |
| // This would normally be replaced with WebSocket or API calls | |
| // For demo purposes, we'll just update the timestamp | |
| const now = new Date(); | |
| if (now.getSeconds() % 30 === 0) { | |
| // Simulate a new order every 30 seconds | |
| // In a real app, this would come from a server push | |
| } | |
| }, 1000); | |
| </script> | |
| </body> | |
| </html> |