Update: 2026-06-21 02:07:00
This commit is contained in:
751
knowledge/siro_admin_simulation.html
Normal file
751
knowledge/siro_admin_simulation.html
Normal file
@@ -0,0 +1,751 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Siro Admin – محاكاة لوحة التحكم والعمليات</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #090a0f;
|
||||
--surface: #11131c;
|
||||
--surface-elevated: #1a1d2b;
|
||||
--border: #23273c;
|
||||
--primary: #4776e6;
|
||||
--primary-glow: rgba(71, 118, 230, 0.3);
|
||||
--accent: #8e2de2;
|
||||
--success: #10b981;
|
||||
--warning: #f59e0b;
|
||||
--danger: #ef4444;
|
||||
--info: #06b6d4;
|
||||
--text-primary: #f3f4f6;
|
||||
--text-secondary: #9ca3af;
|
||||
--divider: #1f2937;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Tajawal', sans-serif;
|
||||
background-color: var(--bg);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Header styling with Glassmorphism */
|
||||
header {
|
||||
background: rgba(17, 19, 28, 0.85);
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 16px 24px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 900;
|
||||
color: #ffffff;
|
||||
font-size: 20px;
|
||||
box-shadow: 0 0 15px var(--primary-glow);
|
||||
}
|
||||
|
||||
.brand h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(to left, #ffffff, var(--text-secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.header-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border: 1px solid var(--success);
|
||||
color: var(--success);
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.pulse {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: var(--success);
|
||||
border-radius: 50%;
|
||||
animation: pulse-animation 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse-animation {
|
||||
0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
|
||||
70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
|
||||
100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
||||
}
|
||||
|
||||
/* Main layout setup */
|
||||
.dashboard-container {
|
||||
display: grid;
|
||||
grid-template-columns: 280px 1fr;
|
||||
flex: 1;
|
||||
height: calc(100vh - 73px);
|
||||
}
|
||||
|
||||
/* Sidebar controls */
|
||||
.sidebar {
|
||||
background-color: var(--surface);
|
||||
border-left: 1px solid var(--border);
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.menu-section-title {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.sidebar-btn {
|
||||
width: 100%;
|
||||
background: var(--surface-elevated);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
color: var(--text-primary);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.2s ease;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.sidebar-btn:hover {
|
||||
border-color: var(--primary);
|
||||
background: rgba(71, 118, 230, 0.05);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.sidebar-btn.active {
|
||||
border-color: var(--primary);
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
color: #ffffff;
|
||||
box-shadow: 0 4px 15px var(--primary-glow);
|
||||
}
|
||||
|
||||
/* Workspace Panel */
|
||||
.workspace {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Top stats row */
|
||||
.stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
padding: 24px;
|
||||
background-color: rgba(9, 10, 15, 0.5);
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background-color: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stat-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(to left, var(--primary), var(--accent));
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.stat-card:hover::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.stat-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--text-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.stat-change {
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.stat-change.up { color: var(--success); }
|
||||
.stat-change.down { color: var(--danger); }
|
||||
|
||||
/* Action view area */
|
||||
.action-view {
|
||||
padding: 0 24px 24px 24px;
|
||||
overflow-y: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
/* Card Panels */
|
||||
.panel-card {
|
||||
background-color: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
/* Simulation Canvas Map */
|
||||
.map-panel {
|
||||
position: relative;
|
||||
height: 320px;
|
||||
background-color: #0b0d19;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.map-controls {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 12px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.map-btn {
|
||||
background: rgba(17, 19, 28, 0.9);
|
||||
border: 1px solid var(--border);
|
||||
color: #fff;
|
||||
padding: 6px 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.map-btn:hover {
|
||||
background: var(--primary);
|
||||
}
|
||||
|
||||
/* Logs view */
|
||||
.logs-container {
|
||||
max-height: 280px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
padding: 10px 14px;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
background-color: var(--surface-elevated);
|
||||
border-right: 3px solid var(--border);
|
||||
}
|
||||
|
||||
.log-item.success { border-color: var(--success); }
|
||||
.log-item.warning { border-color: var(--warning); }
|
||||
.log-item.danger { border-color: var(--danger); }
|
||||
.log-item.info { border-color: var(--info); }
|
||||
|
||||
/* Forms */
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
input, select {
|
||||
background-color: var(--surface-elevated);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input:focus, select:focus {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 12px;
|
||||
border-radius: 10px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* List queues (Captains documents) */
|
||||
.doc-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: var(--surface-elevated);
|
||||
padding: 12px 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.doc-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.doc-name { font-weight: 600; font-size: 14px; }
|
||||
.doc-details { font-size: 12px; color: var(--text-secondary); }
|
||||
|
||||
.doc-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 6px 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.action-btn.approve { background-color: rgba(16, 185, 129, 0.15); color: var(--success); }
|
||||
.action-btn.reject { background-color: rgba(239, 68, 68, 0.15); color: var(--danger); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header -->
|
||||
<header>
|
||||
<div class="brand">
|
||||
<div class="logo-container">S</div>
|
||||
<h1>Siro Admin — محاكاة المشرف والعمليات</h1>
|
||||
</div>
|
||||
<div class="header-status">
|
||||
<div class="status-badge">
|
||||
<span class="pulse"></span>
|
||||
اتصال WebSocket نشط
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Container -->
|
||||
<div class="dashboard-container">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<div>
|
||||
<div class="menu-section-title">إدارة لوحة التحكم</div>
|
||||
<button class="sidebar-btn active" onclick="switchTab('dashboard', this)">
|
||||
<span>📊</span> لوحة التحكم الرئيسية
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="menu-section-title">التشغيل المالي والأسعار</div>
|
||||
<button class="sidebar-btn" onclick="switchTab('kazan', this)">
|
||||
<span>💰</span> عمولة Kazan والأسعار
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="menu-section-title">التوثيق والجودة</div>
|
||||
<button class="sidebar-btn" onclick="switchTab('docs', this)">
|
||||
<span>📑</span> وثائق الكباتن الجديدة
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="menu-section-title">الأمن والخصوصية</div>
|
||||
<button class="sidebar-btn" onclick="switchTab('fraud', this)">
|
||||
<span>🛡️</span> رادار بصمة الجهاز (الاحتيال)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workspace -->
|
||||
<div class="workspace">
|
||||
|
||||
<!-- Stats Row -->
|
||||
<div class="stats-row">
|
||||
<div class="stat-card">
|
||||
<div class="stat-header">
|
||||
<span>إجمالي الركاب</span>
|
||||
<span class="stat-change up">▲ 12%</span>
|
||||
</div>
|
||||
<div class="stat-value" id="countPassengers">18,240</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div class="stat-header">
|
||||
<span>إجمالي الكباتن</span>
|
||||
<span class="stat-change up">▲ 8%</span>
|
||||
</div>
|
||||
<div class="stat-value" id="countDrivers">4,912</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div class="stat-header">
|
||||
<span>رحلات الشهر الحالي</span>
|
||||
<span class="stat-change up">▲ 24%</span>
|
||||
</div>
|
||||
<div class="stat-value" id="countRides">32,490</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div class="stat-header">
|
||||
<span>محفظة النظام (عمولات)</span>
|
||||
<span class="stat-change down">▼ 2%</span>
|
||||
</div>
|
||||
<div class="stat-value" id="walletBalance">145,200 SP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab Content Area -->
|
||||
<div class="action-view">
|
||||
|
||||
<!-- Tab 1: Dashboard -->
|
||||
<div id="tab-dashboard" class="panel-card" style="grid-column: 1 / 3;">
|
||||
<div class="panel-title">📡 مراقبة الرحلات المباشرة والعمليات</div>
|
||||
|
||||
<div class="map-panel">
|
||||
<canvas id="liveMapCanvas"></canvas>
|
||||
<div class="map-controls">
|
||||
<button class="map-btn" onclick="triggerMockRide()">محاكاة رحلة جديدة</button>
|
||||
<button class="map-btn" onclick="clearSimulation()">مسح الخريطة</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-title">📝 سجل الأحداث والعمليات الفورية</div>
|
||||
<div class="logs-container" id="logsContainer">
|
||||
<div class="log-item info">[النظام]: تم تشغيل محاكاة Siro Admin بنجاح.</div>
|
||||
<div class="log-item success">[العمليات]: تم الاتصال بخادم الـ Websocket (rides.intaleq.xyz).</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab 2: Kazan pricing -->
|
||||
<div id="tab-kazan" class="panel-card" style="display:none;">
|
||||
<div class="panel-title">💰 تعديل عمولة Kazan ومعدلات التعرفة</div>
|
||||
<div class="form-group">
|
||||
<label>الدولة والمنطقة</label>
|
||||
<select id="countrySelect">
|
||||
<option value="Syria">سوريا (دمشق)</option>
|
||||
<option value="Jordan">الأردن (عمان)</option>
|
||||
<option value="Egypt">مصر (القاهرة)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>نسبة عمولة Kazan (%)</label>
|
||||
<input type="number" id="commissionPct" value="15" min="5" max="30">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>تعرفة الكيلومتر الأساسية (عملة محلية)</label>
|
||||
<input type="number" id="baseKmPrice" value="1200">
|
||||
</div>
|
||||
<button class="submit-btn" onclick="updateKazanCommission()">حفظ وتحديث نظام التسعير</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab 3: Captin Documents (Azure OCR Simulation) -->
|
||||
<div id="tab-docs" class="panel-card" style="display:none;">
|
||||
<div class="panel-title">📑 وثائق الكباتن بانتظار التدقيق والتحقق</div>
|
||||
|
||||
<div style="display:flex; flex-direction:column; gap:12px;" id="docsQueue">
|
||||
<div class="doc-item" id="doc-c1">
|
||||
<div class="doc-info">
|
||||
<span class="doc-name">الكابتن: محمد أحمد الحموي</span>
|
||||
<span class="doc-details">رقم السيارة: دمشق - 482920 • نوع المستند: رخصة القيادة</span>
|
||||
<span class="doc-details" style="color:var(--success);">[تحليل الذكاء الاصطناعي Azure OCR]: الاسم والتواريخ متطابقة بنسبة 98%</span>
|
||||
</div>
|
||||
<div class="doc-actions">
|
||||
<button class="action-btn approve" onclick="verifyDocument('c1', true)">قبول</button>
|
||||
<button class="action-btn reject" onclick="verifyDocument('c1', false)">رفض</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-item" id="doc-c2">
|
||||
<div class="doc-info">
|
||||
<span class="doc-name">الكابتن: رامي طارق المصري</span>
|
||||
<span class="doc-details">رقم السيارة: ريف دمشق - 729221 • نوع المستند: تأمين المركبة</span>
|
||||
<span class="doc-details" style="color:var(--warning);">[تحليل الذكاء الاصطناعي Azure OCR]: المستند ينتهي خلال 3 أيام</span>
|
||||
</div>
|
||||
<div class="doc-actions">
|
||||
<button class="action-btn approve" onclick="verifyDocument('c2', true)">قبول</button>
|
||||
<button class="action-btn reject" onclick="verifyDocument('c2', false)">رفض</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab 4: Fraud radar device fingerprints -->
|
||||
<div id="tab-fraud" class="panel-card" style="display:none;">
|
||||
<div class="panel-title">🛡️ رادار كشف الاحتيال وتكرار بصمات الأجهزة</div>
|
||||
<div class="log-item danger" style="padding:14px;">
|
||||
<strong>تنبيه أمني هام:</strong> تم اكتشاف بصمة جهاز مكررة مرتبطة بـ 3 كباتن مختلفين!
|
||||
<br>Device FP: <code>SHA256:d89ef239fbc87a1d...</code>
|
||||
</div>
|
||||
<div style="display:flex; flex-direction:column; gap:10px;">
|
||||
<div class="doc-item">
|
||||
<div class="doc-info">
|
||||
<span class="doc-name">كابتن 1: علي سليم (نشط)</span>
|
||||
<span class="doc-details">رقم الهاتف: 963992019283</span>
|
||||
</div>
|
||||
<button class="action-btn reject" style="background-color:rgba(239,68,68,0.25)" onclick="blockCaptain('علي سليم')">حظر فوري</button>
|
||||
</div>
|
||||
<div class="doc-item">
|
||||
<div class="doc-info">
|
||||
<span class="doc-name">كابتن 2: سامر وحيد (نشط)</span>
|
||||
<span class="doc-details">رقم الهاتف: 963942091922</span>
|
||||
</div>
|
||||
<button class="action-btn reject" style="background-color:rgba(239,68,68,0.25)" onclick="blockCaptain('سامر وحيد')">حظر فوري</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Tab switching logic
|
||||
function switchTab(tabId, btn) {
|
||||
document.getElementById('tab-dashboard').style.display = 'none';
|
||||
document.getElementById('tab-kazan').style.display = 'none';
|
||||
document.getElementById('tab-docs').style.display = 'none';
|
||||
document.getElementById('tab-fraud').style.display = 'none';
|
||||
|
||||
document.getElementById('tab-' + tabId).style.display = 'flex';
|
||||
|
||||
const buttons = document.querySelectorAll('.sidebar-btn');
|
||||
buttons.forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
|
||||
if (tabId === 'dashboard') {
|
||||
initCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
// Logging helpers
|
||||
function log(message, type = 'info') {
|
||||
const container = document.getElementById('logsContainer');
|
||||
const time = new Date().toLocaleTimeString('ar-EG');
|
||||
const div = document.createElement('div');
|
||||
div.className = `log-item ${type}`;
|
||||
div.innerText = `[${time}] ${message}`;
|
||||
container.prepend(div);
|
||||
}
|
||||
|
||||
// Kazan changes
|
||||
function updateKazanCommission() {
|
||||
const pct = document.getElementById('commissionPct').value;
|
||||
const kmPrice = document.getElementById('baseKmPrice').value;
|
||||
const country = document.getElementById('countrySelect').value;
|
||||
|
||||
// Update stats
|
||||
document.getElementById('walletBalance').innerText = `${(pct * 10000).toLocaleString()} SP`;
|
||||
log(`[نظام كازان]: تم تحديث العمولة لتصبح ${pct}% لـ ${country} مع سعر كم قدره ${kmPrice}.`, 'success');
|
||||
}
|
||||
|
||||
// Document approvals
|
||||
function verifyDocument(id, approved) {
|
||||
const element = document.getElementById(`doc-${id}`);
|
||||
if (element) {
|
||||
element.remove();
|
||||
log(`[المستندات]: تم ${approved ? 'قبول' : 'رفض'} الوثائق للكابتن بنجاح.`, approved ? 'success' : 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
// Block captain
|
||||
function blockCaptain(name) {
|
||||
log(`[الأمان والخصوصية]: تم حظر الكابتن (${name}) وتجميد محفظته بسبب مطابقة البصمة الرقمية المكررة.`, 'danger');
|
||||
}
|
||||
|
||||
// Canvas map rendering
|
||||
let canvas, ctx, animId;
|
||||
let particles = [];
|
||||
|
||||
function initCanvas() {
|
||||
canvas = document.getElementById('liveMapCanvas');
|
||||
if (!canvas) return;
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
// Resize canvas relative to its container client dimensions
|
||||
canvas.width = canvas.parentElement.clientWidth;
|
||||
canvas.height = canvas.parentElement.clientHeight || 320;
|
||||
|
||||
// Seed initial dummy drivers
|
||||
particles = [
|
||||
{ x: canvas.width * 0.3, y: canvas.height * 0.4, label: '🚗 Comfort', angle: 0.5, speed: 0.3 },
|
||||
{ x: canvas.width * 0.6, y: canvas.height * 0.7, label: '🏍️ Bike', angle: 1.2, speed: 0.6 },
|
||||
{ x: canvas.width * 0.7, y: canvas.height * 0.3, label: '🚗 Speed', angle: 2.3, speed: 0.4 }
|
||||
];
|
||||
|
||||
if (animId) cancelAnimationFrame(animId);
|
||||
draw();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = '#0b0d19';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Grid background
|
||||
ctx.strokeStyle = '#181b2e';
|
||||
ctx.lineWidth = 1;
|
||||
for (let x = 0; x < canvas.width; x += 40) {
|
||||
ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke();
|
||||
}
|
||||
for (let y = 0; y < canvas.height; y += 40) {
|
||||
ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke();
|
||||
}
|
||||
|
||||
// Draw cars
|
||||
particles.forEach(p => {
|
||||
p.x += Math.cos(p.angle) * p.speed;
|
||||
p.y += Math.sin(p.angle) * p.speed;
|
||||
|
||||
// Boundary checks
|
||||
if (p.x < 0 || p.x > canvas.width) p.angle = Math.PI - p.angle;
|
||||
if (p.y < 0 || p.y > canvas.height) p.angle = -p.angle;
|
||||
|
||||
// Draw car indicator
|
||||
ctx.fillStyle = '#4776e6';
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, 8, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Label
|
||||
ctx.fillStyle = '#9ca3af';
|
||||
ctx.font = '10px Tajawal';
|
||||
ctx.fillText(p.label, p.x + 12, p.y + 4);
|
||||
});
|
||||
|
||||
animId = requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
function triggerMockRide() {
|
||||
const newCar = {
|
||||
x: canvas.width * 0.1,
|
||||
y: canvas.height * 0.1,
|
||||
label: '🚗 Speed (Active Ride)',
|
||||
angle: 0.8,
|
||||
speed: 1.2
|
||||
};
|
||||
particles.push(newCar);
|
||||
log('[رحلة جديدة]: تم بدء رحلة نشطة للراكب #3829 مع الكابتن #4928.', 'info');
|
||||
}
|
||||
|
||||
function clearSimulation() {
|
||||
particles = [];
|
||||
log('[النظام]: تم إخلاء الخريطة وتصفية كافة المركبات.', 'warning');
|
||||
}
|
||||
|
||||
// Run canvas on page load
|
||||
window.onload = initCanvas;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user