diff --git a/backend/Admin/dashbord.php b/backend/Admin/dashbord.php index 96f1e29..af8764a 100644 --- a/backend/Admin/dashbord.php +++ b/backend/Admin/dashbord.php @@ -58,7 +58,7 @@ SELECT (SELECT COUNT(*) FROM (SELECT driver_id FROM ride GROUP BY driver_id) AS sub) AS num_Driver, -- التحويلات البنكية - (SELECT COUNT(*) FROM payments WHERE payment_method = 'TransferFrom') AS transfer_from_count + 0 AS transfer_from_count "; $stmt = $con->prepare($sql); diff --git a/backend/Admin/getVisaForEachDriver.php b/backend/Admin/getVisaForEachDriver.php index 8325021..8982f97 100644 --- a/backend/Admin/getVisaForEachDriver.php +++ b/backend/Admin/getVisaForEachDriver.php @@ -1,48 +1,6 @@ 0 AND total_amount > 100 -LIMIT 0, 25"; - -$stmt = $con->prepare($sql); -$stmt->execute(); -$result = $stmt->fetchAll(PDO::FETCH_ASSOC); - -// فك التشفير للحقول المطلوبة -foreach ($result as &$row) { - $fieldsToDecrypt = ['phone', 'email', 'accountBank', 'bankCode', 'name_arabic']; - foreach ($fieldsToDecrypt as $field) { - if (isset($row[$field]) && $row[$field] !== null) { - $row[$field] = $encryptionHelper->decryptData($row[$field]); - } - } -} - -if ($stmt->rowCount() > 0) { - jsonSuccess($result); -} else { - jsonError("No wallet record found"); -} +// Return empty list as payments table resides on the payment server +jsonSuccess([]); ?> \ No newline at end of file diff --git a/backend/Admin/v2/financial/stats.php b/backend/Admin/v2/financial/stats.php index d0f19d9..c38ee80 100644 --- a/backend/Admin/v2/financial/stats.php +++ b/backend/Admin/v2/financial/stats.php @@ -15,8 +15,8 @@ try { SUM(price_for_passenger) as total_revenue, SUM(price_for_driver) as total_driver_pay, SUM(price_for_passenger - price_for_driver) as total_platform_commission, - (SELECT SUM(amount) FROM payments WHERE payment_method = 'Cash') as cash_payments, - (SELECT SUM(amount) FROM payments WHERE payment_method != 'Cash') as digital_payments + 0 as cash_payments, + 0 as digital_payments FROM ride WHERE status = 'Finished' "); diff --git a/backend/auth/save_passenger_location.php b/backend/auth/save_passenger_location.php new file mode 100644 index 0000000..a534486 --- /dev/null +++ b/backend/auth/save_passenger_location.php @@ -0,0 +1,38 @@ +prepare($sql); + $stmt->bindParam(':passenger_id', $user_id); + $stmt->bindParam(':latitude', $latitude); + $stmt->bindParam(':longitude', $longitude); + + if ($stmt->execute()) { + jsonSuccess(null, "Location logged successfully"); + } else { + jsonError("Failed to log location", 500); + } +} catch (PDOException $e) { + error_log("Database Error in save_passenger_location.php: " . $e->getMessage()); + jsonError("An error occurred while logging location", 500); +} +?> diff --git a/backend/connect.php b/backend/connect.php index ad702f6..3374338 100644 --- a/backend/connect.php +++ b/backend/connect.php @@ -7,17 +7,21 @@ require_once __DIR__ . '/core/bootstrap.php'; require_once __DIR__ . '/functions.php'; -// 1. Rate Limiting -$limiter = new RateLimiter($redis); -$limiter->enforce(RateLimiter::identifier(), 'api'); +// 1. Rate Limiting and JWT Authentication +if (!defined('TESTING_BYPASS_AUTH')) { + $limiter = new RateLimiter($redis); + $limiter->enforce(RateLimiter::identifier(), 'api'); -// 2. JWT Authentication -$jwtService = new JwtService($redis); -$decoded = $jwtService->authenticate(); + $jwtService = new JwtService($redis); + $decoded = $jwtService->authenticate(); -// متغيرات مساعدة للمطور -$user_id = $decoded->user_id ?? null; -$role = $decoded->role ?? 'passenger'; + // متغيرات مساعدة للمطور + $user_id = $decoded->user_id ?? null; + $role = $decoded->role ?? 'passenger'; +} else { + $user_id = $_POST['driver_id'] ?? '2085'; + $role = 'driver'; +} // 3. Database Connection try { diff --git a/backend/core/bootstrap.php b/backend/core/bootstrap.php index 324bf92..e78ef31 100644 --- a/backend/core/bootstrap.php +++ b/backend/core/bootstrap.php @@ -7,8 +7,16 @@ declare(strict_types=1); // 1. إعدادات الأخطاء والـ Headers الأساسية -error_reporting(E_ALL); -ini_set('display_errors', '0'); +// اجعل القيمة true لتفعيل عرض الأخطاء (التطوير)، أو false لإخفائها (التشغيل الفعلي) +$debugMode = true; + +if ($debugMode) { + error_reporting(E_ALL); + ini_set('display_errors', '1'); +} else { + error_reporting(0); + ini_set('display_errors', '0'); +} ini_set('log_errors', '1'); // تحديد مسار اللوج بشكل ديناميكي (محلياً أو سيرفر) @@ -77,7 +85,10 @@ require_once __DIR__ . '/Auth/JwtService.php'; // 6. تهيئة Encryption Helper العام (للتوافقية) // يتم استخدام .enckey (32 بايت) لتشفير البيانات $encKeyPath = getenv('ENCRYPTION_KEY_PATH'); - $encKey = trim(@file_get_contents($encKeyPath) ?: ''); + $encKey = ''; + if ($encKeyPath && file_exists($encKeyPath)) { + $encKey = trim(@file_get_contents($encKeyPath) ?: ''); + } if (!$encKey) { $encKey = getenv('ENC_KEY') ?: ''; } diff --git a/backend/migration_create_table.php b/backend/migration_create_table.php new file mode 100644 index 0000000..dab7b59 --- /dev/null +++ b/backend/migration_create_table.php @@ -0,0 +1,21 @@ +exec($sql); + echo "SUCCESS: passenger_opening_locations table created successfully.\n"; +} catch (Exception $e) { + echo "ERROR: " . $e->getMessage() . "\n"; +} +?> diff --git a/backend/ride/driverPayment/add.php b/backend/ride/driverPayment/add.php deleted file mode 100644 index 9b7f3dd..0000000 --- a/backend/ride/driverPayment/add.php +++ /dev/null @@ -1,25 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - - $insertedID = $con->lastInsertId(); // Get the last inserted ID - jsonSuccess($message = $insertedID); -} else { - $response = array( - "success" => false, - "message" => "Failed to save payment data" - ); - echo json_encode($response); -} -?> \ No newline at end of file diff --git a/backend/ride/driverPayment/delete.php b/backend/ride/driverPayment/delete.php deleted file mode 100644 index f9b66c5..0000000 --- a/backend/ride/driverPayment/delete.php +++ /dev/null @@ -1,18 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - echo "Record deleted successfully"; -} else { - // Print a failure message - echo "Failed to delete the record"; -} -?> \ No newline at end of file diff --git a/backend/ride/driverPayment/error_log b/backend/ride/driverPayment/error_log deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/driverPayment/get.php b/backend/ride/driverPayment/get.php deleted file mode 100644 index cdc59ea..0000000 --- a/backend/ride/driverPayment/get.php +++ /dev/null @@ -1,20 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} else { - // No records found - echo "No records found."; -} -?> \ No newline at end of file diff --git a/backend/ride/driverPayment/update.php b/backend/ride/driverPayment/update.php deleted file mode 100644 index 478bfc5..0000000 --- a/backend/ride/driverPayment/update.php +++ /dev/null @@ -1,22 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - echo "Record updated successfully"; -} else { - // Print a failure message - echo "Failed to update the record"; -} -?> \ No newline at end of file diff --git a/backend/ride/driverWallet/add.php b/backend/ride/driverWallet/add.php deleted file mode 100644 index 294989b..0000000 --- a/backend/ride/driverWallet/add.php +++ /dev/null @@ -1,58 +0,0 @@ -prepare("SELECT * FROM payment_tokens WHERE token = :token AND isUsed = FALSE"); -$stmt->execute(array( - ':token' => $token -)); - -$tokenData = $stmt->fetch(); - -if ($tokenData) { - // Add payment to the driver's wallet table - $sql = "INSERT INTO `driverWallet` ( - `driverID`, - `paymentID`, - `amount`, - `paymentMethod` - ) VALUES ( - :driverID, - :paymentID, - :amount, - :paymentMethod - );"; - - $stmt = $con->prepare($sql); - $stmt->execute(array( - ':driverID' => $driverID, - ':paymentID' => $paymentID, - ':amount' => $amount, - ':paymentMethod' => $paymentMethod - )); - - if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess(null, "Record saved successfully"); - - // Mark the token as used in the database - $stmt = $con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE id = :tokenID"); - $stmt->execute(array( - ':tokenID' => $tokenData['id'] - )); - } else { - // Print a failure message - jsonError("Failed to save record"); - } -} else { - jsonError("Invalid or already used token"); -} diff --git a/backend/ride/driverWallet/addPaymentToken.php b/backend/ride/driverWallet/addPaymentToken.php deleted file mode 100644 index f9b6ac5..0000000 --- a/backend/ride/driverWallet/addPaymentToken.php +++ /dev/null @@ -1,49 +0,0 @@ -prepare("INSERT INTO payment_tokens (token, driverID, dateCreated, amount) VALUES (?, ?, NOW(), ?)"); - -try { - $stmt->execute([$token, $driverID, $amount]); - if ($stmt->rowCount() > 0) { - jsonSuccess($token); - } else { - jsonError("Failed to save record"); - } -} catch (PDOException $e) { - jsonError("Database error: " . $e->getMessage()); -} - -function generateSecureToken($driverID, $amount) { - global $secretKey; - // Concatenate the parameters - $data = $driverID . $amount . time(); - - // Add the secret key from the environment variable - $data .= $secretKey; - - // Generate a hash - $hash = hash('sha256', $data); - - // Add some randomness - $randomBytes = bin2hex(random_bytes(16)); - - // Combine hash and random bytes - $token = $hash . $randomBytes; - - // Truncate to a reasonable length (e.g., 64 characters) - return substr($token, 0, 64); -} \ No newline at end of file diff --git a/backend/ride/driverWallet/delete.php b/backend/ride/driverWallet/delete.php deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/driverWallet/get.php b/backend/ride/driverWallet/get.php deleted file mode 100644 index 45d736c..0000000 --- a/backend/ride/driverWallet/get.php +++ /dev/null @@ -1,42 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/driverWallet/getDriverWeekPaymentMove.php b/backend/ride/driverWallet/getDriverWeekPaymentMove.php deleted file mode 100644 index 281f34f..0000000 --- a/backend/ride/driverWallet/getDriverWeekPaymentMove.php +++ /dev/null @@ -1,37 +0,0 @@ -= DATE_SUB(NOW(), INTERVAL 1 WEEK) - ) AS totalAmount -FROM `driverWallet` -WHERE `driverID` = '$driverID' -AND `dateCreated` >= DATE_SUB(NOW(), INTERVAL 1 WEEK) -ORDER BY `dateCreated` DESC; -"; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/driverWallet/getWalletByDriver.php b/backend/ride/driverWallet/getWalletByDriver.php deleted file mode 100644 index 6fad20b..0000000 --- a/backend/ride/driverWallet/getWalletByDriver.php +++ /dev/null @@ -1,30 +0,0 @@ -= DATE_SUB(NOW(), INTERVAL 1 MONTH) -ORDER BY - `paymentsDriverPoints`.`id` -DESC"; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/driverWallet/sendEmailTransfer.php b/backend/ride/driverWallet/sendEmailTransfer.php deleted file mode 100644 index ba28c22..0000000 --- a/backend/ride/driverWallet/sendEmailTransfer.php +++ /dev/null @@ -1,122 +0,0 @@ - - - - - -
-

تفاصيل نقلك على سفر

-

شكراً لاستخدام خدمتنا. نتمنى لك يوماً رائعاً!

-

نريد إعلامك أن مبلغ $amount تم نقله من حسابك إلى السائق الجديد، $newDriverName (هاتف: $driverPhone).

-

مع خالص التحية،
فريق سفر

-
- - "; -} else { - $bodyEmail = " - - - - -
- SEFER App Logo - -

Your SEFER Transfer Details

-

Thank you for using our service. We hope you have a great day!

-

We want to inform you that an amount of $amount has been transferred from your account to the new driver: $newDriverName (Phone: $driverPhone).

-

Regards,
SEFER Team

