From 5ebff42841a53af02d7bed70a78e9c2b9bc9c013 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 24 Jul 2026 23:23:55 +0300 Subject: [PATCH] Update: 2026-07-24 23:23:54 --- dashboard/siro-admin/index.html | 38 +++++++- dashboard/siro-admin/js/app.js | 168 ++++++++++++++++++++++++++++++-- 2 files changed, 198 insertions(+), 8 deletions(-) diff --git a/dashboard/siro-admin/index.html b/dashboard/siro-admin/index.html index 54f703e3..dfde2aa1 100644 --- a/dashboard/siro-admin/index.html +++ b/dashboard/siro-admin/index.html @@ -28,10 +28,19 @@
+
+ + +
+
- +
- +
@@ -500,6 +509,31 @@ + + + diff --git a/dashboard/siro-admin/js/app.js b/dashboard/siro-admin/js/app.js index c23f3d20..6352a8b4 100644 --- a/dashboard/siro-admin/js/app.js +++ b/dashboard/siro-admin/js/app.js @@ -47,24 +47,180 @@ document.addEventListener('DOMContentLoaded', () => { setupEvents(); } + // Web Device Fingerprint Generator + function getWebFingerprint() { + let fp = localStorage.getItem('siro_web_fp'); + if (!fp) { + fp = 'web_' + Math.random().toString(36).substring(2) + Date.now().toString(36); + localStorage.setItem('siro_web_fp', fp); + } + return fp; + } + + const deviceFingerprint = getWebFingerprint(); + + // Mode State (Live vs Demo) + let isLiveMode = true; + + const modeLiveBtn = document.getElementById('modeLiveBtn'); + const modeDemoBtn = document.getElementById('modeDemoBtn'); + + modeLiveBtn?.addEventListener('click', () => { + isLiveMode = true; + modeLiveBtn.style.background = 'var(--primary)'; + modeLiveBtn.style.color = '#fff'; + modeDemoBtn.style.background = 'transparent'; + modeDemoBtn.style.color = 'var(--text-muted)'; + }); + + modeDemoBtn?.addEventListener('click', () => { + isLiveMode = false; + modeDemoBtn.style.background = 'var(--primary)'; + modeDemoBtn.style.color = '#fff'; + modeLiveBtn.style.background = 'transparent'; + modeLiveBtn.style.color = 'var(--text-muted)'; + }); + // Auth Functions function checkAuth() { if (currentUser) { authWrapper.classList.add('hidden'); + if (currentUser.isLive && currentUser.jwt) { + fetchLiveDashboardData(); + } } else { authWrapper.classList.remove('hidden'); } } - loginForm?.addEventListener('submit', (e) => { + let pendingOtpPhone = ''; + let pendingOtpPassword = ''; + + loginForm?.addEventListener('submit', async (e) => { e.preventDefault(); - const email = document.getElementById('loginEmail').value; - currentUser = { name: 'Super Admin', email: email, role: 'Administrator', authMethod: 'Password' }; - localStorage.setItem('siro_admin_user', JSON.stringify(currentUser)); - authWrapper.classList.add('hidden'); - showNotification('Welcome back, Super Admin!', 'success'); + const phone = document.getElementById('loginEmail').value.trim(); + const password = document.getElementById('loginPass').value.trim(); + + if (isLiveMode) { + showNotification('Authenticating device with server...', 'info'); + try { + const formData = new FormData(); + formData.append('phone', phone); + formData.append('password', password); + formData.append('fingerprint', deviceFingerprint); + formData.append('aud', 'admin'); + + const response = await fetch('/backend/Admin/auth/login.php', { + method: 'POST', + body: formData + }); + + const res = await response.json(); + if (response.ok && res.status === 'success') { + if (res.jwt) { + currentUser = { + name: res.admin?.name || 'Admin', + email: res.admin?.email || phone, + role: res.admin?.role || 'Administrator', + jwt: res.jwt, + isLive: true + }; + localStorage.setItem('siro_admin_user', JSON.stringify(currentUser)); + authWrapper.classList.add('hidden'); + showNotification('Access Granted! Device Fingerprint Verified.', 'success'); + fetchLiveDashboardData(); + } else if (res.message && res.message.status === 'otp_required' || res.status === 'otp_required') { + pendingOtpPhone = phone; + pendingOtpPassword = password; + const masked = res.phone || res.message?.phone || phone; + document.getElementById('otpPhoneText').textContent = `Verification code sent to WhatsApp (${masked})`; + document.getElementById('otpModal').classList.add('active'); + } + } else { + showNotification(res.message || 'Invalid credentials or device not registered.', 'warning'); + } + } catch (err) { + console.error(err); + showNotification('Cannot connect to Live Backend. Entering Demo Mode.', 'info'); + currentUser = { name: 'Super Admin (Demo)', email: phone, role: 'Administrator', isLive: false }; + localStorage.setItem('siro_admin_user', JSON.stringify(currentUser)); + authWrapper.classList.add('hidden'); + } + } else { + currentUser = { name: 'Super Admin (Demo)', email: phone, role: 'Administrator', isLive: false }; + localStorage.setItem('siro_admin_user', JSON.stringify(currentUser)); + authWrapper.classList.add('hidden'); + showNotification('Welcome to Interactive Demo Mode!', 'success'); + } }); + // Submit OTP Code + document.getElementById('submitOtpBtn')?.addEventListener('click', async () => { + const otp = document.getElementById('otpInput').value.trim(); + if (!otp || otp.length < 3) { + showNotification('Please enter the 3-digit OTP code', 'warning'); + return; + } + + try { + const formData = new FormData(); + formData.append('otp', otp); + formData.append('fingerprint', deviceFingerprint); + formData.append('aud', 'admin'); + + const response = await fetch('/backend/Admin/auth/verify_login.php', { + method: 'POST', + body: formData + }); + + const res = await response.json(); + if (response.ok && res.status === 'success') { + currentUser = { + name: res.admin?.name || 'Admin', + email: res.admin?.email || pendingOtpPhone, + role: res.admin?.role || 'Administrator', + jwt: res.jwt, + isLive: true + }; + localStorage.setItem('siro_admin_user', JSON.stringify(currentUser)); + closeOtpModal(); + authWrapper.classList.add('hidden'); + showNotification('OTP Verified! Welcome back, Admin.', 'success'); + fetchLiveDashboardData(); + } else { + showNotification(res.message || 'Invalid OTP code', 'danger'); + } + } catch (err) { + showNotification('OTP verification error', 'danger'); + } + }); + + window.closeOtpModal = function() { + document.getElementById('otpModal')?.classList.remove('active'); + }; + + async function fetchLiveDashboardData() { + try { + const response = await fetch('/backend/Admin/dashbord.php', { + headers: { + 'Authorization': `Bearer ${currentUser?.jwt || ''}` + } + }); + const data = await response.json(); + if (data && data.status === 'success' && data.data && data.data[0]) { + const stats = data.data[0]; + // Update DOM elements with real MySQL DB counters + const revCard = document.querySelector('.stat-card .stat-value'); + if (revCard && stats.countRide) { + revCard.textContent = `${stats.countRide} Trips`; + } + showNotification('Live Database Stats Synchronized!', 'success'); + } + } catch (err) { + console.log('Using local fallback metrics for display.'); + } + } + const fingerprintLoginBtn = document.getElementById('fingerprintLoginBtn'); fingerprintLoginBtn?.addEventListener('click', async () => { showNotification('Touch Fingerprint sensor on your device...', 'info');