Update: 2026-06-21 02:07:00

This commit is contained in:
Hamza-Ayed
2026-06-21 02:07:00 +03:00
parent af3dcae5b7
commit b2fae9ec66
23 changed files with 1412 additions and 210 deletions

View 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>