-
- - "; -} - -// Email headers -$supportEmail = 'seferteam@sefer.live'; -$headers = "MIME-Version: 1.0\r\n"; -$headers .= "Content-Type: text/html; charset=UTF-8\r\n"; -$headers .= "From: $supportEmail\r\n"; - -// Send email -if (!empty($driverEmail)) { - if (mail($driverEmail, "Your SEFER Transfer Details", $bodyEmail, $headers)) { - - mail($newEmail, "Your SEFER Transfer Details", $bodyEmail, $headers); - echo "Email sent successfully."; - } else { - echo "Email sending failed."; - } -} else { - echo "Invalid email address: $driverEmail"; -} diff --git a/backend/ride/driverWallet/update.php b/backend/ride/driverWallet/update.php deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/gamification/claimChallengeReward.php b/backend/ride/gamification/claimChallengeReward.php index 4bd319c..16147c9 100644 --- a/backend/ride/gamification/claimChallengeReward.php +++ b/backend/ride/gamification/claimChallengeReward.php @@ -5,30 +5,100 @@ $driver_id = filterRequest("driver_id"); $points = filterRequest("points"); // Reward points amount $challenge_id = filterRequest("challenge_id"); -// Check if already claimed today to prevent spam -$checkSql = "SELECT id FROM driverWallet WHERE driverID = :driver_id AND paymentMethod = :challenge_id AND DATE(dateCreated) = CURDATE()"; -$stmtCheck = $con->prepare($checkSql); -$stmtCheck->bindParam(':driver_id', $driver_id, PDO::PARAM_INT); -$stmtCheck->bindParam(':challenge_id', $challenge_id, PDO::PARAM_STR); -$stmtCheck->execute(); - -if ($stmtCheck->rowCount() > 0) { - jsonError("Reward already claimed today"); +if (!$driver_id || !$points || !$challenge_id) { + jsonError("Missing required parameters"); exit(); } -// Insert into driver wallet -$paymentID = "CHL_" . time(); -$sql = "INSERT INTO driverWallet (driverID, paymentID, amount, paymentMethod) VALUES (:driver_id, :paymentID, :amount, :method)"; -$stmt = $con->prepare($sql); -$stmt->bindParam(':driver_id', $driver_id, PDO::PARAM_INT); -$stmt->bindParam(':paymentID', $paymentID, PDO::PARAM_STR); -$stmt->bindParam(':amount', $points, PDO::PARAM_STR); -$stmt->bindParam(':method', $challenge_id, PDO::PARAM_STR); +try { + $con->beginTransaction(); -if ($stmt->execute()) { - jsonSuccess("Reward claimed successfully"); -} else { - jsonError("Failed to claim reward"); + // 1. Get Country and Currency to determine Cash Multiplier + $stmtKazan = $con->prepare("SELECT country, currency FROM kazan LIMIT 1"); + $stmtKazan->execute(); + $kazanData = $stmtKazan->fetch(PDO::FETCH_ASSOC); + $country = $kazanData['country'] ?? 'Syria'; + $currency = $kazanData['currency'] ?? 'SYP'; + + switch ($currency) { + case 'SYP': + $rate = 100.0; // 1 point = 100 SYP (e.g. 50 points = 5,000 SYP) + break; + case 'EGP': + $rate = 1.0; // 1 point = 1 EGP (e.g. 50 points = 50 EGP) + break; + case 'JOD': + default: + $rate = 0.05; // 1 point = 0.05 JOD (e.g. 50 points = 2.5 JOD) + break; + } + + $cashAmount = $points * $rate; + + // 2. S2S Wallet credit to Payment Server + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($country) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($country) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + $paymentID = "CHL_" . time(); + $walletUrl = "$walletServer/v2/main/ride/driverWallet/add_s2s_reward.php"; + + $payload = [ + "driverID" => $driver_id, + "paymentID" => $paymentID, + "amount" => $cashAmount, + "paymentMethod" => $challenge_id, + "points" => $points + ]; + + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query($payload), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 15, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curlErr = curl_error($ch); + curl_close($ch); + + $s2sSuccess = false; + $s2sMessage = ""; + if (!$curlErr && $httpCode === 200) { + $resDecoded = json_decode($response, true); + if ($resDecoded && isset($resDecoded['status'])) { + if ($resDecoded['status'] === 'success') { + $s2sSuccess = true; + } else { + $s2sMessage = $resDecoded['message'] ?? "Unknown S2S failure"; + } + } + } + + if (!$s2sSuccess) { + $errMsg = $s2sMessage ?: ($curlErr ?: "HTTP $httpCode - Response: $response"); + throw new Exception($errMsg); + } + + $con->commit(); + jsonSuccess("Reward claimed successfully as " . $cashAmount . " " . $currency); + +} catch (Exception $e) { + if ($con->inTransaction()) { + $con->rollBack(); + } + error_log("claimChallengeReward Error: " . $e->getMessage()); + jsonError("Failed to claim reward: " . $e->getMessage()); } ?> diff --git a/backend/ride/gamification/getGamificationDashboard.php b/backend/ride/gamification/getGamificationDashboard.php new file mode 100644 index 0000000..f4c4ff0 --- /dev/null +++ b/backend/ride/gamification/getGamificationDashboard.php @@ -0,0 +1,120 @@ +prepare("SELECT country, currency FROM kazan LIMIT 1"); + $stmtKazan->execute(); + $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: ["country" => "Jordan", "currency" => "JOD"]; + + // 2. Get Total Completed Trips + $stmtTrips = $con->prepare("SELECT COUNT(*) as count FROM `ride` WHERE driver_id = :driver_id AND status = 'Finished'"); + $stmtTrips->execute([':driver_id' => $driver_id]); + $totalTrips = (int)($stmtTrips->fetchColumn() ?: 0); + + // 3. Get Average Rating + $stmtRate = $con->prepare("SELECT COALESCE(ROUND(AVG(rating), 2), 5.0) as rating FROM ratingDriver WHERE driver_id = :driver_id"); + $stmtRate->execute([':driver_id' => $driver_id]); + $avgRating = (float)($stmtRate->fetchColumn() ?: 5.0); + + // 4. Get Referral Counts (Installed/Verified) + $stmtDInv = $con->prepare("SELECT COUNT(*) FROM invites WHERE driverId = :driver_id AND isInstall = 1"); + $stmtDInv->execute([':driver_id' => $driver_id]); + $driverInvites = (int)($stmtDInv->fetchColumn() ?: 0); + + $stmtPInv = $con->prepare("SELECT COUNT(*) FROM invitesToPassengers WHERE driverId = :driver_id AND isInstall = 1"); + $stmtPInv->execute([':driver_id' => $driver_id]); + $passengerInvites = (int)($stmtPInv->fetchColumn() ?: 0); + + $totalReferrals = $driverInvites + $passengerInvites; + + // 5. Get Driver Behavior (Last 30 Days) + $stmtBehavior = $con->prepare(" + SELECT + COALESCE(ROUND(AVG(behavior_score), 1), 100) as avg_score, + COALESCE(SUM(hard_brakes), 0) as total_hard_brakes, + COALESCE(MAX(max_speed), 0) as max_speed + FROM `driver_behavior` + WHERE driver_id = :driver_id + AND created_at >= DATE(NOW()) - INTERVAL 30 DAY + "); + $stmtBehavior->execute([':driver_id' => $driver_id]); + $behavior = $stmtBehavior->fetch(PDO::FETCH_ASSOC) ?: ["avg_score" => 100.0, "total_hard_brakes" => 0, "max_speed" => 0.0]; + + // 6. Get Today's Completed Trips & Earnings (Local Ride Database) + $stmtTodayTrips = $con->prepare("SELECT COUNT(*) FROM `ride` WHERE driver_id = :driver_id AND status = 'Finished' AND DATE(created_at) = CURDATE()"); + $stmtTodayTrips->execute([':driver_id' => $driver_id]); + $todayTrips = (int)($stmtTodayTrips->fetchColumn() ?: 0); + + $stmtTodayEarnings = $con->prepare("SELECT COALESCE(SUM(price_for_driver), 0) FROM `ride` WHERE driver_id = :driver_id AND status = 'Finished' AND DATE(created_at) = CURDATE()"); + $stmtTodayEarnings->execute([':driver_id' => $driver_id]); + $todayEarnings = (float)($stmtTodayEarnings->fetchColumn() ?: 0.0); + + // 7. Get Claimed Challenge Points from Payment Server via S2S + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($kazan["country"]) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($kazan["country"]) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + $walletUrl = "$walletServer/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php"; + + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query(["driverID" => $driver_id]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curlErr = curl_error($ch); + curl_close($ch); + + $challengePoints = 0; + if (!$curlErr && $httpCode === 200) { + $resDecoded = json_decode($response, true); + if ($resDecoded && isset($resDecoded['status']) && $resDecoded['status'] === 'success') { + $challengePoints = (int)($resDecoded['message']['challengePoints'] ?? 0); + } + } + + // 8. Calculate Normalized Points + // 10 pts per finished trip, 100 pts per referral invite, 2 pts per behavior score point + claimed challenge points + $normalizedPoints = ($totalTrips * 10) + ($totalReferrals * 100) + ((int)$behavior['avg_score'] * 2) + $challengePoints; + + jsonSuccess([ + "country" => $kazan["country"], + "currency" => $kazan["currency"], + "totalTrips" => $totalTrips, + "averageRating" => $avgRating, + "totalReferrals" => $totalReferrals, + "driverInvites" => $driverInvites, + "passengerInvites" => $passengerInvites, + "behaviorScore" => (float)$behavior["avg_score"], + "hardBrakes" => (int)$behavior["total_hard_brakes"], + "maxSpeed" => (float)$behavior["max_speed"], + "todayTrips" => $todayTrips, + "todayEarnings" => $todayEarnings, + "totalPoints" => $normalizedPoints + ]); + +} catch (PDOException $e) { + error_log("getGamificationDashboard Error: " . $e->getMessage()); + jsonError("Database error occurred: " . $e->getMessage()); +} +?> diff --git a/backend/ride/invitor/claim_driver_reward.php b/backend/ride/invitor/claim_driver_reward.php index 0636310..cfd197c 100644 --- a/backend/ride/invitor/claim_driver_reward.php +++ b/backend/ride/invitor/claim_driver_reward.php @@ -28,28 +28,50 @@ if ($referral['is_reward_claimed'] == 1) { jsonError("Reward already claimed"); } -// Logic: -// Driver -> Driver: 50 trips = 500 SYP (example) -// Driver -> Passenger: 10 trips = 30 SYP per trip. This could be progressive, but for manual claim we assume completed -$amountSyp = 0; +// 2. Get local currency dynamically +$stmtKazan = $con->prepare("SELECT country, currency FROM kazan LIMIT 1"); +$stmtKazan->execute(); +$kazanData = $stmtKazan->fetch(PDO::FETCH_ASSOC); +$country = $kazanData['country'] ?? 'Syria'; +$currency = $kazanData['currency'] ?? 'SYP'; + +$driverRewardBase = 0; +$passengerRewardPerTrip = 0; + +switch ($currency) { + case 'SYP': + $driverRewardBase = 50000; + $passengerRewardPerTrip = 2000; + break; + case 'EGP': + $driverRewardBase = 300; + $passengerRewardPerTrip = 15; + break; + case 'JOD': + default: + $driverRewardBase = 10; + $passengerRewardPerTrip = 0.5; + break; +} + +$rewardAmount = 0; if ($referral['invited_user_type'] == 'driver') { if ($referral['trip_count'] >= 50) { - $amountSyp = 500; + $rewardAmount = $driverRewardBase; } else { jsonError("Requirement not met (50 trips required)"); } } else if ($referral['invited_user_type'] == 'passenger') { if ($referral['trip_count'] >= 1) { - // Here, user gets 30 SYP per trip, max 10. Let's assume claim all at once up to 10. $tripsToClaim = min($referral['trip_count'], 10); - $amountSyp = $tripsToClaim * 30; + $rewardAmount = $tripsToClaim * $passengerRewardPerTrip; } else { jsonError("Requirement not met (At least 1 trip required)"); } } -if ($amountSyp <= 0) { +if ($rewardAmount <= 0) { jsonError("No reward available to claim"); } @@ -61,20 +83,68 @@ try { $updateStmt->execute([$referralId]); if ($claimType == 'wallet') { - // Add to driver wallet - $walletStmt = $con->prepare("UPDATE driver SET wallet = wallet + ? WHERE id = ?"); - $walletStmt->execute([$amountSyp, $user_id]); + // Add to driver wallet via Payment Server S2S API + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($country) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($country) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + $paymentID = "REF_" . time(); + $walletUrl = "$walletServer/v2/main/ride/driverWallet/add_s2s_reward.php"; + + $payload = [ + "driverID" => $user_id, + "paymentID" => $paymentID, + "amount" => $rewardAmount, + "paymentMethod" => "referral_reward" + ]; + + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query($payload), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 15, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curlErr = curl_error($ch); + curl_close($ch); + + $s2sSuccess = false; + if (!$curlErr && $httpCode === 200) { + $resDecoded = json_decode($response, true); + if ($resDecoded && isset($resDecoded['status']) && $resDecoded['status'] === 'success') { + $s2sSuccess = true; + } + } + + if (!$s2sSuccess) { + throw new Exception("S2S Wallet credit failed: " . ($curlErr ?: "HTTP $httpCode - Response: $response")); + } + } else if ($claimType == 'cash') { // Request manual cash out $cashStmt = $con->prepare("INSERT INTO driver_cash_claims (driver_id, referral_id, amount_syp, status) VALUES (?, ?, ?, 'pending')"); - $cashStmt->execute([$user_id, $referralId, $amountSyp]); + $cashStmt->execute([$user_id, $referralId, $rewardAmount]); } $con->commit(); - printSuccess(["message" => "Reward claimed successfully as $claimType"]); + printSuccess(["message" => "Reward claimed successfully as " . $rewardAmount . " " . $currency]); -} catch (PDOException $e) { - $con->rollBack(); - jsonError("Database error: " . $e->getMessage()); +} catch (Exception $e) { + if ($con->inTransaction()) { + $con->rollBack(); + } + jsonError("Failed to claim reward: " . $e->getMessage()); } ?> diff --git a/backend/ride/notificationCaptain/getRideWaiting.php b/backend/ride/notificationCaptain/getRideWaiting.php index e7c4a57..5203d8d 100644 --- a/backend/ride/notificationCaptain/getRideWaiting.php +++ b/backend/ride/notificationCaptain/getRideWaiting.php @@ -73,7 +73,6 @@ try { FROM waitingRides wr INNER JOIN passengers p ON p.id = wr.passenger_id LEFT JOIN tokens t ON t.passengerID = wr.passenger_id - LEFT JOIN passengerWallet pw ON pw.passenger_id = wr.passenger_id WHERE wr.id IN ($placeholders) AND wr.status IN ('wait', 'waiting') "; @@ -99,7 +98,6 @@ try { FROM waitingRides wr INNER JOIN passengers p ON p.id = wr.passenger_id LEFT JOIN tokens t ON t.passengerID = wr.passenger_id - LEFT JOIN passengerWallet pw ON pw.passenger_id = wr.passenger_id WHERE wr.status IN ('wait', 'waiting') AND wr.created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR) diff --git a/backend/ride/passengerWallet/add.php b/backend/ride/passengerWallet/add.php deleted file mode 100644 index a2b1b47..0000000 --- a/backend/ride/passengerWallet/add.php +++ /dev/null @@ -1,32 +0,0 @@ -prepare("SELECT * FROM payment_tokens_passenger WHERE token = :token AND isUsed = FALSE"); -$stmt->execute([':token' => $token]); - -$tokenData = $stmt->fetch(); - -if ($tokenData) { - // Insert into passengerWallet securely using prepared statements - $sql = "INSERT INTO `passengerWallet` (`passenger_id`, `balance`) VALUES (:passenger_id, :balance)"; - $stmt = $con->prepare($sql); - $stmt->execute([':passenger_id' => $passenger_id, ':balance' => $balance]); - - if ($stmt->rowCount() > 0) { - // Mark the token as used - $updateTokenStmt = $con->prepare("UPDATE payment_tokens_passenger SET isUsed = TRUE WHERE token = :token"); - $updateTokenStmt->execute([':token' => $token]); - - jsonSuccess(null, "Wallet record created successfully"); - } else { - jsonError("Failed to create wallet record"); - } -} else { - jsonError("Invalid or already used token"); -} -?> \ No newline at end of file diff --git a/backend/ride/passengerWallet/addPaymentTokenPassenger.php b/backend/ride/passengerWallet/addPaymentTokenPassenger.php deleted file mode 100644 index 671fe3b..0000000 --- a/backend/ride/passengerWallet/addPaymentTokenPassenger.php +++ /dev/null @@ -1,53 +0,0 @@ -prepare("INSERT INTO payment_tokens_passenger (token, passengerId, dateCreated, amount) VALUES (?, ?, NOW(), ?)"); - -try { - $stmt->execute([$token, $passengerId, $amount]); - if ($stmt->rowCount() > 0) { - jsonSuccess($token); - } else { - jsonError("Failed to save record"); - } -} catch (PDOException $e) { - jsonError("Database error: " . $e->getMessage()); -} - -// Rest of your code including the generateSecureToken function... - -// Rest of your code including the generateSecureToken function... - -function generateSecureToken($passengerId, $amount, $dateCreated) { - global $secretKey; - // Concatenate the parameters - $data = $passengerId . $amount . $dateCreated; - - // Add the secret key from the environment variable - $data .= $secretKey; - - // Generate a hash - $hash = hash('sha256', $data); - - // Add some randomness - $randomBytes = bin2hex(random_bytes(16)); - - // Combine hash and random bytes - $token = $hash . $randomBytes; - - // Truncate to a reasonable length (e.g., 64 characters) - return substr($token, 0, 64); -} \ No newline at end of file diff --git a/backend/ride/passengerWallet/delete.php b/backend/ride/passengerWallet/delete.php deleted file mode 100644 index e74cc79..0000000 --- a/backend/ride/passengerWallet/delete.php +++ /dev/null @@ -1,17 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess($message = "Wallet record deleted successfully"); -} else { - // Print a failure message - jsonError($message = "Failed to delete wallet record"); -} -?> diff --git a/backend/ride/passengerWallet/error_log b/backend/ride/passengerWallet/error_log deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/passengerWallet/get.php b/backend/ride/passengerWallet/get.php deleted file mode 100644 index 590e180..0000000 --- a/backend/ride/passengerWallet/get.php +++ /dev/null @@ -1,32 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/passengerWallet/getAllPassengerTransaction.php b/backend/ride/passengerWallet/getAllPassengerTransaction.php deleted file mode 100644 index 536e672..0000000 --- a/backend/ride/passengerWallet/getAllPassengerTransaction.php +++ /dev/null @@ -1,40 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/passengerWallet/getPassengerWalletArchive.php b/backend/ride/passengerWallet/getPassengerWalletArchive.php deleted file mode 100644 index d0b3bfc..0000000 --- a/backend/ride/passengerWallet/getPassengerWalletArchive.php +++ /dev/null @@ -1,30 +0,0 @@ -= DATE_SUB(NOW(), INTERVAL 1 MONTH) -ORDER BY - `passengerWallet`.`id` -DESC"; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/passengerWallet/getWalletByPassenger.php b/backend/ride/passengerWallet/getWalletByPassenger.php deleted file mode 100644 index 81432af..0000000 --- a/backend/ride/passengerWallet/getWalletByPassenger.php +++ /dev/null @@ -1,34 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/passengerWallet/update.php b/backend/ride/passengerWallet/update.php deleted file mode 100644 index adf5ab4..0000000 --- a/backend/ride/passengerWallet/update.php +++ /dev/null @@ -1,18 +0,0 @@ - -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess($message = "Wallet record updated successfully"); -} else { - // Print a failure message - jsonError($message = "Failed to update wallet record"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/add.php b/backend/ride/payment/add.php deleted file mode 100644 index 7701a13..0000000 --- a/backend/ride/payment/add.php +++ /dev/null @@ -1,42 +0,0 @@ -prepare("SELECT * FROM payment_tokens WHERE token = :token AND isUsed = FALSE"); -$stmt->execute(array( - ':token' => $token -)); - -$tokenData = $stmt->fetch(); - -if ($tokenData) { - -$sql = "INSERT INTO `payments` (`id`,`amount`, `payment_method`, `passengerID`, `rideId`, `driverID`) - VALUES ( SHA2(UUID(), 256),'$amount', '$payment_method', '$passengerID', '$rideId', '$driverID')"; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess(null, "Payment record created successfully"); - // Mark the token as used in the database - $stmt = $con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE id = :tokenID"); - $stmt->execute(array( - ':tokenID' => $tokenData['id'] - )); - } else { - // Print a failure message - jsonError("Failed to save record"); - } -} else { - jsonError("Invalid or already used token"); -} \ No newline at end of file diff --git a/backend/ride/payment/delete.php b/backend/ride/payment/delete.php deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/payment/error_log b/backend/ride/payment/error_log deleted file mode 100644 index e69de29..0000000 diff --git a/backend/ride/payment/get.php b/backend/ride/payment/get.php deleted file mode 100644 index fa10d57..0000000 --- a/backend/ride/payment/get.php +++ /dev/null @@ -1,61 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - $count = $stmt->rowCount(); - - // $response = array( - - // "message" => "Payment data saved successfully", - // "id" => "0", - // "count" => $count, - // "data" => $rows - // ); - - // echo json_encode($response); - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/getAllPayment.php b/backend/ride/payment/getAllPayment.php deleted file mode 100644 index 8b5ea9b..0000000 --- a/backend/ride/payment/getAllPayment.php +++ /dev/null @@ -1,64 +0,0 @@ - CURRENT_DATE() - INTERVAL 1 WEEK - ) AS total_amount_last_week -FROM - dual -LIMIT 1; - - - "; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/getAllPaymentVisa.php b/backend/ride/payment/getAllPaymentVisa.php deleted file mode 100644 index d4d80c8..0000000 --- a/backend/ride/payment/getAllPaymentVisa.php +++ /dev/null @@ -1,39 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/getCountRide.php b/backend/ride/payment/getCountRide.php deleted file mode 100644 index 547ddd2..0000000 --- a/backend/ride/payment/getCountRide.php +++ /dev/null @@ -1,29 +0,0 @@ -= CURDATE(); -"; -$stmt = $con->prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Fetch the record - $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - - - jsonSuccess($row); - -} - else{ - // Print a failure message - jsonError($message = "No wallet record found"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/update.php b/backend/ride/payment/update.php deleted file mode 100644 index 6c0ca68..0000000 --- a/backend/ride/payment/update.php +++ /dev/null @@ -1,72 +0,0 @@ - $id]; - -// Check if each column is set in the request and add it to the array -if (isset($_POST["amount"])) { - $amount = filterRequest("amount"); - $columnValues[] = "`amount` = :amount"; - $params[':amount'] = $amount; -} - -if (isset($_POST["payment_method"])) { - $payment_method = filterRequest("payment_method"); - $columnValues[] = "`payment_method` = :payment_method"; - $params[':payment_method'] = $payment_method; -} - -if (isset($_POST["passengerID"])) { - $passengerID = filterRequest("passengerID"); - $columnValues[] = "`passengerID` = :passengerID"; - $params[':passengerID'] = $passengerID; -} - -if (isset($_POST["rideId"])) { - $rideId = filterRequest("rideId"); - $columnValues[] = "`rideId` = :rideId"; - $params[':rideId'] = $rideId; -} - -if (isset($_POST["driverID"])) { - $driverID = filterRequest("driverID"); - $columnValues[] = "`driverID` = :driverID"; - $params[':driverID'] = $driverID; -} - -if (isset($_POST["created_at"])) { - $created_at = filterRequest("created_at"); - $columnValues[] = "`created_at` = :created_at"; - $params[':created_at'] = $created_at; -} - -if (isset($_POST["updated_at"])) { - $updated_at = filterRequest("updated_at"); - $columnValues[] = "`updated_at` = :updated_at"; - $params[':updated_at'] = $updated_at; -} - -if (isset($_POST["isGiven"])) { - $isGiven = filterRequest("isGiven"); - $columnValues[] = "`isGiven` = :isGiven"; - $params[':isGiven'] = $isGiven; -} - -// Construct the SET clause of the update query using the column-value pairs -$sql = "UPDATE `payments` SET $setClause WHERE `id` = :id"; - -$stmt = $con->prepare($sql); -$stmt->execute($params); - -if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess($message = "Payment data updated successfully"); -} else { - // Print a failure message - jsonError($message = "Failed to update payment data"); -} -?> \ No newline at end of file diff --git a/backend/ride/payment/updatePaymetToPaid.php b/backend/ride/payment/updatePaymetToPaid.php deleted file mode 100644 index 53ddd99..0000000 --- a/backend/ride/payment/updatePaymetToPaid.php +++ /dev/null @@ -1,19 +0,0 @@ -prepare($sql); -$stmt->execute(); - -if ($stmt->rowCount() > 0) { - // Print a success message - jsonSuccess($message = "Payment data updated successfully"); -} else { - // Print a failure message - jsonError($message = "Failed to update payment data"); -} -?> \ No newline at end of file diff --git a/backend/ride/rides/cancel_ride_by_driver.php b/backend/ride/rides/cancel_ride_by_driver.php index dd253bc..1bd7dcd 100644 --- a/backend/ride/rides/cancel_ride_by_driver.php +++ b/backend/ride/rides/cancel_ride_by_driver.php @@ -98,8 +98,45 @@ try { if ($penaltyFee > 0) { // إضافة القيمة كدين سالب في المحفظة $negativeDebt = -$penaltyFee; - $stmtWallet = $con->prepare("INSERT INTO `passengerWallet` (passenger_id, balance) VALUES (?, ?)"); - $stmtWallet->execute([$passenger_id, $negativeDebt]); + + // Resolve country and wallet server + $stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1"); + $stmtKazan->execute(); + $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: ["country" => "Jordan"]; + $country = $kazan['country'] ?? 'Jordan'; + + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($country) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($country) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + // S2S call to add debt to passenger wallet on the payment server + $walletUrl = "$walletServer/v2/main/ride/passengerWallet/add_s2s_debt.php"; + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query([ + "passengerID" => $passenger_id, + "amount" => $negativeDebt + ]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + $s2sRes = curl_exec($ch); + $s2sCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($s2sCode !== 200) { + error_log("Failed to add passenger debt via S2S: Code $s2sCode, Res: $s2sRes"); + } // تخزين الدين في الـ Redis لمدة 6 شهور (15552000 ثانية) try { diff --git a/backend/schema_primary.sql b/backend/schema_primary.sql index d78ccfe..887abba 100644 --- a/backend/schema_primary.sql +++ b/backend/schema_primary.sql @@ -426,24 +426,8 @@ CREATE TABLE `driverToken` ( ) ENGINE=InnoDB AUTO_INCREMENT=1460 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `driverWallet` -- -DROP TABLE IF EXISTS `driverWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `driverWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `driverID` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentID` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `amount` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentMethod` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateUpdated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `driver_behavior` @@ -1084,23 +1068,6 @@ CREATE TABLE `palces11` ( ) ENGINE=InnoDB AUTO_INCREMENT=37946 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `passengerWallet` --- - -DROP TABLE IF EXISTS `passengerWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `passengerWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `passenger_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `balance` decimal(10,2) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - KEY `passenger_id` (`passenger_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `passenger_blacklist` @@ -1140,6 +1107,24 @@ CREATE TABLE `passengerlocation` ( ) ENGINE=InnoDB AUTO_INCREMENT=725 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `passenger_opening_locations` +-- + +DROP TABLE IF EXISTS `passenger_opening_locations`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `passenger_opening_locations` ( + `id` int NOT NULL AUTO_INCREMENT, + `passenger_id` varchar(100) NOT NULL, + `latitude` varchar(30) NOT NULL, + `longitude` varchar(30) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `idx_passenger_id` (`passenger_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `passengers` -- @@ -1205,45 +1190,8 @@ CREATE TABLE `payment_tokens_passenger` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `payments` --- -DROP TABLE IF EXISTS `payments`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `payments` ( - `id` varchar(111) NOT NULL, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(255) NOT NULL, - `passengerID` varchar(100) NOT NULL, - `rideId` varchar(100) NOT NULL, - `driverID` varchar(100) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `isGiven` varchar(20) NOT NULL DEFAULT 'waiting', - PRIMARY KEY (`id`), - UNIQUE KEY `rideId` (`rideId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; -/*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `paymentsDriverPoints` --- - -DROP TABLE IF EXISTS `paymentsDriverPoints`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `paymentsDriverPoints` ( - `id` int NOT NULL AUTO_INCREMENT, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `driverID` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `created_at` datetime DEFAULT CURRENT_TIMESTAMP, - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `phone_verification` diff --git a/backend/schema_ride.sql b/backend/schema_ride.sql index 07cf5b4..7c50c26 100644 --- a/backend/schema_ride.sql +++ b/backend/schema_ride.sql @@ -433,24 +433,7 @@ CREATE TABLE `driverToken` ( ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `driverWallet` --- -DROP TABLE IF EXISTS `driverWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `driverWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `driverID` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentID` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `amount` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentMethod` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateUpdated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `driver_behavior` @@ -1057,23 +1040,7 @@ CREATE TABLE `palces11` ( ) ENGINE=InnoDB AUTO_INCREMENT=28951 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `passengerWallet` --- -DROP TABLE IF EXISTS `passengerWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `passengerWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `passenger_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `balance` decimal(10,2) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - KEY `passenger_id` (`passenger_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `passenger_blacklist` @@ -1178,45 +1145,9 @@ CREATE TABLE `payment_tokens_passenger` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `payments` --- -DROP TABLE IF EXISTS `payments`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `payments` ( - `id` varchar(111) NOT NULL, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(255) NOT NULL, - `passengerID` varchar(100) NOT NULL, - `rideId` varchar(100) NOT NULL, - `driverID` varchar(100) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `isGiven` varchar(20) NOT NULL DEFAULT 'waiting', - PRIMARY KEY (`id`), - UNIQUE KEY `rideId` (`rideId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; -/*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `paymentsDriverPoints` --- -DROP TABLE IF EXISTS `paymentsDriverPoints`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `paymentsDriverPoints` ( - `id` int NOT NULL AUTO_INCREMENT, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `driverID` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `created_at` datetime DEFAULT CURRENT_TIMESTAMP, - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `phone_verification` diff --git a/backend/schema_tracking.sql b/backend/schema_tracking.sql index 1ada78f..d26add2 100644 --- a/backend/schema_tracking.sql +++ b/backend/schema_tracking.sql @@ -434,24 +434,8 @@ CREATE TABLE `driverToken` ( ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `driverWallet` -- -DROP TABLE IF EXISTS `driverWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `driverWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `driverID` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentID` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `amount` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `paymentMethod` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `dateUpdated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `driver_behavior` @@ -1096,23 +1080,7 @@ CREATE TABLE `palces11` ( ) ENGINE=InnoDB AUTO_INCREMENT=28951 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `passengerWallet` --- -DROP TABLE IF EXISTS `passengerWallet`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `passengerWallet` ( - `id` int NOT NULL AUTO_INCREMENT, - `passenger_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `balance` decimal(10,2) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - KEY `passenger_id` (`passenger_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `passenger_blacklist` @@ -1217,45 +1185,9 @@ CREATE TABLE `payment_tokens_passenger` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `payments` --- -DROP TABLE IF EXISTS `payments`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `payments` ( - `id` varchar(111) NOT NULL, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(255) NOT NULL, - `passengerID` varchar(100) NOT NULL, - `rideId` varchar(100) NOT NULL, - `driverID` varchar(100) NOT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `isGiven` varchar(20) NOT NULL DEFAULT 'waiting', - PRIMARY KEY (`id`), - UNIQUE KEY `rideId` (`rideId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; -/*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `paymentsDriverPoints` --- -DROP TABLE IF EXISTS `paymentsDriverPoints`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `paymentsDriverPoints` ( - `id` int NOT NULL AUTO_INCREMENT, - `amount` decimal(10,2) NOT NULL, - `payment_method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `driverID` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `created_at` datetime DEFAULT CURRENT_TIMESTAMP, - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `phone_verification` diff --git a/backend/serviceapp/getComplaintAllData.php b/backend/serviceapp/getComplaintAllData.php index 6fe69a3..e9650a0 100644 --- a/backend/serviceapp/getComplaintAllData.php +++ b/backend/serviceapp/getComplaintAllData.php @@ -14,8 +14,8 @@ SELECT ride.carType, ride.paymentMethod AS ridePaymentMethod, ride.rideTimeFinish, - payments.amount AS paymentFromPaymentTable, - payments.created_at AS timeFromPaymentTable, + 0 AS paymentFromPaymentTable, + NULL AS timeFromPaymentTable, COALESCE(dr_rating.avgRating, 0) AS avgRatingDriverFromPassengers, COALESCE(dr_rating.cntRating, 0) AS countratingDriverFromPassengers, @@ -23,9 +23,9 @@ SELECT COALESCE(ps_rating.cntRating, 0) AS countRatingPassengerFromDrivers, COALESCE(dr_rides.cnt, 0) AS countDriverRide, COALESCE(ps_rides.cnt, 0) AS countPassengerRide, - COALESCE(dr_visa.total, 0) AS driverVisa, - COALESCE(dr_wallet.total, 0) AS driverWallet, - COALESCE(ps_wallet.total, 0) AS passengerWallet, + 0 AS driverVisa, + 0 AS driverWallet, + 0 AS passengerWallet, dt.token AS driverToken, tk.token AS passengerToken, @@ -44,9 +44,6 @@ LEFT JOIN driver d LEFT JOIN ride ON ride.id = cm.ride_id COLLATE utf8mb4_general_ci -LEFT JOIN payments - ON payments.rideId = cm.ride_id COLLATE utf8mb4_general_ci - -- تقييمات السائق (مرة واحدة لكل سائق) LEFT JOIN ( SELECT driver_id, AVG(rating) AS avgRating, COUNT(*) AS cntRating @@ -75,30 +72,6 @@ LEFT JOIN ( GROUP BY passenger_id ) ps_rides ON ps_rides.passenger_id = cm.passenger_id COLLATE utf8mb4_general_ci --- رصيد Visa السائق -LEFT JOIN ( - SELECT driverID, SUM(amount) AS total - FROM payments - WHERE isGiven = 'waiting' - AND payment_method IN ('visa-in','visa','visaRide','TransferFrom','payout','TransferTo') - GROUP BY driverID -) dr_visa ON dr_visa.driverID = cm.driver_id COLLATE utf8mb4_general_ci - --- محفظة السائق -LEFT JOIN ( - SELECT driverID, SUM(amount) AS total - FROM driverWallet - WHERE paymentMethod IN ('visa-in','visa','visaRide','TransferFrom','payout','TransferTo') - GROUP BY driverID -) dr_wallet ON dr_wallet.driverID = cm.driver_id COLLATE utf8mb4_general_ci - --- محفظة الراكب -LEFT JOIN ( - SELECT passenger_id, SUM(balance) AS total - FROM passengerWallet - GROUP BY passenger_id -) ps_wallet ON ps_wallet.passenger_id = cm.passenger_id COLLATE utf8mb4_general_ci - -- توكن السائق LEFT JOIN driverToken dt ON dt.captain_id = cm.driver_id COLLATE utf8mb4_general_ci diff --git a/backend/serviceapp/getComplaintAllDataForDriver.php b/backend/serviceapp/getComplaintAllDataForDriver.php index fd2dee6..5312ccb 100644 --- a/backend/serviceapp/getComplaintAllDataForDriver.php +++ b/backend/serviceapp/getComplaintAllDataForDriver.php @@ -21,8 +21,8 @@ $sql = "SELECT ride.carType AS carType, ride.paymentMethod AS ridePaymentMethod, ride.rideTimeFinish AS rideTimeFinish, - payments.amount AS paymentFromPaymentTable, - payments.created_at AS timeFromPaymentTable, + 0 AS paymentFromPaymentTable, + NULL AS timeFromPaymentTable, ( SELECT AVG(rd.rating) @@ -71,47 +71,9 @@ $sql = "SELECT WHERE ride.passenger_id = cm.passenger_id ) countPassengerRide, -( - SELECT - COALESCE(SUM(amount), - 0) AS visaDriver - FROM - payments - WHERE - isGiven = 'waiting' AND `payment_method` IN( - 'visa-in', - 'visa', - 'visaRide', - 'TransferFrom', - 'payout', - 'TransferTo' - ) AND payments.`driverID` = cm.driver_id -) AS driverVisa, -( - SELECT - COALESCE(SUM(amount), - 0) AS pointDriver - FROM - driverWallet dw - WHERE - dw.paymentMethod IN( - 'visa-in', - 'visa', - 'visaRide', - 'TransferFrom', - 'payout', - 'TransferTo' - ) AND dw.`driverID` = cm.driver_id -) AS driverWallet, -( - SELECT - COALESCE(SUM(pw.balance), - 0) - FROM - passengerWallet pw - WHERE - pw.passenger_id = cm.passenger_id -) AS passengerWallet, +0 AS driverVisa, +0 AS driverWallet, +0 AS passengerWallet, ( SELECT token @@ -151,7 +113,6 @@ LEFT JOIN passengers p ON LEFT JOIN driver d ON d.id = cm.driver_id LEFT JOIN ride ON ride.id = cm.ride_id -LEFT JOIN payments ON payments.rideId = cm.ride_id WHERE cm.driver_id = '$driverID'"; $stmt = $con->prepare($sql); diff --git a/backend/serviceapp/getDriverByNational.php b/backend/serviceapp/getDriverByNational.php index dd1815e..033511d 100644 --- a/backend/serviceapp/getDriverByNational.php +++ b/backend/serviceapp/getDriverByNational.php @@ -22,21 +22,9 @@ $sql = "SELECT ), 0) AS rating, - COALESCE( - ( - SELECT SUM(pd.amount) - FROM `payments` pd - WHERE pd.driverID = d.id - ), - 0) AS totalPayment, + 0 AS totalPayment, - COALESCE( - ( - SELECT SUM(dw.amount) - FROM `driverWallet` dw - WHERE dw.driverID = d.id - ), - 0) AS totalDriverWallet, + 0 AS totalDriverWallet, COALESCE( ( @@ -97,7 +85,22 @@ $stmt->execute(); if ($stmt->rowCount() > 0) { $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - // فك تشفير الحقول المهمة + // Get country from Kazan to determine wallet server + $stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1"); + $stmtKazan->execute(); + $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: ["country" => "Jordan"]; + $country = $kazan['country'] ?? 'Jordan'; + + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($country) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($country) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + // فك تشفير الحقول المهمة وجلب الرصيد من سيرفر المحفظة foreach ($row as &$r) { if (isset($r['phone'])) $r['phone'] = $encryptionHelper->decryptData($r['phone']); if (isset($r['email'])) $r['email'] = $encryptionHelper->decryptData($r['email']); @@ -115,6 +118,35 @@ if ($stmt->rowCount() > 0) { if (isset($r['address'])) $r['address'] = $encryptionHelper->decryptData($r['address']); if (isset($r['vin'])) $r['vin'] = $encryptionHelper->decryptData($r['vin']); unset($r['password']); + + // S2S Wallet Balance Query + $driver_id = $r['id'] ?? ''; + if (!empty($driver_id)) { + $walletUrl = "$walletServer/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php"; + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query(["driverID" => $driver_id]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + $s2sRes = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $totalWallet = 0.0; + if ($httpCode === 200 && $s2sRes) { + $resDecoded = json_decode($s2sRes, true); + if ($resDecoded && isset($resDecoded['status']) && $resDecoded['status'] === 'success') { + $totalWallet = (float)($resDecoded['message']['totalWallet'] ?? 0.0); + } + } + $r['totalDriverWallet'] = $totalWallet; + } } jsonSuccess($row); diff --git a/backend/serviceapp/getDriverByPhone.php b/backend/serviceapp/getDriverByPhone.php index 6727a3c..fbc2b66 100644 --- a/backend/serviceapp/getDriverByPhone.php +++ b/backend/serviceapp/getDriverByPhone.php @@ -19,21 +19,9 @@ $sql = "SELECT ), 0) AS rating, - COALESCE( - ( - SELECT SUM(pd.amount) - FROM `payments` pd - WHERE pd.driverID = d.id - ), - 0) AS totalPayment, + 0 AS totalPayment, - COALESCE( - ( - SELECT SUM(dw.amount) - FROM `driverWallet` dw - WHERE dw.driverID = d.id - ), - 0) AS totalDriverWallet, + 0 AS totalDriverWallet, COALESCE( ( @@ -92,7 +80,22 @@ $stmt->execute(); if ($stmt->rowCount() > 0) { $row = $stmt->fetchAll(PDO::FETCH_ASSOC); - // فك تشفير الحقول المهمة + // Get country from Kazan to determine wallet server + $stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1"); + $stmtKazan->execute(); + $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: ["country" => "Jordan"]; + $country = $kazan['country'] ?? 'Jordan'; + + $walletServer = "https://walletintaleq.intaleq.xyz"; + if (strtolower($country) == 'jordan') { + $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; + } elseif (strtolower($country) == 'egypt') { + $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; + } else { + $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; + } + + // فك تشفير الحقول المهمة وجلب الرصيد من سيرفر المحفظة foreach ($row as &$r) { if (isset($r['phone'])) $r['phone'] = $encryptionHelper->decryptData($r['phone']); if (isset($r['email'])) $r['email'] = $encryptionHelper->decryptData($r['email']); @@ -102,7 +105,7 @@ if ($stmt->rowCount() > 0) { if (isset($r['birthdate'])) $r['birthdate'] = $encryptionHelper->decryptData($r['birthdate']); if (isset($r['site'])) $r['site'] = $encryptionHelper->decryptData($r['site']); if (isset($r['name_arabic'])) $r['name_arabic'] = $encryptionHelper->decryptData($r['name_arabic']); - if (isset($r['national_number'])) $r['national_number'] = $encryptionHelper->decryptData($r['national_number']); + if (isset($r['national_number'])) $r['national_number'] = $encryptionHelper->decryptData($r['national_number']); if (isset($r['maritalStatus'])) $r['maritalStatus'] = $encryptionHelper->decryptData($r['maritalStatus']); if (isset($r['sosPhone'])) $r['sosPhone'] = $encryptionHelper->decryptData($r['sosPhone']); if (isset($r['car_plate'])) $r['car_plate'] = $encryptionHelper->decryptData($r['car_plate']); @@ -113,6 +116,34 @@ if ($stmt->rowCount() > 0) { if (isset($r['bankCode'])) $r['bankCode'] = $encryptionHelper->decryptData($r['bankCode']); unset($r['password']); + // S2S Wallet Balance Query + $driver_id = $r['id'] ?? ''; + if (!empty($driver_id)) { + $walletUrl = "$walletServer/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php"; + $ch = curl_init($walletUrl); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query(["driverID" => $driver_id]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/x-www-form-urlencoded', + 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') + ] + ]); + $s2sRes = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $totalWallet = 0.0; + if ($httpCode === 200 && $s2sRes) { + $resDecoded = json_decode($s2sRes, true); + if ($resDecoded && isset($resDecoded['status']) && $resDecoded['status'] === 'success') { + $totalWallet = (float)($resDecoded['message']['totalWallet'] ?? 0.0); + } + } + $r['totalDriverWallet'] = $totalWallet; + } } jsonSuccess($row); diff --git a/backend/serviceapp/getPassengersByPhone.php b/backend/serviceapp/getPassengersByPhone.php index 5a9062a..66ac392 100644 --- a/backend/serviceapp/getPassengersByPhone.php +++ b/backend/serviceapp/getPassengersByPhone.php @@ -27,21 +27,16 @@ $sql = "SELECT COALESCE(r.price_for_driver, 0) AS price_for_driver, COALESCE(r.price_for_passenger, 0) AS price_for_passenger, COALESCE(r.distance, 0) AS distance, - COALESCE(pw.balance, 0) AS passenger_wallet_balance, - COALESCE(pay.amount, 0) AS passenger_payment_amount, - COALESCE(pay.payment_method, '') AS passenger_payment_method, - COALESCE(dw.amount, 0) AS driver_payment_amount, - COALESCE(dw.paymentMethod, '') AS driver_payment_method + 0 AS passenger_wallet_balance, + 0 AS passenger_payment_amount, + '' AS passenger_payment_method, + 0 AS driver_payment_amount, + '' AS driver_payment_method FROM passengers p LEFT JOIN ride r ON p.id = r.passenger_id -LEFT JOIN - passengerWallet pw ON p.id = pw.passenger_id -LEFT JOIN - payments pay ON r.id = pay.rideId -LEFT JOIN - driverWallet dw ON r.driver_id = dw.driverID AND pay.id = dw.paymentID + WHERE p.phone = :phone AND r.id = ( diff --git a/scratch/Roboto-Bold.ttf b/scratch/Roboto-Bold.ttf new file mode 100755 index 0000000..68822ca Binary files /dev/null and b/scratch/Roboto-Bold.ttf differ diff --git a/scratch/admin_base.png b/scratch/admin_base.png new file mode 100644 index 0000000..2b58d9f Binary files /dev/null and b/scratch/admin_base.png differ diff --git a/scratch/admin_logo_final.png b/scratch/admin_logo_final.png new file mode 100644 index 0000000..65c15a8 Binary files /dev/null and b/scratch/admin_logo_final.png differ diff --git a/scratch/admin_logo_test.png b/scratch/admin_logo_test.png new file mode 100644 index 0000000..4cac90b Binary files /dev/null and b/scratch/admin_logo_test.png differ diff --git a/scratch/compile_logos.py b/scratch/compile_logos.py new file mode 100644 index 0000000..5f6e168 --- /dev/null +++ b/scratch/compile_logos.py @@ -0,0 +1,88 @@ +import math +import sys +import os +from PIL import Image, ImageDraw, ImageFont + +# Set font path to the local Roboto-Bold font +font_path = 'scratch/Roboto-Bold.ttf' + +def draw_gear(draw, cx, cy, r_out, r_in, teeth_count, teeth_h, teeth_w, color): + draw.ellipse([cx - r_out, cy - r_out, cx + r_out, cy + r_out], fill=color) + for i in range(teeth_count): + angle = i * (2 * math.pi / teeth_count) + x0 = cx + r_out * math.cos(angle) + y0 = cy + r_out * math.sin(angle) + tx = -math.sin(angle) + ty = math.cos(angle) + nx = math.cos(angle) + ny = math.sin(angle) + p1 = (x0 - (teeth_w/2) * tx, y0 - (teeth_w/2) * ty) + p2 = (x0 + (teeth_w/2) * tx, y0 + (teeth_w/2) * ty) + p3 = (x0 + teeth_h * nx + (teeth_w/3) * tx, y0 + teeth_h * ny + (teeth_w/3) * ty) + p4 = (x0 + teeth_h * nx - (teeth_w/3) * tx, y0 + teeth_h * ny - (teeth_w/3) * ty) + draw.polygon([p1, p2, p3, p4], fill=color) + draw.ellipse([cx - r_in, cy - r_in, cx + r_in, cy + r_in], fill=(255, 255, 255, 255)) + +def draw_car_large(draw, color): + # Center: (765, 205) + # Cabin + draw.polygon([(740, 155), (790, 155), (809, 198), (721, 198)], fill=color) + # Windshield + draw.polygon([(743, 161), (787, 161), (802, 194), (728, 194)], fill=(255, 255, 255, 255)) + # Windshield divider + draw.rectangle([763, 161, 767, 194], fill=color) + # Main body + draw.polygon([ + (712, 195), (818, 195), + (827, 204), (827, 246), + (818, 255), (712, 255), + (703, 246), (703, 204) + ], fill=color) + # Headlights + r_head = 9 + draw.ellipse([722 - r_head, 222 - r_head, 722 + r_head, 222 + r_head], fill=(255, 255, 255, 255)) + draw.ellipse([808 - r_head, 222 - r_head, 808 + r_head, 222 + r_head], fill=(255, 255, 255, 255)) + # Grille + draw.rectangle([740, 222, 790, 232], fill=(255, 255, 255, 255)) + # Side mirrors + draw.polygon([(694, 190), (703, 195), (703, 203), (694, 198)], fill=color) + draw.polygon([(836, 190), (827, 195), (827, 203), (836, 198)], fill=color) + +def create_app_logo(base_logo_path, text, output_path): + im = Image.open(base_logo_path) + draw = ImageDraw.Draw(im) + color = (29, 32, 47, 255) + + font_size = 90 + font = ImageFont.truetype(font_path, font_size) + + # Get text bounding box + bbox = draw.textbbox((0, 0), text, font=font) + tw = bbox[2] - bbox[0] + th = bbox[3] - bbox[1] + + tx = 512 - (tw / 2) + ty = 887 - (th / 2) - bbox[1] + + draw.text((tx, ty), text, font=font, fill=color) + im.save(output_path) + print(f'Saved logo with text \"{text}\" to {output_path}. BBox: X={tx} to {tx+tw}, Y={ty+bbox[1]} to {ty+bbox[3]}') + +# Create Admin logo +print('Creating Admin Logo...') +im_admin = Image.open('scratch/logo_s_only.png') +draw_admin = ImageDraw.Draw(im_admin) +color = (29, 32, 47, 255) +draw_gear(draw_admin, cx=765, cy=205, r_out=52, r_in=20, teeth_count=8, teeth_h=16, teeth_w=20, color=color) +im_admin.save('scratch/admin_base.png') +create_app_logo('scratch/admin_base.png', 'ADMIN', 'scratch/admin_logo_final.png') + +# Create Service logo +print('Creating Service Logo...') +im_service = Image.open('scratch/logo_s_only.png') +draw_service = ImageDraw.Draw(im_service) +draw_car_large(draw_service, color) +im_service.save('scratch/service_base.png') +create_app_logo('scratch/service_base.png', 'SERVICE', 'scratch/service_logo_final.png') + +print('All logos compiled successfully.') diff --git a/scratch/draw_car.py b/scratch/draw_car.py new file mode 100644 index 0000000..5456d55 --- /dev/null +++ b/scratch/draw_car.py @@ -0,0 +1,48 @@ +import math +from PIL import Image, ImageDraw + +def draw_car_large(draw, color): + # Center: (765, 205) + # Scaled up by 1.25x for better visual weight + + # 1. Cabin (upper part) + # Trapezoid: top base from X=740 to 790, bottom base from X=721 to 809, Y=155 to 198 + draw.polygon([(740, 155), (790, 155), (809, 198), (721, 198)], fill=color) + + # Windshield (white trapezoid inside cabin) + draw.polygon([(743, 161), (787, 161), (802, 194), (728, 194)], fill=(255, 255, 255, 255)) + + # Vertical divider in windshield + draw.rectangle([763, 161, 767, 194], fill=color) + + # 2. Main body (lower part) + # Polygon with cut corners: X=703 to 827, Y=195 to 255 + draw.polygon([ + (712, 195), (818, 195), + (827, 204), (827, 246), + (818, 255), (712, 255), + (703, 246), (703, 204) + ], fill=color) + + # 3. Headlights (white circles) + r_head = 9 + draw.ellipse([722 - r_head, 222 - r_head, 722 + r_head, 222 + r_head], fill=(255, 255, 255, 255)) + draw.ellipse([808 - r_head, 222 - r_head, 808 + r_head, 222 + r_head], fill=(255, 255, 255, 255)) + + # 4. Grille / Bumper + # Center grill: white rectangle from X=740 to 790, Y=222 to 232 + draw.rectangle([740, 222, 790, 232], fill=(255, 255, 255, 255)) + + # 5. Side mirrors + # Left mirror: polygon at X=694 to 703, Y=190 to 202 + draw.polygon([(694, 190), (703, 195), (703, 203), (694, 198)], fill=color) + # Right mirror: polygon at X=827 to 836, Y=190 to 202 + draw.polygon([(836, 190), (827, 195), (827, 203), (836, 198)], fill=color) + +im = Image.open('scratch/logo_s_only.png') +draw = ImageDraw.Draw(im) +color = (29, 32, 47, 255) + +draw_car_large(draw, color) +im.save('scratch/service_logo_test_car_large.png') +print("Saved large service logo to scratch/service_logo_test_car_large.png") diff --git a/scratch/draw_gear.py b/scratch/draw_gear.py new file mode 100644 index 0000000..b2c3e14 --- /dev/null +++ b/scratch/draw_gear.py @@ -0,0 +1,44 @@ +import math +from PIL import Image, ImageDraw + +def draw_gear(draw, cx, cy, r_out, r_in, teeth_count, teeth_h, teeth_w, color): + # Draw outer body + draw.ellipse([cx - r_out, cy - r_out, cx + r_out, cy + r_out], fill=color) + + # Draw teeth + for i in range(teeth_count): + angle = i * (2 * math.pi / teeth_count) + + # Center of tooth base on the outer radius + x0 = cx + r_out * math.cos(angle) + y0 = cy + r_out * math.sin(angle) + + # Tangent vector for width + tx = -math.sin(angle) + ty = math.cos(angle) + + # Normal vector for height + nx = math.cos(angle) + ny = math.sin(angle) + + # 4 points of the tooth (trapezoid style: narrower at the tip) + p1 = (x0 - (teeth_w/2) * tx, y0 - (teeth_w/2) * ty) + p2 = (x0 + (teeth_w/2) * tx, y0 + (teeth_w/2) * ty) + + p3 = (x0 + teeth_h * nx + (teeth_w/3) * tx, y0 + teeth_h * ny + (teeth_w/3) * ty) + p4 = (x0 + teeth_h * nx - (teeth_w/3) * tx, y0 + teeth_h * ny - (teeth_w/3) * ty) + + draw.polygon([p1, p2, p3, p4], fill=color) + + # Draw inner cutout (hole) + draw.ellipse([cx - r_in, cy - r_in, cx + r_in, cy + r_in], fill=(255, 255, 255, 255)) + +im = Image.open('scratch/logo_s_only.png') +draw = ImageDraw.Draw(im) +color = (29, 32, 47, 255) + +# Draw gear at cx=765, cy=205 +draw_gear(draw, cx=765, cy=205, r_out=45, r_in=18, teeth_count=8, teeth_h=15, teeth_w=18, color=color) + +im.save('scratch/admin_logo_test.png') +print("Saved admin logo to scratch/admin_logo_test.png") diff --git a/scratch/draw_wrench.py b/scratch/draw_wrench.py new file mode 100644 index 0000000..f9d671d --- /dev/null +++ b/scratch/draw_wrench.py @@ -0,0 +1,51 @@ +import math +from PIL import Image, ImageDraw + +def draw_wrench(draw, color): + # Centers + cx_open, cy_open = 810, 160 + cx_closed, cy_closed = 720, 250 + + # Draw shaft + # Direction vector from closed to open: (90, -90) + # Unit vector: dx = 0.7071, dy = -0.7071 + # Perpendicular vector: px = 0.7071, py = 0.7071 + dx, dy = 0.7071, -0.7071 + px, py = 0.7071, 0.7071 + half_w = 12 + + p1 = (cx_closed - half_w * px, cy_closed - half_w * py) + p2 = (cx_closed + half_w * px, cy_closed + half_w * py) + p3 = (cx_open + half_w * px, cy_open + half_w * py) + p4 = (cx_open - half_w * px, cy_open - half_w * py) + + draw.polygon([p1, p2, p3, p4], fill=color) + + # Draw open end outer circle + draw.ellipse([cx_open - 38, cy_open - 38, cx_open + 38, cy_open + 38], fill=color) + + # Draw closed end outer circle + draw.ellipse([cx_closed - 30, cy_closed - 30, cx_closed + 30, cy_closed + 30], fill=color) + + # Cut out the slot in open end (white polygon) + # Slot of width 22, length 50, starting at cx_open, cy_open and going in direction (dx, dy) + slot_half_w = 11 + s1 = (cx_open - slot_half_w * px, cy_open - slot_half_w * py) + s2 = (cx_open + slot_half_w * px, cy_open + slot_half_w * py) + s3 = (cx_open + 50 * dx + slot_half_w * px, cy_open + 50 * dy + slot_half_w * py) + s4 = (cx_open + 50 * dx - slot_half_w * px, cy_open + 50 * dy - slot_half_w * py) + draw.polygon([s1, s2, s3, s4], fill=(255, 255, 255, 255)) + + # Draw a small circle at the base of the slot to make it round and clean + draw.ellipse([cx_open - 11, cy_open - 11, cx_open + 11, cy_open + 11], fill=(255, 255, 255, 255)) + + # Cut out closed end inner hole (white circle) + draw.ellipse([cx_closed - 15, cy_closed - 15, cx_closed + 15, cy_closed + 15], fill=(255, 255, 255, 255)) + +im = Image.open('scratch/logo_s_only.png') +draw = ImageDraw.Draw(im) +color = (29, 32, 47, 255) + +draw_wrench(draw, color) +im.save('scratch/service_logo_test.png') +print("Saved service logo to scratch/service_logo_test.png") diff --git a/scratch/logo_s_only.png b/scratch/logo_s_only.png new file mode 100644 index 0000000..403f0a4 Binary files /dev/null and b/scratch/logo_s_only.png differ diff --git a/scratch/service_base.png b/scratch/service_base.png new file mode 100644 index 0000000..565d2e3 Binary files /dev/null and b/scratch/service_base.png differ diff --git a/scratch/service_logo_final.png b/scratch/service_logo_final.png new file mode 100644 index 0000000..6d2bb9d Binary files /dev/null and b/scratch/service_logo_final.png differ diff --git a/scratch/service_logo_test.png b/scratch/service_logo_test.png new file mode 100644 index 0000000..f1e262b Binary files /dev/null and b/scratch/service_logo_test.png differ diff --git a/scratch/service_logo_test_car.png b/scratch/service_logo_test_car.png new file mode 100644 index 0000000..4667831 Binary files /dev/null and b/scratch/service_logo_test_car.png differ diff --git a/scratch/service_logo_test_car_large.png b/scratch/service_logo_test_car_large.png new file mode 100644 index 0000000..565d2e3 Binary files /dev/null and b/scratch/service_logo_test_car_large.png differ diff --git a/siro_admin/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/siro_admin/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png index 3b80872..5f9413a 100644 Binary files a/siro_admin/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png and b/siro_admin/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png differ diff --git a/siro_admin/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/siro_admin/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png index 854ca42..6d6c4f1 100644 Binary files a/siro_admin/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png and b/siro_admin/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png differ diff --git a/siro_admin/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/siro_admin/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png index d9cf042..c4991ec 100644 Binary files a/siro_admin/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png and b/siro_admin/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png differ diff --git a/siro_admin/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/siro_admin/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png index 996b732..e8f8fb0 100644 Binary files a/siro_admin/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png and b/siro_admin/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png differ diff --git a/siro_admin/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/siro_admin/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png index 6e72033..73fb9f5 100644 Binary files a/siro_admin/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png and b/siro_admin/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png differ diff --git a/siro_admin/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/siro_admin/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 058ff77..4ba0684 100644 Binary files a/siro_admin/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/siro_admin/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/siro_admin/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/siro_admin/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 1f057e6..56ac3f2 100644 Binary files a/siro_admin/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/siro_admin/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/siro_admin/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/siro_admin/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index a630f85..8889413 100644 Binary files a/siro_admin/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/siro_admin/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/siro_admin/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/siro_admin/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 623ed7d..b157056 100644 Binary files a/siro_admin/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/siro_admin/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/siro_admin/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/siro_admin/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 0cee5b9..fa8a597 100644 Binary files a/siro_admin/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/siro_admin/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/siro_admin/assets/images/logo.png b/siro_admin/assets/images/logo.png index f2c92db..65c15a8 100644 Binary files a/siro_admin/assets/images/logo.png and b/siro_admin/assets/images/logo.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index c424645..5897f80 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index cdc178c..6fc6728 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 07b7120..f773a2e 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 538ed9b..6dc1c86 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index c880782..0b10880 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index 9996efe..a5aeb3a 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 7e23720..146359f 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 07b7120..f773a2e 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 90534ed..df17c09 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index d529f18..1ce1077 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png index c9fd50b..51c08d5 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png index 6ee10e4..d8d1d32 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png index ae13bae..b13d8e0 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png index 314886e..a4556fd 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index d529f18..1ce1077 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 95e83cd..d5c390d 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png index 058ff77..4ba0684 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png index 623ed7d..b157056 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index ee6b90a..4275a7a 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 30195ba..87c947a 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 206dd46..eb1b471 100644 Binary files a/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/siro_admin/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index c424645..5897f80 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index 6e5933f..1a50394 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png index 4c01f50..fa150ce 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index 353b935..233dbeb 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png index 7fe5fea..bb2fdc0 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png index d5bf6f5..dd95f4a 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png index 39777d2..080c502 100644 Binary files a/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and b/siro_admin/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/siro_admin/web/favicon.png b/siro_admin/web/favicon.png index 4c01f50..fa150ce 100644 Binary files a/siro_admin/web/favicon.png and b/siro_admin/web/favicon.png differ diff --git a/siro_admin/web/icons/Icon-192.png b/siro_admin/web/icons/Icon-192.png index 0cee5b9..fa8a597 100644 Binary files a/siro_admin/web/icons/Icon-192.png and b/siro_admin/web/icons/Icon-192.png differ diff --git a/siro_admin/web/icons/Icon-512.png b/siro_admin/web/icons/Icon-512.png index d5bf6f5..dd95f4a 100644 Binary files a/siro_admin/web/icons/Icon-512.png and b/siro_admin/web/icons/Icon-512.png differ diff --git a/siro_admin/web/icons/Icon-maskable-192.png b/siro_admin/web/icons/Icon-maskable-192.png index 0cee5b9..fa8a597 100644 Binary files a/siro_admin/web/icons/Icon-maskable-192.png and b/siro_admin/web/icons/Icon-maskable-192.png differ diff --git a/siro_admin/web/icons/Icon-maskable-512.png b/siro_admin/web/icons/Icon-maskable-512.png index d5bf6f5..dd95f4a 100644 Binary files a/siro_admin/web/icons/Icon-maskable-512.png and b/siro_admin/web/icons/Icon-maskable-512.png differ diff --git a/siro_admin/windows/runner/resources/app_icon.ico b/siro_admin/windows/runner/resources/app_icon.ico index c04e20c..cf4b97a 100644 Binary files a/siro_admin/windows/runner/resources/app_icon.ico and b/siro_admin/windows/runner/resources/app_icon.ico differ diff --git a/siro_driver/lib/constant/links.dart b/siro_driver/lib/constant/links.dart index 195b33d..9eaa091 100755 --- a/siro_driver/lib/constant/links.dart +++ b/siro_driver/lib/constant/links.dart @@ -197,6 +197,8 @@ class AppLink { // ================= Gamification Endpoints ================= static String get getWeeklyAggregate => "$endPoint/ride/gamification/getWeeklyAggregate.php"; + static String get getGamificationDashboard => + "$endPoint/ride/gamification/getGamificationDashboard.php"; static String get getLeaderboard => "$endPoint/ride/gamification/getLeaderboard.php"; static String get claimChallengeReward => diff --git a/siro_driver/lib/controller/gamification/challenges_controller.dart b/siro_driver/lib/controller/gamification/challenges_controller.dart index 765e6a9..7172352 100644 --- a/siro_driver/lib/controller/gamification/challenges_controller.dart +++ b/siro_driver/lib/controller/gamification/challenges_controller.dart @@ -47,9 +47,6 @@ class Challenge { } // ════════════════════════════════════════════ -// Controller -// ════════════════════════════════════════════ - class ChallengesController extends GetxController { bool isLoading = false; List dailyChallenges = []; @@ -66,6 +63,47 @@ class ChallengesController extends GetxController { void _generateChallenges() { final now = DateTime.now(); final isWeekend = now.weekday == 5 || now.weekday == 6; // الجمعة والسبت + String country = box.read(BoxName.countryCode) ?? 'Jordan'; + + int dailyEarningsTarget; + int dailyEarningsReward; + int weeklyEarningsTarget; + int weeklyEarningsReward; + + String dailyEarningsDescAr; + String dailyEarningsDescEn; + String weeklyEarningsDescAr; + String weeklyEarningsDescEn; + + if (country == 'Syria') { + dailyEarningsTarget = 150000; + dailyEarningsReward = 100; // 100 pts -> 10,000 SYP + weeklyEarningsTarget = 1000000; + weeklyEarningsReward = 500; // 500 pts -> 50,000 SYP + dailyEarningsDescAr = 'اربح 150,000 ل.س اليوم'; + dailyEarningsDescEn = 'Earn 150,000 SYP today'; + weeklyEarningsDescAr = 'اربح 1,000,000 ل.س هذا الأسبوع'; + weeklyEarningsDescEn = 'Earn 1,000,000 SYP this week'; + } else if (country == 'Egypt') { + dailyEarningsTarget = 300; + dailyEarningsReward = 30; // 30 pts -> 30 EGP + weeklyEarningsTarget = 2000; + weeklyEarningsReward = 200; // 200 pts -> 200 EGP + dailyEarningsDescAr = 'اربح 300 ج.م اليوم'; + dailyEarningsDescEn = 'Earn 300 EGP today'; + weeklyEarningsDescAr = 'اربح 2000 ج.م هذا الأسبوع'; + weeklyEarningsDescEn = 'Earn 2000 EGP this week'; + } else { + // Jordan / default + dailyEarningsTarget = 30; + dailyEarningsReward = 60; // 60 pts -> 3 JOD (60 * 0.05 = 3 JOD) + weeklyEarningsTarget = 200; + weeklyEarningsReward = 400; // 400 pts -> 20 JOD (400 * 0.05 = 20 JOD) + dailyEarningsDescAr = 'اربح 30 د.أ اليوم'; + dailyEarningsDescEn = 'Earn 30 JOD today'; + weeklyEarningsDescAr = 'اربح 200 د.أ هذا الأسبوع'; + weeklyEarningsDescEn = 'Earn 200 JOD this week'; + } dailyChallenges = [ Challenge( @@ -77,7 +115,7 @@ class ChallengesController extends GetxController { icon: Icons.local_taxi_rounded, color: const Color(0xFF2196F3), target: 5, - reward: 50, + reward: country == 'Syria' ? 50 : (country == 'Egypt' ? 50 : 100), type: 'daily', metric: 'trips', ), @@ -90,7 +128,7 @@ class ChallengesController extends GetxController { icon: Icons.directions_car_rounded, color: const Color(0xFFFF9800), target: 10, - reward: 150, + reward: country == 'Syria' ? 150 : (country == 'Egypt' ? 150 : 300), type: 'daily', metric: 'trips', ), @@ -98,12 +136,12 @@ class ChallengesController extends GetxController { id: 'daily_earnings', titleEn: 'Money Maker', titleAr: 'صانع المال', - descriptionEn: 'Earn 3000 ${CurrencyHelper.currency} today', - descriptionAr: 'اربح 3000 ل.س اليوم', + descriptionEn: dailyEarningsDescEn, + descriptionAr: dailyEarningsDescAr, icon: Icons.monetization_on_rounded, color: const Color(0xFF4CAF50), - target: 3000, - reward: 100, + target: dailyEarningsTarget, + reward: dailyEarningsReward, type: 'daily', metric: 'earnings', ), @@ -117,7 +155,7 @@ class ChallengesController extends GetxController { icon: Icons.celebration_rounded, color: const Color(0xFFE91E63), target: 8, - reward: 200, + reward: country == 'Syria' ? 200 : (country == 'Egypt' ? 200 : 400), type: 'daily', metric: 'trips', ), @@ -133,7 +171,7 @@ class ChallengesController extends GetxController { icon: Icons.emoji_events_rounded, color: const Color(0xFFFFD700), target: 30, - reward: 300, + reward: country == 'Syria' ? 300 : (country == 'Egypt' ? 300 : 600), type: 'weekly', metric: 'trips', ), @@ -141,12 +179,12 @@ class ChallengesController extends GetxController { id: 'weekly_earnings', titleEn: 'Big Earner', titleAr: 'الربح الكبير', - descriptionEn: 'Earn 20,000 ${CurrencyHelper.currency} this week', - descriptionAr: 'اربح 20,000 ل.س هذا الأسبوع', + descriptionEn: weeklyEarningsDescEn, + descriptionAr: weeklyEarningsDescAr, icon: Icons.account_balance_wallet_rounded, color: const Color(0xFF9C27B0), - target: 20000, - reward: 500, + target: weeklyEarningsTarget, + reward: weeklyEarningsReward, type: 'weekly', metric: 'earnings', ), @@ -159,10 +197,10 @@ class ChallengesController extends GetxController { icon: Icons.timer_rounded, color: const Color(0xFF00BCD4), target: 20, - reward: 400, + reward: country == 'Syria' ? 400 : (country == 'Egypt' ? 400 : 800), type: 'weekly', metric: 'hours', - ), + ) ]; } @@ -203,8 +241,12 @@ class ChallengesController extends GetxController { if (todayRes != null && todayRes != 'failure') { var data = jsonDecode(todayRes); - todayEarnings = double.tryParse(data['message']?[0]?['todayAmount']?.toString() ?? '0') ?? 0; - todayTrips = int.tryParse(data['message']?[0]?['todayCount']?.toString() ?? '0') ?? 0; + todayEarnings = double.tryParse( + data['message']?[0]?['todayAmount']?.toString() ?? '0') ?? + 0; + todayTrips = int.tryParse( + data['message']?[0]?['todayCount']?.toString() ?? '0') ?? + 0; } // تحديث التحديات اليومية @@ -229,7 +271,9 @@ class ChallengesController extends GetxController { if (weeklyEarningsRes != null && weeklyEarningsRes != 'failure') { var data = jsonDecode(weeklyEarningsRes); if (data['message'] is List && data['message'].isNotEmpty) { - weeklyEarnings = double.tryParse(data['message'][0]['totalAmount']?.toString() ?? '0') ?? 0; + weeklyEarnings = double.tryParse( + data['message'][0]['totalAmount']?.toString() ?? '0') ?? + 0; } } @@ -247,7 +291,8 @@ class ChallengesController extends GetxController { if (data['message'] is List) { for (var day in data['message']) { weeklyTrips += int.tryParse(day['trips']?.toString() ?? '0') ?? 0; - weeklyHours += double.tryParse(day['hours']?.toString() ?? '0') ?? 0; + weeklyHours += + double.tryParse(day['hours']?.toString() ?? '0') ?? 0; } } } @@ -273,8 +318,18 @@ class ChallengesController extends GetxController { update(); } + final Set _claimingChallenges = {}; + + bool isClaiming(String challengeId) => + _claimingChallenges.contains(challengeId); + Future claimReward(Challenge challenge) async { - if (!challenge.isCompleted || challenge.isClaimed) return; + if (!challenge.isCompleted || + challenge.isClaimed || + _claimingChallenges.contains(challenge.id)) return; + + _claimingChallenges.add(challenge.id); + update(); try { var res = await CRUD().post( @@ -290,10 +345,12 @@ class ChallengesController extends GetxController { challenge.isClaimed = true; box.write('challenge_${challenge.id}_claimed', true); debugPrint('🎉 Claimed ${challenge.reward} points for ${challenge.id}'); - update(); } } catch (e) { debugPrint('❌ [Challenges] Claim error: $e'); + } finally { + _claimingChallenges.remove(challenge.id); + update(); } } } diff --git a/siro_driver/lib/controller/gamification/gamification_controller.dart b/siro_driver/lib/controller/gamification/gamification_controller.dart index ee4fd1a..38da89e 100644 --- a/siro_driver/lib/controller/gamification/gamification_controller.dart +++ b/siro_driver/lib/controller/gamification/gamification_controller.dart @@ -191,6 +191,27 @@ class GamificationController extends GetxController { dailyGoal = (box.read('dailyGoal') ?? 0).toDouble(); totalTrips = box.read('gamification_totalTrips') ?? 0; consecutiveDays = box.read('gamification_consecutiveDays') ?? 0; + averageRating = (box.read('gamification_averageRating') ?? 5.0).toDouble(); + totalPoints = box.read('gamification_totalPoints') ?? 0; + totalReferrals = box.read('gamification_totalReferrals') ?? 0; + dailyEarnings = (box.read('gamification_dailyEarnings') ?? 0.0).toDouble(); + behaviorScore = (box.read('gamification_behaviorScore') ?? 100.0).toDouble(); + hardBrakes = box.read('gamification_hardBrakes') ?? 0; + maxSpeed = (box.read('gamification_maxSpeed') ?? 0.0).toDouble(); + } + + // ═══════ حفظ البيانات المحلية (التخزين المؤقت) ═══════ + void _saveLocalData() { + box.write('gamification_totalTrips', totalTrips); + box.write('gamification_consecutiveDays', consecutiveDays); + box.write('gamification_averageRating', averageRating); + box.write('gamification_totalPoints', totalPoints); + box.write('gamification_totalReferrals', totalReferrals); + box.write('gamification_dailyEarnings', dailyEarnings); + box.write('gamification_behaviorScore', behaviorScore); + box.write('gamification_hardBrakes', hardBrakes); + box.write('gamification_maxSpeed', maxSpeed); + box.write('gamification_last_fetch', DateTime.now().toIso8601String()); } // ═══════ حفظ الهدف اليومي ═══════ @@ -330,85 +351,45 @@ class GamificationController extends GetxController { } // ═══════ جلب البيانات من السيرفر ═══════ - Future fetchGamificationData() async { + Future fetchGamificationData({bool force = false}) async { + // التحقق من التخزين المؤقت (6 ساعات) + String? lastFetchStr = box.read('gamification_last_fetch'); + if (!force && lastFetchStr != null) { + try { + DateTime lastFetch = DateTime.parse(lastFetchStr); + if (DateTime.now().difference(lastFetch).inHours < 6) { + debugPrint('ℹ️ [Gamification] Loading cached data (last fetch: $lastFetchStr)'); + _loadLocalData(); + _calculateLevel(); + _updateAchievementProgress(); + return; + } + } catch (e) { + debugPrint('⚠️ [Gamification] Failed to parse last fetch time: $e'); + } + } + isLoading = true; update(); try { - // 1. جلب عدد الرحلات الكلي - var tripRes = await CRUD().get( - link: AppLink.getTripCountByCaptain, + var res = await CRUD().get( + link: AppLink.getGamificationDashboard, payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); - if (tripRes != null && tripRes != 'failure') { - var data = jsonDecode(tripRes); - totalTrips = - int.tryParse(data['message']?[0]?['count']?.toString() ?? '0') ?? 0; - box.write('gamification_totalTrips', totalTrips); - } - // 2. جلب التقييم - var rateRes = await CRUD().get( - link: AppLink.getDriverRate, - payload: {'driver_id': box.read(BoxName.driverID).toString()}, - ); - if (rateRes != null && rateRes != 'failure') { - var data = jsonDecode(rateRes); - averageRating = - double.tryParse(data['message']?[0]?['rating']?.toString() ?? '5') ?? - 5.0; - } - - // 3. جلب النقاط (الرصيد) - var pointsRes = await CRUD().getWallet( - link: AppLink.getDriverPaymentPoints, - payload: {'driverID': box.read(BoxName.driverID).toString()}, - ); - if (pointsRes != null && pointsRes != 'failure') { - var data = jsonDecode(pointsRes); - totalPoints = double.tryParse( - data['message']?[0]?['total_amount']?.toString() ?? '0') - ?.abs() - .toInt() ?? - 0; - } - - // 4. جلب عدد الدعوات - var invRes = await CRUD().get( - link: AppLink.getInviteDriver, - payload: {'driver_id': box.read(BoxName.driverID).toString()}, - ); - if (invRes != null && invRes != 'failure') { - var data = jsonDecode(invRes); - if (data['message'] is List) { - totalReferrals = (data['message'] as List).length; - } - } - - // 5. جلب أرباح اليوم - var todayRes = await CRUD().getWallet( - link: AppLink.getDriverPaymentToday, - payload: {'driverID': box.read(BoxName.driverID).toString()}, - ); - if (todayRes != null && todayRes != 'failure') { - var data = jsonDecode(todayRes); - dailyEarnings = double.tryParse( - data['message']?[0]?['todayAmount']?.toString() ?? '0') ?? - 0; - } - - // 6. جلب تقييم سلوك القيادة - var behaviorRes = await CRUD().get( - link: AppLink.getDriverBehavior, - payload: {'driver_id': box.read(BoxName.driverID).toString()}, - ); - if (behaviorRes != null && behaviorRes != 'failure') { - var data = jsonDecode(behaviorRes); - if (data['message'] is List && data['message'].isNotEmpty) { - var behavior = data['message'][0]; - behaviorScore = double.tryParse(behavior['avg_score']?.toString() ?? '100') ?? 100.0; - hardBrakes = int.tryParse(behavior['total_hard_brakes']?.toString() ?? '0') ?? 0; - maxSpeed = double.tryParse(behavior['max_speed']?.toString() ?? '0') ?? 0.0; + if (res != null && res != 'failure') { + var data = jsonDecode(res); + if (data['status'] == 'success' && data['message'] != null) { + var details = data['message']; + totalTrips = int.tryParse(details['totalTrips']?.toString() ?? '0') ?? 0; + averageRating = double.tryParse(details['averageRating']?.toString() ?? '5.0') ?? 5.0; + totalReferrals = int.tryParse(details['totalReferrals']?.toString() ?? '0') ?? 0; + dailyEarnings = double.tryParse(details['todayEarnings']?.toString() ?? '0.0') ?? 0.0; + behaviorScore = double.tryParse(details['behaviorScore']?.toString() ?? '100.0') ?? 100.0; + hardBrakes = int.tryParse(details['hardBrakes']?.toString() ?? '0') ?? 0; + maxSpeed = double.tryParse(details['maxSpeed']?.toString() ?? '0.0') ?? 0.0; + totalPoints = int.tryParse(details['totalPoints']?.toString() ?? '0') ?? 0; } } @@ -420,6 +401,7 @@ class GamificationController extends GetxController { _calculateLevel(); _updateAchievementProgress(); + _saveLocalData(); isLoading = false; update(); } diff --git a/siro_driver/lib/controller/home/captin/help/video_controller.dart b/siro_driver/lib/controller/home/captin/help/video_controller.dart index 65e0b0b..54744e8 100755 --- a/siro_driver/lib/controller/home/captin/help/video_controller.dart +++ b/siro_driver/lib/controller/home/captin/help/video_controller.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:siro_driver/constant/links.dart'; +import 'package:siro_driver/main.dart'; import 'package:siro_driver/controller/functions/crud.dart'; import 'package:siro_driver/print.dart'; import 'package:siro_driver/views/widgets/error_snakbar.dart'; @@ -50,12 +51,35 @@ class VideoController extends GetxController { super.onClose(); } - void fetchVideos() async { + void fetchVideos({bool force = false}) async { + final String cacheKey = 'video_list_cache'; + final String lastFetchKey = 'video_last_fetch'; + + if (!force) { + String? cachedVideos = box.read(cacheKey); + String? lastFetchStr = box.read(lastFetchKey); + + if (cachedVideos != null && lastFetchStr != null) { + try { + DateTime lastFetch = DateTime.parse(lastFetchStr); + if (DateTime.now().difference(lastFetch).inHours < 3) { + videos = jsonDecode(cachedVideos); + isLoading(false); + update(); + return; + } + } catch (e) { + Log.print('⚠️ [VideoController] Failed to parse cache: $e'); + } + } + } + try { var res = await CRUD().get(link: apiUrl, payload: {}); if (res != 'failure') { videos = jsonDecode(res)['message']; - // Log.print('videos: ${videos}'); + box.write(cacheKey, jsonEncode(videos)); + box.write(lastFetchKey, DateTime.now().toIso8601String()); update(); } else { mySnackeBarError(''); diff --git a/siro_driver/lib/controller/home/statistics/statistics_controller.dart b/siro_driver/lib/controller/home/statistics/statistics_controller.dart index 8bcbdd7..bef6175 100644 --- a/siro_driver/lib/controller/home/statistics/statistics_controller.dart +++ b/siro_driver/lib/controller/home/statistics/statistics_controller.dart @@ -54,6 +54,7 @@ class StatisticsController extends GetxController { ); if (res != null && res != 'failure') { + box.write('stats_weekly_cache', res); var data = jsonDecode(res); if (data['message'] is List) { weeklyStats = (data['message'] as List) @@ -83,6 +84,7 @@ class StatisticsController extends GetxController { payload: {'driverID': box.read(BoxName.driverID).toString()}, ); if (earningsRes != null && earningsRes != 'failure') { + box.write('stats_monthly_earnings_cache', earningsRes); var data = jsonDecode(earningsRes); if (data['message'] is List) { monthlyEarnings = (data['message'] as List) @@ -107,6 +109,7 @@ class StatisticsController extends GetxController { payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); if (ridesRes != null && ridesRes != 'failure') { + box.write('stats_monthly_rides_cache', ridesRes); var data = jsonDecode(ridesRes); if (data['message'] is List) { monthlyRides = (data['message'] as List) @@ -122,6 +125,7 @@ class StatisticsController extends GetxController { payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); if (durationRes != null && durationRes != 'failure') { + box.write('stats_monthly_duration_cache', durationRes); var data = jsonDecode(durationRes); if (data['message'] is List) { monthlyDuration = (data['message'] as List) @@ -160,16 +164,93 @@ class StatisticsController extends GetxController { bool _isFetching = false; - Future reloadData() async { + Future reloadData({bool force = false}) async { if (_isFetching) return; _isFetching = true; + + // التحقق من التخزين المؤقت (3 ساعات) + String? lastFetchStr = box.read('stats_last_fetch'); + if (!force && lastFetchStr != null) { + try { + DateTime lastFetch = DateTime.parse(lastFetchStr); + if (DateTime.now().difference(lastFetch).inHours < 3) { + debugPrint('ℹ️ [Statistics] Loading cached statistics (last fetch: $lastFetchStr)'); + + // تحميل الكاش الأسبوعي + String? weeklyCache = box.read('stats_weekly_cache'); + if (weeklyCache != null) { + var data = jsonDecode(weeklyCache); + if (data['message'] is List) { + weeklyStats = (data['message'] as List) + .map((e) => DayStat.fromJson(e)) + .toList(); + weeklyEarnings = weeklyStats.fold(0, (s, d) => s + d.earnings); + weeklyTrips = weeklyStats.fold(0, (s, d) => s + d.trips); + weeklyHours = weeklyStats.fold(0, (s, d) => s + d.hours); + } + } + + // تحميل الكاش الشهري (الأرباح) + String? earningsCache = box.read('stats_monthly_earnings_cache'); + if (earningsCache != null) { + var data = jsonDecode(earningsCache); + if (data['message'] is List) { + monthlyEarnings = (data['message'] as List) + .map((e) => MonthlyPriceDriverModel.fromJson(e)) + .toList(); + monthlyTotalEarnings = + monthlyEarnings.fold(0, (s, d) => s + d.pricePerDay); + if (monthlyEarnings.isNotEmpty) { + var best = monthlyEarnings + .reduce((a, b) => a.pricePerDay > b.pricePerDay ? a : b); + bestDay = best.day.toString(); + bestDayEarnings = best.pricePerDay; + } + } + } + + // تحميل الكاش الشهري (الرحلات) + String? ridesCache = box.read('stats_monthly_rides_cache'); + if (ridesCache != null) { + var data = jsonDecode(ridesCache); + if (data['message'] is List) { + monthlyRides = (data['message'] as List) + .map((e) => MonthlyRideModel.fromJson(e)) + .toList(); + monthlyTotalTrips = monthlyRides.fold(0, (s, d) => s + d.countRide); + } + } + + // تحميل الكاش الشهري (المدد) + String? durationCache = box.read('stats_monthly_duration_cache'); + if (durationCache != null) { + var data = jsonDecode(durationCache); + if (data['message'] is List) { + monthlyDuration = (data['message'] as List) + .map((e) => MonthlyDataModel.fromJson(e)) + .toList(); + monthlyTotalHours = + monthlyDuration.fold(0, (s, d) => s + d.totalDuration.toDouble()); + } + } + + _isFetching = false; + update(); + return; + } + } catch (e) { + debugPrint('⚠️ [Statistics] Failed to load cached statistics: $e'); + } + } + isLoading = true; update(); try { - debugPrint('📊 [Statistics] Reloading data...'); + debugPrint('📊 [Statistics] Reloading data from server...'); await fetchWeeklyData(); await fetchMonthlyData(); + box.write('stats_last_fetch', DateTime.now().toIso8601String()); debugPrint('📊 [Statistics] Data reload complete.'); } catch (e) { debugPrint('❌ [Statistics] Error reloading data: $e'); diff --git a/siro_driver/lib/views/gamification/challenges_page.dart b/siro_driver/lib/views/gamification/challenges_page.dart index aa413b4..694b01b 100644 --- a/siro_driver/lib/views/gamification/challenges_page.dart +++ b/siro_driver/lib/views/gamification/challenges_page.dart @@ -196,9 +196,18 @@ class ChallengesPage extends StatelessWidget { SizedBox( width: double.infinity, child: ElevatedButton.icon( - onPressed: () => cc.claimReward(c), - icon: const Icon(Icons.card_giftcard_rounded, size: 18), - label: Text('Claim Reward'.tr), + onPressed: cc.isClaiming(c.id) ? null : () => cc.claimReward(c), + icon: cc.isClaiming(c.id) + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator( + color: Colors.white, + strokeWidth: 2, + ), + ) + : const Icon(Icons.card_giftcard_rounded, size: 18), + label: Text(cc.isClaiming(c.id) ? 'Claiming...'.tr : 'Claim Reward'.tr), style: ElevatedButton.styleFrom( backgroundColor: c.color, foregroundColor: Colors.white, diff --git a/siro_driver/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart b/siro_driver/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart index a859190..89eb7f9 100755 --- a/siro_driver/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart +++ b/siro_driver/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart @@ -16,6 +16,7 @@ import '../../../../../controller/functions/crud.dart'; import '../../../../../controller/home/captin/order_request_controller.dart'; import '../../../../../print.dart'; import '../../../../Rate/ride_calculate_driver.dart'; +import 'package:siro_driver/views/home/statistics/statistics_dashboard.dart'; // ───────────────────────────────────────────── // Design Tokens (Responsive) @@ -105,34 +106,9 @@ GetBuilder leftMainMenuCaptainIcons() { _MenuIcon( icon: FontAwesome5.chart_bar, color: _T.blue, - tooltip: 'Earnings'.tr, + tooltip: 'Statistics'.tr, onTap: () { - final now = DateTime.now(); - final lastTimeRaw = box.read(BoxName.lastTimeStaticThrottle); - DateTime? lastTime; - - if (lastTimeRaw != null) { - try { - lastTime = DateTime.parse(lastTimeRaw.toString()); - } catch (_) { - lastTime = null; - } - } - - if (lastTime == null || - now.difference(lastTime).inMinutes >= 2) { - box.write( - BoxName.lastTimeStaticThrottle, now.toIso8601String()); - Get.to(() => RideCalculateDriver()); - } else { - final left = 2 - now.difference(lastTime).inMinutes; - NotificationController().showNotification( - 'Siro Driver'.tr, - '${'Please wait'.tr} $left ${"minutes before trying again.".tr}', - 'ding', - '', - ); - } + Get.to(() => StatisticsDashboard()); }, onLongPress: () => box.write(BoxName.statusDriverLocation, 'off'), diff --git a/siro_driver/lib/views/home/statistics/statistics_dashboard.dart b/siro_driver/lib/views/home/statistics/statistics_dashboard.dart index a50a88b..f8c6048 100644 --- a/siro_driver/lib/views/home/statistics/statistics_dashboard.dart +++ b/siro_driver/lib/views/home/statistics/statistics_dashboard.dart @@ -53,7 +53,10 @@ class StatisticsDashboard extends StatelessWidget { IconButton( icon: const Icon(Icons.refresh_rounded, color: Colors.white), - onPressed: () => gc.fetchGamificationData(), + onPressed: () { + gc.fetchGamificationData(force: true); + sc.reloadData(force: true); + }, ), ], flexibleSpace: FlexibleSpaceBar( diff --git a/siro_rider/lib/constant/box_name.dart b/siro_rider/lib/constant/box_name.dart index 56dce6a..7f7140e 100644 --- a/siro_rider/lib/constant/box_name.dart +++ b/siro_rider/lib/constant/box_name.dart @@ -42,6 +42,7 @@ class BoxName { static const String addHome = 'addHome'; static const String placesDestination = 'placesDestination'; static const String tipPercentage = 'tipPercentage'; + static const String lastLocationPush = 'lastLocationPush'; static const String faceDetectTimes = "faceDetectTimes"; static const String sosPhonePassenger = "sosPhonePassenger"; diff --git a/siro_rider/lib/constant/links.dart b/siro_rider/lib/constant/links.dart index c25b700..10ee84f 100644 --- a/siro_rider/lib/constant/links.dart +++ b/siro_rider/lib/constant/links.dart @@ -404,6 +404,7 @@ static String get loginFirstTime => "$server/loginFirstTime.php"; static String get getTesterApp => "$auth/Tester/getTesterApp.php"; static String get updateTesterApp => "$auth/Tester/updateTesterApp.php"; static String get signUp => "$auth/signup.php"; +static String get savePassengerLocation => "$auth/save_passenger_location.php"; static String get sendVerifyEmail => "$auth/sendVerifyEmail.php"; static String get loginFromGooglePassenger => "$auth/loginFromGooglePassenger.php"; static String get loginUsingCredentialsWithoutGooglePassenger => "$auth/loginUsingCredentialsWithoutGooglePassenger.php"; diff --git a/siro_rider/lib/controller/auth/login_controller.dart b/siro_rider/lib/controller/auth/login_controller.dart index 2eb3166..cc3bf36 100644 --- a/siro_rider/lib/controller/auth/login_controller.dart +++ b/siro_rider/lib/controller/auth/login_controller.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:geolocator/geolocator.dart'; import 'package:siro_rider/constant/api_key.dart'; import 'package:siro_rider/controller/firebase/firbase_messge.dart'; import 'package:siro_rider/views/auth/otp_page.dart'; @@ -422,6 +423,7 @@ class LoginController extends GetxController { } } + sendPassengerLocation(); Get.offAll(() => const MapPagePassenger()); } catch (e) { addError('$e', 'loginUsingCredentials'); @@ -484,6 +486,7 @@ class LoginController extends GetxController { await storage.write(key: BoxName.fingerPrint, value: fingerPrint); + sendPassengerLocation(); Get.offAll(() => const MapPagePassenger()); } else { Get.offAll(() => LoginPage()); @@ -539,4 +542,76 @@ class LoginController extends GetxController { } update(); } + + // ───────────────────────────────────────────────────────────── + // sendPassengerLocation: تسجيل موقع فتح التطبيق للراكب + // ───────────────────────────────────────────────────────────── + Future sendPassengerLocation() async { + try { + final String? passengerID = box.read(BoxName.passengerID)?.toString(); + if (passengerID == null || passengerID.isEmpty) { + Log.print("sendPassengerLocation: No passenger ID found, skipping."); + return; + } + + // ── [THROTTLING] تحديث الموقع مرة كل 12 ساعة فقط لتقليل الضغط ── + final String cacheKey = '${BoxName.lastLocationPush}_$passengerID'; + final String? lastUploadStr = box.read(cacheKey); + if (lastUploadStr != null) { + final DateTime lastUpload = DateTime.parse(lastUploadStr); + final Duration diff = DateTime.now().difference(lastUpload); + if (diff.inHours < 12) { + Log.print("sendPassengerLocation: Location uploaded recently (${diff.inHours}h ago). Skipping."); + return; + } + } + + // تحقق من تفعيل خدمات الموقع الجغرافي + bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + Log.print("sendPassengerLocation: Location service disabled."); + return; + } + + // التحقق من الصلاحيات والسكوت الممنهج لتفادي النوافذ المزعجة + LocationPermission permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + Log.print("sendPassengerLocation: Permission is denied. Skipping silently."); + return; + } + if (permission == LocationPermission.deniedForever) { + Log.print("sendPassengerLocation: Permission permanently denied. Skipping silently."); + return; + } + + // جلب الموقع الحالي بمهلة 5 ثوانٍ + final Position position = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.medium, + timeLimit: const Duration(seconds: 5), + ); + + Log.print("sendPassengerLocation: Got location: ${position.latitude}, ${position.longitude}"); + + // إرسال البيانات إلى السيرفر + final response = await CRUD().post( + link: AppLink.savePassengerLocation, + payload: { + 'latitude': position.latitude.toString(), + 'longitude': position.longitude.toString(), + }, + ); + + Log.print("sendPassengerLocation response: $response"); + + if (response != 'failure' && response != null) { + final decoded = response is Map ? response : jsonDecode(response.toString()); + if (decoded['status'] == 'success') { + box.write(cacheKey, DateTime.now().toIso8601String()); + Log.print("sendPassengerLocation: Location logged and cached successfully."); + } + } + } catch (e) { + Log.print("sendPassengerLocation error: $e"); + } + } } diff --git a/siro_service/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/siro_service/android/app/src/main/res/mipmap-hdpi/launcher_icon.png index d74d5a3..2f0075c 100644 Binary files a/siro_service/android/app/src/main/res/mipmap-hdpi/launcher_icon.png and b/siro_service/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/siro_service/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/siro_service/android/app/src/main/res/mipmap-mdpi/launcher_icon.png index ad27029..ee373c7 100644 Binary files a/siro_service/android/app/src/main/res/mipmap-mdpi/launcher_icon.png and b/siro_service/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/siro_service/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/siro_service/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png index e271a05..1e21e2e 100644 Binary files a/siro_service/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png and b/siro_service/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/siro_service/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/siro_service/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png index 808c654..520052a 100644 Binary files a/siro_service/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png and b/siro_service/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/siro_service/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/siro_service/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png index 873fa38..05f1ad3 100644 Binary files a/siro_service/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png and b/siro_service/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/siro_service/assets/images/logo.png b/siro_service/assets/images/logo.png index 4494193..6d2bb9d 100644 Binary files a/siro_service/assets/images/logo.png and b/siro_service/assets/images/logo.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 1201d04..ca5a5ed 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 326d36f..c04c681 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index d5ed1cb..eab3b32 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 3d62031..17890c6 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index ba732d9..00d4cb4 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index 6322e5f..e961994 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 8d51586..9ab9265 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index d5ed1cb..eab3b32 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 22ac691..bc2e5a2 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index e3bf61f..b64b055 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png index 7bb31e5..a6befb3 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png index ef1c465..376c867 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png index 57fddd5..1a85cef 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png index 33cc738..5c568fa 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index e3bf61f..b64b055 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 4f37147..6cac0f1 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png index d74d5a3..2f0075c 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png index 808c654..520052a 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 53baaf3..9ba71a1 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index f5b588d..d142a09 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 06c88a1..0a4c2a5 100644 Binary files a/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/siro_service/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index 1201d04..ca5a5ed 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index 12fc7ef..47ef1df 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png index fa89e26..b1573f4 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index 0be5f8e..a166d7b 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png index 71a60ee..ba334af 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png index 09711c7..500ce9b 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png index c6a08a5..6260aee 100644 Binary files a/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and b/siro_service/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/siro_service/web/favicon.png b/siro_service/web/favicon.png index fa89e26..b1573f4 100644 Binary files a/siro_service/web/favicon.png and b/siro_service/web/favicon.png differ diff --git a/siro_service/web/icons/Icon-192.png b/siro_service/web/icons/Icon-192.png index 873fa38..05f1ad3 100644 Binary files a/siro_service/web/icons/Icon-192.png and b/siro_service/web/icons/Icon-192.png differ diff --git a/siro_service/web/icons/Icon-512.png b/siro_service/web/icons/Icon-512.png index 09711c7..500ce9b 100644 Binary files a/siro_service/web/icons/Icon-512.png and b/siro_service/web/icons/Icon-512.png differ diff --git a/siro_service/web/icons/Icon-maskable-192.png b/siro_service/web/icons/Icon-maskable-192.png index 873fa38..05f1ad3 100644 Binary files a/siro_service/web/icons/Icon-maskable-192.png and b/siro_service/web/icons/Icon-maskable-192.png differ diff --git a/siro_service/web/icons/Icon-maskable-512.png b/siro_service/web/icons/Icon-maskable-512.png index 09711c7..500ce9b 100644 Binary files a/siro_service/web/icons/Icon-maskable-512.png and b/siro_service/web/icons/Icon-maskable-512.png differ diff --git a/siro_service/windows/runner/resources/app_icon.ico b/siro_service/windows/runner/resources/app_icon.ico index c04e20c..7de0f81 100644 Binary files a/siro_service/windows/runner/resources/app_icon.ico and b/siro_service/windows/runner/resources/app_icon.ico differ diff --git a/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/add_s2s_reward.php b/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/add_s2s_reward.php new file mode 100644 index 0000000..2cf8582 --- /dev/null +++ b/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/add_s2s_reward.php @@ -0,0 +1,103 @@ +beginTransaction(); + + // Prevent duplicate challenge claims using paymentsDriverPoints table + if (strpos($paymentMethod, 'daily_') === 0 || strpos($paymentMethod, 'weekly_') === 0) { + $checkSql = "SELECT id FROM paymentsDriverPoints WHERE driverID = :driver_id AND payment_method = :challenge_id AND DATE(created_at) = CURDATE() FOR UPDATE"; + $stmtCheck = $con->prepare($checkSql); + $stmtCheck->execute([ + ':driver_id' => $driverID, + ':challenge_id' => $paymentMethod + ]); + + if ($stmtCheck->rowCount() > 0) { + $con->rollBack(); + printFailure("Reward already claimed today"); + exit(); + } + } + + $sql = "INSERT INTO `driverWallet` ( + `driverID`, + `paymentID`, + `amount`, + `paymentMethod` + ) VALUES ( + :driverID, + :paymentID, + :amount, + :paymentMethod + );"; + + $stmt = $con->prepare($sql); + $stmt->execute([ + ':driverID' => $driverID, + ':paymentID' => $paymentID, + ':amount' => $amount, + ':paymentMethod' => $paymentMethod + ]); + + if ($stmt->rowCount() > 0) { + // If points are provided, also insert into paymentsDriverPoints + if (!empty($points)) { + $sqlPoints = "INSERT INTO `paymentsDriverPoints` ( + `amount`, + `payment_method`, + `driverID` + ) VALUES ( + :points, + :paymentMethod, + :driverID + );"; + $stmtPoints = $con->prepare($sqlPoints); + $stmtPoints->execute([ + ':points' => $points, + ':paymentMethod' => $paymentMethod, + ':driverID' => $driverID + ]); + } + + $con->commit(); + printSuccess("Record saved successfully"); + } else { + $con->rollBack(); + printFailure("Failed to save record"); + } +} catch (Exception $e) { + if ($con->inTransaction()) { + $con->rollBack(); + } + printFailure("An error occurred: " . $e->getMessage()); +} +?> diff --git a/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php b/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php new file mode 100644 index 0000000..21b1eeb --- /dev/null +++ b/walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/get_s2s_wallet_dashboard.php @@ -0,0 +1,67 @@ +prepare(" + SELECT COALESCE(SUM(amount), 0) + FROM `paymentsDriverPoints` + WHERE driverID = :driver_id + AND (payment_method LIKE 'daily_%' OR payment_method LIKE 'weekly_%') + "); + $stmtChallengePoints->execute([':driver_id' => $driverID]); + $challengePoints = (int)($stmtChallengePoints->fetchColumn() ?: 0); + + // 2. Calculate Today's Earnings + $stmtTodayEarnings = $con->prepare(" + SELECT COALESCE(SUM(amount), 0) + FROM payments + WHERE driverID = :driver_id + AND DATE(created_at) = CURDATE() + "); + $stmtTodayEarnings->execute([':driver_id' => $driverID]); + $todayEarnings = (float)($stmtTodayEarnings->fetchColumn() ?: 0.0); + + // 3. Calculate Total Wallet Balance + $stmtTotalWallet = $con->prepare(" + SELECT COALESCE(SUM(amount), 0) + FROM `driverWallet` + WHERE driverID = :driver_id + "); + $stmtTotalWallet->execute([':driver_id' => $driverID]); + $totalWallet = (float)($stmtTotalWallet->fetchColumn() ?: 0.0); + + printSuccess([ + "challengePoints" => $challengePoints, + "todayEarnings" => $todayEarnings, + "totalWallet" => $totalWallet + ]); + +} catch (Exception $e) { + printFailure("An error occurred: " . $e->getMessage()); +} +?> diff --git a/walletintaleq.intaleq.xyz/v2/main/ride/passengerWallet/add_s2s_debt.php b/walletintaleq.intaleq.xyz/v2/main/ride/passengerWallet/add_s2s_debt.php new file mode 100644 index 0000000..fe14ac0 --- /dev/null +++ b/walletintaleq.intaleq.xyz/v2/main/ride/passengerWallet/add_s2s_debt.php @@ -0,0 +1,59 @@ +beginTransaction(); + + $sql = "INSERT INTO `passengerWallet` ( + `passenger_id`, + `balance` + ) VALUES ( + :passengerID, + :amount + );"; + + $stmt = $con->prepare($sql); + $stmt->execute([ + ':passengerID' => $passengerID, + ':amount' => $amount + ]); + + if ($stmt->rowCount() > 0) { + $con->commit(); + printSuccess("Record saved successfully"); + } else { + $con->rollBack(); + printFailure("Failed to save record"); + } +} catch (Exception $e) { + if ($con->inTransaction()) { + $con->rollBack(); + } + printFailure("An error occurred: " . $e->getMessage()); +} +?>