chore: استيراد أولي من سيرو (ecfe7568) — بلا أي تعديل
نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق». نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا `cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules · .dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore. هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ. ⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
$type = isset($_POST['type']) ? filterRequest("type") : 'trips';
|
||||
|
||||
try {
|
||||
global $redis;
|
||||
$redisKey = "gamification_leaderboard:{$type}";
|
||||
|
||||
// 1. Try to read from Redis first
|
||||
if (isset($redis)) {
|
||||
try {
|
||||
$cached = $redis->get($redisKey);
|
||||
if ($cached) {
|
||||
$data = json_decode($cached, true);
|
||||
if ($data !== null) {
|
||||
jsonSuccess($data);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Redis read error in getLeaderboard: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fallback to Database
|
||||
if ($type === 'earnings') {
|
||||
$sql = "
|
||||
SELECT
|
||||
d.id as driver_id,
|
||||
COALESCE(d.name, d.nameArabic, d.firstName, 'Driver') as name,
|
||||
d.personal_photo as photoUrl,
|
||||
COALESCE(SUM(r.price_for_driver), 0) as value
|
||||
FROM `driver` d
|
||||
JOIN `ride` r ON d.id = r.driver_id
|
||||
WHERE r.status = 'Finished'
|
||||
AND r.created_at >= DATE(NOW() - INTERVAL WEEKDAY(NOW()) DAY)
|
||||
GROUP BY d.id
|
||||
ORDER BY value DESC
|
||||
LIMIT 10
|
||||
";
|
||||
} else {
|
||||
// Default to trips
|
||||
$sql = "
|
||||
SELECT
|
||||
d.id as driver_id,
|
||||
COALESCE(d.name, d.nameArabic, d.firstName, 'Driver') as name,
|
||||
d.personal_photo as photoUrl,
|
||||
COUNT(r.id) as value
|
||||
FROM `driver` d
|
||||
JOIN `ride` r ON d.id = r.driver_id
|
||||
WHERE r.status = 'Finished'
|
||||
AND r.created_at >= DATE(NOW() - INTERVAL WEEKDAY(NOW()) DAY)
|
||||
GROUP BY d.id
|
||||
ORDER BY value DESC
|
||||
LIMIT 10
|
||||
";
|
||||
}
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->execute();
|
||||
} catch (PDOException $e) {
|
||||
error_log("getLeaderboard Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred");
|
||||
}
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Add Rank manually to support older MySQL versions
|
||||
$rank = 1;
|
||||
foreach ($rows as &$row) {
|
||||
$row['rank'] = $rank++;
|
||||
}
|
||||
|
||||
$responseData = $rows;
|
||||
} else {
|
||||
$responseData = [];
|
||||
}
|
||||
|
||||
// 3. Save the DB result into Redis for future reads
|
||||
if (isset($redis)) {
|
||||
try {
|
||||
// Cache leaderboard for 1 hour (3600 seconds)
|
||||
$redis->setex($redisKey, 3600, json_encode($responseData));
|
||||
} catch (Exception $e) {
|
||||
error_log("Redis write error in getLeaderboard: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
jsonSuccess($responseData);
|
||||
?>
|
||||
Reference in New Issue
Block a user