feat: توجيه كل النداءات إلى api.intaleqapp.com وطيّ تبديل الدول
⚠️ الطيّ ضرورة أمان لا ترتيب: كل عائلة سيرفرات في links.dart كانت switch بأربعة فروع (Syria · Egypt · Jordan · default)، وفروع سوريا ومصر تشير إلى **سيرفرات سيرو الإنتاجية** (api-syria.siromove.com وغيرها). إبقاؤها في انطلق يعني أن أي جهاز مخزَّن فيه countryCode='Syria' يخاطب إنتاج سيرو مباشرة. انطلق نشرٌ واحد على مضيف واحد (docs/34: سيرفر لكل مستأجر)، والدولة تُحل على السيرفر من GLOBAL_COUNTRY. طُويت 35 كتلة switch إلى قيمة واحدة (11 rider · 11 driver · 6 admin · 7 service)، والخريطة مأخوذة من تعليق docker/nginx/default.conf نفسه («نقطة واحدة لكل الخدمات — التطبيق يغيّر الدومين فقط»): server / rideServer → https://api.intaleqapp.com/backend paymentServer → https://api.intaleqapp.com/v2/main location → …/backend/ride/location locationServerSide(د) → …/loction_server/siro/ride/location سوكيت الركاب → https://api.intaleqapp.com:3030 سوكيت السائقين → https://api.intaleqapp.com:2020 وأيضاً: - appDomain و invite: siromove.com → intaleqapp.com، والمجلد siromove.com/ → intaleqapp.com/ (فيه invite.php الذي يقصده التطبيق). - روابط التنزيل siro.app → intaleqapp.com · بريد السائق المولَّد @siromove.com → @intaleqapp.com · صفحة التتبع · محاكاة تسجيل سوريا. - حُذف getter `syria` الميت من links.dart الثلاثة (لا مستدعي له، وكان يشير إلى إنتاج سيرو). لم يُمسّ عمداً: - `ssl_pinning.dart`: `badCertificateCallback` لا يُستدعى إلا عند فشل التحقق العادي، فشهادة api.intaleqapp.com الصالحة تمرّ بلا مساس. ولا أختلق بصمة شهادة: تُضاف بصمة انطلق بعد إصدار الشهادة (docs/30 G7). - `routesjo.intaleq.xyz` و `map-saas.intaleqapp.com`: خدمات خارجية قائمة بذاتها للمالك (قرار الخرائط المباشرة) لا تُنقل إلى api. - `com.siromove.admin` في userAgentPackageName (5 مواضع): من عائلة هويات المتاجر — كوميت الهويات، وهو يحتاج قرار المالك. ⚠️ يحتاج نشراً على الطرف الآخر: invite.php و track/index.php و /driver على intaleqapp.com. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0aab85c732
commit
53322d87a6
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Siro Unified Redirect Gateway (One-Click Redirect for non-Syrian countries)
|
||||
* URL Format: https://siromove.com/invite.php?code=REF_CODE&app=rider|driver
|
||||
*/
|
||||
|
||||
// 1. Core Config & Links
|
||||
$config = [
|
||||
'rider' => [
|
||||
'ios_store' => 'https://apps.apple.com/st/app/siro-rider/id6748075179',
|
||||
'android_store' => 'https://play.google.com/store/apps/details?id=com.Siro.siro'
|
||||
],
|
||||
'driver' => [
|
||||
'ios_store' => 'https://apps.apple.com/st/app/siro-driver/id6482995159',
|
||||
'android_store' => 'https://play.google.com/store/apps/details?id=com.siro_driver'
|
||||
]
|
||||
];
|
||||
|
||||
$code = htmlspecialchars($_GET['code'] ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$appType = ($_GET['app'] ?? 'rider') === 'driver' ? 'driver' : 'rider';
|
||||
$appConfig = $config[$appType];
|
||||
|
||||
// 2. Helper Functions
|
||||
function getVisitorCountry() {
|
||||
if (!empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
|
||||
return strtoupper($_SERVER['HTTP_CF_IPCOUNTRY']);
|
||||
}
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!empty($_SESSION['visitor_country'])) {
|
||||
return $_SESSION['visitor_country'];
|
||||
}
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
if ($ip === '127.0.0.1' || $ip === '::1' || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
|
||||
return 'JO'; // Default Jordan
|
||||
}
|
||||
|
||||
try {
|
||||
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
|
||||
$apiResponse = @file_get_contents("http://ip-api.com/json/{$ip}", false, $ctx);
|
||||
if ($apiResponse) {
|
||||
$data = json_decode($apiResponse, true);
|
||||
if (!empty($data['countryCode'])) {
|
||||
$_SESSION['visitor_country'] = strtoupper($data['countryCode']);
|
||||
return $_SESSION['visitor_country'];
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Fallback
|
||||
}
|
||||
return 'JO';
|
||||
}
|
||||
|
||||
function getDeviceOS() {
|
||||
$userAgent = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
|
||||
if (strpos($userAgent, 'iphone') !== false || strpos($userAgent, 'ipad') !== false || strpos($userAgent, 'ipod') !== false) {
|
||||
return 'ios';
|
||||
}
|
||||
if (strpos($userAgent, 'android') !== false) {
|
||||
return 'android';
|
||||
}
|
||||
return 'desktop';
|
||||
}
|
||||
|
||||
$country = getVisitorCountry();
|
||||
$os = getDeviceOS();
|
||||
|
||||
// 3. Fallback Handoff for Syrian Users
|
||||
if ($country === 'SY') {
|
||||
header("Location: https://siromove.com/inviteSyria.php?code=" . urlencode($code) . "&app=" . urlencode($appType));
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4. One-Click Instant Redirection (Jordan / Egypt / others)
|
||||
if ($os === 'ios') {
|
||||
header("Location: " . $appConfig['ios_store']);
|
||||
exit;
|
||||
} else {
|
||||
// Android or Desktop default
|
||||
header("Location: " . $appConfig['android_store']);
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,357 @@
|
||||
<?php
|
||||
/**
|
||||
* Siro Syria Redirect Gateway
|
||||
* URL Format: https://siromove.com/inviteSyria.php?code=REF_CODE&app=rider|driver
|
||||
*/
|
||||
|
||||
$config = [
|
||||
'rider' => [
|
||||
'ios_store' => 'https://apps.apple.com/st/app/siro-rider/id6748075179',
|
||||
'android_store' => 'https://play.google.com/store/apps/details?id=com.Siro.siro',
|
||||
'direct_apk' => 'https://api-syria.siromove.com/downloads/siro_rider.apk',
|
||||
'app_name' => 'Siro Rider',
|
||||
'app_name_ar' => 'سيرو الراكب'
|
||||
],
|
||||
'driver' => [
|
||||
'ios_store' => 'https://apps.apple.com/st/app/siro-driver/id6482995159',
|
||||
'android_store' => 'https://play.google.com/store/apps/details?id=com.siro_driver',
|
||||
'direct_apk' => 'https://api-syria.siromove.com/downloads/siro_driver.apk',
|
||||
'app_name' => 'Siro Driver',
|
||||
'app_name_ar' => 'سيرو الكابتن'
|
||||
]
|
||||
];
|
||||
|
||||
$code = htmlspecialchars($_GET['code'] ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$appType = ($_GET['app'] ?? 'rider') === 'driver' ? 'driver' : 'rider';
|
||||
$appConfig = $config[$appType];
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>تحميل تطبيق <?php echo $appConfig['app_name_ar']; ?></title>
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- Fonts -->
|
||||
<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=Cairo:wght@400;700;900&family=Outfit:wght@400;600;800;900&display=swap" rel="stylesheet">
|
||||
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#00E5FF',
|
||||
secondary: '#9C27B0',
|
||||
bg: '#0F172A',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Cairo', 'Outfit', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* Smart Highlight Animations & Classes */
|
||||
.highlight-btn {
|
||||
border-color: rgba(0, 229, 255, 0.5);
|
||||
background-color: rgba(0, 229, 255, 0.08);
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 0 20px rgba(0, 229, 255, 0.15);
|
||||
}
|
||||
|
||||
.dimmed-btn {
|
||||
opacity: 0.4;
|
||||
filter: grayscale(0.8);
|
||||
}
|
||||
.dimmed-btn:hover {
|
||||
opacity: 1;
|
||||
filter: none;
|
||||
transform: scale(1.01);
|
||||
}
|
||||
|
||||
/* Clipboard confirmation bubble animation */
|
||||
@keyframes scaleIn {
|
||||
from { transform: scale(0.9) translateY(5px); opacity: 0; }
|
||||
to { transform: scale(1) translateY(0); opacity: 1; }
|
||||
}
|
||||
.toast-active {
|
||||
animation: scaleIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-[#0F172A] text-slate-100 min-h-screen relative overflow-x-hidden selection:bg-cyan-500 selection:text-white flex items-center justify-center p-4">
|
||||
|
||||
<!-- Ambient Glowing Background Elements -->
|
||||
<div class="fixed inset-0 z-0 overflow-hidden pointer-events-none">
|
||||
<div class="absolute -top-[10%] -left-[10%] w-[60%] h-[60%] bg-cyan-500/10 rounded-full filter blur-[120px] animate-pulse"></div>
|
||||
<div class="absolute bottom-[5%] -right-[10%] w-[50%] h-[50%] bg-purple-500/8 rounded-full filter blur-[120px] animate-pulse" style="animation-delay: 2s;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Language Toggle Button -->
|
||||
<div class="absolute top-5 left-5 z-50">
|
||||
<button id="lang-toggle" class="px-5 py-2 text-sm font-bold bg-white/5 hover:bg-white/10 hover:border-white/20 backdrop-blur-md rounded-full transition duration-300 border border-white/10 shadow-lg cursor-pointer">
|
||||
English
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Main Card Container -->
|
||||
<div class="relative z-10 w-full max-w-lg bg-slate-900/60 backdrop-blur-xl border border-white/10 rounded-3xl p-8 shadow-2xl flex flex-col items-center">
|
||||
|
||||
<!-- Animated Glow Header -->
|
||||
<header class="text-center mb-8">
|
||||
<h1 class="text-4xl font-black tracking-widest mb-3 bg-gradient-to-r from-cyan-400 to-purple-500 bg-clip-text text-transparent" id="logo">
|
||||
SIRO
|
||||
</h1>
|
||||
<h2 class="text-2xl font-bold mb-2 text-slate-100" id="welcome-title">مرحباً بك في سيرو</h2>
|
||||
<p class="text-sm text-slate-400 max-w-sm mx-auto leading-relaxed" id="tagline">
|
||||
تمت دعوتك للانضمام إلى منصة التوصيل الأسرع والأوفر. يرجى اتباع التعليمات بالأسفل لتحميل التطبيق.
|
||||
</p>
|
||||
|
||||
<!-- Floating Device Message Badge -->
|
||||
<div id="device-message" class="hidden mt-4 inline-block px-4 py-1.5 rounded-full bg-cyan-500/10 border border-cyan-500/30 text-cyan-300 text-xs font-bold animate-bounce">
|
||||
<!-- JS Populated -->
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Referral Code Section -->
|
||||
<?php if (!empty($code)): ?>
|
||||
<div class="w-full bg-slate-950/40 border border-dashed border-cyan-500/30 rounded-2xl p-5 mb-8 flex flex-col items-center gap-3">
|
||||
<span class="text-xs font-semibold tracking-wider text-slate-400 uppercase" id="referral-label">كود الإحالة الخاص بك</span>
|
||||
<span class="text-3xl font-black tracking-widest text-cyan-400" id="refCode"><?php echo $code; ?></span>
|
||||
<button class="px-5 py-2 text-xs font-bold bg-cyan-400/10 text-cyan-300 border border-cyan-400/20 hover:bg-cyan-400 hover:text-slate-950 rounded-full transition duration-300 cursor-pointer" onclick="copyReferralCode()" id="copy-btn">نسخ كود الإحالة</button>
|
||||
<div id="copy-toast" class="hidden text-xs text-green-400 font-bold mt-1"></div>
|
||||
<p class="text-xs text-slate-400 text-center leading-relaxed mt-2" id="referral-tip">💡 إذا لم تفتح الروابط تلقائياً، قم بنسخ هذا الكود يدوياً وأدخله في التطبيق بعد تحميله.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Dynamic Action Cards -->
|
||||
<main class="w-full space-y-4">
|
||||
|
||||
<!-- iOS App Card -->
|
||||
<div class="ios-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
|
||||
<div class="flex items-center gap-3 mb-2 justify-end">
|
||||
<span class="text-xs text-slate-400" id="ios-info">المتجر الرسمي</span>
|
||||
<h3 class="text-md font-bold text-slate-100" id="ios-title">🔒 متجر التطبيقات محظور</h3>
|
||||
</div>
|
||||
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="ios-desc">
|
||||
نظراً للقيود الجغرافية، يرجى تفعيل تطبيق الـ VPN على هاتفك أولاً، ثم الضغط على الزر بالأسفل للانتقال لصفحة التحميل الرسمية على متجر آبل.
|
||||
</p>
|
||||
<a href="<?php echo $appConfig['ios_store']; ?>" target="_blank" class="w-full py-3 bg-slate-800 border border-white/10 hover:bg-slate-700/80 text-slate-100 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="ios-btn">
|
||||
<!-- Apple SVG -->
|
||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 24 24"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-4.2 14.33-1.38 18.82zM15.97 4.17c.66-.81 1.11-1.93.99-3.06-1 .04-2.2.67-2.92 1.49-.62.71-1.16 1.85-1.01 2.96 1.1.09 2.22-.57 2.94-1.39z"/></svg>
|
||||
<span>التحميل من App Store</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Android Direct APK Card -->
|
||||
<div class="android-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
|
||||
<div class="flex items-center gap-3 mb-2 justify-end">
|
||||
<span class="text-xs text-green-400 font-bold" id="apk-info">✅ لا يحتاج VPN</span>
|
||||
<h3 class="text-md font-bold text-slate-100" id="apk-title">🚀 تحميل مباشر (APK) - بدون VPN</h3>
|
||||
</div>
|
||||
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="apk-desc">
|
||||
يمكنك تحميل وتثبيت التطبيق مباشرة كملف تثبيت أندرويد دون الحاجة لمتجر جوجل بلاي أو تفعيل VPN.
|
||||
</p>
|
||||
<a href="<?php echo $appConfig['direct_apk']; ?>" class="w-full py-3 bg-cyan-400 text-slate-950 hover:bg-cyan-300 text-slate-950 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="apk-btn">
|
||||
<!-- Download SVG -->
|
||||
<svg class="w-4 h-4 fill-none stroke-current" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
|
||||
<span>تحميل تطبيق APK مباشرة</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Android Play Store Card -->
|
||||
<div class="android-card bg-slate-800/30 border border-white/5 rounded-2xl p-5 text-right transition duration-300 flex flex-col">
|
||||
<div class="flex items-center gap-3 mb-2 justify-end">
|
||||
<span class="text-xs text-yellow-500 font-bold" id="play-info">⚠️ قد يحتاج VPN</span>
|
||||
<h3 class="text-md font-bold text-slate-100" id="play-title">🤖 التحميل من Google Play</h3>
|
||||
</div>
|
||||
<p class="text-xs text-slate-400 leading-relaxed mb-4" id="play-desc">
|
||||
إذا كنت تستخدم شبكة VPN نشطة على جهازك، يمكنك التحميل من متجر جوجل بلاي الرسمي.
|
||||
</p>
|
||||
<a href="<?php echo $appConfig['android_store']; ?>" target="_blank" class="w-full py-3 bg-slate-800 border border-white/10 hover:bg-slate-700/80 text-slate-100 text-sm font-bold rounded-xl transition duration-300 flex items-center justify-center gap-2" id="play-btn">
|
||||
<!-- Play Store SVG -->
|
||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 24 24"><path d="M5.223 2.013a1.5 1.5 0 00-1.31 1.782l3.29 5.637-3.29 5.637a1.5 1.5 0 001.31 1.782l10.99-6.419c.75-.447.75-1.58 0-2.027L5.223 2.013z"/></svg>
|
||||
<span>التحميل من Google Play</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="mt-8 text-center text-xs text-slate-500" id="footer-text">
|
||||
حقوق النشر © <?php echo date('Y'); ?> سيرو. جميع الحقوق محفوظة.
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Bilingual content JSON -->
|
||||
<script>
|
||||
const content = {
|
||||
ar: {
|
||||
appName: "سيرو",
|
||||
welcome: "مرحباً بك في سيرو",
|
||||
tagline: "تمت دعوتك للانضمام إلى منصة التوصيل الأسرع والأوفر. يرجى اتباع التعليمات بالأسفل لتحميل التطبيق.",
|
||||
referralLabel: "كود الإحالة الخاص بك",
|
||||
copyBtn: "نسخ كود الإحالة",
|
||||
copiedMsg: "تم نسخ كود الإحالة: ",
|
||||
referralTip: "💡 إذا لم تفتح الروابط تلقائياً، قم بنسخ هذا الكود يدوياً وأدخله في التطبيق بعد تحميله.",
|
||||
iosTitle: "🔒 متجر التطبيقات محظور",
|
||||
iosDesc: "نظراً للقيود الجغرافية، يرجى تفعيل تطبيق الـ VPN على هاتفك أولاً، ثم الضغط على الزر بالأسفل للانتقال لصفحة التحميل الرسمية على متجر آبل.",
|
||||
iosBtn: "التحميل من App Store",
|
||||
iosInfo: "المتجر الرسمي",
|
||||
apkTitle: "🚀 تحميل مباشر (APK) - بدون VPN",
|
||||
apkDesc: "يمكنك تحميل وتثبيت التطبيق مباشرة كملف تثبيت أندرويد دون الحاجة لمتجر جوجل بلاي أو تفعيل VPN.",
|
||||
apkBtn: "تحميل تطبيق APK مباشرة",
|
||||
apkInfo: "✅ لا يحتاج VPN",
|
||||
playTitle: "🤖 التحميل من Google Play",
|
||||
playDesc: "إذا كنت تستخدم شبكة VPN نشطة على جهازك، يمكنك التحميل من متجر جوجل بلاي الرسمي.",
|
||||
playBtn: "التحميل من Google Play",
|
||||
playInfo: "⚠️ قد يحتاج VPN",
|
||||
footer: "حقوق النشر © 2026 سيرو. جميع الحقوق محفوظة.",
|
||||
msgAndroid: "تم اكتشاف جهاز أندرويد 🤖 - تم تظليل الروابط المباشرة",
|
||||
msgIos: "تم اكتشاف جهاز آيفون 🍎 - تم تظليل متجر التطبيقات"
|
||||
},
|
||||
en: {
|
||||
appName: "SIRO",
|
||||
welcome: "Welcome to Siro",
|
||||
tagline: "You have been invited to join the fastest and most affordable delivery platform. Please follow the instructions below to download the app.",
|
||||
referralLabel: "Your Referral Code",
|
||||
copyBtn: "Copy Referral Code",
|
||||
copiedMsg: "Referral code copied: ",
|
||||
referralTip: "💡 If deep links don't open automatically, copy this code and enter it manually in the app after downloading.",
|
||||
iosTitle: "🔒 App Store is Geo-Restricted",
|
||||
iosDesc: "Due to local network restrictions, please enable a VPN on your device first, then click below to download from the Apple App Store.",
|
||||
iosBtn: "Download from App Store",
|
||||
iosInfo: "Official Store",
|
||||
apkTitle: "🚀 Direct APK Download - No VPN Required",
|
||||
apkDesc: "You can download and install the app directly as an Android package (APK) without needing a VPN or the Play Store.",
|
||||
apkBtn: "Download APK Directly",
|
||||
apkInfo: "✅ No VPN Required",
|
||||
playTitle: "🤖 Download from Google Play",
|
||||
playDesc: "If you have an active VPN connection on your device, you can download the app from the official Google Play Store.",
|
||||
playBtn: "Download from Google Play",
|
||||
playInfo: "⚠️ May Require VPN",
|
||||
footer: "Copyright © 2026 Siro. All rights reserved.",
|
||||
msgAndroid: "Android Device Detected 🤖 - Direct APK links highlighted",
|
||||
msgIos: "iOS Device Detected 🍎 - Apple Store highlighted"
|
||||
}
|
||||
};
|
||||
|
||||
let currentLang = 'ar';
|
||||
|
||||
function detectOS() {
|
||||
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
||||
const androidCards = document.querySelectorAll('.android-card');
|
||||
const iosCards = document.querySelectorAll('.ios-card');
|
||||
const deviceMessage = document.getElementById('device-message');
|
||||
|
||||
// Reset highlight/dimmed states
|
||||
[...androidCards, ...iosCards].forEach(card => {
|
||||
card.classList.remove('highlight-btn', 'dimmed-btn');
|
||||
});
|
||||
deviceMessage.classList.add('hidden');
|
||||
|
||||
if (/android/i.test(userAgent)) {
|
||||
androidCards.forEach(c => c.classList.add('highlight-btn'));
|
||||
iosCards.forEach(c => c.classList.add('dimmed-btn'));
|
||||
|
||||
deviceMessage.textContent = content[currentLang].msgAndroid;
|
||||
deviceMessage.classList.remove('hidden');
|
||||
} else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
|
||||
iosCards.forEach(c => c.classList.add('highlight-btn'));
|
||||
androidCards.forEach(c => c.classList.add('dimmed-btn'));
|
||||
|
||||
deviceMessage.textContent = content[currentLang].msgIos;
|
||||
deviceMessage.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function updateLanguage(lang) {
|
||||
currentLang = lang;
|
||||
const t = content[lang];
|
||||
const isAr = lang === 'ar';
|
||||
|
||||
document.documentElement.setAttribute('dir', isAr ? 'rtl' : 'ltr');
|
||||
document.documentElement.setAttribute('lang', lang);
|
||||
|
||||
// Update DOM text contents
|
||||
document.getElementById('logo').textContent = t.appName;
|
||||
document.getElementById('welcome-title').textContent = t.welcome;
|
||||
document.getElementById('tagline').textContent = t.tagline;
|
||||
|
||||
const refLabel = document.getElementById('referral-label');
|
||||
if (refLabel) refLabel.textContent = t.referralLabel;
|
||||
|
||||
const copyBtn = document.getElementById('copy-btn');
|
||||
if (copyBtn) copyBtn.textContent = t.copyBtn;
|
||||
|
||||
const refTip = document.getElementById('referral-tip');
|
||||
if (refTip) refTip.textContent = t.referralTip;
|
||||
|
||||
document.getElementById('ios-title').textContent = t.iosTitle;
|
||||
document.getElementById('ios-desc').textContent = t.iosDesc;
|
||||
document.querySelector('#ios-btn span').textContent = t.iosBtn;
|
||||
document.getElementById('ios-info').textContent = t.iosInfo;
|
||||
|
||||
document.getElementById('apk-title').textContent = t.apkTitle;
|
||||
document.getElementById('apk-desc').textContent = t.apkDesc;
|
||||
document.querySelector('#apk-btn span').textContent = t.apkBtn;
|
||||
document.getElementById('apk-info').textContent = t.apkInfo;
|
||||
|
||||
document.getElementById('play-title').textContent = t.playTitle;
|
||||
document.getElementById('play-desc').textContent = t.playDesc;
|
||||
document.querySelector('#play-btn span').textContent = t.playBtn;
|
||||
document.getElementById('play-info').textContent = t.playInfo;
|
||||
|
||||
document.getElementById('footer-text').textContent = t.footer;
|
||||
|
||||
// Toggle language button text
|
||||
document.getElementById('lang-toggle').textContent = isAr ? 'English' : 'العربية';
|
||||
|
||||
detectOS();
|
||||
}
|
||||
|
||||
document.getElementById('lang-toggle').addEventListener('click', () => {
|
||||
updateLanguage(currentLang === 'ar' ? 'en' : 'ar');
|
||||
});
|
||||
|
||||
function copyReferralCode() {
|
||||
const codeText = document.getElementById("refCode").innerText;
|
||||
const toast = document.getElementById("copy-toast");
|
||||
|
||||
navigator.clipboard.writeText(codeText).then(() => {
|
||||
showToast(content[currentLang].copiedMsg + codeText);
|
||||
}, () => {
|
||||
// Fallback
|
||||
const dummy = document.createElement("textarea");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.value = codeText;
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
showToast(content[currentLang].copiedMsg + codeText);
|
||||
});
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.getElementById("copy-toast");
|
||||
toast.textContent = message;
|
||||
toast.classList.remove('hidden');
|
||||
toast.classList.add('toast-active');
|
||||
setTimeout(() => {
|
||||
toast.classList.add('hidden');
|
||||
toast.classList.remove('toast-active');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateLanguage('ar');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,539 @@
|
||||
<meta charset="utf-8">
|
||||
<title>سيرو — التقرير الشامل للمنظومة</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
|
||||
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
|
||||
--line:#E1E5E1; --line2:#D2D8D3;
|
||||
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
|
||||
--amber:#9A6B12; --amber-soft:#F6EDDA;
|
||||
--red:#B3362B; --red-soft:#F7E5E2;
|
||||
--good:#2E7D4F; --good-soft:#E4F1E8;
|
||||
--sans:-apple-system, BlinkMacSystemFont, "SF Pro Arabic", "Helvetica Neue", Arial, sans-serif;
|
||||
--mono:ui-monospace,"SF Mono",Consolas,monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root{
|
||||
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
|
||||
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
|
||||
--line:#26302B; --line2:#32403A;
|
||||
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
|
||||
--amber:#E0AE55; --amber-soft:#33290F;
|
||||
--red:#E07065; --red-soft:#361A16;
|
||||
--good:#57C287; --good-soft:#14301F;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
|
||||
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
|
||||
--line:#26302B; --line2:#32403A;
|
||||
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
|
||||
--amber:#E0AE55; --amber-soft:#33290F;
|
||||
--red:#E07065; --red-soft:#361A16;
|
||||
--good:#57C287; --good-soft:#14301F;
|
||||
}
|
||||
:root[data-theme="light"]{
|
||||
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
|
||||
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
|
||||
--line:#E1E5E1; --line2:#D2D8D3;
|
||||
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
|
||||
--amber:#9A6B12; --amber-soft:#F6EDDA;
|
||||
--red:#B3362B; --red-soft:#F7E5E2;
|
||||
--good:#2E7D4F; --good-soft:#E4F1E8;
|
||||
}
|
||||
|
||||
html{ scroll-behavior:smooth; }
|
||||
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }
|
||||
|
||||
.page{
|
||||
background:var(--bg); color:var(--ink);
|
||||
font-family:var(--sans); font-size:16px; line-height:1.85;
|
||||
min-height:100%;
|
||||
}
|
||||
.page *{ box-sizing:border-box; }
|
||||
.wrap{ max-width:840px; margin:0 auto; padding:0 22px; }
|
||||
.page h1,.page h2,.page h3,.page h4{ margin:0; color:var(--ink); text-wrap:balance; line-height:1.35; }
|
||||
.page p{ margin:0; }
|
||||
.page a{ color:var(--brand); }
|
||||
.page a:focus-visible, .page summary:focus-visible{ outline:2px solid var(--brand); outline-offset:2px; border-radius:4px; }
|
||||
code{
|
||||
direction:ltr; unicode-bidi:isolate; font-family:var(--mono); font-size:.82em;
|
||||
background:var(--surface2); border:1px solid var(--line); border-radius:5px; padding:.08em .4em;
|
||||
}
|
||||
.num{ font-variant-numeric:tabular-nums; }
|
||||
|
||||
/* ===== Hero ===== */
|
||||
.hero{ padding:64px 0 36px; border-bottom:1px solid var(--line); }
|
||||
.hero .kicker{
|
||||
display:inline-block; font-size:.78rem; font-weight:700; letter-spacing:.04em;
|
||||
color:var(--brand-ink); background:var(--brand-soft); border-radius:99px; padding:4px 14px;
|
||||
margin-bottom:18px;
|
||||
}
|
||||
.hero h1{ font-size:clamp(1.7rem, 4.5vw, 2.5rem); font-weight:800; }
|
||||
.hero .lede{ margin-top:14px; font-size:1.05rem; color:var(--muted); max-width:60ch; }
|
||||
.hero .meta{ margin-top:16px; font-size:.8rem; color:var(--faint); }
|
||||
|
||||
.stats{ display:grid; grid-template-columns:repeat(6,1fr); gap:0; margin-top:30px;
|
||||
border:1px solid var(--line); border-radius:14px; background:var(--surface); overflow:hidden; }
|
||||
.stat{ padding:14px 10px; text-align:center; border-inline-start:1px solid var(--line); }
|
||||
.stat:first-child{ border-inline-start:none; }
|
||||
.stat b{ display:block; font-size:1.35rem; font-weight:800; color:var(--brand-ink); font-variant-numeric:tabular-nums; }
|
||||
.stat span{ font-size:.72rem; color:var(--muted); line-height:1.4; display:block; margin-top:2px; }
|
||||
@media (max-width:700px){
|
||||
.stats{ grid-template-columns:repeat(3,1fr); }
|
||||
.stat:nth-child(4){ border-inline-start:none; }
|
||||
.stat:nth-child(-n+3){ border-bottom:1px solid var(--line); }
|
||||
}
|
||||
|
||||
/* ===== Sticky TOC ===== */
|
||||
.tocbar{
|
||||
position:sticky; top:0; z-index:10;
|
||||
background:color-mix(in srgb, var(--bg) 75%, transparent);
|
||||
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
|
||||
border-bottom:1px solid var(--line); padding:10px 0;
|
||||
}
|
||||
.tocbar .row{ display:flex; gap:8px; overflow-x:auto; scrollbar-width:none; padding:2px; }
|
||||
.tocbar .row::-webkit-scrollbar{ display:none; }
|
||||
.tocbar a{
|
||||
flex:none; text-decoration:none; font-size:.8rem; font-weight:700; color:var(--muted);
|
||||
border:1px solid var(--line); background:var(--surface); border-radius:99px; padding:5px 13px;
|
||||
white-space:nowrap; transition: all 0.2s ease;
|
||||
}
|
||||
.tocbar a b{ color:var(--brand); font-weight:800; margin-inline-end:4px; font-variant-numeric:tabular-nums; }
|
||||
.tocbar a:hover{ border-color:var(--brand); color:var(--ink); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
|
||||
|
||||
/* ===== Sections ===== */
|
||||
section{ padding:46px 0 8px; }
|
||||
.sec-head{ margin-bottom:20px; }
|
||||
.sec-head .eyebrow{
|
||||
font-size:.75rem; font-weight:800; color:var(--brand); letter-spacing:.08em;
|
||||
font-variant-numeric:tabular-nums;
|
||||
}
|
||||
.sec-head h2{ font-size:1.45rem; font-weight:800; margin-top:4px; }
|
||||
.sec-head .thesis{ margin-top:8px; color:var(--muted); font-size:.95rem; max-width:66ch; }
|
||||
|
||||
.subhead{
|
||||
font-size:.82rem; font-weight:800; color:var(--faint); letter-spacing:.03em;
|
||||
margin:26px 0 10px; display:flex; align-items:center; gap:10px;
|
||||
}
|
||||
.subhead::after{ content:""; flex:1; height:1px; background:var(--line); }
|
||||
|
||||
/* compact feature rows */
|
||||
.rows{ border:1px solid var(--line); border-radius:14px; background:var(--surface); overflow:hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.02); }
|
||||
.row-item{ padding:13px 18px; border-top:1px solid var(--line); transition: all 0.2s ease; cursor: default; }
|
||||
.row-item:first-child{ border-top:none; }
|
||||
.row-item:hover{ background:var(--surface2); padding-inline-start:22px; }
|
||||
.row-item h4{ font-size:.95rem; font-weight:800; display:inline; }
|
||||
.row-item p{ display:inline; color:var(--muted); font-size:.9rem; }
|
||||
.row-item h4::after{ content:" — "; color:var(--faint); font-weight:400; }
|
||||
.row-item .why{ display:block; margin-top:3px; font-size:.83rem; color:var(--brand-ink); }
|
||||
|
||||
/* alerts */
|
||||
.alert{ border-radius:12px; padding:14px 18px; margin:16px 0; font-size:.9rem; border:1px solid; }
|
||||
.alert p{ color:var(--ink); }
|
||||
.alert .tag{ display:inline-block; font-size:.72rem; font-weight:800; border-radius:6px; padding:1px 9px; margin-bottom:6px; }
|
||||
.alert.crit{ background:var(--red-soft); border-color:color-mix(in srgb, var(--red) 35%, transparent); }
|
||||
.alert.crit .tag{ background:var(--red); color:var(--bg); }
|
||||
.alert.warn{ background:var(--amber-soft); border-color:color-mix(in srgb, var(--amber) 35%, transparent); }
|
||||
.alert.warn .tag{ background:var(--amber); color:var(--bg); }
|
||||
.alert.good{ background:var(--good-soft); border-color:color-mix(in srgb, var(--good) 35%, transparent); }
|
||||
.alert.good .tag{ background:var(--good); color:var(--bg); }
|
||||
|
||||
/* ===== Ride flow timeline ===== */
|
||||
.flow{ position:relative; padding-inline-start:26px; margin-top:8px; }
|
||||
.flow::before{ content:""; position:absolute; inset-inline-start:8px; top:8px; bottom:8px; width:2px;
|
||||
background:linear-gradient(var(--brand), var(--line2)); border-radius:2px; }
|
||||
.step{ position:relative; padding:0 0 26px; }
|
||||
.step::before{
|
||||
content:""; position:absolute; inset-inline-start:-24px; top:7px; width:12px; height:12px;
|
||||
border-radius:50%; background:var(--bg); border:3px solid var(--brand);
|
||||
}
|
||||
.step h4{ font-size:1rem; font-weight:800; }
|
||||
.step h4 .t{ font-size:.72rem; font-weight:700; color:var(--brand-ink); background:var(--brand-soft);
|
||||
border-radius:99px; padding:2px 10px; margin-inline-start:8px; vertical-align:2px; white-space:nowrap; }
|
||||
.step p{ color:var(--muted); font-size:.9rem; margin-top:4px; max-width:62ch; }
|
||||
|
||||
/* ===== two-col mini grid ===== */
|
||||
.duo{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
|
||||
@media (max-width:640px){ .duo{ grid-template-columns:1fr; } }
|
||||
.panel{ border:1px solid var(--line); border-radius:14px; background:var(--surface); padding:16px 18px; transition: all 0.2s ease; cursor: default; }
|
||||
.panel:hover{ transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.04); border-color: color-mix(in srgb, var(--brand) 30%, var(--line)); }
|
||||
.panel h4{ font-size:.95rem; font-weight:800; margin-bottom:6px; }
|
||||
.panel p, .panel li{ color:var(--muted); font-size:.88rem; }
|
||||
.panel ul{ margin:6px 0 0; padding-inline-start:18px; display:flex; flex-direction:column; gap:5px; }
|
||||
.panel.can h4{ color:var(--good); }
|
||||
.panel.cannot h4{ color:var(--red); }
|
||||
|
||||
/* ===== tutorial modules ===== */
|
||||
.mods{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
|
||||
@media (max-width:640px){ .mods{ grid-template-columns:1fr; } }
|
||||
.mod{ border:1px solid var(--line); border-radius:14px; background:var(--surface); padding:16px 18px; position:relative; transition: all 0.2s ease; cursor: default; }
|
||||
.mod:hover{ transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.04); border-color: color-mix(in srgb, var(--brand) 30%, var(--line)); }
|
||||
.mod .shots{ position:absolute; top:14px; inset-inline-end:16px; font-size:.7rem; font-weight:800;
|
||||
color:var(--brand-ink); background:var(--brand-soft); border-radius:99px; padding:2px 10px; font-variant-numeric:tabular-nums; }
|
||||
.mod h4{ font-size:.95rem; font-weight:800; padding-inline-end:70px; }
|
||||
.mod ol{ margin:8px 0 0; padding-inline-start:18px; color:var(--muted); font-size:.85rem; display:flex; flex-direction:column; gap:4px; }
|
||||
.mod .note{ margin-top:8px; font-size:.8rem; color:var(--brand-ink); }
|
||||
|
||||
/* transit actors */
|
||||
.actors{ display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin:14px 0 4px; }
|
||||
@media (max-width:760px){ .actors{ grid-template-columns:1fr 1fr; } }
|
||||
.actor{ border:1px solid var(--line); border-radius:12px; background:var(--surface); padding:12px 14px; text-align:center; }
|
||||
.actor .ic{ font-size:1.4rem; }
|
||||
.actor b{ display:block; font-size:.85rem; margin-top:4px; }
|
||||
.actor span{ font-size:.74rem; color:var(--muted); display:block; line-height:1.5; }
|
||||
|
||||
footer.end{ margin-top:56px; border-top:1px solid var(--line); padding:22px 0 60px;
|
||||
font-size:.8rem; color:var(--faint); display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px; }
|
||||
</style>
|
||||
|
||||
<div class="page" dir="rtl" lang="ar">
|
||||
|
||||
<header class="hero"><div class="wrap">
|
||||
<span class="kicker">التقرير الشامل — نسخة محدّثة تشمل مواصلاتي وسير الرحلة والتوتوريال</span>
|
||||
<h1>سيرو — الإرث الرقمي لمنظومة التنقّل المتكاملة</h1>
|
||||
<p class="lede">
|
||||
جرد كامل لكل ما بُني في منصة Siro ولماذا بُني: تطبيقات الراكب والسائق والإدارة وخدمة العملاء،
|
||||
البنية الخلفية ومحرك التسعير، الخرائط والتتبع الحي، نظام «مواصلاتي» لباصات الجامعات،
|
||||
البوتات والذكاء الاصطناعي، والمنظومة المالية — مع سير الرحلة خطوة بخطوة وخطة التوتوريال الكاملة.
|
||||
</p>
|
||||
<p class="meta">أُعدّ بفحص مباشر للكود المصدري — كل رقم ومسار ملف تمّ التحقق منه فعلياً · آخر تحديث 2026-07-14</p>
|
||||
<div class="stats">
|
||||
<div class="stat"><b>4</b><span>تطبيقات موبايل</span></div>
|
||||
<div class="stat"><b>9</b><span>فئات مركبات</span></div>
|
||||
<div class="stat"><b>3</b><span>دول تشغيل</span></div>
|
||||
<div class="stat"><b>13+</b><span>لغة مدعومة</span></div>
|
||||
<div class="stat"><b>10+</b><span>طرق دفع محلية</span></div>
|
||||
<div class="stat"><b>2</b><span>خطا أعمال: مشاوير + مواصلاتي</span></div>
|
||||
</div>
|
||||
</div></header>
|
||||
|
||||
<nav class="tocbar" aria-label="فهرس التقرير"><div class="wrap"><div class="row">
|
||||
<a href="#overview"><b>00</b>نظرة عامة</a>
|
||||
<a href="#rideflow"><b>01</b>سير الرحلة</a>
|
||||
<a href="#rider"><b>02</b>الراكب</a>
|
||||
<a href="#driver"><b>03</b>السائق</a>
|
||||
<a href="#ops"><b>04</b>الإدارة والدعم</a>
|
||||
<a href="#backend"><b>05</b>البنية والتسعير</a>
|
||||
<a href="#maps"><b>06</b>الخرائط</a>
|
||||
<a href="#transit"><b>07</b>مواصلاتي</a>
|
||||
<a href="#bots"><b>08</b>البوتات</a>
|
||||
<a href="#finance"><b>09</b>المالية والاستثمار</a>
|
||||
<a href="#legacy"><b>10</b>القيمة</a>
|
||||
<a href="#risks"><b>11</b>المخاطر</a>
|
||||
<a href="#tutorial"><b>12</b>التوتوريال</a>
|
||||
</div></div></nav>
|
||||
|
||||
<main class="wrap">
|
||||
|
||||
<!-- 00 -->
|
||||
<section id="overview">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">00</span>
|
||||
<h2>نظرة عامة: منصة واحدة، تسعة أنظمة متكاملة</h2>
|
||||
<p class="thesis">سيرو ليست «تطبيق طلب سيارة» — هي منظومة من 4 تطبيقات Flutter، وباك اند PHP/Node ضخم، وخوادم Socket خاصة للتتبع الحي، ومحرك تسعير بالذكاء الاصطناعي، ونظام نقل جماعي للجامعات، وبنية مالية متعددة الدول — كلها مبنية داخلياً وتعمل في الأردن ومصر وسوريا.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>🚕 أربعة تطبيقات Flutter</h4><p>الراكب (226 ملف)، السائق (275 ملف — الأكبر)، الإدارة (131)، خدمة العملاء (66) — تشترك بنفس الباك اند.</p></div>
|
||||
<div class="row-item"><h4>🗄️ باك اند PHP مقسّم بأمان مركزي</h4><p>كل وحدة (مصادقة، رحلات، تسعير، تأمين…) تمر إجبارياً عبر طبقة JWT + تشفير + تحديد معدل طلبات واحدة.</p></div>
|
||||
<div class="row-item"><h4>📍 خوادم Socket خاصة للموقع</h4><p>خادم سائق وخادم راكب منفصلان — تتبع لحظي دون الاعتماد على Google Maps، بتوفير تكلفة ضخم.</p></div>
|
||||
<div class="row-item"><h4>🤖 محرك تسعير ذكي</h4><p>بوت يقرأ أسعار المنافسين من تطبيقاتهم، محرك يفكّك معادلاتهم، وكرون جوبز تُبقي سيرو أرخص بـ 6.5% آلياً.</p></div>
|
||||
<div class="row-item"><h4>🚌 مواصلاتي</h4><p>نظام نقل جماعي للجامعات والمؤسسات (SaaS مجاني) بقاعدة بيانات معزولة ولوحة تحكم ويب مستقلة — القسم 07.</p></div>
|
||||
<div class="row-item"><h4>💳 محفظة ودفع متعدد الدول</h4><p>خدمة منفصلة (268 ملف) تربط MTN وSyriatel Cash وShamCash وCliq وPayMob وeCash.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 01 RIDE FLOW -->
|
||||
<section id="rideflow">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">01</span>
|
||||
<h2>سير الرحلة — من فتح التطبيق حتى التقييم</h2>
|
||||
<p class="thesis">الدورة الكاملة كما تعمل فعلياً في الكود: كل خطوة لها شاشة وحالة (State) وقناة تواصل حي. هذه الدورة نفسها هي أساس التوتوريال في القسم 12.</p>
|
||||
</div>
|
||||
<div class="flow">
|
||||
<div class="step"><h4>الدخول والتحقق <span class="t">أقل من دقيقة</span></h4><p>رقم الهاتف + رمز OTP (واتساب/SMS حسب الدولة) — لا بريد إلكتروني إجباري ولا بطاقة. الجلسة تُربط ببصمة الجهاز فلا يعمل الرمز المسروق على جهاز آخر.</p></div>
|
||||
<div class="step"><h4>تحديد الوجهة والسعر <span class="t">فوري</span></h4><p>بحث عن المكان، اختيار فئة من 9 فئات، والسعر يُحسب بالكامل على الخادم ويُختم برمز موقّت صالح 7 دقائق — لا يمكن التلاعب به بين شاشة العرض والتأكيد.</p></div>
|
||||
<div class="step"><h4>البحث عن كابتن <span class="t">حتى 90 ثانية</span></h4><p>مطابقة «أقرب سائق» عبر Redis الجغرافي. إذا لم يقبل أحد خلال 90 ثانية يقترح «المفاوض الذكي» رفع السعر ~5% بدل إلغاء الطلب.</p></div>
|
||||
<div class="step"><h4>قبول الكابتن والتوجه إليك <span class="t">تتبع حي</span></h4><p>بطاقة الكابتن (اسم، تقييم، سيارة، لوحة) ومسار أصفر يتحرك لحظياً عبر WebSocket، مع إشعار FCM وLive Activity على iOS.</p></div>
|
||||
<div class="step"><h4>الوصول والانتظار <span class="t">مهلة 5 دقائق</span></h4><p>إشعار «الكابتن وصل» ويبدأ عداد انتظار. الإلغاء قبل القبول مجاني دائماً؛ بعد الوصول قد تُطبَّق رسوم.</p></div>
|
||||
<div class="step"><h4>الرحلة الجارية <span class="t">مسار أزرق + SOS</span></h4><p>عداد حي، كشف انحراف عن المسار (50م)، تنبيه تجاوز سرعة 100كم/س، زر طوارئ يعمل بهزّ الهاتف، ومشاركة الرحلة مع الأهل برابط حي.</p></div>
|
||||
<div class="step"><h4>التسوية والدفع <span class="t">من الخادم</span></h4><p>السعر النهائي يُعاد حسابه من المسافة والزمن الفعليين بسقوف أمان (≤1.6× المعروض)، ثم الدفع: كاش، محفظة، PayMob، MTN، Syriatel، Cliq.</p></div>
|
||||
<div class="step"><h4>التقييم والإكرامية <span class="t">اختياري</span></h4><p>تقييم الكابتن بالنجوم مع إكرامية اختيارية، وتُحفظ الرحلة في السجل مع الفاتورة.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 02 RIDER -->
|
||||
<section id="rider">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">02</span>
|
||||
<h2>تطبيق الراكب</h2>
|
||||
<p class="thesis">واجهة المستخدم النهائي — أعمق بكثير من «اطلب وادفع»، وفيها ميزات ثقة وسلامة نادرة حتى عند منافسين أكبر.</p>
|
||||
</div>
|
||||
|
||||
<div class="subhead">الحجز والتسعير</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>9 فئات ركوب</h4><p>اقتصادية (Balash/Awfar)، Comfort، كهربائية، Lady نسائية، Van عائلية، VIP/مشوار (اختيار سائق بالاسم لموعد لاحق)، توصيل، ورايح-جاي بين المدن (+23 كم).</p><span class="why">كل فئة تفتح شريحة سوق مختلفة — من الطالب حتى العائلة والراكبات.</span></div>
|
||||
<div class="row-item"><h4>شارة مقارنة أسعار</h4><p>«أنت توفّر X% مقارنة بكريم/أوبر/يلا-جو» بالاسم صراحة على شاشة الطلب.</p></div>
|
||||
<div class="row-item"><h4>المفاوض الذكي</h4><p>اقتراح آلي لرفع السعر عند عدم توفر كابتن — يقلل الطلبات الفاشلة.</p></div>
|
||||
</div>
|
||||
|
||||
<div class="subhead">الدفع والولاء</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>Siro Prime</h4><p>اشتراك ~4$ شهرياً: بلا تسعير ذروة، أولوية مطابقة، شارة تزيد قبول السائقين — إيراد شهري متكرر.</p></div>
|
||||
<div class="row-item"><h4>مكافآت شحن المحفظة</h4><p>«ادفع 20 خذ 21» — يشجع الرصيد المسبق ويقلل الكاش.</p></div>
|
||||
<div class="row-item"><h4>تنبيه الرصيد السالب</h4><p>بانر دائم + قراءة صوتية عند وجود دين من رحلة كاش سابقة — تحصيل استباقي.</p></div>
|
||||
<div class="row-item"><h4>إحالة ثنائية</h4><p>دعوة أصدقاء كركاب أو سائقين عبر واتساب، والمكافأة تُفتح بعد رحلتين فعليتين.</p></div>
|
||||
</div>
|
||||
|
||||
<div class="subhead">السلامة والثقة</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>زر الطوارئ SOS</h4><p>واتساب فوري لجهة طوارئ مع الموقع الحي واسم السائق واللوحة — ويتفعّل بهزّ الهاتف 5 مرات.</p></div>
|
||||
<div class="row-item"><h4>مراقبة حية لطرف ثالث</h4><p>رابط يتيح لولي الأمر متابعة الموقع والسرعة دون تثبيت التطبيق — تمايز حقيقي لشريحة الطالبات.</p></div>
|
||||
<div class="row-item"><h4>مكالمات WebRTC داخلية</h4><p>اتصال راكب↔سائق دون كشف الأرقام، ببنية ذاتية بدل Agora المدفوعة.</p></div>
|
||||
<div class="row-item"><h4>تسجيل صوتي للرحلة + تنبيه سرعة</h4><p>دليل عند النزاع، وتنبيه فوري عند تجاوز 100 كم/س.</p></div>
|
||||
<div class="row-item"><h4>حماية تقنية</h4><p>بصمة جهاز، كشف Root/Jailbreak، تثبيت SSL ضد اعتراض البيانات.</p></div>
|
||||
</div>
|
||||
|
||||
<div class="subhead">تجربة مصممة للمنطقة</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>13+ لغة بثلاث لهجات عربية</h4><p>مصري/أردني/سوري بملفات منفصلة + RTL كامل — جاهزية توسع حقيقية.</p></div>
|
||||
<div class="row-item"><h4>خرائط دون اتصال + كشف نوعية الجهاز</h4><p>تحميل مسبق للبلاطات، وتخفيف الرسوميات آلياً على الأجهزة الاقتصادية.</p></div>
|
||||
<div class="row-item"><h4>قراءة صوتية TTS</h4><p>وصف الرحلات والتنبيهات صوتياً — يشمل ضعاف البصر، سوق مهمَل من المنافسين.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 03 DRIVER -->
|
||||
<section id="driver">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">03</span>
|
||||
<h2>تطبيق السائق</h2>
|
||||
<p class="thesis">أكبر تطبيق في المنظومة (275 ملف) — محرك تشغيل الأسطول: مكافحة احتيال، نظام تدرّج بخصومات عمولة فعلية، وذكاء تشغيلي يوجّه السائق للربح.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert good"><span class="tag">✅ مؤكد في الكود</span>
|
||||
<p>ميزة «أرباحك أعلى بـ X مقارنة بالتطبيقات الأخرى» موجودة ومفعّلة: <code>driver_earnings_badge.dart</code> يعرض شارة خضراء على شاشة قبول الطلب مبنية على حقل <code>driver_earnings_extra</code> من الخادم.</p>
|
||||
</div>
|
||||
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>تدرّج بخصم عمولة حقيقي</h4><p>برونزي ← فضي (−1%) ← ذهبي (−2%) ← ماسي (−5% + أولوية) — ولاء بمكافأة مالية ملموسة.</p></div>
|
||||
<div class="row-item"><h4>سلسلة رحلات بلا إلغاء</h4><p>5 رحلات متتالية = عمولة 0% لبقية اليوم؛ أي إلغاء يصفّر السلسلة.</p></div>
|
||||
<div class="row-item"><h4>خارطة طلب تنبؤية</h4><p>أين سيرتفع الطلب خلال الساعة القادمة، من بيانات الرحلات التاريخية.</p></div>
|
||||
<div class="row-item"><h4>حد 12 ساعة قيادة + حظر بعد 3 إلغاءات</h4><p>راحة إجبارية 6 ساعات، وحماية موثوقية السوق من الإلغاء المتكرر.</p></div>
|
||||
<div class="row-item"><h4>تحقق مسافة قبل إنهاء الرحلة</h4><p>مقارنة إزاحة GPS الفعلية بالمتوقعة — يمنع تزوير إتمام الرحلات.</p></div>
|
||||
<div class="row-item"><h4>توثيق بالذكاء الاصطناعي</h4><p>Gemini يقرأ الهوية والرخصة، ومطابقة وجه (سيلفي↔هوية) قبل قبول التسجيل، وكشف «الرحلة الذاتية» بمقارنة بصمتي الجهازين.</p></div>
|
||||
<div class="row-item"><h4>Android Auto / CarPlay</h4><p>جسر ملاحة مخصص لشاشة السيارة — تجربة مكافئة لأوبر/كريم.</p></div>
|
||||
<div class="row-item"><h4>سحب أرباح متعدد القنوات</h4><p>PayMob، MTN، Cliq، eCash، حساب بنكي، وحتى SMS في سوريا.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 04 OPS -->
|
||||
<section id="ops">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">04</span>
|
||||
<h2>الإدارة وخدمة العملاء</h2>
|
||||
<p class="thesis">لوحة تشغيل داخلية حقيقية بطبقتين (قديمة + V2 تحليلية)، وتطبيق دعم ميداني سريع — مع فجوات تشغيلية يجب قولها بصراحة.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>مركز عمليات حي (V2)</h4><p>رحلات نشطة، سائقون متصلون، إيراد اليوم مقابل الأمس، شكاوى — يتحدث كل دقيقتين.</p></div>
|
||||
<div class="row-item"><h4>محرر تسعير «كازان»</h4><p>عمولة كل دولة، سعر الكيلومتر لكل فئة، وتسعير الدقيقة حسب الوقت — أهم رافعة إيراد في المنصة.</p></div>
|
||||
<div class="row-item"><h4>مساعد تسجيل بالذكاء الاصطناعي</h4><p>Gemini + Claude Haiku يقرآن الوثائق المصرية ويكشفان الانتهاء وعدم تطابق الأسماء آلياً.</p></div>
|
||||
<div class="row-item"><h4>بطاقة جودة السائق + سجل تدقيق</h4><p>قرارات حظر مبنية على بيانات، وكل إجراء موظف حساس مسجّل بالاسم والوقت.</p></div>
|
||||
<div class="row-item"><h4>دعم ميداني سريع</h4><p>بحث برقم هاتف/رحلة، تفعيل سائقين، وقوالب واتساب عربية جاهزة — بدون CRM مكلف.</p></div>
|
||||
</div>
|
||||
<div class="alert warn"><span class="tag">فجوات تشغيلية</span>
|
||||
<p>شاشة عرض الشكوى في تطبيق خدمة العملاء ما زالت فارغة (stub) رغم جاهزية قاعدة البيانات لسير تحقيق كامل · لا توجد أداة استرجاع مبلغ (Refund) في كامل النظام · لا يوجد تتبع SLA أو تصعيد للشكاوى الحرجة.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 05 BACKEND -->
|
||||
<section id="backend">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">05</span>
|
||||
<h2>البنية الخلفية ومحرك التسعير</h2>
|
||||
<p class="thesis">قلب المنصة: كل طلب يمر عبر طبقة أمان مركزية قبل أي منطق عمل، ومحرك رحلات (202 ملف) يتخذ قرارات تجارية آلياً.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>JWT مربوط ببصمة الجهاز</h4><p>الرمز المسروق لا يعمل على جهاز آخر.</p></div>
|
||||
<div class="row-item"><h4>تشفير AES-256 للبيانات الحساسة</h4><p>أسماء، هواتف، هويات، لوحات — مشفّرة حتى لو تسربت القاعدة.</p></div>
|
||||
<div class="row-item"><h4>Rate Limiting مخصص لكل نوع طلب</h4><p>حدود أشد للشكاوى لأن كل شكوى تستدعي Gemini + واتساب.</p></div>
|
||||
<div class="row-item"><h4>رمز سعر موقّع (7 دقائق)</h4><p>يغلق ثغرة التلاعب بالسعر بين العرض والتأكيد.</p></div>
|
||||
<div class="row-item"><h4>تسوية أجرة آمنة</h4><p>إعادة حساب من الخادم بسقوف (≤1.6× السعر، ≤1.5× المسافة) قبل التحويل للمحفظة.</p></div>
|
||||
<div class="row-item"><h4>مطابقة الوجهة (Destination Matching)</h4><p>سائق متجه للبيت يأخذ أولوية الطلبات القريبة من وجهته، والراكب يخصم 14%.</p></div>
|
||||
<div class="row-item"><h4>تسعير ديناميكي متكامل</h4><p>ذروة حسب العرض/الطلب لكل قطعة جغرافية، مطابقة ذروة المنافسين، مضاعفات رمضان/الأعياد، وخصم مسافات طويلة.</p></div>
|
||||
</div>
|
||||
<div class="alert good"><span class="tag">وثيقة موجودة فعلاً</span>
|
||||
<p>يوجد تدقيق أمني داخلي بأسلوب اختبار اختراق يصنّف النتائج من حرج لمنخفض — نقاط قوة موثقة (لا SQL Injection، AES-256) مقابل بنود مفتوحة (Rate limiting معطّل بأماكن، ملفات اختبار في الإنتاج، تشفير CBC بـ IV ثابت). راجع <code>docs/08_security</code>.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 06 MAPS -->
|
||||
<section id="maps">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">06</span>
|
||||
<h2>الخرائط والموقع الجغرافي</h2>
|
||||
<p class="thesis">القرار الأهم: لا اعتماد على Google Maps للتتبع الحي أو المطابقة — خادما WebSocket خاصان وفهرسة Redis جغرافية، بتحكم كامل وتوفير ضخم.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>تتبع حي مُفلتر ومُجمّع</h4><p>موقع السائق كل 1–3 ثوانٍ، يُرسل فقط عند تحرك حقيقي (10م)، يُجمَّع ويُكتب لـ Redis كل نصف ثانية دفعة واحدة ثم يُدفع للراكب.</p></div>
|
||||
<div class="row-item"><h4>أقرب سائق عبر GEORADIUS</h4><p>بحث نصف قطر على آلاف السائقين لحظياً، مرتب بالتقييم — لا توجد خدمة جاهزة تقدم هذا.</p></div>
|
||||
<div class="row-item"><h4>استعلام مخصص لكل فئة</h4><p>Balash يختار أقدم السيارات فعلياً، وElectric يفلتر وقود «كهربائي» — منطق عمل مستحيل بخدمة عامة.</p></div>
|
||||
<div class="row-item"><h4>خرائط حرارية + تتبع أسطول حي</h4><p>«رؤية إلهية» لفريق العمليات دون شراء أداة BI.</p></div>
|
||||
<div class="row-item"><h4>تجزئة جغرافية (Geo-Sharding)</h4><p>كل نطاق إحداثيات يمكن ربطه بخادم مختلف — توسع مدينة-بمدينة دون إعادة هندسة.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 07 TRANSIT -->
|
||||
<section id="transit">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">07</span>
|
||||
<h2>مواصلاتي — النقل الجماعي للجامعات والمؤسسات</h2>
|
||||
<p class="thesis">خط الأعمال الثاني: رقمنة أساطيل الجامعات والمدارس والشركات مجاناً (SaaS)، مقابل استحواذ سيرو على المستخدمين وتحويلهم لركاب مدفوعين — بعزل تقني كامل عن نظام المشاوير (قاعدة <code>siro_transit</code> مستقلة + سوكيتات خاصة).</p>
|
||||
</div>
|
||||
|
||||
<div class="actors">
|
||||
<div class="actor"><span class="ic">🏛️</span><b>فريق سيرو</b><span>ينشئ المؤسسة، يضيف مشرفيها، ويعتمد الخطوط المرسومة قبل ظهورها للطلاب</span></div>
|
||||
<div class="actor"><span class="ic">🧑💼</span><b>مشرف المؤسسة</b><span>لوحة ويب: باصات، سائقون، رسم الخطوط والمحطات، الجداول، ورفع كشف الطلاب CSV</span></div>
|
||||
<div class="actor"><span class="ic">🚌</span><b>سائق الباص</b><span>تطبيق السائق بوضع Bus Mode مبسّط: زر ابدأ/أنهِ فقط، والمحطات تمرّ آلياً بالـ Geofencing</span></div>
|
||||
<div class="actor"><span class="ic">🎓</span><b>الطالب</b><span>تفعيل فوري بالرقم الجامعي، تتبع حي للباص، وإشعارات اقتراب ذكية</span></div>
|
||||
</div>
|
||||
|
||||
<div class="subhead">كيف تسير رحلة الباص</div>
|
||||
<div class="flow">
|
||||
<div class="step"><h4>الإعداد <span class="t">مرة واحدة</span></h4><p>المشرف يرسم المسار على خريطة تفاعلية ويحدد المحطات بمحيط جغرافي (150م افتراضياً)، والخط يبقى «مسودة» حتى يعتمده فريق سيرو، ثم تُحدد أوقات الانطلاق وأيام العمل.</p></div>
|
||||
<div class="step"><h4>بدء الرحلة <span class="t">زر واحد</span></h4><p>السائق يضغط «ابدأ الرحلة» ويبدأ بث موقعه عبر السوكيت كل عدة ثوانٍ — مع إشعار انطلاق للمشتركين.</p></div>
|
||||
<div class="step"><h4>المرور بالمحطات <span class="t">آلي بالكامل</span></h4><p>دخول الباص محيط أي محطة يحدّث شريط التقدم تلقائياً دون تدخل السائق، ويُرسل «الباص يبعد محطة واحدة عنك» للطلاب التاليين. زر «تأخير» متاح عند الزحام.</p></div>
|
||||
<div class="step"><h4>التتبع الحي للطالب <span class="t">Socket</span></h4><p>الطالب يرى الباص يتحرك على المسار لحظياً — ولا يُسمح له بالانضمام لغرفة البث إلا بعضوية نشطة في المؤسسة المالكة للخط.</p></div>
|
||||
<div class="step"><h4>نقطة التحويل الربحية <span class="t">جوهر النموذج</span></h4><p>إذا فات الطالبَ الباصُ يظهر زر بارز: «فاتك الباص؟ اطلب سيارة الآن» — يحوّله لرحلة مدفوعة عادية من سيرو. هذا هو العائد الأساسي لخط الأعمال كله.</p></div>
|
||||
</div>
|
||||
|
||||
<div class="duo" style="margin-top:14px;">
|
||||
<div class="panel"><h4>ضوابط أمنية مبنية</h4><ul>
|
||||
<li>حماية IDOR: لا يستطيع سائق إنهاء رحلة سائق آخر.</li>
|
||||
<li>تشفير أرقام الهواتف والأرقام الجامعية في القاعدة.</li>
|
||||
<li>Rate Limiting على OTP وتسجيل الدخول.</li>
|
||||
<li>تفعيل الطالب فوري بمطابقة الكشف — دون OTP إضافي لتوفير التكلفة.</li>
|
||||
</ul></div>
|
||||
<div class="panel"><h4>نمطان تشغيليان</h4><ul>
|
||||
<li><b>أسطول المؤسسة:</b> الجامعة تملك باصاتها وسائقيها.</li>
|
||||
<li><b>الناقل المتعاقد:</b> شركة نقل طرف ثالث تشغّل خطوط مؤسسة بلا أسطول، بنفس برمجيات التتبع.</li>
|
||||
<li>سائق الباص منفصل تماماً عن كابتن المشاوير ولا يتلقى طلبات عادية.</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
|
||||
<div class="alert warn"><span class="tag">فجوات معروفة قيد المعالجة</span>
|
||||
<p>المراجعة الفنية الكاملة في <code>docs/05_transit_mawasalati</code> توثّق بنوداً مفتوحة: نواقص في ربط السائق، واعتماد الخطوط، وحالات IDOR إضافية — يجب إغلاقها قبل أول إطلاق جامعي واسع.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 08 BOTS -->
|
||||
<section id="bots">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">08</span>
|
||||
<h2>البوتات والذكاء الاصطناعي التسويقي</h2>
|
||||
<p class="thesis">منظومة مغلقة: بوت يسحب أسعار المنافسين من تطبيقاتهم ← محرك يفكّك معادلاتهم ← إعادة تسعير آلية ← بوتات سوشيال تصنع «نقاشات» لصالح سيرو. ميزة تنافسية حقيقية، بمخاطر قانونية وسمعية واضحة.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>بوت أندرويد يقرأ تطبيقات المنافسين</h4><p>Accessibility Service يفتح كريم/أوبر/يلا-جو/TaxiF/زاكن فعلياً، يدخل نقطتين، ويقرأ السعر من الشاشة.</p></div>
|
||||
<div class="row-item"><h4>فك معادلة تسعير المنافس</h4><p>انحدار إحصائي يشتق (أساس + لكل كم + لكل دقيقة) ويكشف حتى الحد الأدنى الخفي للأجرة.</p></div>
|
||||
<div class="row-item"><h4>إعادة تسعير آلية −6.5%</h4><p>كرون جوب يُبقي سيرو أرخص تلقائياً، مع «وضع الظل»: العروض المؤقتة للمنافس تُقابل بكود خصم بدل حرق السعر الأساسي (سقف تغيير 3% وتهدئة 3 أيام).</p></div>
|
||||
<div class="row-item"><h4>بوتات سوشيال بلهجات محلية</h4><p>حسابات مُدارة بتدوير IP، تعليقات Gemini بلهجة كل بلد، و«دراما حوار» مفتعلة (تشكيك ثم رد داعم) بتأخير عشوائي.</p></div>
|
||||
</div>
|
||||
<div class="alert crit"><span class="tag">⚠️ خطر قانوني وسمعي</span>
|
||||
<p>سحب الأسعار آلياً يخالف غالباً شروط استخدام تطبيقات المنافسين، والحسابات المنسّقة الوهمية تُصنَّف «تلاعباً منسّقاً غير أصيل» يخالف سياسات المنصات صراحة — خطر حظر جماعي وضرر سمعي إذا انكشف. قرار يجب اتخاذه بوعي كامل بالمخاطرة، لا بالعائد فقط.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 09 FINANCE -->
|
||||
<section id="finance">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">09</span>
|
||||
<h2>نبيه، المحفظة، والاستثمار</h2>
|
||||
<p class="thesis">تصحيح مهم: «نبيه» ليست منصة استثمار — لا فوائد ولا حصص في الكود. هي مزوّد أتمتة خارجي عبر واتساب. الاستثمار الحقيقي في وثائق المستثمرين، مع نقطة تحتاج انتباهاً فورياً.</p>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<div class="row-item"><h4>نبيه فعلياً</h4><p>أتمتة واتساب بالذكاء الاصطناعي: تسجيل سائقين بالمحادثة، استفسارات أرباح، فحص شكاوى بـ Gemini، وتحقق بصري من إيصالات الدفع.</p></div>
|
||||
<div class="row-item"><h4>محفظة سيرو</h4><p>خدمة منفصلة (268 ملف): MTN، Syriatel Cash، ShamCash، Cliq، PayMob، eCash — مع تحويل فعلي بين محافظ السائقين برسوم للشركة.</p></div>
|
||||
<div class="row-item"><h4>طلب تمويل موثّق</h4><p>200,000$ مقابل 22% (تقييم ضمني ~909K$) بأربع طبقات إيراد: عمولة، Prime، إعلانات جغرافية، وترخيص خرائط سيرو كبديل أرخص من Google Maps.</p></div>
|
||||
<div class="row-item"><h4>عقد سوريا المنفصل</h4><p>اتفاقية حصة أرباح 180,000$ لسوريا فقط — سرديتان تمويليتان تحتاجان توحيداً قبل أي عرض رسمي.</p></div>
|
||||
</div>
|
||||
<div class="alert crit"><span class="tag">⚠️ تسريب بيانات — إجراء فوري</span>
|
||||
<p><code>siromove.com/contract.html</code> على النطاق العام يحتوي نص العقد الاستثماري كاملاً مع <b>أرقام هوية/جواز حقيقية</b> لمؤسسَين ومستثمر — متاح لأي زائر. يجب إزالته من الوصول العام أو حمايته بمصادقة فوراً.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 10 LEGACY -->
|
||||
<section id="legacy">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">10</span>
|
||||
<h2>الإرث الرقمي: القيمة الفكرية والمادية</h2>
|
||||
<p class="thesis">لو حلّ نموذج ذكاء اصطناعي محل الفريق، هل كان يبني هذا من الصفر؟ جزء كبير من الكود: نعم. الجزء الأكثر قيمة: لا — وهذا ما يحدد قيمة المشروع.</p>
|
||||
</div>
|
||||
<div class="duo">
|
||||
<div class="panel can"><h4>✅ ما يُنتجه الذكاء الاصطناعي بسرعة</h4><ul>
|
||||
<li>شاشات Flutter القياسية والتكاملات الجاهزة (PayMob، Gemini، Firebase).</li>
|
||||
<li>منطق CRUD الإداري والأمان القياسي (JWT، تشفير، Rate Limiting).</li>
|
||||
<li>نمط Socket + Redis Geo كتصميم هندسي معروف بالصناعة.</li>
|
||||
</ul></div>
|
||||
<div class="panel cannot"><h4>❌ ما لا يُخترع بمجرد Prompt</h4><ul>
|
||||
<li><b>معادلات تسعير المنافسين الفعلية</b> — أشهر من بيانات سوق حقيقية.</li>
|
||||
<li><b>القيم المضبوطة تشغيلياً</b> (12 ساعة، 3 إلغاءات، 90 ثانية) — نتاج حوادث وتجربة موثقة.</li>
|
||||
<li><b>العلاقات المحلية</b>: ترخيص سوريا (قانون 16/2021)، اتفاقيات MTN وSyriatel وCliq، وتوزيع APK خارج المتجر بسبب العقوبات.</li>
|
||||
<li><b>القاعدة الفعلية</b>: 1,447 سائقاً و2,891 راكباً في 45 يوماً بميزانية محدودة — أصل شبكي لا يُشترى.</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<div class="alert good" style="margin-top:14px;"><span class="tag">الخلاصة</span>
|
||||
<p>هذا المشروع مثال حي على الفرق بين «الكود» و«الشركة»: الذكاء الاصطناعي يسرّع كتابة الكود فعلاً، لكنه لا يعوّض الوقت الفعلي والمخاطرة الفعلية والعلاقات الفعلية — وهذه، لا الكود، هي القيمة غير القابلة للنسخ. القيمة المادية الموثقة داخلياً: تقييم ضمني ~909 ألف دولار.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 11 RISKS -->
|
||||
<section id="risks">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">11</span>
|
||||
<h2>المخاطر والفجوات المجمّعة</h2>
|
||||
<p class="thesis">كل ما يحتاج قراراً أو إجراءً، من الأشد إلحاحاً للأقل.</p>
|
||||
</div>
|
||||
<div class="alert crit"><span class="tag">حرج — الآن</span><p>أرقام هوية حقيقية منشورة بلا حماية على <code>siromove.com/contract.html</code> — القسم 09.</p></div>
|
||||
<div class="alert warn"><span class="tag">قانوني وسمعي</span><p>بوتات سحب الأسعار والتلاعب المنسّق بالسوشيال — القسم 08.</p></div>
|
||||
<div class="alert warn"><span class="tag">حوكمة تمويل</span><p>سرديتان تمويليتان متضاربتان (180K$ سوريا مقابل 200K$/22% عامة) تحتاجان توحيداً.</p></div>
|
||||
<div class="alert warn"><span class="tag">تشغيلي</span><p>لا أداة عرض/حل شكوى فعلية، لا Refund، لا SLA — القسم 04. وفجوات مواصلاتي المفتوحة — القسم 07.</p></div>
|
||||
<div class="alert warn"><span class="tag">أمني</span><p>بنود التدقيق الأمني غير المغلقة: Rate limiting معطّل بأماكن، ملفات اختبار في الإنتاج، تشفير CBC بـ IV ثابت.</p></div>
|
||||
</section>
|
||||
|
||||
<!-- 12 TUTORIAL -->
|
||||
<section id="tutorial">
|
||||
<div class="sec-head">
|
||||
<span class="eyebrow">12</span>
|
||||
<h2>خطة التوتوريال داخل الموقع — «كيف تستخدم سيرو»</h2>
|
||||
<p class="thesis">صفحة <code>siromove.com/tutorial</code> بسبع وحدات تشرح كل عملية خطوة بخطوة بلقطات شاشة حقيقية داخل إطار هاتف. المطلوب تصويره: <b class="num">34 لقطة</b> في جلسة واحدة (~ساعتين) على بيئة تجريبية. الخطة التفصيلية بأسماء الشاشات في الكود: <code>docs/02_journeys_and_tutorials/TUTORIAL_PLAN_AR.md</code>.</p>
|
||||
</div>
|
||||
<div class="mods">
|
||||
<div class="mod"><span class="shots">5 لقطات</span><h4>1 · التسجيل</h4>
|
||||
<ol><li>شاشة البداية بالشعار</li><li>شرائح التعريف</li><li>رقم الهاتف واختيار الدولة</li><li>رمز التحقق OTP</li><li>إكمال الاسم والبدء</li></ol>
|
||||
<p class="note">الرسالة: رقم هاتف فقط — أقل من دقيقة حتى الخريطة.</p></div>
|
||||
<div class="mod"><span class="shots">6 لقطات</span><h4>2 · طلب الرحلة</h4>
|
||||
<ol><li>الخريطة والسيارات القريبة</li><li>البحث عن الوجهة</li><li>دبوس الانطلاق</li><li>الفئات التسع مع شارة التوفير</li><li>كود الخصم</li><li>تأكيد الطلب بالسعر النهائي</li></ol>
|
||||
<p class="note">الرسالة: السعر نهائي ومحسوب من الخادم — لا مفاجآت.</p></div>
|
||||
<div class="mod"><span class="shots">4 لقطات</span><h4>3 · الانتظار والمطابقة</h4>
|
||||
<ol><li>نافذة البحث مع المؤقّت</li><li>اقتراح المفاوض الذكي (بعد 90 ثانية)</li><li>بطاقة الكابتن</li><li>الكابتن في الطريق مع المسار</li></ol></div>
|
||||
<div class="mod"><span class="shots">5 لقطات</span><h4>4 · أثناء الرحلة والسلامة</h4>
|
||||
<ol><li>إشعار «الكابتن وصل» ومهلة 5 دقائق</li><li>المسار الأزرق والعداد</li><li>مشاركة الرحلة مع الأهل</li><li>زر SOS وهزّ الهاتف</li><li>المكالمة داخل التطبيق</li></ol></div>
|
||||
<div class="mod"><span class="shots">3 لقطات</span><h4>5 · الإلغاء</h4>
|
||||
<ol><li>مكان زر الإلغاء</li><li>اختيار السبب</li><li>التأكيد وسياسة الرسوم</li></ol>
|
||||
<p class="note">قبل قبول الكابتن: مجاني دائماً. بعد وصوله: قد تُطبَّق رسوم.</p></div>
|
||||
<div class="mod"><span class="shots">6 لقطات</span><h4>6 · الدفع والتقييم</h4>
|
||||
<ol><li>الفاتورة النهائية</li><li>قائمة طرق الدفع</li><li>تأكيد الكاش</li><li>المحفظة والشحن بمكافأة</li><li>التقييم والإكرامية</li><li>سجل الرحلات</li></ol></div>
|
||||
<div class="mod"><span class="shots">5 لقطات</span><h4>7 · مواصلاتي للطلاب</h4>
|
||||
<ol><li>اختيار الجامعة</li><li>تفعيل الرقم الجامعي</li><li>الخطوط والجداول</li><li>التتبع الحي للباص</li><li>زر «فاتك الباص؟ اطلب سيارة»</li></ol></div>
|
||||
<div class="mod"><span class="shots">التنفيذ</span><h4>خطوات الإطلاق</h4>
|
||||
<ol><li>بناء الصفحة بتبويبات RTL بنفس هوية هذا التقرير</li><li>صور Placeholder بأسماء الملفات النهائية حتى تجهز اللقطات</li><li>جلسة تصوير واحدة للـ 34 لقطة بترتيب الوحدات</li><li>لاحقاً: فيديوهات 30–60 ثانية + Coach Marks داخل التطبيق</li></ol></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="end">
|
||||
<span>أُعدّ بفحص مباشر لكود المشروع — لا تخمين ولا محتوى عام.</span>
|
||||
<span class="num">آخر تحديث 2026-07-14 · Siro Digital Legacy Report</span>
|
||||
</footer>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,253 @@
|
||||
import json
|
||||
|
||||
units = [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "التسجيل وإنشاء الحساب",
|
||||
"desc": "التسجيل يحتاج رقم هاتف فقط — لا بريد إلكتروني إجباري ولا بطاقة دفع. أقل من دقيقة من التحميل حتى أول شاشة خريطة.",
|
||||
"steps": [
|
||||
{"title": "تحميل التطبيق وفتحه", "desc": "شاشة البداية بشعار Siro", "img": "tutorial/registration/01_splash_screen.png"},
|
||||
{"title": "شاشات التعريف", "desc": "شريحة الـ Onboarding الأولى", "img": "tutorial/registration/02_onboarding.png"},
|
||||
{"title": "إدخال رقم الهاتف", "desc": "حقل الهاتف مع اختيار الدولة", "img": "tutorial/registration/03_phone_number.png"},
|
||||
{"title": "رمز التحقق OTP", "desc": "شاشة إدخال الرمز (يصل واتساب/SMS)", "img": "tutorial/registration/04_otp.png"},
|
||||
{"title": "إكمال البيانات", "desc": "الاسم + البريد (اختياري) ثم «ابدأ»", "img": "tutorial/registration/05_complete_profile.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "طلب الرحلة",
|
||||
"desc": "السعر المعروض نهائي ومحسوب من الخادم — لا مفاجآت عند الدفع (ما لم تتغير الوجهة أو يزد الانتظار).",
|
||||
"steps": [
|
||||
{"title": "الخريطة الرئيسية", "desc": "الخريطة مع السيارات القريبة تتحرك", "img": "tutorial/booking/01_map_main.png"},
|
||||
{"title": "تحديد الوجهة", "desc": "شريط البحث + النتائج", "img": "tutorial/booking/02_search_destination.png"},
|
||||
{"title": "تأكيد نقطة الانطلاق", "desc": "دبوس الانطلاق قابل للسحب", "img": "tutorial/booking/03_pickup_pin.png"},
|
||||
{"title": "اختيار فئة السيارة", "desc": "قائمة الفئات التسع مع السعر وشارة التوفير", "img": "tutorial/booking/04_select_car_type.png"},
|
||||
{"title": "كود الخصم", "desc": "حقل البرومو مطبّق على السعر", "img": "tutorial/booking/05_promo_code.png"},
|
||||
{"title": "تأكيد الطلب", "desc": "زر «اطلب الآن» مع السعر النهائي", "img": "tutorial/booking/06_confirm_order.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "الانتظار والمطابقة",
|
||||
"desc": "متوسط زمن المطابقة أقل من 90 ثانية. إذا لم يقبل أحد، النظام يقترح تعديلاً بسيطاً على السعر بدل إلغاء طلبك.",
|
||||
"steps": [
|
||||
{"title": "البحث عن كابتن", "desc": "نافذة البحث مع المؤقّت", "img": "tutorial/matching/01_searching_captain.png"},
|
||||
{"title": "اقتراح المفاوض الذكي", "desc": "حوار رفع السعر بعد 90 ثانية", "img": "tutorial/matching/02_smart_negotiator.png"},
|
||||
{"title": "قبول الكابتن", "desc": "بطاقة الكابتن: الاسم، الصورة، التقييم، اللوحة", "img": "tutorial/matching/03_captain_card.png"},
|
||||
{"title": "الكابتن في الطريق", "desc": "الخريطة مع المسار الأصفر والوقت المتوقع", "img": "tutorial/matching/04_captain_on_way.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "أثناء الرحلة والسلامة",
|
||||
"desc": "تتبع حي للرحلة مع خيارات أمان متقدمة واتصال آمن بالكابتن.",
|
||||
"steps": [
|
||||
{"title": "وصول الكابتن", "desc": "إشعار «الكابتن وصل» ومهلة انتظار 5 دقائق", "img": "tutorial/ride/01_captain_arrived.png"},
|
||||
{"title": "بدء الرحلة", "desc": "المسار الأزرق + العداد الحي", "img": "tutorial/ride/02_ride_started.png"},
|
||||
{"title": "مشاركة الرحلة", "desc": "رابط متابعة لطرف ثالث (للأهل)", "img": "tutorial/ride/03_share_ride.png"},
|
||||
{"title": "زر الطوارئ SOS", "desc": "زر الطوارئ (وهزّ الهاتف 5 مرات)", "img": "tutorial/ride/04_sos_button.png"},
|
||||
{"title": "الاتصال بالكابتن", "desc": "شاشة المكالمة داخل التطبيق", "img": "tutorial/ride/05_in_app_call.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "الإلغاء",
|
||||
"desc": "الإلغاء قبل القبول مجاني، وبعد الوصول قد تُطبّق رسوم. السائق يواجه إيقافاً بعد 3 إلغاءات.",
|
||||
"steps": [
|
||||
{"title": "زر الإلغاء", "desc": "مكان الزر أثناء البحث/الانتظار", "img": "tutorial/cancel/01_cancel_button.png"},
|
||||
{"title": "اختيار السبب", "desc": "قائمة أسباب الإلغاء", "img": "tutorial/cancel/02_cancel_reason.png"},
|
||||
{"title": "تأكيد الإلغاء", "desc": "رسالة التأكيد + سياسة الرسوم", "img": "tutorial/cancel/03_cancel_confirm.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "الدفع والتقييم",
|
||||
"desc": "دفع مرن مع نقاط مكافأة للمحفظة، وتقييم يعزز جودة الخدمة.",
|
||||
"steps": [
|
||||
{"title": "نهاية الرحلة", "desc": "شاشة الفاتورة النهائية", "img": "tutorial/payment/01_ride_finished.png"},
|
||||
{"title": "طرق الدفع", "desc": "كاش/محفظة/بطاقة ووسائل الدفع المحلية", "img": "tutorial/payment/02_payment_methods.png"},
|
||||
{"title": "الدفع كاش", "desc": "حوار تأكيد الكاش", "img": "tutorial/payment/03_cash_confirm.png"},
|
||||
{"title": "الدفع بالمحفظة", "desc": "الخصم من الرصيد وعروض الشحن", "img": "tutorial/payment/04_wallet_pay.png"},
|
||||
{"title": "تقييم الكابتن", "desc": "النجوم + الإكرامية", "img": "tutorial/payment/05_rate_captain.png"},
|
||||
{"title": "سجل الرحلات", "desc": "قائمة الرحلات السابقة والفواتير", "img": "tutorial/payment/06_ride_history.png"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"title": "مواصلاتي — للطلاب",
|
||||
"desc": "خدمة تتبع باصات الجامعات مجاناً مع إمكانية تحويل الطالب لرحلة مدفوعة إذا فاته الباص.",
|
||||
"steps": [
|
||||
{"title": "اختيار الجامعة", "desc": "تبويب مواصلاتي واختيار الجامعة", "img": "tutorial/transit/01_select_university.png"},
|
||||
{"title": "تفعيل العضوية", "desc": "إدخال الرقم الجامعي للتفعيل الفوري", "img": "tutorial/transit/02_activate_student_id.png"},
|
||||
{"title": "استعراض الخطوط", "desc": "قائمة الخطوط المعتمدة وجداولها", "img": "tutorial/transit/03_transit_lines.png"},
|
||||
{"title": "التتبع الحي", "desc": "الباص يتحرك على المسار والمحطات", "img": "tutorial/transit/04_live_tracking.png"},
|
||||
{"title": "فاتك الباص؟", "desc": "الزر البارز لطلب سيارة بديلة", "img": "tutorial/transit/05_missed_bus.png"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
html_template = """<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>كيف تستخدم سيرو — التوتوريال الشامل</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
|
||||
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
|
||||
--line:#E1E5E1; --line2:#D2D8D3;
|
||||
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
|
||||
--amber:#9A6B12; --amber-soft:#F6EDDA;
|
||||
--red:#B3362B; --red-soft:#F7E5E2;
|
||||
--good:#2E7D4F; --good-soft:#E4F1E8;
|
||||
--sans:"SF Arabic","Segoe UI",system-ui,-apple-system,"Noto Sans Arabic",Tahoma,sans-serif;
|
||||
--mono:ui-monospace,"SF Mono",Consolas,monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root{
|
||||
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
|
||||
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
|
||||
--line:#26302B; --line2:#32403A;
|
||||
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
|
||||
--amber:#E0AE55; --amber-soft:#33290F;
|
||||
--red:#E07065; --red-soft:#361A16;
|
||||
--good:#57C287; --good-soft:#14301F;
|
||||
}
|
||||
}
|
||||
body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 16px; line-height: 1.85; }
|
||||
* { box-sizing: border-box; }
|
||||
.wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px; }
|
||||
h1, h2, h3, h4 { margin: 0; color: var(--ink); line-height: 1.35; text-wrap: balance; }
|
||||
p { margin: 0; }
|
||||
.hero { padding: 64px 0 36px; border-bottom: 1px solid var(--line); }
|
||||
.hero .kicker {
|
||||
display: inline-block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
|
||||
color: var(--brand-ink); background: var(--brand-soft); border-radius: 99px; padding: 4px 14px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.hero h1 { font-size: clamp(1.7rem, 4.5vw, 2.5rem); font-weight: 800; }
|
||||
.hero .lede { margin-top: 14px; font-size: 1.05rem; color: var(--muted); max-width: 60ch; }
|
||||
.hero .meta { margin-top: 16px; font-size: 0.8rem; color: var(--faint); }
|
||||
|
||||
.tabs {
|
||||
display: flex; gap: 8px; overflow-x: auto; padding: 20px 0 10px;
|
||||
margin-top: 10px; scrollbar-width: none;
|
||||
}
|
||||
.tabs::-webkit-scrollbar { display: none; }
|
||||
.tab-btn {
|
||||
background: var(--surface); border: 1px solid var(--line); color: var(--muted);
|
||||
font-family: var(--sans); font-size: 0.95rem; font-weight: 700; padding: 10px 20px;
|
||||
border-radius: 99px; cursor: pointer; white-space: nowrap; transition: all 0.2s;
|
||||
}
|
||||
.tab-btn:hover { border-color: var(--brand); color: var(--ink); }
|
||||
.tab-btn.active { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand-ink); font-weight: 800; }
|
||||
|
||||
.tab-content { display: none; animation: fadeIn 0.3s ease; padding: 30px 0 80px; }
|
||||
.tab-content.active { display: block; }
|
||||
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
.sec-head { margin-bottom: 40px; text-align: center; }
|
||||
.sec-head h2 { font-size: 1.8rem; font-weight: 800; margin-bottom: 12px; }
|
||||
.sec-head .thesis { color: var(--muted); font-size: 1.1rem; max-width: 66ch; margin: 0 auto; }
|
||||
|
||||
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; margin-top: 20px; }
|
||||
.step-card {
|
||||
display: flex; flex-direction: column; gap: 20px; align-items: center;
|
||||
background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 30px 20px;
|
||||
}
|
||||
.step-info { text-align: center; }
|
||||
.step-num {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 32px; height: 32px; background: var(--brand); color: #fff;
|
||||
border-radius: 50%; font-size: 1rem; font-weight: 800; margin-bottom: 12px; font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.step-info h4 { font-size: 1.1rem; font-weight: 800; margin-bottom: 6px; }
|
||||
.step-info p { font-size: 0.9rem; color: var(--muted); }
|
||||
|
||||
.phone-frame {
|
||||
width: 260px; height: 540px; border: 12px solid #1a1a1a; border-radius: 36px;
|
||||
overflow: hidden; position: relative; box-shadow: 0 10px 25px rgba(0,0,0,0.05); background: #f1f3f2;
|
||||
}
|
||||
.phone-notch {
|
||||
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
|
||||
width: 110px; height: 26px; background: #1a1a1a;
|
||||
border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; z-index: 2;
|
||||
}
|
||||
.phone-screen {
|
||||
width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
|
||||
text-align: center; padding: 20px; color: var(--faint); font-family: var(--mono);
|
||||
font-size: 0.75rem; word-break: break-all; background-color: var(--surface2);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="hero"><div class="wrap">
|
||||
<span class="kicker">خطة التوتوريال — 34 لقطة</span>
|
||||
<h1>كيف تستخدم سيرو</h1>
|
||||
<p class="lede">صفحات شرح تفاعلية تشرح للمستخدم الجديد كل عملية خطوة بخطوة، مدعومة بلقطات شاشة حقيقية من التطبيق.</p>
|
||||
<p class="meta">تم بناء هذه الصفحة حسب التقرير الشامل — في انتظار إدراج اللقطات النهائية</p>
|
||||
</div></header>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="tabs">
|
||||
{tabs_html}
|
||||
</div>
|
||||
|
||||
<div class="tab-contents">
|
||||
{contents_html}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showTab(id) {
|
||||
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||||
document.getElementById('btn-' + id).classList.add('active');
|
||||
document.getElementById('tab-' + id).classList.add('active');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
tabs_html = ""
|
||||
contents_html = ""
|
||||
|
||||
for unit in units:
|
||||
active_class = " active" if unit["id"] == 1 else ""
|
||||
tabs_html += f'<button id="btn-{unit["id"]}" class="tab-btn{active_class}" onclick="showTab({unit["id"]})">{unit["id"]}. {unit["title"]}</button>\n '
|
||||
|
||||
steps_html = ""
|
||||
for i, step in enumerate(unit["steps"]):
|
||||
steps_html += f"""
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">{i+1}</span>
|
||||
<h4>{step['title']}</h4>
|
||||
<p>{step['desc']}</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">{step['img']}</div>
|
||||
</div>
|
||||
</div>"""
|
||||
|
||||
contents_html += f"""
|
||||
<div id="tab-{unit['id']}" class="tab-content{active_class}">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة {unit['id']}: {unit['title']}</h2>
|
||||
<p class="thesis">{unit['desc']}</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
{steps_html}
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
final_html = html_template.replace('{tabs_html}', tabs_html).replace('{contents_html}', contents_html)
|
||||
|
||||
with open("/Users/hamzaaleghwairyeen/development/App/Siro/siromove.com/tutorial/index.html", "w", encoding="utf-8") as f:
|
||||
f.write(final_html)
|
||||
|
||||
print("Generated HTML successfully.")
|
||||
@@ -0,0 +1,574 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>كيف تستخدم سيرو — التوتوريال الشامل</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#F6F7F5; --surface:#FFFFFF; --surface2:#EEF1EE;
|
||||
--ink:#1A241F; --muted:#5B6862; --faint:#8B968F;
|
||||
--line:#E1E5E1; --line2:#D2D8D3;
|
||||
--brand:#0E7A5F; --brand-ink:#0A5945; --brand-soft:#E4F0EB;
|
||||
--amber:#9A6B12; --amber-soft:#F6EDDA;
|
||||
--red:#B3362B; --red-soft:#F7E5E2;
|
||||
--good:#2E7D4F; --good-soft:#E4F1E8;
|
||||
--sans:"SF Arabic","Segoe UI",system-ui,-apple-system,"Noto Sans Arabic",Tahoma,sans-serif;
|
||||
--mono:ui-monospace,"SF Mono",Consolas,monospace;
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root{
|
||||
--bg:#0F1512; --surface:#161E19; --surface2:#1C2620;
|
||||
--ink:#E8EDEA; --muted:#9BA8A1; --faint:#6E7B74;
|
||||
--line:#26302B; --line2:#32403A;
|
||||
--brand:#3FBF97; --brand-ink:#8FE0C5; --brand-soft:#15342A;
|
||||
--amber:#E0AE55; --amber-soft:#33290F;
|
||||
--red:#E07065; --red-soft:#361A16;
|
||||
--good:#57C287; --good-soft:#14301F;
|
||||
}
|
||||
}
|
||||
body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 16px; line-height: 1.85; }
|
||||
* { box-sizing: border-box; }
|
||||
.wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px; }
|
||||
h1, h2, h3, h4 { margin: 0; color: var(--ink); line-height: 1.35; text-wrap: balance; }
|
||||
p { margin: 0; }
|
||||
.hero { padding: 64px 0 36px; border-bottom: 1px solid var(--line); }
|
||||
.hero .kicker {
|
||||
display: inline-block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
|
||||
color: var(--brand-ink); background: var(--brand-soft); border-radius: 99px; padding: 4px 14px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.hero h1 { font-size: clamp(1.7rem, 4.5vw, 2.5rem); font-weight: 800; }
|
||||
.hero .lede { margin-top: 14px; font-size: 1.05rem; color: var(--muted); max-width: 60ch; }
|
||||
.hero .meta { margin-top: 16px; font-size: 0.8rem; color: var(--faint); }
|
||||
|
||||
.tabs {
|
||||
display: flex; gap: 8px; overflow-x: auto; padding: 20px 0 10px;
|
||||
margin-top: 10px; scrollbar-width: none;
|
||||
}
|
||||
.tabs::-webkit-scrollbar { display: none; }
|
||||
.tab-btn {
|
||||
background: var(--surface); border: 1px solid var(--line); color: var(--muted);
|
||||
font-family: var(--sans); font-size: 0.95rem; font-weight: 700; padding: 10px 20px;
|
||||
border-radius: 99px; cursor: pointer; white-space: nowrap; transition: all 0.2s;
|
||||
}
|
||||
.tab-btn:hover { border-color: var(--brand); color: var(--ink); }
|
||||
.tab-btn.active { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand-ink); font-weight: 800; }
|
||||
|
||||
.tab-content { display: none; animation: fadeIn 0.3s ease; padding: 30px 0 80px; }
|
||||
.tab-content.active { display: block; }
|
||||
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
.sec-head { margin-bottom: 40px; text-align: center; }
|
||||
.sec-head h2 { font-size: 1.8rem; font-weight: 800; margin-bottom: 12px; }
|
||||
.sec-head .thesis { color: var(--muted); font-size: 1.1rem; max-width: 66ch; margin: 0 auto; }
|
||||
|
||||
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; margin-top: 20px; }
|
||||
.step-card {
|
||||
display: flex; flex-direction: column; gap: 20px; align-items: center;
|
||||
background: var(--surface); border: 1px solid var(--line); border-radius: 24px; padding: 30px 20px;
|
||||
}
|
||||
.step-info { text-align: center; }
|
||||
.step-num {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 32px; height: 32px; background: var(--brand); color: #fff;
|
||||
border-radius: 50%; font-size: 1rem; font-weight: 800; margin-bottom: 12px; font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.step-info h4 { font-size: 1.1rem; font-weight: 800; margin-bottom: 6px; }
|
||||
.step-info p { font-size: 0.9rem; color: var(--muted); }
|
||||
|
||||
.phone-frame {
|
||||
width: 260px; height: 540px; border: 12px solid #1a1a1a; border-radius: 36px;
|
||||
overflow: hidden; position: relative; box-shadow: 0 10px 25px rgba(0,0,0,0.05); background: #f1f3f2;
|
||||
}
|
||||
.phone-notch {
|
||||
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
|
||||
width: 110px; height: 26px; background: #1a1a1a;
|
||||
border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; z-index: 2;
|
||||
}
|
||||
.phone-screen {
|
||||
width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
|
||||
text-align: center; padding: 20px; color: var(--faint); font-family: var(--mono);
|
||||
font-size: 0.75rem; word-break: break-all; background-color: var(--surface2);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="hero"><div class="wrap">
|
||||
<span class="kicker">خطة التوتوريال — 34 لقطة</span>
|
||||
<h1>كيف تستخدم سيرو</h1>
|
||||
<p class="lede">صفحات شرح تفاعلية تشرح للمستخدم الجديد كل عملية خطوة بخطوة، مدعومة بلقطات شاشة حقيقية من التطبيق.</p>
|
||||
<p class="meta">تم بناء هذه الصفحة حسب التقرير الشامل — في انتظار إدراج اللقطات النهائية</p>
|
||||
</div></header>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="tabs">
|
||||
<button id="btn-1" class="tab-btn active" onclick="showTab(1)">1. التسجيل وإنشاء الحساب</button>
|
||||
<button id="btn-2" class="tab-btn" onclick="showTab(2)">2. طلب الرحلة</button>
|
||||
<button id="btn-3" class="tab-btn" onclick="showTab(3)">3. الانتظار والمطابقة</button>
|
||||
<button id="btn-4" class="tab-btn" onclick="showTab(4)">4. أثناء الرحلة والسلامة</button>
|
||||
<button id="btn-5" class="tab-btn" onclick="showTab(5)">5. الإلغاء</button>
|
||||
<button id="btn-6" class="tab-btn" onclick="showTab(6)">6. الدفع والتقييم</button>
|
||||
<button id="btn-7" class="tab-btn" onclick="showTab(7)">7. مواصلاتي — للطلاب</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-contents">
|
||||
|
||||
<div id="tab-1" class="tab-content active">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 1: التسجيل وإنشاء الحساب</h2>
|
||||
<p class="thesis">التسجيل يحتاج رقم هاتف فقط — لا بريد إلكتروني إجباري ولا بطاقة دفع. أقل من دقيقة من التحميل حتى أول شاشة خريطة.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>تحميل التطبيق وفتحه</h4>
|
||||
<p>شاشة البداية بشعار Siro</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/registration/01_splash_screen.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>شاشات التعريف</h4>
|
||||
<p>شريحة الـ Onboarding الأولى</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/registration/02_onboarding.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>إدخال رقم الهاتف</h4>
|
||||
<p>حقل الهاتف مع اختيار الدولة</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/registration/03_phone_number.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>رمز التحقق OTP</h4>
|
||||
<p>شاشة إدخال الرمز (يصل واتساب/SMS)</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/registration/04_otp.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">5</span>
|
||||
<h4>إكمال البيانات</h4>
|
||||
<p>الاسم + البريد (اختياري) ثم «ابدأ»</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/registration/05_complete_profile.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-2" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 2: طلب الرحلة</h2>
|
||||
<p class="thesis">السعر المعروض نهائي ومحسوب من الخادم — لا مفاجآت عند الدفع (ما لم تتغير الوجهة أو يزد الانتظار).</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>الخريطة الرئيسية</h4>
|
||||
<p>الخريطة مع السيارات القريبة تتحرك</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/01_map_main.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>تحديد الوجهة</h4>
|
||||
<p>شريط البحث + النتائج</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/02_search_destination.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>تأكيد نقطة الانطلاق</h4>
|
||||
<p>دبوس الانطلاق قابل للسحب</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/03_pickup_pin.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>اختيار فئة السيارة</h4>
|
||||
<p>قائمة الفئات التسع مع السعر وشارة التوفير</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/04_select_car_type.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">5</span>
|
||||
<h4>كود الخصم</h4>
|
||||
<p>حقل البرومو مطبّق على السعر</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/05_promo_code.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">6</span>
|
||||
<h4>تأكيد الطلب</h4>
|
||||
<p>زر «اطلب الآن» مع السعر النهائي</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/booking/06_confirm_order.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-3" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 3: الانتظار والمطابقة</h2>
|
||||
<p class="thesis">متوسط زمن المطابقة أقل من 90 ثانية. إذا لم يقبل أحد، النظام يقترح تعديلاً بسيطاً على السعر بدل إلغاء طلبك.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>البحث عن كابتن</h4>
|
||||
<p>نافذة البحث مع المؤقّت</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/matching/01_searching_captain.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>اقتراح المفاوض الذكي</h4>
|
||||
<p>حوار رفع السعر بعد 90 ثانية</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/matching/02_smart_negotiator.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>قبول الكابتن</h4>
|
||||
<p>بطاقة الكابتن: الاسم، الصورة، التقييم، اللوحة</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/matching/03_captain_card.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>الكابتن في الطريق</h4>
|
||||
<p>الخريطة مع المسار الأصفر والوقت المتوقع</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/matching/04_captain_on_way.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-4" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 4: أثناء الرحلة والسلامة</h2>
|
||||
<p class="thesis">تتبع حي للرحلة مع خيارات أمان متقدمة واتصال آمن بالكابتن.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>وصول الكابتن</h4>
|
||||
<p>إشعار «الكابتن وصل» ومهلة انتظار 5 دقائق</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/ride/01_captain_arrived.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>بدء الرحلة</h4>
|
||||
<p>المسار الأزرق + العداد الحي</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/ride/02_ride_started.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>مشاركة الرحلة</h4>
|
||||
<p>رابط متابعة لطرف ثالث (للأهل)</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/ride/03_share_ride.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>زر الطوارئ SOS</h4>
|
||||
<p>زر الطوارئ (وهزّ الهاتف 5 مرات)</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/ride/04_sos_button.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">5</span>
|
||||
<h4>الاتصال بالكابتن</h4>
|
||||
<p>شاشة المكالمة داخل التطبيق</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/ride/05_in_app_call.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-5" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 5: الإلغاء</h2>
|
||||
<p class="thesis">الإلغاء قبل القبول مجاني، وبعد الوصول قد تُطبّق رسوم. السائق يواجه إيقافاً بعد 3 إلغاءات.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>زر الإلغاء</h4>
|
||||
<p>مكان الزر أثناء البحث/الانتظار</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/cancel/01_cancel_button.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>اختيار السبب</h4>
|
||||
<p>قائمة أسباب الإلغاء</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/cancel/02_cancel_reason.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>تأكيد الإلغاء</h4>
|
||||
<p>رسالة التأكيد + سياسة الرسوم</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/cancel/03_cancel_confirm.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-6" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 6: الدفع والتقييم</h2>
|
||||
<p class="thesis">دفع مرن مع نقاط مكافأة للمحفظة، وتقييم يعزز جودة الخدمة.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>نهاية الرحلة</h4>
|
||||
<p>شاشة الفاتورة النهائية</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/01_ride_finished.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>طرق الدفع</h4>
|
||||
<p>كاش/محفظة/بطاقة ووسائل الدفع المحلية</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/02_payment_methods.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>الدفع كاش</h4>
|
||||
<p>حوار تأكيد الكاش</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/03_cash_confirm.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>الدفع بالمحفظة</h4>
|
||||
<p>الخصم من الرصيد وعروض الشحن</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/04_wallet_pay.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">5</span>
|
||||
<h4>تقييم الكابتن</h4>
|
||||
<p>النجوم + الإكرامية</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/05_rate_captain.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">6</span>
|
||||
<h4>سجل الرحلات</h4>
|
||||
<p>قائمة الرحلات السابقة والفواتير</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/payment/06_ride_history.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-7" class="tab-content">
|
||||
<div class="sec-head">
|
||||
<h2>الوحدة 7: مواصلاتي — للطلاب</h2>
|
||||
<p class="thesis">خدمة تتبع باصات الجامعات مجاناً مع إمكانية تحويل الطالب لرحلة مدفوعة إذا فاته الباص.</p>
|
||||
</div>
|
||||
<div class="steps-grid">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">1</span>
|
||||
<h4>اختيار الجامعة</h4>
|
||||
<p>تبويب مواصلاتي واختيار الجامعة</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/transit/01_select_university.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">2</span>
|
||||
<h4>تفعيل العضوية</h4>
|
||||
<p>إدخال الرقم الجامعي للتفعيل الفوري</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/transit/02_activate_student_id.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">3</span>
|
||||
<h4>استعراض الخطوط</h4>
|
||||
<p>قائمة الخطوط المعتمدة وجداولها</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/transit/03_transit_lines.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">4</span>
|
||||
<h4>التتبع الحي</h4>
|
||||
<p>الباص يتحرك على المسار والمحطات</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/transit/04_live_tracking.png</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-card">
|
||||
<div class="step-info">
|
||||
<span class="step-num">5</span>
|
||||
<h4>فاتك الباص؟</h4>
|
||||
<p>الزر البارز لطلب سيارة بديلة</p>
|
||||
</div>
|
||||
<div class="phone-frame">
|
||||
<div class="phone-notch"></div>
|
||||
<div class="phone-screen">tutorial/transit/05_missed_bus.png</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showTab(id) {
|
||||
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||||
document.getElementById('btn-' + id).classList.add('active');
|
||||
document.getElementById('tab-' + id).classList.add('active');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user