Files
Siro/siro_driver/lib/controller/home/captin/home_captain_controller.dart
2026-06-13 01:32:15 +03:00

861 lines
28 KiB
Dart
Executable File

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:intaleq_maps/intaleq_maps.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;
import 'package:siro_driver/constant/box_name.dart';
import 'dart:async';
import '../../../constant/links.dart';
import '../../../constant/style.dart';
import '../../../constant/table_names.dart';
import '../../../main.dart';
import '../../../print.dart';
import '../../../views/home/my_wallet/walet_captain.dart';
import '../../../views/widgets/elevated_btn.dart';
import '../../firebase/firbase_messge.dart';
import '../../functions/background_service.dart';
import '../../functions/crud.dart';
import '../../functions/location_background_controller.dart';
import '../../functions/location_controller.dart';
import '../payment/captain_wallet_controller.dart';
class HomeCaptainController extends GetxController {
bool isActive = false;
DateTime? activeStartTime;
Duration activeDuration = Duration.zero;
Timer? activeTimer;
Map data = {};
bool isHomeMapActive = true;
InlqBitmap carIcon = InlqBitmap.fromAsset('assets/images/car.png');
bool isMapReadyForCommands = false;
bool isLoading = true;
late double kazan = 0;
double latePrice = 0;
double heavyPrice = 0;
double comfortPrice = 0,
speedPrice = 0,
deliveryPrice = 0,
mashwariPrice = 0,
familyPrice = 0,
fuelPrice = 0;
double naturePrice = 0;
bool isCallOn = false;
String totalMoneyToday = '0';
double? rating = 5;
String rideId = '0';
String countRideToday = '0';
String totalMoneyInSEFER = '0';
String totalDurationToday = '0';
Timer? timer;
Timer? _cameraFollowTimer;
LatLng myLocation = const LatLng(33.5138, 36.2765);
String totalPoints = '0';
String countRefuse = '0';
bool mapType = false;
bool mapTrafficON = false;
double widthMapTypeAndTraffic = 50;
// === متغيرات الهيت ماب الجديدة ===
bool isHeatmapVisible = false;
Set<Polygon> heatmapPolygons =
{}; // سنستخدم Polygon لرسم المربعات على جوجل مابس
// Inject the LocationController class
// final locationController = Get.put(LocationController());
// الكود الصحيح
final locationController = Get.find<LocationController>();
// final locationBackController = Get.put(LocationBackgroundController());
String formatDuration(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "${duration.inHours}:$twoDigitMinutes:$twoDigitSeconds";
}
// دالة لتغيير حالة الهيت ماب (عرض/إخفاء)
void toggleHeatmap() async {
isHeatmapVisible = !isHeatmapVisible;
print("🔥 [Heatmap] Visibility toggled to: $isHeatmapVisible");
if (isHeatmapVisible) {
startHeatmapCycle();
} else {
_heatmapTimer?.cancel();
heatmapPolygons.clear();
print("🧹 [Heatmap] Polygons cleared.");
}
update(); // تحديث الواجهة
}
// داخل MapDriverController
// متغير لتخزين المربعات
// Set<Polygon> heatmapPolygons = {};
// دالة جلب البيانات ورسم الخريطة
Future<void> fetchAndDrawHeatmap() async {
print("🚀 [Heatmap] Fetching live data...");
// استخدم الرابط المباشر لملف JSON لسرعة قصوى
final String jsonUrl = "${AppLink.ride}/rides/heatmap_live.json";
try {
// نستخدم timestamp لمنع الكاش من الموبايل نفسه
final response = await http.get(
Uri.parse("$jsonUrl?t=${DateTime.now().millisecondsSinceEpoch}"));
if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
print("✅ [Heatmap] Data received. Points count: ${data.length}");
_generatePolygons(data);
} else {
print("⚠️ [Heatmap] Server error: ${response.statusCode}");
}
} catch (e) {
print("❌ [Heatmap] Error: $e");
}
}
void _generatePolygons(List<dynamic> data) {
print("🎨 [Heatmap] Processing polygons...");
Set<Polygon> tempPolygons = {};
// الأوفست لرسم المربع (نصف حجم الشبكة)
// الشبكة دقتها 0.01 درجة، لذا نصفها 0.005
double offset = 0.005;
int highCount = 0, medCount = 0, lowCount = 0;
for (var point in data) {
double lat = double.parse(point['lat'].toString());
double lng = double.parse(point['lng'].toString());
String intensity = point['intensity'] ?? 'low';
int count = int.parse(point['count'].toString()); // ✅ جلب العدد
Color color;
Color strokeColor;
// 🧠 منطق الألوان: ندمج الذكاء (Intensity) مع العدد (Count)
if (intensity == 'high' || count >= 5) {
highCount++;
// منطقة مشتعلة (أحمر)
// إما فيها طلبات ضائعة (Timeout) أو فيها عدد كبير من الطلبات
color = Colors.red.withValues(alpha: 0.35);
strokeColor = Colors.red.withValues(alpha: 0.8);
} else if (intensity == 'medium' || count >= 3) {
medCount++;
// منطقة متوسطة (برتقالي)
color = Colors.orange.withValues(alpha: 0.35);
strokeColor = Colors.orange.withValues(alpha: 0.8);
} else {
lowCount++;
// منطقة خفيفة (أصفر)
color = Colors.yellow.withValues(alpha: 0.3);
strokeColor = Colors.yellow.withValues(alpha: 0.6);
}
// رسم المربع
tempPolygons.add(Polygon(
polygonId: PolygonId("$lat-$lng"),
// consumeTapEvents: true, // للسماح بالضغط عليه مستقبلاً
points: [
LatLng(lat - offset, lng - offset),
LatLng(lat + offset, lng - offset),
LatLng(lat + offset, lng + offset),
LatLng(lat - offset, lng + offset),
],
fillColor: color,
strokeColor: strokeColor,
strokeWidth: 2,
));
}
heatmapPolygons = tempPolygons;
print(
"✨ [Heatmap] Rendering Done. (🔥 High: $highCount, 🟠 Med: $medCount, 🟡 Low: $lowCount)");
print("📍 [Heatmap] Total Polygons on Map: ${heatmapPolygons.length}");
update(); // تحديث الخريطة
}
Timer? _heatmapTimer;
// دالة لتشغيل الخريطة الحرارية كل فترة (كل 5 دقائق) لضمان نشاط البيانات
void startHeatmapCycle() {
_heatmapTimer?.cancel();
fetchAndDrawHeatmap();
// Refresh every 15 min instead of 5 to reduce data & battery usage
_heatmapTimer = Timer.periodic(const Duration(minutes: 15), (timer) {
if (isHeatmapVisible) {
print("🔄 [Heatmap] Periodic refresh started...");
fetchAndDrawHeatmap();
} else {
timer.cancel();
}
});
}
void goToWalletFromConnect() {
Get.back();
Get.back();
Get.to(() => WalletCaptainRefactored());
}
void changeRideId() {
rideId = 'rideId';
update();
}
void addCustomCarIcon() {
carIcon = InlqBitmap.fromAsset('assets/images/car.png');
update();
}
String stringActiveDuration = '';
int _fatigueSeconds = 0; // عداد ثواني الإرهاق المؤقت
// ==========================================
// ====== 🛡️ Fatigue Monitoring System ======
// ==========================================
void _checkFatigueBeforeOnline() {
int totalSecondsToday = box.read('fatigue_total_seconds') ?? 0;
String? lastOfflineStr = box.read('fatigue_last_offline');
if (lastOfflineStr != null) {
DateTime lastOffline = DateTime.parse(lastOfflineStr);
// If offline for more than 6 continuous hours, reset the fatigue counter
if (DateTime.now().difference(lastOffline).inHours >= 6) {
totalSecondsToday = 0;
box.write('fatigue_total_seconds', 0);
}
}
if (totalSecondsToday >= 12 * 3600) {
// 12 Hours
_forceOfflineDueToFatigue();
throw Exception('Fatigue Limit Exceeded');
}
}
void _forceOfflineDueToFatigue() {
if (isActive) {
isActive = false;
locationController.stopLocationUpdates();
activeStartTime = null;
activeTimer?.cancel();
update();
}
Get.defaultDialog(
title: 'Safety First 🛑'.tr,
middleText:
'You have been driving for 12 hours. For your safety and compliance, please take a 6-hour break.'
.tr,
barrierDismissible: false,
titleStyle:
const TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
confirm: ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () => Get.back(),
child: Text('OK'.tr, style: const TextStyle(color: Colors.white)),
),
);
}
double get minPointsThreshold {
String country = box.read(BoxName.countryCode) ?? 'Syria';
if (country == 'Jordan') {
return -3.0;
} else if (country == 'Egypt') {
return -200.0;
} else {
return -200.0; // Default (Syria / other)
}
}
void onButtonSelected() {
if (!Get.isRegistered<CaptainWalletController>()) {
Get.put(CaptainWalletController());
}
totalPoints = Get.find<CaptainWalletController>().totalPoints;
// Toggle Active State
isActive = !isActive;
if (isActive) {
try {
_checkFatigueBeforeOnline(); // Throws exception if tired
if (double.parse(totalPoints) > minPointsThreshold) {
locationController.startLocationUpdates();
HapticFeedback.heavyImpact();
activeStartTime = DateTime.now();
activeTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
activeDuration = DateTime.now().difference(activeStartTime!);
stringActiveDuration = formatDuration(activeDuration);
// Increment Fatigue Counter (write to box every 30s)
_fatigueSeconds++;
if (_fatigueSeconds % 30 == 0) {
int totalSeconds =
(box.read('fatigue_total_seconds') ?? 0) + _fatigueSeconds;
box.write('fatigue_total_seconds', totalSeconds);
_fatigueSeconds = 0;
if (totalSeconds >= 12 * 3600) {
// 12 hours
_forceOfflineDueToFatigue();
}
}
update();
});
} else {
locationController.stopLocationUpdates();
activeStartTime = null;
activeTimer?.cancel();
savePeriod(activeDuration);
activeDuration = Duration.zero;
box.write('fatigue_last_offline', DateTime.now().toIso8601String());
update();
}
} catch (e) {
// Driver is fatigued, revert state
isActive = false;
update();
}
} else {
locationController.stopLocationUpdates();
activeStartTime = null;
activeTimer?.cancel();
savePeriod(activeDuration);
activeDuration = Duration.zero;
// Save offline time for Fatigue Monitoring reset
box.write('fatigue_last_offline', DateTime.now().toIso8601String());
update();
}
}
// متغيرات العداد للحظر
RxString remainingBlockTimeStr = "".obs;
Timer? _blockTimer;
/// دالة الفحص والدايلوج
void checkAndShowBlockDialog() {
String? blockStr = box.read(BoxName.blockUntilDate);
if (blockStr == null || blockStr.isEmpty) return;
DateTime blockExpiry = DateTime.parse(blockStr);
DateTime now = DateTime.now();
if (now.isBefore(blockExpiry)) {
// 1. إجبار السائق على وضع الأوفلاين
box.write(BoxName.statusDriverLocation, 'blocked');
update();
// 2. بدء العداد
_startBlockCountdown(blockExpiry);
// 3. إظهار الديالوج المانع
Get.defaultDialog(
title: "Your account is temporarily restricted ⛔".tr,
titleStyle:
const TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
barrierDismissible: false, // 🚫 ممنوع الإغلاق بالضغط خارجاً
onWillPop: () async => false, // 🚫 ممنوع زر الرجوع في الأندرويد
content: Obx(() => Column(
children: [
const Icon(Icons.timer_off_outlined,
size: 50, color: Colors.orange),
const SizedBox(height: 15),
Text(
"You have exceeded the allowed cancellation limit (3 times).\nYou cannot work until the penalty expires."
.tr,
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
Text(
remainingBlockTimeStr.value, // 🔥 الوقت يتحدث هنا
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black87),
),
const SizedBox(height: 20),
],
)),
confirm: Obx(() {
// الزر يكون مفعلاً فقط عندما ينتهي الوقت
bool isFinished = remainingBlockTimeStr.value == "00:00:00" ||
remainingBlockTimeStr.value == "Done";
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: isFinished ? Colors.green : Colors.grey,
),
onPressed: isFinished
? () {
Get.back(); // إغلاق الديالوج
box.remove(BoxName.blockUntilDate); // إزالة الحظر
Get.snackbar("Welcome".tr, "You can now receive orders".tr,
backgroundColor: Colors.green);
}
: null, // زر معطل
child: Text(isFinished ? "Go Online".tr : "Wait for timer".tr),
);
}),
);
} else {
// الوقت انتهى أصلاً -> تنظيف
box.remove(BoxName.blockUntilDate);
}
}
/// دالة العداد التنازلي
void _startBlockCountdown(DateTime expiry) {
_blockTimer?.cancel();
_blockTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
DateTime now = DateTime.now();
if (now.isAfter(expiry)) {
// انتهى الوقت
remainingBlockTimeStr.value = "Done";
timer.cancel();
} else {
// حساب الفرق وتنسيقه
Duration diff = expiry.difference(now);
String twoDigits(int n) => n.toString().padLeft(2, "0");
String hours = twoDigits(diff.inHours);
String minutes = twoDigits(diff.inMinutes.remainder(60));
String seconds = twoDigits(diff.inSeconds.remainder(60));
remainingBlockTimeStr.value = "$hours:$minutes:$seconds";
}
});
}
@override
void onClose() {
print("🔥 [HomeCaptain] onClose called. Tearing down map resources...");
_blockTimer?.cancel();
activeTimer?.cancel();
_cameraFollowTimer?.cancel();
_heatmapTimer?.cancel();
stopTimer();
mapHomeCaptainController = null;
super.onClose();
}
void getRefusedOrderByCaptain() async {
DateTime today = DateTime.now();
int todayDay = today.day;
String driverId = box.read(BoxName.driverID).toString();
String customQuery = '''
SELECT COUNT(*) AS count
FROM ${TableName.driverOrdersRefuse}
WHERE driver_id = '$driverId'
AND created_at LIKE '%$todayDay%'
''';
try {
List<Map<String, dynamic>> results =
await sql.getCustomQuery(customQuery);
countRefuse = results[0]['count'].toString();
update();
if (double.parse(totalPoints) <= minPointsThreshold) {
// if (int.parse(countRefuse) > 3 || double.parse(totalPoints) <= minPointsThreshold) {
locationController.stopLocationUpdates();
activeStartTime = null;
activeTimer?.cancel();
savePeriod(activeDuration);
activeDuration = Duration.zero;
update();
Get.defaultDialog(
// backgroundColor: CupertinoColors.destructiveRed,
barrierDismissible: false,
title: 'You Are Stopped For this Day !'.tr,
content: Text(
'You Refused 3 Rides this Day that is the reason \nSee you Tomorrow!'
.tr,
style: AppStyle.title,
),
confirm: MyElevatedButton(
title: 'Ok , See you Tomorrow'.tr,
onPressed: () {
// إغلاق الديالوج والعودة قسرياً
navigatorKey.currentState?.pop();
Get.back();
}));
}
} catch (e) {}
}
void changeMapType() {
mapType = !mapType;
// heightButtomSheetShown = isButtomSheetShown == true ? 240 : 0;
update();
}
void changeMapTraffic() {
mapTrafficON = !mapTrafficON;
update();
}
// late SiroMapController mapHomeCaptainController;
IntaleqMapController? mapHomeCaptainController;
LatLng? _lastCameraLoc; // لتتبع آخر موقع حرك الكاميرا
// --- FIX 2: Smart Map Creation ---
void onMapCreated(IntaleqMapController controller) {
print("🔥 [HomeCaptain] onMapCreated started");
mapHomeCaptainController = controller;
// We delay the first move to ensure the native side is fully ready
Future.delayed(const Duration(milliseconds: 800), () {
if (isClosed || mapHomeCaptainController == null) return;
try {
var currentLoc = locationController.myLocation;
if (currentLoc.latitude != 0 &&
currentLoc.latitude != null &&
!currentLoc.latitude.isNaN) {
print(
"🔥 [HomeCaptain] Safely moving camera to: ${currentLoc.latitude}");
mapHomeCaptainController!.moveCamera(
CameraUpdate.newLatLngZoom(currentLoc, 17.5),
);
} else {
print("🔥 [HomeCaptain] Safely moving to default Damascus");
mapHomeCaptainController!.moveCamera(
CameraUpdate.newLatLngZoom(myLocation, 12),
);
}
// Mark as ready for regular listener updates
isMapReadyForCommands = true;
} catch (e) {
print("❌ [HomeCaptain] Map move failed: $e");
}
});
}
void savePeriod(Duration period) {
final periods = box.read<List<dynamic>>(BoxName.periods) ?? [];
periods.add(period.inSeconds);
box.write(BoxName.periods, periods);
}
Duration calculateTotalDuration() {
final periods = box.read<List<dynamic>>(BoxName.periods) ?? [];
Duration totalDuration = Duration.zero;
for (dynamic periodInSeconds in periods) {
final periodDuration = Duration(seconds: periodInSeconds);
totalDuration += periodDuration;
}
return totalDuration;
}
Timer? _localDurationTimer;
RxString totalDurationDisplay = "00:00:00".obs; // لعرض الوقت في الواجهة
Duration _currentDuration = Duration.zero; // لتخزين الوقت ككائن Duration
void startPeriodicExecution() async {
await getCaptainDurationOnToday();
String? initialDurationStr = totalDurationToday;
if (initialDurationStr != '0') {
// تحويل النص (01:20:30) إلى كائن Duration
List<String> parts = initialDurationStr.split(':');
_currentDuration = Duration(
hours: int.parse(parts[0]),
minutes: int.parse(parts[1]),
seconds: int.parse(parts[2]),
);
// بدء العداد المحلي
_startLocalClock();
}
// Timer.periodic(const Duration(seconds: 30), (timer) async {
// await getCaptainDurationOnToday();
// });
}
void _startLocalClock() {
_localDurationTimer?.cancel();
_localDurationTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
// زيادة ثانية واحدة محلياً
_currentDuration += const Duration(seconds: 1);
// تحديث النص المعروض في الواجهة (Formatting)
totalDurationDisplay.value = _formatDuration(_currentDuration);
// اختيارياً: كل 5 دقائق فقط، قم بتحديث القيمة من السيرفر للتأكد من المزامنة
if (timer.tick % 300 == 0) {
getCaptainDurationOnToday();
}
});
}
String _formatDuration(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String hours = twoDigits(duration.inHours);
String minutes = twoDigits(duration.inMinutes.remainder(60));
String seconds = twoDigits(duration.inSeconds.remainder(60));
return "$hours:$minutes:$seconds";
}
void stopTimer() {
_localDurationTimer?.cancel();
}
getlocation() async {
isLoading = true;
update();
try {
// ننتظر جلب الموقع مع مهلة 10 ثوانٍ لتجنب التعليق
var locData = await locationController.getLocation().timeout(
const Duration(seconds: 10),
onTimeout: () => null,
);
if (locData != null && locData.latitude != null) {
myLocation = LatLng(locData.latitude!, locData.longitude!);
print(
"📍 [HomeCaptain] Location updated: ${myLocation.latitude}, ${myLocation.longitude}");
} else {
print(
"⚠️ [HomeCaptain] Could not get current location, using default.");
}
} catch (e) {
print("❌ Error in getlocation: $e");
} finally {
isLoading = false;
update();
}
}
Map walletDriverPointsDate = {};
Future getCaptainWalletFromBuyPoints() async {
// isLoading = true;
update();
var res = await CRUD().getWallet(
link: AppLink.getDriverPaymentPoints,
payload: {'driverID': box.read(BoxName.driverID).toString()},
);
isLoading = false;
// update();
if (res != 'failure') {
walletDriverPointsDate = jsonDecode(res);
double totalPointsDouble = double.parse(
walletDriverPointsDate['message'][0]['total_amount'].toString());
totalPoints = totalPointsDouble.toStringAsFixed(0);
update();
} else {
totalPoints = '0';
}
}
// 3. دالة نستدعيها عند قبول الطلب
void pauseHomeMapUpdates() {
isHomeMapActive = false;
update();
}
// 4. دالة نستدعيها عند العودة للصفحة الرئيسية
void resumeHomeMapUpdates() {
isHomeMapActive = true;
// تم حذف استدعاء onMapCreated المتكرر لمنع قفز الخريطة عند العودة
update();
}
@override
void onInit() async {
// ✅ تم إرجاعه كتعليق لمنع الديالوج عند التشغيل (كما كان في الكود الأصلي)
// bool permissionsGranted = await PermissionsHelper.requestAllPermissions();
// if (permissionsGranted) {
// await BackgroundServiceHelper.startService();
// }
Get.put(FirebaseMessagesController());
addToken();
await getlocation();
onButtonSelected();
getDriverRate();
addCustomCarIcon();
getKazanPercent();
getPaymentToday();
getCountRideToday();
getAllPayment();
startPeriodicExecution();
getCaptainWalletFromBuyPoints();
// onMapCreated(mapHomeCaptainController!);
// totalPoints = Get.find<CaptainWalletController>().totalPoints.toString();
// getRefusedOrderByCaptain();
// 🔥 الفحص عند تشغيل التطبيق
checkAndShowBlockDialog();
box.write(BoxName.statusDriverLocation, 'off');
// 2. عدل الليسنر ليصبح مشروطاً
// Camera follow timer — only moves when the driver has
// actually moved > 15 meters, saving GPU/battery on idle.
_cameraFollowTimer = Timer.periodic(const Duration(seconds: 8), (timer) {
if (isClosed ||
!isHomeMapActive ||
mapHomeCaptainController == null ||
!isMapReadyForCommands ||
!isActive) return;
var loc = locationController.myLocation;
if (loc.latitude != 0 && loc.latitude != null && !loc.latitude.isNaN) {
// Skip if driver hasn't moved significantly
if (_lastCameraLoc != null) {
final double dist = Geolocator.distanceBetween(
_lastCameraLoc!.latitude,
_lastCameraLoc!.longitude,
loc.latitude,
loc.longitude,
);
if (dist < 15) return;
}
_lastCameraLoc = loc;
try {
if (mapHomeCaptainController != null) {
mapHomeCaptainController?.animateCamera(
CameraUpdate.newLatLngZoom(loc, 17.5),
);
}
} catch (e) {
print("❌ [HomeCaptain] Camera movement failed: $e");
}
}
});
// LocationController().getLocation();
super.onInit();
}
addToken() async {
String? fingerPrint = await storage.read(key: BoxName.fingerPrint);
final payload = {
'token': (box.read(BoxName.tokenDriver)),
'captain_id': (box.read(BoxName.driverID)).toString(),
'fingerPrint': (fingerPrint).toString()
};
// Log.print('payload: ${payload}');
CRUD().post(link: AppLink.addTokensDriver, payload: payload);
}
getPaymentToday() async {
var res = await CRUD().getWallet(
link: AppLink.getDriverPaymentToday,
payload: {'driverID': box.read(BoxName.driverID).toString()});
if (res != 'failure') {
data = jsonDecode(res);
totalMoneyToday = data['message'][0]['todayAmount'].toString();
update();
} else {}
}
getKazanPercent() async {
var res = await CRUD().get(
link: AppLink.getKazanPercent,
payload: {'country': box.read(BoxName.countryCode).toString()},
);
if (res != 'failure') {
var json = jsonDecode(res);
kazan = double.parse(json['message'][0]['kazan']);
naturePrice = double.parse(json['message'][0]['naturePrice']);
heavyPrice = double.parse(json['message'][0]['heavyPrice']);
latePrice = double.parse(json['message'][0]['latePrice']);
comfortPrice = double.parse(json['message'][0]['comfortPrice']);
speedPrice = double.parse(json['message'][0]['speedPrice']);
deliveryPrice = double.parse(json['message'][0]['deliveryPrice']);
mashwariPrice = double.parse(json['message'][0]['freePrice']);
familyPrice = double.parse(json['message'][0]['familyPrice']);
fuelPrice = double.parse(json['message'][0]['fuelPrice']);
}
update();
}
double mpg = 0;
calculateConsumptionFuel() {
mpg = fuelPrice / 12; //todo in register car add mpg in box
}
getCountRideToday() async {
var res = await CRUD().get(
link: AppLink.getCountRide,
payload: {'driver_id': box.read(BoxName.driverID).toString()});
data = jsonDecode(res);
countRideToday = data['message'][0]['count'].toString();
update();
}
getDriverRate() async {
var res = await CRUD().get(
link: AppLink.getDriverRate,
payload: {'driver_id': box.read(BoxName.driverID).toString()});
if (res != 'failure') {
var decod = jsonDecode(res);
if (decod['message'][0]['rating'] != null) {
rating = double.parse(decod['message'][0]['rating'].toString());
} else {
rating = 5.0; // Set a default value (e.g., 5.0 for full rating)
}
} else {
rating = 5;
}
}
getAllPayment() async {
var res = await CRUD().getWallet(
link: AppLink.getAllPaymentFromRide,
payload: {'driverID': box.read(BoxName.driverID).toString()});
if (res == 'failure') {
totalMoneyInSEFER = '0';
} else {
data = jsonDecode(res);
totalMoneyInSEFER = data['message'][0]['total_amount'];
}
update();
}
void changeToAppliedRide(String status) {
box.write(BoxName.rideStatus, status);
Log.print('rideStatus from homcaptain : ${box.read(BoxName.rideStatus)}');
update();
}
Future<void> getCaptainDurationOnToday() async {
try {
var res = await CRUD().get(
link: AppLink.getTotalDriverDurationToday,
payload: {'driver_id': box.read(BoxName.driverID).toString()},
);
if (res == null || res == 'failure') {
totalDurationToday = '0';
update();
return;
}
var data = jsonDecode(res);
totalDurationToday = data['message']?[0]?['total_duration'] ?? '0';
} catch (e) {
print('Error in getCaptainDurationOnToday: $e');
totalDurationToday = '0';
}
update();
}
}