// ========== CASHIER DASHBOARD FUNCTIONS ========== let _cashierPollingInterval = null; let _cashierAutoRefreshInterval = null; function showCashierTab() { const tab = document.getElementById('nav-cashier'); if (!user || user.role !== 'cashier') { if (tab) tab.style.display = 'none'; } else { if (tab) tab.style.display = 'flex'; } } function pollCashierStatus() { if (!user || (user.role !== 'cashier' && user.role !== 'admin')) return; // Obtener totales del día api.req('GET', '/api/sales?date=' + new Date().toISOString().split('T')[0], {}, (err, data) => { if (err) return; let cash = 0, card = 0, transfer = 0, total = 0; (data || []).forEach(sale => { const amount = sale.total || 0; if (sale.payment_method === 'cash') cash += amount; else if (sale.payment_method === 'card') card += amount; else if (sale.payment_method === 'transfer') transfer += amount; total += amount; }); document.getElementById('total-cash').textContent = '$' + cash.toFixed(2); document.getElementById('total-card').textContent = '$' + card.toFixed(2); document.getElementById('total-transfer').textContent = '$' + transfer.toFixed(2); document.getElementById('total-general').textContent = '$' + total.toFixed(2); document.getElementById('expected-amount').textContent = '$' + total.toFixed(2); }); // Mesas pendientes (si es restaurante) loadPendingTables(); // Historial de sesiones loadCashierSessions(); } function loadPendingTables() { api.req('GET', '/api/restaurant/tables?status=open', {}, (err, tables) => { if (err || !tables || tables.length === 0) { document.getElementById('pending-tables-card').style.display = 'none'; return; } document.getElementById('pending-tables-card').style.display = 'block'; const tbody = document.getElementById('pending-tables-tbody'); tbody.innerHTML = ''; tables.forEach(table => { const row = document.createElement('tr'); row.style.borderBottom = '1px solid var(--border)'; row.innerHTML = ` ${table.table_number || 'N/A'} ${table.waiter_name || 'Sin asignar'} $${(table.total || 0).toFixed(2)} ${table.payment_method || 'Pendiente'} `; tbody.appendChild(row); }); }); } function loadCashierSessions() { api.req('GET', '/api/cash-sessions?limit=10', {}, (err, sessions) => { if (err || !sessions) return; const tbody = document.getElementById('sessions-history-tbody'); tbody.innerHTML = ''; sessions.forEach(session => { const date = new Date(session.opened_at); const difference = (session.counted_amount || 0) - (session.total || 0); const differenceClass = difference === 0 ? 'green' : (difference > 0 ? 'blue' : 'red'); const row = document.createElement('tr'); row.style.borderBottom = '1px solid var(--border)'; row.innerHTML = ` ${date.toLocaleString('es-DO')} $${(session.opening_amount || 0).toFixed(2)} $${(session.total || 0).toFixed(2)} $${difference.toFixed(2)} `; tbody.appendChild(row); }); }); } function collectPaymentFromTable(tableId) { const amount = prompt('Ingrese el monto a cobrar:'); if (!amount || isNaN(parseFloat(amount))) return; api.req('POST', `/api/restaurant/tables/${tableId}/collect`, {amount: parseFloat(amount)}, (err, data) => { if (err) { alert('Error: ' + err); return; } alert('Pago registrado correctamente'); pollCashierStatus(); } ); } function closeCashierSessionModal() { const countedAmount = parseFloat(document.getElementById('counted-amount').value || 0); const expectedAmount = parseFloat(document.getElementById('expected-amount').textContent.replace('$', '') || 0); const notes = document.getElementById('close-notes').value || ''; if (countedAmount === 0) { alert('Ingrese el monto contado'); return; } if (!confirm(`Cerrar caja con diferencia de $${(countedAmount - expectedAmount).toFixed(2)}?`)) { return; } api.req('POST', '/api/cash-sessions/close', { counted_amount: countedAmount, notes: notes }, (err, data) => { if (err) { alert('Error: ' + err); return; } alert('Caja cerrada correctamente'); document.getElementById('counted-amount').value = ''; document.getElementById('close-notes').value = ''; pollCashierStatus(); } ); } // Evento para calcular diferencia al ingresar monto document.addEventListener('DOMContentLoaded', () => { const countedInput = document.getElementById('counted-amount'); if (countedInput) { countedInput.addEventListener('input', (e) => { const counted = parseFloat(e.target.value || 0); const expected = parseFloat(document.getElementById('expected-amount').textContent.replace('$', '') || 0); const difference = counted - expected; const indicator = document.getElementById('difference-indicator'); document.getElementById('amount-difference').textContent = '$' + difference.toFixed(2); if (difference === 0) { indicator.style.background = 'rgba(16,185,129,0.1)'; indicator.style.color = '#10b981'; indicator.textContent = 'Cuadra perfecto'; } else if (difference > 0) { indicator.style.background = 'rgba(59,130,246,0.1)'; indicator.style.color = '#3b82f6'; indicator.textContent = `Sobrante: $${difference.toFixed(2)}`; } else { indicator.style.background = 'rgba(239,68,68,0.1)'; indicator.style.color = '#ef4444'; indicator.textContent = `Faltante: $${Math.abs(difference).toFixed(2)}`; } }); } }); function startCashierAutoRefresh() { stopCashierAutoRefresh(); _cashierAutoRefreshInterval = setInterval(() => { if (currentViewName === 'cashier') { pollCashierStatus(); } }, 5000); // Actualizar cada 5 segundos } function stopCashierAutoRefresh() { if (_cashierAutoRefreshInterval) { clearInterval(_cashierAutoRefreshInterval); _cashierAutoRefreshInterval = null; } } // AUTO-LOGIN: Si hay sesión guardada, mostrar app automáticamente window.addEventListener('DOMContentLoaded', async () => { console.log('🔍 Verificando sesión guardada...'); // Agregar event listener al botón de login const loginBtn = document.getElementById('login-btn'); if (loginBtn) { loginBtn.addEventListener('click', doLogin); loginBtn.addEventListener('touchend', (e) => { e.preventDefault(); doLogin(); }); } // También agregar Enter en campos de password const passInput = document.getElementById('login-pass'); if (passInput) { passInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') doLogin(); }); } if (token && currentUser) { console.log('✅ Sesión encontrada. Usuario:', currentUser.name); try { await showApp(); console.log('✅ App cargada automáticamente'); } catch(err) { console.error('❌ Error cargando app:', err); // Limpiar sesión y volver al login token = null; currentUser = null; sessionStorage.clear(); document.getElementById('login-screen').style.display = 'flex'; document.getElementById('app').style.display = 'none'; } } else { console.log('ℹ️ Sin sesión. Mostrando login.'); document.getElementById('login-screen').style.display = 'flex'; document.getElementById('app').style.display = 'none'; } });